Частичная синхронизация с CMS
This commit is contained in:
parent
312f18a20a
commit
b26e521657
62 changed files with 827 additions and 5992 deletions
|
|
@ -8,18 +8,23 @@ class Connection_HttpRequest
|
|||
private $param = array(); // Параметры запроса
|
||||
public $data = null; // Содержание
|
||||
public $url; // Адресс
|
||||
public $method = self::GET; // Метод
|
||||
public $method; // Метод
|
||||
public $port = 80;
|
||||
public $host = "";
|
||||
public $proxy_host = false;
|
||||
public $proxy_port = false;
|
||||
public $proxy_host = null;
|
||||
public $proxy_port = null;
|
||||
public $http_version = 'HTTP/1.1';
|
||||
|
||||
function __construct() {
|
||||
$this->method = self::GET;
|
||||
}
|
||||
|
||||
/**
|
||||
* Возвращает заголовок соединения
|
||||
*/
|
||||
public function getHeader()
|
||||
{
|
||||
$result = $this->method . " " . $this->url . " HTTP/1.1\r\n";
|
||||
$result = $this->method . " " . $this->url . " " . $this->http_version . "\r\n";
|
||||
$result .= "Host: ". $this->host ."\r\n";
|
||||
foreach ($this->param as $key => $value) {
|
||||
$result .= $key . ": " . $value . "\r\n";
|
||||
|
|
@ -74,10 +79,10 @@ class Connection_HttpRequest
|
|||
{
|
||||
$host = ($this->proxy_host) ? $this->proxy_host : $this->host;
|
||||
$port = ($this->proxy_port) ? $this->proxy_port : $this->port;
|
||||
$errno = 0;
|
||||
$errstr = '';
|
||||
$socket = fsockopen($host, $port, $errno, $errstr, 30);
|
||||
if (! $socket) {
|
||||
return null; // Exception
|
||||
} else {
|
||||
if (is_resource($socket)) {
|
||||
$header = $this->getHeader();
|
||||
fwrite($socket, $header);
|
||||
|
||||
|
|
@ -90,5 +95,17 @@ class Connection_HttpRequest
|
|||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
static function getJSON($url, $data) {
|
||||
$c = new Connection_HttpRequest();
|
||||
$c->http_version = "HTTP/1.0";
|
||||
|
||||
$query = http_build_query($data);
|
||||
$c->setUrl($q = $url . '?' . $query);
|
||||
$page = $c->getPage();
|
||||
|
||||
$response = new Connection_HttpResponse($page);
|
||||
return json_decode((string) preg_replace('/[\x00-\x09\x0B\x0C\x0E-\x1F\x7F]/', '', $response->getData()), true);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -9,8 +9,8 @@ class Connection_HttpResponse
|
|||
private $param = array ();
|
||||
private $code;
|
||||
public $response;
|
||||
public $data;
|
||||
public $version;
|
||||
public $data;
|
||||
|
||||
public function __construct($response)
|
||||
{
|
||||
|
|
|
|||
16
src/Controller/Request.php
Normal file
16
src/Controller/Request.php
Normal file
|
|
@ -0,0 +1,16 @@
|
|||
<?php
|
||||
|
||||
class Controller_Request {
|
||||
function __construct($request, $id) {
|
||||
$this->r = $request;
|
||||
$this->id = $id;
|
||||
}
|
||||
|
||||
function get($name) {
|
||||
$v = $this->r->get($name);
|
||||
if ($id && is_array($v)) {
|
||||
return isset($v[$id]) ? $v[$id] : $def;
|
||||
}
|
||||
return $v;
|
||||
}
|
||||
}
|
||||
64
src/Controller/Service.php
Normal file
64
src/Controller/Service.php
Normal file
|
|
@ -0,0 +1,64 @@
|
|||
<?php
|
||||
|
||||
/**
|
||||
* Класс сервиса = Упрощенный компонент
|
||||
*/
|
||||
class Controller_Service
|
||||
{
|
||||
public $viewPath = array();
|
||||
public $registry; // Registry->getInstance
|
||||
public $template;
|
||||
public $templatePath;
|
||||
public $COMPONENTS_WEB;
|
||||
|
||||
public function getTemplatePath($name)
|
||||
{
|
||||
return Path::join($this->viewPath[0], 'templates', 'modern', $name);
|
||||
}
|
||||
|
||||
public function getTemplateWebPath()
|
||||
{
|
||||
return Path::join($this->webPath[0], strtolower(get_class($this)), 'templates', 'modern');
|
||||
}
|
||||
|
||||
/**
|
||||
* @param $name Имя модели
|
||||
*/
|
||||
private function getModelPath($name)
|
||||
{
|
||||
return Path::join (CMS_PATH, "model", $name . ".php");
|
||||
}
|
||||
|
||||
/**
|
||||
* Создает модель
|
||||
* @param string $name
|
||||
* @return model
|
||||
*/
|
||||
public function getModel($name)
|
||||
{
|
||||
require_once 'mapper/mapper.php';
|
||||
|
||||
require_once ($this->getModelPath ($name));
|
||||
$modelName = $name . "Mapper";
|
||||
$model = new $modelName ();
|
||||
$model->db = $this->db;
|
||||
return $model;
|
||||
}
|
||||
|
||||
public function options($key, $val, $res) {
|
||||
$result = array();
|
||||
while($res->next()) {
|
||||
$result[] = array('value' => $res->getInt($key), 'name' => $res->getString($val));
|
||||
}
|
||||
return $result;
|
||||
}
|
||||
|
||||
public function optionsPair($list, $selected = false) {
|
||||
$result = array();
|
||||
foreach ($list as $key => $value) {
|
||||
$result [] = array('value' => $key, 'name' => $value, 'selected' => $key == $selected);
|
||||
}
|
||||
return $result;
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -8,11 +8,11 @@ class Database_IdGenerator {
|
|||
}
|
||||
|
||||
function isBeforeInsert() {
|
||||
return $this->db->isPostgres();
|
||||
return false;
|
||||
}
|
||||
|
||||
function isAfterInsert() {
|
||||
return !$this->db->isPostgres();
|
||||
return true;
|
||||
}
|
||||
|
||||
function getId($seq) {
|
||||
|
|
|
|||
|
|
@ -1,86 +0,0 @@
|
|||
<?php
|
||||
|
||||
// Report simple running errors
|
||||
define('ERROR_FILE', 'phedor@edu.yar.ru');
|
||||
define('ERROR_TYPE', 1);
|
||||
|
||||
ini_set('error_reporting', 0);
|
||||
ini_set('display_errors', 0);
|
||||
error_reporting(0);
|
||||
|
||||
function get_error_name($id) {
|
||||
$names = array(1 => 'E_ERROR',
|
||||
2 => 'E_WARNING',
|
||||
4 => 'E_PARSE',
|
||||
8 => 'E_NOTICE',
|
||||
16 => 'E_CORE_ERROR',
|
||||
32 => 'E_CORE_WARNING',
|
||||
64 => 'E_COMPILE_ERROR',
|
||||
128 => 'E_COMPILE_WARNING',
|
||||
256 => 'E_USER_ERROR',
|
||||
512 => 'E_USER_WARNING',
|
||||
1024 => 'E_USER_NOTICE',
|
||||
2048 => 'E_STRICT',
|
||||
4096 => 'E_RECOVERABLE_ERROR',
|
||||
8192 => 'E_DEPRECATED',
|
||||
16384 => 'E_USER_DEPRECATED',
|
||||
30719 => 'E_ALL');
|
||||
return $names[$id];
|
||||
}
|
||||
|
||||
|
||||
function send_error($description) {
|
||||
$message = "request: " . "http://".$_SERVER['SERVER_NAME'].$_SERVER['REQUEST_URI'] . "\n";
|
||||
$message .= "from: " . $_SERVER['REMOTE_ADDR'] . "\n";
|
||||
if(isset($_SERVER['HTTP_REFERER'])) $message .= "referer: " . $_SERVER['HTTP_REFERER'] . "\n";
|
||||
$message .= "post:" . var_export($_POST, true) . "\n";
|
||||
$message .= "description: " . $description;
|
||||
|
||||
// error_log($message, ERROR_TYPE, ERROR_FILE);
|
||||
return false;
|
||||
}
|
||||
|
||||
function error_handler($errno, $errstr, $errfile, $errline) {
|
||||
$message = "request: " . "http://".$_SERVER['SERVER_NAME'].$_SERVER['REQUEST_URI'] . "\n";
|
||||
$message .= "from: " . $_SERVER['REMOTE_ADDR'] . "\n";
|
||||
if(isset($_SERVER['HTTP_REFERER'])) $message .= "referer: " . $_SERVER['HTTP_REFERER'] . "\n";
|
||||
$message .= "post:" . var_export($_POST, true) . "\n";
|
||||
$message .= "type: " . get_error_name($errno) . "\n"
|
||||
. "error: " . $errstr . "\n"
|
||||
. "line: " . $errline . "\n"
|
||||
. "file: " . $errfile;
|
||||
|
||||
// error_log($message, ERROR_TYPE, ERROR_FILE);
|
||||
return false;
|
||||
}
|
||||
|
||||
function shutdown() {
|
||||
$error = error_get_last();
|
||||
$message = "request: " . "http://".$_SERVER['SERVER_NAME'].$_SERVER['REQUEST_URI'] . "\n";
|
||||
$message .= "from: " . $_SERVER['REMOTE_ADDR'] . "\n";
|
||||
if(isset($_SERVER['HTTP_REFERER'])) $message .= "referer: " . $_SERVER['HTTP_REFERER'] . "\n";
|
||||
if (is_array($error)) {
|
||||
foreach ($error as $info => $string) {
|
||||
$message .= "{$info}: {$string}\n";
|
||||
}
|
||||
}
|
||||
|
||||
error_log($message, ERROR_TYPE, ERROR_FILE);
|
||||
}
|
||||
|
||||
function exception_handler($exception) {
|
||||
$message = "request: " . "http://".$_SERVER['SERVER_NAME'].$_SERVER['REQUEST_URI'] . "\n";
|
||||
$message .= "from: " . $_SERVER['REMOTE_ADDR'] . "\n";
|
||||
if(isset($_SERVER['HTTP_REFERER'])) $message .= "referer: " . $_SERVER['HTTP_REFERER'] . "\n";
|
||||
$message .=
|
||||
"file: " . $exception->getFile() . "\n"
|
||||
. "line: " . $exception->getLine() . "\n"
|
||||
. "message: " . $exception->getMessage() . "\n"
|
||||
. "trace: " . $exception->getTraceAsString();
|
||||
error_log($message, ERROR_TYPE, ERROR_FILE);
|
||||
return true;
|
||||
}
|
||||
|
||||
set_exception_handler('exception_handler');
|
||||
set_error_handler("error_handler");
|
||||
//register_shutdown_function('shutdown');
|
||||
80
src/File.php
80
src/File.php
|
|
@ -1,80 +0,0 @@
|
|||
<?php
|
||||
|
||||
require_once 'core/sort.php';
|
||||
|
||||
//Становиться похоже на работу файлов через SPL возможно стоит реализовать на базе его
|
||||
class FileRecord
|
||||
{
|
||||
public $file;
|
||||
protected $src;
|
||||
protected $parent;
|
||||
|
||||
function __construct(array $file, $src, $parent = false)
|
||||
{
|
||||
$this->file = $file;
|
||||
$this->filename = $src;
|
||||
$this->parent = $parent;
|
||||
}
|
||||
|
||||
function get($name) {
|
||||
return isset($this->file[$name]) ? $this->file[$name] : null;
|
||||
}
|
||||
|
||||
function fileStat()
|
||||
{
|
||||
$type = is_dir($this->filename);
|
||||
return array(
|
||||
'name' => ($this->parent) ? ".." : $this->getName(),
|
||||
'type' => $type,
|
||||
'extension' => ($type) ? 'folder' : pathinfo($this->filename, PATHINFO_EXTENSION),
|
||||
'date' => date("d.m.Y H:i", $this->getTime()),
|
||||
'access' => 0,
|
||||
'size' => ($type) ? "" : $this->getSizeString(),
|
||||
'state' => isset($this->file['state']) ? $this->file['state'] : 'unknown',
|
||||
'title' => $this->getTitle(),
|
||||
/*'author' => $this->file['author'],
|
||||
'description' => $this->file['description'],
|
||||
'keywords' => $this->file['keywords'],*/
|
||||
);
|
||||
}
|
||||
|
||||
function isExpected()
|
||||
{
|
||||
if (isset($this->file['state'])) {
|
||||
return ($this->file['state'] == 'expected');
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
function getSizeString()
|
||||
{
|
||||
$size = $this->getSize();
|
||||
foreach (array('б ', 'Kб', 'Mб') as $suffix) {
|
||||
if (($size / 1024) <= 1) {
|
||||
return round($size, 0) . ' ' . $suffix;
|
||||
}
|
||||
$size /= 1024;
|
||||
}
|
||||
return round($size, 0) . ' GB';
|
||||
}
|
||||
|
||||
function getSize()
|
||||
{
|
||||
return ($this->isExpected()) ? 0 : filesize($this->filename);
|
||||
}
|
||||
|
||||
function getTime()
|
||||
{
|
||||
return ($this->isExpected()) ? 0 : filemtime($this->filename);
|
||||
}
|
||||
|
||||
function getName()
|
||||
{
|
||||
return pathinfo($this->filename, PATHINFO_BASENAME);
|
||||
}
|
||||
|
||||
function getTitle()
|
||||
{
|
||||
return isset($this->file['title']) ? $this->file['title'] : $this->getName();
|
||||
}
|
||||
}
|
||||
|
|
@ -6,9 +6,9 @@
|
|||
class Filter_ActionAccess
|
||||
{
|
||||
public $access = array();
|
||||
public $processor;
|
||||
|
||||
function __construct($processor)
|
||||
{
|
||||
function __construct(/*.Filter_Filter.*/$processor) {
|
||||
$this->processor = $processor;
|
||||
}
|
||||
|
||||
|
|
@ -17,14 +17,12 @@ class Filter_ActionAccess
|
|||
* !! Реализация класса проверки действий не должна быть внутри Контроллера!!!
|
||||
* Информация о доступе может быть в файле, базе данных и т.д.
|
||||
*/
|
||||
function checkAction($action)
|
||||
{
|
||||
function checkAction($action) {
|
||||
// Импликация !! http://ru.wikipedia.org/wiki/Импликация
|
||||
return (!isset($this->access[$action]) || in_array(UserAccess::$access, $this->access[$action]));
|
||||
return (!isset($this->access[$action]) || in_array(Filter_UserAccess::$access, $this->access[$action]));
|
||||
}
|
||||
|
||||
function execute(HTTPRequest $request)
|
||||
{
|
||||
function execute(HttpRequest $request) {
|
||||
$action = $request->getAction();
|
||||
if(! $this->checkAction($action)) {
|
||||
$request->set('action', 'index');
|
||||
|
|
|
|||
|
|
@ -7,17 +7,15 @@ class Filter_ActionLogger
|
|||
public $action;
|
||||
public $processor;
|
||||
|
||||
function __construct($processor)
|
||||
{
|
||||
function __construct(/*.Filter_Filter.*/$processor) {
|
||||
$this->processor = $processor;
|
||||
$this->file = fopen(Shortcut::getUrl('access.log'), "a");
|
||||
}
|
||||
|
||||
function execute(HTTPRequest $request)
|
||||
{
|
||||
function execute(HttpRequest $request) {
|
||||
$action = $request->getAction();
|
||||
if(in_array($action, $this->before)) {
|
||||
fwrite($this->file, "time: " . date("r", time()) . " query: ". json::encode(array_merge($_POST, $_GET)) . " by: " . UserAccess::$name . "\n");
|
||||
fwrite($this->file, "time: " . date("r", time()) . " query: ". json_encode(array_merge($_POST, $_GET)) . " by: " . Filter_UserAccess::$name . "\n");
|
||||
}
|
||||
return $this->processor->execute($request);
|
||||
}
|
||||
|
|
|
|||
52
src/Filter/Authorization.php
Normal file
52
src/Filter/Authorization.php
Normal file
|
|
@ -0,0 +1,52 @@
|
|||
<?php
|
||||
|
||||
class Filter_Authorization {
|
||||
const SESSION_BROWSER_SIGN_SECRET = '@w3dsju45Msk#';
|
||||
const SESSION_BROWSER_SIGN_KEYNAME = 'session.app.browser.sign';
|
||||
|
||||
static function isLogged() {
|
||||
if (session_status() == PHP_SESSION_NONE) {
|
||||
session_start();
|
||||
}
|
||||
$hash = self::getBrowserSign();
|
||||
// Если $hash не совпадает $_SESSION['hash'] то удаляем сессию
|
||||
if (isset($_SESSION ['access']) && isset($_SESSION[self::SESSION_BROWSER_SIGN_KEYNAME])) {
|
||||
|
||||
if ($hash == $_SESSION[self::SESSION_BROWSER_SIGN_KEYNAME]) {
|
||||
// UserAccess::getUserById($_SESSION ['access']); // Поиск по идентификатору
|
||||
return true;
|
||||
} else {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
static function enter($id)
|
||||
{
|
||||
// $db->executeQuery("UPDATE visitor SET sid = '' WHERE id_visitor = " . $result->getInt('id_user'));
|
||||
session_register("access");
|
||||
session_register("time");
|
||||
|
||||
// $_SESSION ["group"] = $result->getInt('access');
|
||||
$_SESSION ["access"] = $id; // id_user
|
||||
$_SESSION [self::SESSION_BROWSER_SIGN_KEYNAME] = self::getBrowserSign();
|
||||
$_SESSION ["time"] = time();
|
||||
}
|
||||
|
||||
private static function getBrowserSign()
|
||||
{
|
||||
$rawSign = self::SESSION_BROWSER_SIGN_SECRET;
|
||||
// $signParts = array('HTTP_USER_AGENT', 'HTTP_ACCEPT_ENCODING');
|
||||
$signParts = array();
|
||||
|
||||
foreach ($signParts as $signPart) {
|
||||
$rawSign .= '::' . (isset($_SERVER[$signPart]) ? $_SERVER[$signPart] : 'none');
|
||||
}
|
||||
return md5($rawSign);
|
||||
}
|
||||
|
||||
static function logout() {
|
||||
session_destroy();
|
||||
}
|
||||
}
|
||||
|
|
@ -6,7 +6,7 @@
|
|||
class Filter_Filter
|
||||
{
|
||||
public $processor;
|
||||
public function __construct($processor)
|
||||
public function __construct(/*.Filter_Filter.*/$processor)
|
||||
{
|
||||
$this->processor = $processor;
|
||||
}
|
||||
|
|
@ -16,9 +16,9 @@ class Filter_Filter
|
|||
return $this->processor->execute($request);
|
||||
}
|
||||
|
||||
public function getView($name)
|
||||
public function getView($name, $class = 'View_Top')
|
||||
{
|
||||
return $this->processor->getView($name);
|
||||
return $this->processor->getView($name, $class);
|
||||
}
|
||||
|
||||
public function getConnection()
|
||||
|
|
|
|||
|
|
@ -16,12 +16,12 @@ class Filter_UserAccess
|
|||
{
|
||||
}
|
||||
|
||||
public static function setUp($db)
|
||||
public static function setUp(Database $db)
|
||||
{
|
||||
self::$db = $db;
|
||||
}
|
||||
|
||||
public static function getUserByQuery($stmt)
|
||||
public static function getUserByQuery(Database_Statement $stmt)
|
||||
{
|
||||
global $GROUPS;
|
||||
$result = $stmt->executeQuery();
|
||||
|
|
@ -62,7 +62,7 @@ class Filter_UserAccess
|
|||
$time = time();
|
||||
if ($time - $lasttime > self::LIFE_TIME) return null; // Вышло время сессии
|
||||
$id = self::$id;
|
||||
$stmt = self::$db->executeQuery("UPDATE users SET lasttime = $time WHERE id_user = $id"); // Время последнего обращения входа
|
||||
self::$db->executeQuery("UPDATE users SET lasttime = $time WHERE id_user = $id"); // Время последнего обращения входа
|
||||
}
|
||||
return $result;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,50 +0,0 @@
|
|||
<?php
|
||||
|
||||
/**
|
||||
* Генерация файлов Grpahviz dot
|
||||
*/
|
||||
class Formats_Dot
|
||||
{
|
||||
static function getHeader ()
|
||||
{
|
||||
$header =
|
||||
"digraph G {\n"
|
||||
. "\toverlap=false; splines=true;\n"
|
||||
. "\tfontname = \"Verdana\"\n"
|
||||
. "\tfontsize = 8\n"
|
||||
. "\tnode [\n"
|
||||
. "\t\tfontname = \"Verdana\"\n"
|
||||
. "\t\tfontsize = 8\n"
|
||||
. "\t\tshape = \"record\"\n"
|
||||
. "\t]\n"
|
||||
. "\tedge [\n"
|
||||
. "\t\tfontname = \"Verdana\"\n"
|
||||
. "\t\tfontsize = 8\n"
|
||||
. "\t]\n";
|
||||
|
||||
return $header;
|
||||
}
|
||||
|
||||
static function getFooter ()
|
||||
{
|
||||
$footer = "}\n";
|
||||
return $footer;
|
||||
}
|
||||
|
||||
function assocToDot (array $array, array $label)
|
||||
{
|
||||
$result = array (self::getHeader());
|
||||
// Метки
|
||||
foreach ($label as $value) {
|
||||
$result [] = "\t\"{$value[0]}\" [ label = \"{$value[1]}\" ] \n";
|
||||
}
|
||||
// Ассоциации
|
||||
foreach ($array as $key => $value) {
|
||||
foreach ($value as $n) {
|
||||
$result [] = "\t\"$key\" -> \"$n\"\n";
|
||||
}
|
||||
}
|
||||
$result [] = self::getFooter();
|
||||
return implode("", $result);
|
||||
}
|
||||
}
|
||||
|
|
@ -1,85 +0,0 @@
|
|||
<?php
|
||||
|
||||
define ('URL_CLIP', 0);
|
||||
define ('URL_DIRECTORY', 1);
|
||||
|
||||
class HAuthorize {
|
||||
public $password;
|
||||
public $uuid;
|
||||
public $uuid_writeable;
|
||||
|
||||
public function __construct () {
|
||||
$this->uuid = "*";
|
||||
$this->uuid_writeable = 1;
|
||||
}
|
||||
|
||||
public function getString () {
|
||||
return "{$this->password};{$this->uuid};{$this->uuid_writeable}";
|
||||
}
|
||||
|
||||
public function setPassword ($username, $realm, $password) {
|
||||
$this->password = md5 ("$username:$realm:$password");
|
||||
}
|
||||
}
|
||||
|
||||
class HPermission {
|
||||
public $url;
|
||||
public $url_type;
|
||||
public $permission_type;
|
||||
public $expires;
|
||||
public $debitted_time;
|
||||
|
||||
public function __construct ($url, $url_type) {
|
||||
$this->url = $url;
|
||||
$this->url_type = $url_type;
|
||||
$this->expires = "*"; // MM/DD/YYYY:HH:MM:SS
|
||||
$this->permission_type = 0;
|
||||
$this->debitted_time = 0;
|
||||
}
|
||||
|
||||
public function getString () {
|
||||
return "{$this->url};{$this->url_type};{$this->permission_type};{$this->expires};{$this->debitted_time}";
|
||||
}
|
||||
}
|
||||
|
||||
class HFile {
|
||||
public $authorize;
|
||||
public $permission = array ();
|
||||
|
||||
public function addAuthorize ($name, $realm, $password) {
|
||||
$this->authorize = new HAuthorize ();
|
||||
$this->authorize->setPassword ($name, $realm, $password);
|
||||
}
|
||||
|
||||
public function addPermission ($url, $url_type) {
|
||||
$this->permission[] = new HPermission ($url, $url_type);
|
||||
}
|
||||
|
||||
public function write ($name) {
|
||||
$file = fopen ($name, 'w');
|
||||
fwrite ($file, $this->getString ());
|
||||
fclose ($file);
|
||||
}
|
||||
|
||||
public function writeFTP ($ftp, $path) {
|
||||
$file = tmpfile ();
|
||||
fwrite ($file, $this->getString ());
|
||||
fseek ($file, 0);
|
||||
|
||||
ftp_fput ($ftp, $path, $file, FTP_BINARY);
|
||||
|
||||
fclose ($file);
|
||||
}
|
||||
|
||||
public function getString () {
|
||||
$result = array ();
|
||||
$result[] = $this->authorize->getString ();
|
||||
$result[] = "\n";
|
||||
foreach ($this->permission as $p) {
|
||||
$result[] = $p->getString ();
|
||||
$result[] = "\n";
|
||||
}
|
||||
return implode ("", $result);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -1,12 +0,0 @@
|
|||
<?php
|
||||
|
||||
class Geometry_Point
|
||||
{
|
||||
public $left, $top;
|
||||
function __construct ($left = 0, $top = 0)
|
||||
{
|
||||
$this->left = $left;
|
||||
$this->top = $top;
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -1,49 +0,0 @@
|
|||
<?php
|
||||
|
||||
class Geometry_Rectangle
|
||||
{
|
||||
public $left, $top, $width, $height;
|
||||
|
||||
function __construct($left = 0, $top = 0, $width = 0, $height = 0)
|
||||
{
|
||||
$this->left = $left;
|
||||
$this->top = $top;
|
||||
$this->width = $width;
|
||||
$this->height = $height;
|
||||
}
|
||||
|
||||
function __get($name)
|
||||
{
|
||||
switch ($name) {
|
||||
case 'right': return $this->left + $this->width;
|
||||
case 'bottom': return $this->top + $this->height;
|
||||
}
|
||||
}
|
||||
|
||||
function __set($name, $value)
|
||||
{
|
||||
switch ($name) {
|
||||
case 'right': $this->width = $value - $this->left;
|
||||
case 'bottom': $this->height = $value - $this->top;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Смещает прямоугольник на заданное положение
|
||||
*/
|
||||
function addPoint(Point $point)
|
||||
{
|
||||
$result = clone $this;
|
||||
$result->left += $point->left;
|
||||
$result->top += $point->top;
|
||||
return $result;
|
||||
}
|
||||
|
||||
/**
|
||||
* Координаты точки при выравнивании прямоугольника относительно текущего
|
||||
*/
|
||||
function alignment(Rectangle $base)
|
||||
{
|
||||
return new Point((($base->left + $base->right) - ($this->left + $this->right)) / 2, $base->bottom - $this->height);
|
||||
}
|
||||
}
|
||||
2707
src/IdnaConvert.php
2707
src/IdnaConvert.php
File diff suppressed because it is too large
Load diff
13
src/Layout/Empty.php
Normal file
13
src/Layout/Empty.php
Normal file
|
|
@ -0,0 +1,13 @@
|
|||
<?php
|
||||
|
||||
/**
|
||||
* Самый простой макет
|
||||
*/
|
||||
class Layout_Empty extends Filter_Filter
|
||||
{
|
||||
function execute(HttpRequest $request)
|
||||
{
|
||||
$text = $this->processor->execute($request);
|
||||
return $text;
|
||||
}
|
||||
}
|
||||
|
|
@ -69,8 +69,7 @@ class Layout_Manager extends Filter_Filter
|
|||
if (call_user_func($condition[0], $request)) {
|
||||
$layout = $condition[1];
|
||||
$view = $layout->execute($request);
|
||||
|
||||
if ($view instanceof View_Composite) {
|
||||
if (is_object($view)) {
|
||||
echo $view->render();
|
||||
} else {
|
||||
echo $view;
|
||||
|
|
|
|||
|
|
@ -1,11 +0,0 @@
|
|||
<?php
|
||||
/**
|
||||
* Самый простой макет
|
||||
*/
|
||||
class Layout_None extends Filter_Filter
|
||||
{
|
||||
function execute(HttpRequest $request)
|
||||
{
|
||||
return $this->processor->execute($request);
|
||||
}
|
||||
}
|
||||
|
|
@ -200,9 +200,8 @@ class Mail
|
|||
{
|
||||
$result = mail($this->_to, $this->getSubject(), $this->getMessage(), $this->getHeader());
|
||||
if(! $result) {
|
||||
file_put_contents(Path::resolveFile("send.eml"), $this->eml());
|
||||
throw new Exception('Невозможно отправить почту');
|
||||
// require_once "core/path.php";
|
||||
// file_put_contents(Path::resolveFile("data/email/send.eml"), $this->eml());
|
||||
}
|
||||
return $result;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,28 +0,0 @@
|
|||
<?php
|
||||
|
||||
class ModelFactory
|
||||
{
|
||||
static $shortcut = "model";
|
||||
|
||||
public function __construct (Connection $db)
|
||||
{
|
||||
$this->db = $db;
|
||||
}
|
||||
|
||||
/**
|
||||
* Создает модель
|
||||
* @param string $name
|
||||
* @return model
|
||||
*/
|
||||
public function getModel ($name)
|
||||
{
|
||||
require_once 'core/mapper/mapper.php'; // ????
|
||||
|
||||
require_once (Shortcut::getUrl(self::$shortcut, $name));
|
||||
$modelName = $name . "Mapper";
|
||||
$model = new $modelName();
|
||||
$model->db = $this->db;
|
||||
$model->factory = $this;
|
||||
return $model;
|
||||
}
|
||||
}
|
||||
|
|
@ -1,265 +0,0 @@
|
|||
<?php
|
||||
|
||||
/**
|
||||
* Использовать интерфейсы чтобы определить какие действия можно совершать с обьектом и таким образом
|
||||
* Строить набор действий Action и отображений View для обьекта
|
||||
* Т.к отображение данных может быть не только на таблицу баз данных
|
||||
* И возможно реализованны все интерфейсы
|
||||
*/
|
||||
interface IDataList
|
||||
{
|
||||
function findAll (Collection $request, $id = null);
|
||||
function findById ($id);
|
||||
function getCount (Collection $request, $id);
|
||||
}
|
||||
|
||||
interface IDataSave
|
||||
{
|
||||
function saveTo ($o);
|
||||
function updateTo ($o);
|
||||
}
|
||||
|
||||
/**
|
||||
* Отображение таблицы базы данных в обьекты
|
||||
* Mapper -> DataMapper implements IDataList, IDataSave, IDataSort, IDataDelete ...
|
||||
*
|
||||
* @package core
|
||||
*/
|
||||
class DataMapper implements IDataList
|
||||
{
|
||||
/* Хранить метаданные в статическом свойстве класса для ототбражения ?!, + Скрипт для генерации метаданных!!
|
||||
*/
|
||||
public $factory;
|
||||
public $className; /* Класс на который будет отображаться строчка таблицы */
|
||||
public $filter = ""; /* */
|
||||
public $schema = array (); /* Соответствие между свойством обьекта и столбцом, добавить тип для записей !! */
|
||||
public $database; /* Таблица */
|
||||
public $index; /* Индексный столбец */
|
||||
public $db; /* Соединение с базой данных */
|
||||
public $reference = array (null, null);
|
||||
|
||||
public function __construct ()
|
||||
{
|
||||
}
|
||||
|
||||
public function setRange ($stmt, $page, $size)
|
||||
{
|
||||
$stmt->setLimit ($size);
|
||||
$stmt->setOffset (($page-1) * $size);
|
||||
}
|
||||
|
||||
public function listSQL (array $list)
|
||||
{
|
||||
return implode ($list, ",");
|
||||
}
|
||||
|
||||
/**
|
||||
* Поиск строки в таблице по идентификатору
|
||||
* @param $id Значение идентификатора
|
||||
* @return Обьект класса $className
|
||||
*/
|
||||
public function findById ($id)
|
||||
{
|
||||
// Строки запроса преобразовать в методы (getSQLSelect ...)
|
||||
// Query::from($this->database)->where ($this->index, "=", $id)->select();
|
||||
$stmt = $this->db->prepareStatement ("SELECT * FROM ".$this->database." WHERE ".$this->index." = ?");
|
||||
$stmt->setInt (1, $id);
|
||||
$rs = $stmt->executeQuery ();
|
||||
$rs->next ();
|
||||
return $this->mapOne ($rs);
|
||||
}
|
||||
|
||||
/**
|
||||
* Преобразует parseResult в обьект
|
||||
*/
|
||||
public /* private */ function mapOne ($rs)
|
||||
{
|
||||
$result = new $this->className ();
|
||||
foreach ($this->schema as $key => $value) {
|
||||
list($value) = $value;
|
||||
$result->$value->setRes($rs, $key);
|
||||
}
|
||||
return $result;
|
||||
}
|
||||
|
||||
public /* private */ function mapAll ($rs)
|
||||
{
|
||||
$result = array ();
|
||||
// Преобразование SQL в обьект
|
||||
while ($rs->next ()) {
|
||||
$result[] = $this->mapOne ($rs);
|
||||
}
|
||||
return $result;
|
||||
}
|
||||
|
||||
private function clean ($value) {
|
||||
return strtolower(trim(iconv('utf-8', 'cp1251', $value)));
|
||||
}
|
||||
|
||||
/**
|
||||
* Преобразует параметры формы в SQL запрос WHERE
|
||||
* @param array $params
|
||||
* @param array $schema
|
||||
* @return string
|
||||
*/
|
||||
public function requestToSQL (Collection $request, array $schema)
|
||||
{
|
||||
$result = array ();
|
||||
foreach ($schema as $key => $value) {
|
||||
$param = $request->get ($key);
|
||||
if ($param) {
|
||||
array_push ($result, "lower (".$value.") LIKE '".$this->clean ($param)."%'");
|
||||
}
|
||||
}
|
||||
if (empty ($result)) return null;
|
||||
return implode ($result, " AND ");
|
||||
}
|
||||
|
||||
/**
|
||||
* Удаление строк из таблицы с заданными индексами
|
||||
* @param $list array Массив идентефикаторов
|
||||
*/
|
||||
public function deleteList (array $list)
|
||||
{
|
||||
// Query::from($this->database)->where($this->index, "in", $list)->delete();
|
||||
$sql = "DELETE FROM " . $this->database . " WHERE " . $this->index . " IN (" . $this->listSQL ($list) . ")";
|
||||
return $this->db->executeQuery ($sql);
|
||||
}
|
||||
|
||||
public static function findKey (array $schema, $sort)
|
||||
{
|
||||
foreach ($schema as $key => $item) {
|
||||
list($item) = $item;
|
||||
if ($item == $sort) {
|
||||
return $key;
|
||||
}
|
||||
}
|
||||
return $sort;
|
||||
}
|
||||
|
||||
public function getOrder (Collection $request)
|
||||
{
|
||||
$order = "";
|
||||
$sort = $request->get('key');
|
||||
$desc = ($request->get('desc') == 0)? 'DESC' : 'ASC';
|
||||
if ($sort) {
|
||||
$sort = self::findKey ($this->schema, $sort);
|
||||
$order = " ORDER BY $sort $desc";
|
||||
}
|
||||
return $order;
|
||||
}
|
||||
|
||||
/**
|
||||
* Извлекает список записей из базы данных
|
||||
*/
|
||||
public function findAll (Collection $request, $id = null)
|
||||
{
|
||||
$name0 = $this->database;
|
||||
$foreign = $this->reference[1];
|
||||
// Переписать используя Query !!!
|
||||
if ($foreign && $id) {
|
||||
$filter = ($this->filter)?$filter = " AND ".$this->filter: "";
|
||||
$sql = "SELECT t1.* FROM $name0 as t1 WHERE t1.$foreign = $id " . $filter.self::getOrder($request);
|
||||
} else {
|
||||
$filter = ($this->filter)?$filter = " WHERE " . $this->filter: "";
|
||||
$sql = "SELECT * FROM $name0 " . $filter . self::getOrder($request);
|
||||
}
|
||||
$stmt = $this->db->prepareStatement ($sql);
|
||||
|
||||
$page = $request->get('page');
|
||||
$limit = $request->get('size');
|
||||
if ($page && $limit) {
|
||||
$this->setRange($stmt, $page, $limit);
|
||||
}
|
||||
|
||||
return $this->mapAll($stmt->executeQuery());
|
||||
}
|
||||
|
||||
public function getCount (Collection $request, $id)
|
||||
{
|
||||
$name0 = $this->database;
|
||||
$foreign = $this->reference[1];
|
||||
// Переписать используя Query !!!
|
||||
if ($foreign && $id) {
|
||||
$filter = ($this->filter)?$filter = " AND " . $this->filter: "";
|
||||
$sql = "SELECT count(t1.*) as length FROM $name0 as t1 WHERE t1.$foreign = $id " . $filter;
|
||||
} else {
|
||||
$filter = ($this->filter)?$filter = " WHERE " . $this->filter: "";
|
||||
$sql = "SELECT count(*) as length FROM $name0 " . $filter;
|
||||
}
|
||||
$rs = $this->db->executeQuery($sql);
|
||||
$rs->next();
|
||||
return $rs->getInt('length');
|
||||
}
|
||||
|
||||
/**
|
||||
* Добавление записи в базу данных
|
||||
* @param $o Обьект для записи в базу данных
|
||||
*/
|
||||
public function saveTo (Model $o)
|
||||
{
|
||||
$keys = array ();
|
||||
$values = array ();
|
||||
foreach ($this->schema as $key => $value) {
|
||||
list($value) = $value;
|
||||
if ($key != $this->index) {
|
||||
$keys[] = $key;
|
||||
$values[] = "'".$o->$value."'";
|
||||
}
|
||||
}
|
||||
$stmt = $this->db->prepareStatement ("INSERT INTO ".$this->database." (".implode ($keys, ",").") VALUES (".implode ($values, ",").")");
|
||||
$stmt->executeQuery ();
|
||||
}
|
||||
|
||||
/**
|
||||
* Обновляет запись в базе данных
|
||||
* @param $o Обьект для обновления
|
||||
*/
|
||||
public function updateTo (Model $o)
|
||||
{
|
||||
$keys_values = array ();
|
||||
foreach ($this->schema as $key => $value) {
|
||||
list($value) = $value;
|
||||
if ($key != $this->index && !($o->$value instanceof FKey)) {
|
||||
$keys_values[] = $key." = '".$o->$value."'";
|
||||
}
|
||||
}
|
||||
// Для всех должен быть идентефикатор id
|
||||
$stmt = $this->db->prepareStatement ("UPDATE ".$this->database." SET ".implode($keys_values, ",")." WHERE ".$this->index." = ".$o->id);
|
||||
$stmt->executeQuery ();
|
||||
}
|
||||
|
||||
function saveDB (Model $o)
|
||||
{
|
||||
if ($o->id) {
|
||||
$this->updateTo($o);
|
||||
} else {
|
||||
$this->saveTo($o);
|
||||
}
|
||||
}
|
||||
|
||||
function getModel($name)
|
||||
{
|
||||
require_once 'core/Mapper/Factory.php';
|
||||
if (!$this->factory) {
|
||||
$this->factory = new ModelFactory($this->db);
|
||||
}
|
||||
return $this->factory->getModel($name);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
*
|
||||
*/
|
||||
class Model
|
||||
{
|
||||
public function __construct ()
|
||||
{
|
||||
foreach (get_class_vars (get_class ($this)) as $key => $value) {
|
||||
$this->$key = new Primitive ();
|
||||
}
|
||||
}
|
||||
// __get, __set методы. В метаданных хранится тип свойств, проверять при присваивании!!
|
||||
}
|
||||
|
||||
?>
|
||||
|
|
@ -1,74 +0,0 @@
|
|||
<?php
|
||||
|
||||
/**
|
||||
* Отображение списка папок с настройками на обьект
|
||||
*/
|
||||
class PathMapper
|
||||
{
|
||||
private $count;
|
||||
private $base = null;
|
||||
public $reference = null;
|
||||
|
||||
function plane (&$target, Collection $array)
|
||||
{
|
||||
$vars = get_class_vars(get_class($target));
|
||||
foreach ($vars as $name => $value) {
|
||||
$target->$name = $array->get($name);
|
||||
}
|
||||
}
|
||||
|
||||
function basePath ()
|
||||
{
|
||||
if ( ! $this->base) $this->base = $this->getBasePath();
|
||||
return $this->base;
|
||||
}
|
||||
|
||||
function findAll (Collection $request, $id = null)
|
||||
{
|
||||
$this->reference = $id;
|
||||
|
||||
$base = $this->basePath ();
|
||||
$path = new Path($base);
|
||||
$list = $path->getContent();
|
||||
|
||||
$result = array ();
|
||||
$this->count = 0;
|
||||
foreach ($list as $name) {
|
||||
if (is_dir (Path::join($this->basePath (), $name))
|
||||
&& $module = $this->findById ($name)) {
|
||||
$this->count++;
|
||||
$result [] = $module;
|
||||
}
|
||||
}
|
||||
return $result;
|
||||
}
|
||||
|
||||
function findById ($name)
|
||||
{
|
||||
$file = Path::join($this->basePath(), $this->getSettingsFile ($name));
|
||||
if (file_exists($file)) {
|
||||
$settings = new Settings($file);
|
||||
$settings->read();
|
||||
return $this->settingsMap($name, $settings);
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
/**
|
||||
* Число папок
|
||||
*/
|
||||
function getCount ()
|
||||
{
|
||||
return $this->count;
|
||||
}
|
||||
|
||||
/**
|
||||
* Удаление списка папок
|
||||
*/
|
||||
function deleteList(array $list)
|
||||
{
|
||||
foreach ($list as $name)
|
||||
Path::delete(Path::join($this->getBasePath(), $name));
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -1,113 +0,0 @@
|
|||
<?php
|
||||
/**
|
||||
Copyright (c) 2007 Brady Mulhollem
|
||||
Permission is hereby granted, free of charge, to any person obtaining a
|
||||
copy of this software and associated documentation files (the
|
||||
"Software"), to deal in the Software without restriction, including
|
||||
without limitation the rights to use, copy, modify, merge, publish,
|
||||
distribute, sublicense, and/or sell copies of the Software, and to
|
||||
permit persons to whom the Software is furnished to do so, subject to
|
||||
the following conditions:
|
||||
|
||||
The above copyright notice and this permission notice shall be included
|
||||
in all copies or substantial portions of the Software.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
|
||||
OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
||||
MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
|
||||
IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
|
||||
CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
|
||||
TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
|
||||
SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
||||
**/
|
||||
class Markup_SimpleBBCode{
|
||||
//General Tags
|
||||
var $tags = array('b' => 'strong','i' => 'em','u' => 'span style="text-decoration:underline"','quote' => 'blockquote','s' => 'span style="text-decoration: line-through"', 'list' => 'ul','\*' => 'li');
|
||||
//Tags that must be mapped to diffierent parts
|
||||
var $mapped = array('url' => array('a','href',true),'img' => array('img','src',false));
|
||||
//Tags with atributes
|
||||
var $tags_with_att = array('color' => array('font','color'),'size' => array('font','size'),'url' => array('a','href'));
|
||||
//Gotta have smilies
|
||||
var $smilies = array(':)' => 'smile.gif',':(' => 'frown.gif');
|
||||
//Config Variables
|
||||
//Convert new line charactes to linebreaks?
|
||||
var $convert_newlines = true;
|
||||
//Parse For smilies?
|
||||
var $parse_smilies = true;
|
||||
//auto link urls(http and ftp), and email addresses?
|
||||
var $auto_links = true;
|
||||
//Internal Storage
|
||||
var $_code = '';
|
||||
function __construct($new=true,$parse=true,$links=true){
|
||||
$this->convert_newlines = $new;
|
||||
$this->parse_smilies = $parse;
|
||||
$this->auto_links = $links;
|
||||
}
|
||||
function parse($code){
|
||||
$this->_code = $code;
|
||||
$this->_strip_html();
|
||||
$this->_parse_tags();
|
||||
$this->_parse_mapped();
|
||||
$this->_parse_tags_with_att();
|
||||
$this->_parse_smilies();
|
||||
$this->_parse_links();
|
||||
$this->_convert_nl();
|
||||
return $this->_code;
|
||||
}
|
||||
function _strip_html(){
|
||||
$this->_code = strip_tags($this->_code);
|
||||
}
|
||||
function _convert_nl(){
|
||||
if($this->convert_newlines){
|
||||
$this->_code = nl2br($this->_code);
|
||||
}
|
||||
}
|
||||
function _parse_tags(){
|
||||
foreach($this->tags as $old=>$new){
|
||||
$ex = explode(' ',$new);
|
||||
$this->_code = preg_replace('/\['.$old.'\](.+?)\[\/'.$old.'\]/is','<'.$new.'>$1</'.$ex[0].'>',$this->_code);
|
||||
}
|
||||
}
|
||||
function _parse_mapped(){
|
||||
foreach($this->mapped as $tag=>$data){
|
||||
$reg = '/\['.$tag.'\](.+?)\[\/'.$tag.'\]/is';
|
||||
if($data[2]){
|
||||
$this->_code = preg_replace($reg,'<'.$data[0].' '.$data[1].'="$1">$1</'.$data[0].'>',$this->_code);
|
||||
}
|
||||
else{
|
||||
$this->_code = preg_replace($reg,'<'.$data[0].' '.$data[1].'="$1">',$this->_code);
|
||||
}
|
||||
}
|
||||
}
|
||||
function _parse_tags_with_att(){
|
||||
foreach($this->tags_with_att as $tag=>$data){
|
||||
$this->_code = preg_replace('/\['.$tag.'=(.+?)\](.+?)\[\/'.$tag.'\]/is','<'.$data[0].' '.$data[1].'="$1">$2</'.$data[0].'>',$this->_code);
|
||||
}
|
||||
}
|
||||
function _parse_smilies(){
|
||||
if($this->parse_smilies){
|
||||
foreach($this->smilies as $s=>$im){
|
||||
$this->_code = str_replace($s,'<img src="'.$im.'">',$this->_code);
|
||||
}
|
||||
}
|
||||
}
|
||||
function _parse_links(){
|
||||
if($this->auto_links){
|
||||
$this->_code = preg_replace('/([^"])(http:\/\/|ftp:\/\/)([^\s,]*)/i','$1<a href="$2$3">$2$3</a>',$this->_code);
|
||||
$this->_code = preg_replace('/([^"])([A-Z0-9._%-]+@[A-Z0-9.-]+\.[A-Z]{2,4})/i','$1<a href="mailto:$2">$2</a>',$this->_code);
|
||||
}
|
||||
}
|
||||
function addTag($old,$new){
|
||||
$this->tags[$old] = $new;
|
||||
}
|
||||
function addMapped($bb,$html,$att,$end=true){
|
||||
$this->mapped[$bb] = array($html,$att,$end);
|
||||
}
|
||||
function addTagWithAttribute($bb,$html,$att){
|
||||
$this->tags_with_att[$bb] = array($html,$att);
|
||||
}
|
||||
function addSmiley($code,$src){
|
||||
$this->smilies[$code] = $src;
|
||||
}
|
||||
}
|
||||
?>
|
||||
|
|
@ -1,9 +0,0 @@
|
|||
<?php
|
||||
|
||||
/**
|
||||
* Класс метаданных таблицы
|
||||
*/
|
||||
class Meta
|
||||
{
|
||||
}
|
||||
|
||||
|
|
@ -1,202 +0,0 @@
|
|||
<?php
|
||||
|
||||
/**
|
||||
* Класс для составления запроса
|
||||
*/
|
||||
class Query
|
||||
{
|
||||
static $alias = 0;
|
||||
|
||||
public $table;
|
||||
public $filter = array ();
|
||||
public $calc = array ();
|
||||
public $order = array ();
|
||||
|
||||
/**
|
||||
* Создает пустой зарос
|
||||
*/
|
||||
static function create()
|
||||
{
|
||||
return new Query();
|
||||
}
|
||||
|
||||
/**
|
||||
* Метаданные таблицы
|
||||
* @param string $name Имя таблицы
|
||||
*/
|
||||
function getTableMeta($name)
|
||||
{
|
||||
}
|
||||
|
||||
/**
|
||||
* Создает новый запрос
|
||||
* @param string $name Имя таблицы
|
||||
*
|
||||
* @return Query
|
||||
*/
|
||||
public function from($name)
|
||||
{
|
||||
$result = clone $this;
|
||||
|
||||
$table = new Table();
|
||||
$table->type = 'simple';
|
||||
$table->name = $name;
|
||||
$table->alias = "t" . self::$alias++;
|
||||
|
||||
$result->table = $table;
|
||||
|
||||
return $result;
|
||||
}
|
||||
|
||||
/**
|
||||
* Добавляет к запросу условие
|
||||
* @param string $field Имя поля таблицы
|
||||
* @param string $op Имя оператора
|
||||
* @param $value Значение поля
|
||||
*
|
||||
* @return Query
|
||||
*/
|
||||
public function filter($field, $op, $value)
|
||||
{
|
||||
$result = clone $this;
|
||||
$result->filter [] = $result->table->alias ."." . $field . $op . "'" . $value . "'";
|
||||
return $result;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param string $e Выражение
|
||||
*/
|
||||
public function calc($e)
|
||||
{
|
||||
$result = clone $this;
|
||||
$result->calc [] = $e;
|
||||
return $result;
|
||||
}
|
||||
|
||||
public function joinOn($first, $e)
|
||||
{
|
||||
$result = $this->compose($first, array ('filter', 'calc', 'order'));
|
||||
|
||||
$e = strtr($e, array ("a." => $this->table->alias . ".",
|
||||
"b." => $first->table->alias . "."));
|
||||
|
||||
$table = new Table ();
|
||||
$table->type = 'join';
|
||||
$table->name = $this->table->name;
|
||||
$table->alias = $this->table->alias;
|
||||
$table->join = $first->table;
|
||||
$table->condition = $e;
|
||||
|
||||
$result->table = $table;
|
||||
|
||||
return $result;
|
||||
}
|
||||
|
||||
/**
|
||||
* Обьединяет параметры двух заросов
|
||||
* @param Query $first
|
||||
* @pram array $list Список параметров
|
||||
*
|
||||
* @return Query
|
||||
*/
|
||||
private function compose(Query $first, array $list)
|
||||
{
|
||||
$result = new Query();
|
||||
foreach ($list as $name) {
|
||||
$result->$name = array_merge($this->$name, $first->$name);
|
||||
}
|
||||
return $result;
|
||||
}
|
||||
|
||||
/**
|
||||
* Заковычивает значение
|
||||
*/
|
||||
public function quote ($value)
|
||||
{
|
||||
return "'" . $value . "'";
|
||||
}
|
||||
|
||||
/**
|
||||
* Компиляция таблицы
|
||||
* @param Table $table
|
||||
*
|
||||
* @return string Часть строки SQL
|
||||
*/
|
||||
private function table(Table $table)
|
||||
{
|
||||
if ($table->type == 'simple') {
|
||||
return $table->name ." AS ".$table->alias;
|
||||
}
|
||||
if ($table->type == 'join') {
|
||||
return $table->name ." AS ".$table->alias. " JOIN " . $this->table ($table->join) . " ON " . $table->condition;
|
||||
}
|
||||
return "";
|
||||
}
|
||||
|
||||
/**
|
||||
* Компиляция WHERE
|
||||
*
|
||||
* @return string Часть строки SQL
|
||||
*/
|
||||
private function where ()
|
||||
{
|
||||
return implode(" AND ", $this->filter);
|
||||
}
|
||||
|
||||
/**
|
||||
* Компиляция запроса в SELECT SQL
|
||||
*
|
||||
* @return string SQL выражение
|
||||
*/
|
||||
public function select()
|
||||
{
|
||||
return "SELECT "
|
||||
. ((!empty($this->calc))? implode (",", $this->calc): "*")
|
||||
. " FROM " . $this->table($this->table)
|
||||
. ((!empty ($this->filter))? " WHERE " . $this->where() : "");
|
||||
}
|
||||
|
||||
/**
|
||||
* Компиляция в DELETE
|
||||
*/
|
||||
public function delete()
|
||||
{
|
||||
return "DELETE FROM " . $this->table->name
|
||||
. ((!empty ($this->filter))? " WHERE " . $this->where() : "");
|
||||
}
|
||||
|
||||
private function add_prefix($prefix, $array) {
|
||||
$result = array();
|
||||
foreach ($array as $value) {
|
||||
$result [] = $prefix . $value;
|
||||
}
|
||||
return $result;
|
||||
}
|
||||
|
||||
/**
|
||||
* Компиляция в UPDATE
|
||||
* TODO: Разные типы запросов Query->update(); Query->select(), Query->insert();!!
|
||||
* Возвраащают statement
|
||||
*/
|
||||
public function update($values)
|
||||
{
|
||||
$pairs = array ();
|
||||
foreach ($values as $key => $value) { //
|
||||
$pairs [] = $key . "=" . $this->quote ($value);
|
||||
}
|
||||
return "UPDATE " . $this->table->name . " SET "
|
||||
. implode(",", $pairs)
|
||||
. ((!empty($this->filter))? " WHERE " . $this->where() : "");
|
||||
}
|
||||
|
||||
/**
|
||||
* Компиляция в INSERT
|
||||
*/
|
||||
public function insert($values)
|
||||
{
|
||||
return "INSERT INTO ". $this->table->name . "("
|
||||
. implode(",", array_keys($values))
|
||||
. ") VALUES (" . implode(",", array_map(array($this, 'quote'), array_values($values))) . ")";
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -1,14 +0,0 @@
|
|||
<?php
|
||||
|
||||
/**
|
||||
* Класс таблицы
|
||||
*/
|
||||
class Table
|
||||
{
|
||||
public $type = 'simple';
|
||||
public $name;
|
||||
public $alias;
|
||||
public $join;
|
||||
public $condition;
|
||||
}
|
||||
|
||||
|
|
@ -1,82 +0,0 @@
|
|||
<?php
|
||||
|
||||
/**
|
||||
* Извлекает текст из HTML документа
|
||||
*/
|
||||
function stripText($document)
|
||||
{
|
||||
$search = array("'<script[^>]*?>.*?</script>'si" => "", // strip out javascript
|
||||
"'<[\/\!]*?[^<>]*?>'si" => "", // strip out html tags
|
||||
"'([\r\n])[\s]+'" => "\\1", // strip out white space
|
||||
"'&(quot|#34|#034|#x22);'i" => "\"", // replace html entities
|
||||
"'&(amp|#38|#038|#x26);'i" => "&", // added hexadecimal values
|
||||
"'&(lt|#60|#060|#x3c);'i" => ">",
|
||||
"'&(gt|#62|#062|#x3e);'i" => "<",
|
||||
"'&(nbsp|#160|#xa0);'i" => " ",
|
||||
"'&(iexcl|#161);'i" => chr(161),
|
||||
"'&(cent|#162);'i" => chr(162),
|
||||
"'&(pound|#163);'i" => chr(163),
|
||||
"'&(copy|#169);'i" => chr(169),
|
||||
"'&(reg|#174);'i" => chr(174),
|
||||
"'&(deg|#176);'i" => chr(176));
|
||||
$text = preg_replace(array_keys($search), array_values($search), $document);
|
||||
return $text;
|
||||
}
|
||||
|
||||
/**
|
||||
* Разделение текста на массив слов
|
||||
*/
|
||||
function tokenize ($document)
|
||||
{
|
||||
$array = preg_split("/[\W]+/", $document);
|
||||
return $array;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Ищет один из символов с конца строки
|
||||
*
|
||||
* @param string $haystack
|
||||
* @param array $needle Массив символов для поиска
|
||||
* @param int $offset Смещение от начала строки
|
||||
*
|
||||
* @return int Позицию первого совпадения
|
||||
*/
|
||||
function indexRight ($haystack, $needle, $offset = 0)
|
||||
{
|
||||
if ((bool)$offset === false) $offset = 0;
|
||||
while ($offset >= 0) {
|
||||
if (in_array ($haystack[$offset], $needle)) {
|
||||
return $offset;
|
||||
}
|
||||
$offset --;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
* Ищет один из символов с начала строки
|
||||
*
|
||||
* @param string $haystack
|
||||
* @param array $needle Массив символов для поиска
|
||||
* @param int $offset Смещение от начала строки
|
||||
*
|
||||
* @return int Позицию первого совпадения
|
||||
*/
|
||||
function indexLeft ($haystack, $needle, $offset = 0)
|
||||
{
|
||||
if ($offset < 0) return false;
|
||||
while ($offset < strlen($haystack)) {
|
||||
if ((is_callable($needle) && call_user_func ($needle, $haystack[$offset]))
|
||||
|| (is_array ($needle) && in_array ($haystack[$offset], $needle))) {
|
||||
return $offset;
|
||||
}
|
||||
$offset ++;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
function not_ctype_alpha ($ch)
|
||||
{
|
||||
return !ctype_alpha($ch);
|
||||
}
|
||||
|
|
@ -1,80 +0,0 @@
|
|||
<?php
|
||||
|
||||
/**
|
||||
* Индексирование файлов
|
||||
*/
|
||||
class Index
|
||||
{
|
||||
const ARRAY_FILE = 0;
|
||||
const ARRAY_TEXT = 1;
|
||||
|
||||
public $index = array ();
|
||||
public $text = array ();
|
||||
protected $count = 0;
|
||||
|
||||
function getTitle ($content) {
|
||||
$title = "'<title[^>]*?>(.*?)</title>'si";
|
||||
preg_match($title, $content, $matches);
|
||||
if(isset($matches[1])) {
|
||||
return $matches[1];
|
||||
}
|
||||
return "";
|
||||
}
|
||||
|
||||
// Выбираем основу слова
|
||||
function clean ($word)
|
||||
{
|
||||
return Stemmer::russian(strtolower($word));
|
||||
}
|
||||
|
||||
function process ($base, $files)
|
||||
{
|
||||
$path = new Path($base);
|
||||
// Список документов
|
||||
foreach ($path->getContentRec($files) as $file) {
|
||||
$content = file_get_contents ($file);
|
||||
$text = stripText($content);
|
||||
// $title = self::getTitle ($content);
|
||||
$title = pathinfo($file, PATHINFO_BASENAME);
|
||||
// echo $file, "\n";
|
||||
// Список слов в документе
|
||||
$list = tokenize($text);
|
||||
foreach ($list as $word) {
|
||||
$preword = self::clean($word);
|
||||
if (isset($this->index[$preword])) {
|
||||
$index = $this->index[$preword];
|
||||
if ( ! in_array ($this->count, $index)) $this->index[$preword] [] = $this->count;
|
||||
} else {
|
||||
// Не записываем слова длинна которых меньше 2
|
||||
if (strlen($preword) > 1) {
|
||||
$this->index[$preword] = array ($this->count);
|
||||
}
|
||||
}
|
||||
}
|
||||
$this->text [] = array ($title, $path->relPath ($file), $text);
|
||||
$this->count ++;
|
||||
}
|
||||
ksort($this->index);
|
||||
}
|
||||
|
||||
/**
|
||||
* Сохранение результата поиска
|
||||
*/
|
||||
function saveData ($file)
|
||||
{
|
||||
$file = fopen($file, "w");
|
||||
// Количество слов и текстов
|
||||
fwrite ($file, pack("SS", count($this->index), count($this->text)));
|
||||
foreach ($this->index as $word => $value) {
|
||||
$length = strlen($word);
|
||||
array_unshift ($value, "SSa*S*", $length, count($value), $word);
|
||||
fwrite($file, call_user_func_array ('pack', $value));
|
||||
}
|
||||
|
||||
foreach ($this->text as $text) {
|
||||
fwrite($file, pack("SSSa*a*a*",
|
||||
strlen($text[0]), strlen($text[1]), strlen($text[2])
|
||||
, $text[0], $text[1], $text[2]));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -1,91 +0,0 @@
|
|||
<?php
|
||||
|
||||
/**
|
||||
* Разбирвет строку запроса на токены
|
||||
*/
|
||||
class Lexer
|
||||
{
|
||||
const TOKEN_NOT = 1;
|
||||
const TOKEN_OR = 2;
|
||||
const TOKEN_LPAREN = 3;
|
||||
const TOKEN_RPAREN = 4;
|
||||
const TOKEN_AND = 5;
|
||||
const TOKEN_WORD = 6;
|
||||
const TOKEN_EOL = 7;
|
||||
|
||||
protected $src;
|
||||
private $offset = 0;
|
||||
public $token;
|
||||
|
||||
public function __construct ()
|
||||
{
|
||||
}
|
||||
|
||||
function setSource ($src)
|
||||
{
|
||||
$this->src = $src;
|
||||
$this->offset;
|
||||
}
|
||||
|
||||
private function skipSpace ()
|
||||
{
|
||||
while (!$this->isEOL() && $this->getChar() == " ") {
|
||||
$this->offset++;
|
||||
}
|
||||
}
|
||||
|
||||
private function getChar ()
|
||||
{
|
||||
return $this->src [$this->offset];
|
||||
}
|
||||
|
||||
/**
|
||||
* Проверяет на конец строки
|
||||
*/
|
||||
private function isEOL () {
|
||||
return $this->offset >= strlen($this->src);
|
||||
}
|
||||
|
||||
/**
|
||||
* Односимвольный токен
|
||||
*/
|
||||
private function easyToken () {
|
||||
$ch = $this->getChar ();
|
||||
switch ($ch) {
|
||||
case '~': $token = array(self::TOKEN_NOT, $ch); break;
|
||||
case '|': $token = array(self::TOKEN_OR, $ch); break;
|
||||
case '(': $token = array(self::TOKEN_LPAREN, $ch); break;
|
||||
case ')': $token = array(self::TOKEN_RPAREN, $ch); break;
|
||||
case '&': $token = array(self::TOKEN_AND, $ch); break;
|
||||
default:
|
||||
$this->offset++;
|
||||
$token = $this->getToken();
|
||||
}
|
||||
$this->offset++;
|
||||
return $token;
|
||||
}
|
||||
|
||||
/**
|
||||
* Возвращает следующий токен
|
||||
*/
|
||||
public function getToken ()
|
||||
{
|
||||
$this->skipSpace ();
|
||||
if ($this->isEOL()) {
|
||||
return array(self::TOKEN_EOL, "");
|
||||
}
|
||||
if (ctype_alpha($this->getChar())) {
|
||||
$start = $this->offset;
|
||||
while (!$this->isEOL() && ctype_alpha($this->getChar())) {
|
||||
$this->offset ++;
|
||||
}
|
||||
return array(self::TOKEN_WORD, substr ($this->src, $start, $this->offset-$start));
|
||||
}
|
||||
return $this->easyToken();
|
||||
}
|
||||
|
||||
public function nextToken ()
|
||||
{
|
||||
$this->token = $this->getToken();
|
||||
}
|
||||
}
|
||||
|
|
@ -1,96 +0,0 @@
|
|||
<?php
|
||||
|
||||
require_once __DIR__ '/../functions.php';
|
||||
|
||||
/**
|
||||
* Поиск в индексе
|
||||
*/
|
||||
class Search
|
||||
{
|
||||
private $lexer;
|
||||
private $index;
|
||||
function __construct ($index)
|
||||
{
|
||||
$this->lexer = new Lexer();
|
||||
$this->index = $index;
|
||||
|
||||
$this->op = array ($this, 'Op');
|
||||
$this->binary = array ($this, 'binaryOp');
|
||||
$this->union = array ($this, 'union');
|
||||
$this->intersection = lcurry($this->op, 'array_uintersect', $this->union);
|
||||
|
||||
$this->notQuery = lcurry ($this->binary, Lexer::TOKEN_NOT,
|
||||
lcurry($this->op, 'array_udiff', 'array_udiff'), array ($this, 'easyQuery'));
|
||||
|
||||
$this->orQuery = lcurry ($this->binary, Lexer::TOKEN_OR,
|
||||
lcurry($this->op, $this->union, $this->union), $this->notQuery);
|
||||
|
||||
$this->andQuery = lcurry ($this->binary, Lexer::TOKEN_AND, $this->intersection, $this->orQuery);
|
||||
}
|
||||
|
||||
function union ($a, $b, $callback)
|
||||
{
|
||||
return array_merge($a, $b);
|
||||
}
|
||||
|
||||
function Eq ($a, $b)
|
||||
{
|
||||
return $a == $b;
|
||||
}
|
||||
|
||||
function Op ($files, $words, $a, $b) {
|
||||
return array (
|
||||
'words' => call_user_func ($words, $a['words'], $b['words'], array ($this, 'eq')),
|
||||
'files' => call_user_func ($files, $a['files'], $b['files'], array ($this, 'eq'))
|
||||
);
|
||||
}
|
||||
|
||||
public function getQuery ($source)
|
||||
{
|
||||
$this->lexer->setSource ($source);
|
||||
$this->lexer->nextToken();
|
||||
return $this->topQuery();
|
||||
}
|
||||
|
||||
function topQuery ()
|
||||
{
|
||||
$result = call_user_func ($this->andQuery);
|
||||
while ($this->lexer->token[0] == Lexer::TOKEN_LPAREN) {
|
||||
$result = call_user_func ($this->intersection, $result, call_user_func ($this->andQuery));
|
||||
}
|
||||
return $result;
|
||||
}
|
||||
|
||||
function easyQuery ()
|
||||
{
|
||||
$result = null;
|
||||
if ($this->lexer->token[0] == Lexer::TOKEN_LPAREN) {
|
||||
$this->lexer->nextToken ();
|
||||
$result = $this->topQuery ();
|
||||
if ($this->lexer->token[0] == Lexer::TOKEN_RPAREN) {
|
||||
$this->lexer->nextToken ();
|
||||
}
|
||||
return $result;
|
||||
} else {
|
||||
$result = call_user_func ($this->index, $this->lexer->token[1]);
|
||||
$this->lexer->nextToken ();
|
||||
return $result;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @param int $type Тип лексемы
|
||||
* @param function $op Функция при совпадении типа лексемы при запросе
|
||||
* @param function $next Следующий обработчик запроса
|
||||
*/
|
||||
function binaryOp ($type, $op, $next)
|
||||
{
|
||||
$result = call_user_func($next);
|
||||
while ($this->lexer->token[0] == $type) {
|
||||
$this->lexer->nextToken();
|
||||
$result = call_user_func($op, $result, call_user_func ($next));
|
||||
}
|
||||
return $result;
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -1,97 +0,0 @@
|
|||
<?php
|
||||
|
||||
class Searcher {
|
||||
/* protected */ public $index;
|
||||
protected $text;
|
||||
protected $search;
|
||||
public function __construct ()
|
||||
{
|
||||
// Может передавать обьект метод по умлочанию getWordStat??
|
||||
$this->search = new Search (array ($this, 'getWord'));
|
||||
}
|
||||
|
||||
/**
|
||||
* Читает содержимое индексного файла
|
||||
*
|
||||
* @param string $file Имя файла
|
||||
*/
|
||||
function setSource ($fileName)
|
||||
{
|
||||
$file = fopen($fileName, "r");
|
||||
$words = fread($file, 4);
|
||||
$all = unpack("Swords/Stexts", $words);
|
||||
for ($i = 0; $i < $all['words']; $i++) {
|
||||
$pos = fread($file, 4);
|
||||
$size = unpack("Sword/Sindex", $pos);
|
||||
|
||||
$word = fread($file, $size['word']);
|
||||
$index = unpack("S*", fread($file, $size['index']*2));
|
||||
$this->index[$word] = $index;
|
||||
}
|
||||
|
||||
for ($i = 0; $i < $all['texts']; $i++) {
|
||||
$pos = fread($file, 6);
|
||||
$size = unpack("Stitle/Surl/Stext", $pos);
|
||||
//
|
||||
$title = fread($file, $size['title']);
|
||||
$url = fread($file, $size['url']);
|
||||
$text = fread($file, $size['text']);
|
||||
$this->text [] = array ($title, $url, $text);
|
||||
}
|
||||
}
|
||||
|
||||
// По слову возвращаем список файлов и слово
|
||||
public function getWord ($word)
|
||||
{
|
||||
$preword = Stemmer::russian($word); // Index?? -> clean
|
||||
if (isset($this->index[$preword])) { // Search??
|
||||
return array ('files' => $this->index[$preword], 'words' => array ($preword));
|
||||
}
|
||||
return array ('files' => array (), 'words' => array ());
|
||||
}
|
||||
|
||||
/**
|
||||
* Список документов в которых встечается слово
|
||||
*
|
||||
*/
|
||||
function getResult (&$query)
|
||||
{
|
||||
$result = array ();
|
||||
$word = $query['words'];
|
||||
$list = $query['files'];
|
||||
//
|
||||
foreach ($list as $n) {
|
||||
$result [] = array (
|
||||
'title' => $this->text[$n][0],
|
||||
'file' => $this->text[$n][1],
|
||||
'text' => self::getSlice ($word[0], $this->text[$n][2]));
|
||||
}
|
||||
return $result;
|
||||
}
|
||||
|
||||
/**
|
||||
* Часть документа в котором встречается слово
|
||||
*
|
||||
* @param $word Слово
|
||||
* @param $text Текст содержащий слово
|
||||
*/
|
||||
function getSlice ($word, $text)
|
||||
{
|
||||
$pos = stripos($text, $word);
|
||||
$offset = max(max ($pos-100, indexRight($text, array ("."), $pos) + 1), 0);
|
||||
$real = substr($text, $pos, strlen($word)) ;
|
||||
return substr($text, $offset, $pos - $offset)
|
||||
. "<span style='color: red'>" . $real . "</span>" . substr ($text, $pos + strlen($word), 100);
|
||||
}
|
||||
|
||||
/**
|
||||
* Поиск по запросу
|
||||
*
|
||||
*/
|
||||
function search ($query)
|
||||
{
|
||||
$result = $this->search->getQuery($query);
|
||||
return $this->getResult($result);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -1,180 +0,0 @@
|
|||
<?php
|
||||
/*
|
||||
* PHP5 implementation of Martin Porter's stemming algorithm for Russian language.
|
||||
* Written on a cold winter evening close to the end of 2005 by Dennis Kreminsky (etranger at etranger dot ru)
|
||||
* Use the code freely, but don't hold me responsible if it breaks whatever it might break.
|
||||
*
|
||||
*/
|
||||
|
||||
define ('CHAR_LENGTH', '1'); // all Russian characters take 2 bytes in UTF-8, so instead of using (not supported by default) mb_*
|
||||
// string functions, we use the standard ones with a dirty char-length trick.
|
||||
// Should you want to use WIN-1251 (or any other charset), convert this source file to that encoding
|
||||
// and then change CHAR_LENGTH to the proper value, which is likely to be '1' then.
|
||||
//
|
||||
class Stemmer {
|
||||
|
||||
static public function russian($word)
|
||||
{
|
||||
$a = self::rv($word);
|
||||
$start = $a[0];
|
||||
$rv = $a[1];
|
||||
$rv = self::step1($rv);
|
||||
$rv = self::step2($rv);
|
||||
$rv = self::step3($rv);
|
||||
$rv = self::step4($rv);
|
||||
return $start.$rv;
|
||||
}
|
||||
|
||||
static private function rv($word)
|
||||
{
|
||||
$vowels = array('а','е','и','о','у','ы','э','ю','я');
|
||||
$flag = 0;
|
||||
$rv = '';
|
||||
$start = '';
|
||||
for ($i=0; $i<strlen($word); $i+=CHAR_LENGTH) {
|
||||
if ($flag==1)
|
||||
$rv .= substr($word, $i, CHAR_LENGTH);
|
||||
else
|
||||
$start .= substr($word, $i, CHAR_LENGTH);
|
||||
if (array_search(substr($word,$i,CHAR_LENGTH), $vowels) !== false)
|
||||
$flag=1;
|
||||
}
|
||||
return array($start,$rv);
|
||||
}
|
||||
|
||||
static function substitute ($word, &$suffix_list)
|
||||
{
|
||||
foreach ($suffix_list as $suffix) {
|
||||
if (self::has_suffix($word, $suffix)) {
|
||||
$word = self::cut_suffix($word, $suffix);
|
||||
}
|
||||
}
|
||||
return $word;
|
||||
}
|
||||
|
||||
static function has_suffix ($word, $suffix)
|
||||
{
|
||||
return substr($word, -(strlen($suffix))) == $suffix;
|
||||
}
|
||||
|
||||
static function has_aya ($word, $suffix)
|
||||
{
|
||||
return (substr($word,-strlen($suffix)-CHAR_LENGTH,CHAR_LENGTH)=='а' || substr($word,-strlen($suffix)-CHAR_LENGTH,CHAR_LENGTH)=='я');
|
||||
}
|
||||
|
||||
static function cut_suffix ($word, $suffix)
|
||||
{
|
||||
return substr($word, 0, strlen($word) - strlen($suffix));
|
||||
}
|
||||
|
||||
static private function step1($word)
|
||||
{
|
||||
$perfective1 = array('в', 'вши', 'вшись');
|
||||
foreach ($perfective1 as $suffix) {
|
||||
if (self::has_suffix($word, $suffix) && self::has_aya ($word, $suffix)) {
|
||||
return self::cut_suffix($word, $suffix);
|
||||
}
|
||||
}
|
||||
|
||||
$perfective2 = array('ив','ивши','ившись','ывши','ывшись');
|
||||
foreach ($perfective2 as $suffix) {
|
||||
if (self::has_suffix($word, $suffix)) {
|
||||
return self::cut_suffix($word, $suffix);
|
||||
}
|
||||
}
|
||||
|
||||
$reflexive = array('ся', 'сь');
|
||||
$word = self::substitute($word, $reflexive);
|
||||
|
||||
$adjective = array('ее','ие','ые','ое','ими','ыми','ей','ий','ый','ой','ем','им','ым','ом','его','ого','ему','ому','их','ых','ую','юю','ая','яя','ою','ею');
|
||||
$participle2 = array('ем','нн','вш','ющ','щ');
|
||||
$participle1 = array('ивш','ывш','ующ');
|
||||
foreach ($adjective as $suffix) {
|
||||
if (self::has_suffix($word, $suffix)) {
|
||||
$word = self::cut_suffix($word, $suffix);
|
||||
|
||||
foreach ($participle1 as $suffix)
|
||||
if (self::has_suffix($word, $suffix) && self::has_aya ($word, $suffix))
|
||||
$word = self::cut_suffix($word, $suffix);
|
||||
|
||||
return self::substitute($word, $participle2);
|
||||
}
|
||||
}
|
||||
|
||||
$verb1 = array('ла','на','ете','йте','ли','й','л','ем','н','ло','но','ет','ют','ны','ть','ешь','нно');
|
||||
foreach ($verb1 as $suffix)
|
||||
if (self::has_suffix($word, $suffix) && self::has_aya ($word, $suffix))
|
||||
return self::cut_suffix($word, $suffix);
|
||||
|
||||
$verb2 = array('ила','ыла','ена','ейте','уйте','ите','или','ыли','ей','уй','ил','ыл','им','ым','ен','ило','ыло','ено','ят','ует','уют','ит','ыт','ены','ить','ыть','ишь','ую','ю');
|
||||
foreach ($verb2 as $suffix)
|
||||
if (self::has_suffix($word, $suffix))
|
||||
return self::cut_suffix($word, $suffix);
|
||||
|
||||
$noun = array('а','ев','ов','ие','ье','е','иями','ями','ами','еи','ии','и','ией','ей','ой','ий','й','иям','ям','ием','ем','ам','ом','о','у','ах','иях','ях','ы','ь','ию','ью','ю','ия','ья','я');
|
||||
foreach ($noun as $suffix) {
|
||||
if (self::has_suffix($word, $suffix))
|
||||
return self::cut_suffix($word, $suffix);
|
||||
}
|
||||
|
||||
return $word;
|
||||
}
|
||||
|
||||
static private function step2($word)
|
||||
{
|
||||
if (substr($word,-CHAR_LENGTH,CHAR_LENGTH) == 'и')
|
||||
$word = substr($word, 0, strlen($word)-CHAR_LENGTH);
|
||||
return $word;
|
||||
}
|
||||
|
||||
static private function step3($word)
|
||||
{
|
||||
$vowels = array('а','е','и','о','у','ы','э','ю','я');
|
||||
$flag = 0;
|
||||
$r1 = '';
|
||||
$r2 = '';
|
||||
for ($i=0; $i<strlen($word); $i+=CHAR_LENGTH)
|
||||
{
|
||||
if ($flag==2)
|
||||
$r1.=substr($word, $i, CHAR_LENGTH);
|
||||
if (array_search(substr($word,$i,CHAR_LENGTH), $vowels) !== false)
|
||||
$flag=1;
|
||||
if ($flag=1 && array_search(substr($word,$i,CHAR_LENGTH), $vowels) === false)
|
||||
$flag=2;
|
||||
}
|
||||
$flag=0;
|
||||
for ($i=0; $i<strlen($r1); $i+=CHAR_LENGTH)
|
||||
{
|
||||
if ($flag==2)
|
||||
$r2.=substr($r1, $i, CHAR_LENGTH);
|
||||
if (array_search(substr($r1,$i,CHAR_LENGTH), $vowels) !== false)
|
||||
$flag=1;
|
||||
if ($flag=1 && array_search(substr($r1,$i,CHAR_LENGTH), $vowels) === false)
|
||||
$flag=2;
|
||||
}
|
||||
$derivational=array('ост', 'ость');
|
||||
foreach ($derivational as $suffix)
|
||||
if (substr($r2,-(strlen($suffix))) == $suffix)
|
||||
$word=substr($word, 0, strlen($r2)-strlen($suffix));
|
||||
return $word;
|
||||
}
|
||||
|
||||
static private function step4($word)
|
||||
{
|
||||
if (substr($word,-CHAR_LENGTH*2)=='нн')
|
||||
$word=substr($word, 0, strlen($word)-CHAR_LENGTH);
|
||||
else
|
||||
{
|
||||
$superlative=array('ейш', 'ейше');
|
||||
foreach ($superlative as $suffix)
|
||||
if (substr($word,-(strlen($suffix))) == $suffix)
|
||||
$word = substr($word, 0, strlen($word) - strlen($suffix));
|
||||
if (substr($word,-CHAR_LENGTH*2) == 'нн')
|
||||
$word = substr($word, 0, strlen($word) - CHAR_LENGTH);
|
||||
}
|
||||
// should there be a guard flag? can't think of a russian word that ends with ейшь or ннь anyways, though the algorithm states this is an "otherwise" case
|
||||
if (substr($word,-CHAR_LENGTH,CHAR_LENGTH) == 'ь')
|
||||
$word=substr($word, 0, strlen($word)-CHAR_LENGTH);
|
||||
return $word;
|
||||
}
|
||||
}
|
||||
|
|
@ -2,6 +2,10 @@
|
|||
|
||||
class SortRecord
|
||||
{
|
||||
public $key;
|
||||
public $mode;
|
||||
public $order;
|
||||
|
||||
function __construct($key, $mode, $order)
|
||||
{
|
||||
$this->key = $key;
|
||||
|
|
@ -1,98 +0,0 @@
|
|||
<?php
|
||||
|
||||
require_once 'core/search/htmlhelper.php';
|
||||
/**
|
||||
* Функции для проверки орфографии
|
||||
* rename Spell -> SpellHelper ??
|
||||
*/
|
||||
class Spell
|
||||
{
|
||||
private $pspell;
|
||||
public $autocorrect = false;
|
||||
public function __construct ($language, $encoding)
|
||||
{
|
||||
$this->pspell = pspell_new($language, '', '', $encoding, PSPELL_NORMAL);
|
||||
}
|
||||
|
||||
function spellCheckWord ($word)
|
||||
{
|
||||
$word = $word[0];
|
||||
|
||||
// Ignore ALL CAPS
|
||||
if (preg_match('/^[A-Z0-9]*$/', $word)) return $word;
|
||||
|
||||
// Return dictionary words
|
||||
if (pspell_check($this->pspell, $word))
|
||||
return $word;
|
||||
|
||||
// Auto-correct with the first suggestion, color green
|
||||
if ($this->autocorrect && $suggestions = pspell_suggest($this->pspell, $word))
|
||||
return '<span class="spell-suggest">' . current($suggestions) . '</span>';
|
||||
|
||||
// No suggestions, color red
|
||||
return '<span class="spell-nosuggest">' . $word . '</span>';
|
||||
}
|
||||
|
||||
function isGoodWord ($word)
|
||||
{
|
||||
// Ignore ALL CAPS
|
||||
if (preg_match('/^[A-Z]*$/', $word)) return true;
|
||||
if (preg_match('/^[0-9]*$/', $word)) return true;
|
||||
|
||||
// Return dictionary words
|
||||
if (pspell_check($this->pspell, $word))
|
||||
return true;
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
function suggest ($string)
|
||||
{
|
||||
return preg_replace_callback('/\b\w+\b/', array($this, 'spellCheckWord'), $string);
|
||||
}
|
||||
|
||||
/**
|
||||
* Вызывает функцию для каждого найденного слова
|
||||
*/
|
||||
function eachWord ($call, $string)
|
||||
{
|
||||
$begin = indexLeft ($string, 'ctype_alpha', 0);
|
||||
while ($begin !== false) {
|
||||
$end = indexLeft ($string, 'not_ctype_alpha', $begin);
|
||||
call_user_func ($call, $string, $begin, $end);
|
||||
$begin = indexLeft ($string, 'ctype_alpha', $end);
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
* Проверяет слово на соответствие со словарем
|
||||
*
|
||||
*/
|
||||
function doWord (&$string, $begin, $end)
|
||||
{
|
||||
$word = substr($string, $begin, $end - $begin);
|
||||
if (! $this->isGoodWord ($word)) {
|
||||
$start = max(indexLeft ($string, 'not_ctype_alpha', $begin - 100), 0);
|
||||
$offset = indexLeft ($string, 'not_ctype_alpha', $end + 100);
|
||||
if (! $offset) {
|
||||
$offset = strlen($string);
|
||||
}
|
||||
$length = $offset - $start;
|
||||
throw new Exception ($this->suggest(substr($string, $start, $length)));
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Часть текста содержащий неправильное слово
|
||||
*/
|
||||
function getError ($string)
|
||||
{
|
||||
try {
|
||||
self::eachWord (array ($this, 'doWord'), $string);
|
||||
} catch (Exception $e) {
|
||||
return $e->getMessage();
|
||||
}
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
|
@ -6,7 +6,7 @@ class Excel_Number
|
|||
|
||||
function __construct($value)
|
||||
{
|
||||
$this->value = $value;
|
||||
$this->value = intval($value);
|
||||
}
|
||||
|
||||
function getString()
|
||||
|
|
@ -75,8 +75,8 @@ class ExcelTable
|
|||
private $style;
|
||||
protected $rows = array();
|
||||
|
||||
protected $splitVertical = false;
|
||||
protected $splitHorizontal = false;
|
||||
protected $_splitVertical = false;
|
||||
protected $_splitHorizontal = false;
|
||||
|
||||
function __construct()
|
||||
{
|
||||
|
|
@ -94,7 +94,8 @@ class ExcelTable
|
|||
if(! isset($this->rows[$x])) {
|
||||
$this->rows[$x] = new TableRow();
|
||||
}
|
||||
$this->rows[$x]->setCell($y, $value);
|
||||
/*.TableRow.*/$row = $this->rows[$x];
|
||||
$row->setCell($y, $value);
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
@ -142,12 +143,13 @@ class ExcelTable
|
|||
* @param $cell Номер столбца
|
||||
* @param $merge Количество клеток для обьединения
|
||||
*/
|
||||
function setCellMerge ($row, $cell, $merge)
|
||||
function setCellMerge($x, $cell, $merge)
|
||||
{
|
||||
assert(is_numeric($row) && $row > 0);
|
||||
assert(is_numeric($x) && $x > 0);
|
||||
assert(is_numeric($cell) && $cell > 0);
|
||||
|
||||
$this->rows[$row]->cells[$cell]->merge = $merge;
|
||||
/*.TableRow.*/$row = $this->rows[$x];
|
||||
$row->cells[$cell]->merge = $merge;
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
@ -181,7 +183,8 @@ class ExcelTable
|
|||
*/
|
||||
function getRows()
|
||||
{
|
||||
return max(array_keys($this->rows));
|
||||
/*.array.*/$keys = array_keys($this->rows);
|
||||
return max($keys);
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
@ -189,27 +192,26 @@ class ExcelTable
|
|||
*
|
||||
* @return int
|
||||
*/
|
||||
function getRowCells($row)
|
||||
function getRowCells(TableRow $row)
|
||||
{
|
||||
return max(array_keys($row->cells));
|
||||
/*.array.*/$keys = array_keys($row->cells);
|
||||
return max($keys);
|
||||
}
|
||||
|
||||
/**
|
||||
* Разделяет таблицу на две части по вертикали
|
||||
* @param $n integer Количество столбцов слева
|
||||
*/
|
||||
function splitVertical($n)
|
||||
{
|
||||
$this->splitVertical = $n;
|
||||
function splitVertical($n) {
|
||||
$this->_splitVertical = $n;
|
||||
}
|
||||
|
||||
/**
|
||||
* Разделяет таблицу на две части по горизонтали
|
||||
* @param $n integer Количество столбцов сверху
|
||||
*/
|
||||
function splitHorizontal($n)
|
||||
{
|
||||
$this->splitHorizontal = $n;
|
||||
function splitHorizontal($n) {
|
||||
$this->_splitHorizontal = $n;
|
||||
}
|
||||
|
||||
|
||||
|
|
@ -218,8 +220,7 @@ class ExcelTable
|
|||
*
|
||||
* @return int
|
||||
*/
|
||||
function getColumns()
|
||||
{
|
||||
function getColumns() {
|
||||
return max(array_map(array($this, 'getRowCells'), $this->rows));
|
||||
}
|
||||
|
||||
|
|
@ -231,7 +232,7 @@ class ExcelTable
|
|||
/**
|
||||
* Генерация клетки таблицы (Переработать)
|
||||
*/
|
||||
function createCell ($ncell, XMLWriter $doc, $j, $value, $setIndex) {
|
||||
function createCell (TableCell $ncell, XMLWriter $doc, $j, /*.any.*/$value, $setIndex) {
|
||||
$doc->startElement("Cell");
|
||||
|
||||
if ($ncell->style) {
|
||||
|
|
@ -291,7 +292,7 @@ class ExcelTable
|
|||
$doc->writeAttribute('ss:Height', $this->rows[$i]->height);
|
||||
}
|
||||
|
||||
$nrow = $this->rows[$i];
|
||||
/*.TableRow.*/$nrow = $this->rows[$i];
|
||||
// Флаг индикатор подстановки номера столбца
|
||||
$setIndex = false;
|
||||
for ($j = 1; $j <= $columns; $j++) {
|
||||
|
|
@ -321,17 +322,17 @@ class ExcelTable
|
|||
$doc->writeAttribute('xmlns', 'urn:schemas-microsoft-com:office:excel');
|
||||
|
||||
$doc->writeElement('FrozenNoSplit');
|
||||
if ($this->splitVertical) {
|
||||
$doc->writeElement('SplitVertical', $this->splitVertical);
|
||||
$doc->writeElement('LeftColumnRightPane', $this->splitVertical);
|
||||
if ($this->_splitVertical) {
|
||||
$doc->writeElement('SplitVertical', $this->_splitVertical);
|
||||
$doc->writeElement('LeftColumnRightPane', $this->_splitVertical);
|
||||
}
|
||||
if ($this->splitHorizontal) {
|
||||
$doc->writeElement('SplitHorizontal', $this->splitHorizontal);
|
||||
$doc->writeElement('TopRowBottomPane', $this->splitHorizontal);
|
||||
if ($this->_splitHorizontal) {
|
||||
$doc->writeElement('SplitHorizontal', $this->_splitHorizontal);
|
||||
$doc->writeElement('TopRowBottomPane', $this->_splitHorizontal);
|
||||
}
|
||||
if ($this->splitHorizontal && $this->splitVertical) {
|
||||
if ($this->_splitHorizontal && $this->_splitVertical) {
|
||||
$doc->writeElement('ActivePane', 0);
|
||||
} else if($this->splitHorizontal) {
|
||||
} else if($this->_splitHorizontal) {
|
||||
$doc->writeElement('ActivePane', 2);
|
||||
}
|
||||
$doc->endElement();
|
||||
|
|
@ -377,6 +378,7 @@ class ExcelDocument {
|
|||
if ($type == 'Borders') {
|
||||
$doc->startElement('Borders');
|
||||
foreach ($s as $border) {
|
||||
/*.array.*/$border = $border;
|
||||
$doc->startElement('Border');
|
||||
foreach ($border as $key => $value) {
|
||||
$doc->writeAttribute('ss:' . $key, $value);
|
||||
|
|
@ -403,7 +405,7 @@ class ExcelDocument {
|
|||
function clean ($s) {
|
||||
assert(is_string($s));
|
||||
|
||||
return strtr($s, array ("\n" => ' '));
|
||||
return strtr($s, array ("\n" => " "));
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
@ -412,7 +414,7 @@ class ExcelDocument {
|
|||
*/
|
||||
function save($filename)
|
||||
{
|
||||
$doc = new xmlWriter();
|
||||
$doc = new XMLWriter();
|
||||
$doc->openURI($filename);
|
||||
$doc->setIndent(false);
|
||||
$doc->startDocument('1.0','utf-8');
|
||||
|
|
|
|||
|
|
@ -16,7 +16,6 @@ class Tools_Image
|
|||
{
|
||||
$width = imagesx($image);
|
||||
$height = imagesy($image);
|
||||
|
||||
$percent = min($prewidth / $width, $preheight / $height);
|
||||
if ($percent > 1 && !$force) $percent = 1;
|
||||
$new_width = $width * $percent;
|
||||
|
|
|
|||
|
|
@ -1,32 +0,0 @@
|
|||
<?php
|
||||
|
||||
function generatePassword($length = 9, $strength = 0) {
|
||||
$vowels = 'aeuy';
|
||||
$consonants = 'bdghjmnpqrstvz';
|
||||
if ($strength & 1) {
|
||||
$consonants .= 'BDGHJLMNPQRSTVWXZ';
|
||||
}
|
||||
if ($strength & 2) {
|
||||
$vowels .= "AEUY";
|
||||
}
|
||||
if ($strength & 4) {
|
||||
$consonants .= '23456789';
|
||||
}
|
||||
if ($strength & 8) {
|
||||
$consonants .= '@#$%';
|
||||
}
|
||||
|
||||
$password = '';
|
||||
$alt = time() % 2;
|
||||
for ($i = 0; $i < $length; $i++) {
|
||||
if ($alt == 1) {
|
||||
$password .= $consonants[(rand() % strlen($consonants))];
|
||||
$alt = 0;
|
||||
} else {
|
||||
$password .= $vowels[(rand() % strlen($vowels))];
|
||||
$alt = 1;
|
||||
}
|
||||
}
|
||||
return $password;
|
||||
}
|
||||
|
||||
164
src/Tools/SQLStatementExtractor.php
Normal file
164
src/Tools/SQLStatementExtractor.php
Normal file
|
|
@ -0,0 +1,164 @@
|
|||
<?php
|
||||
/*
|
||||
* $Id: SQLStatementExtractor.php,v 1.5 2004/07/27 23:13:46 hlellelid Exp $
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
||||
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
||||
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
|
||||
* A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
|
||||
* OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
|
||||
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
|
||||
* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
|
||||
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
|
||||
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
||||
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*
|
||||
* This software consists of voluntary contributions made by many individuals
|
||||
* and is licensed under the LGPL. For more information please see
|
||||
* <http://creole.phpdb.org>.
|
||||
*/
|
||||
|
||||
/**
|
||||
* Static class for extracting SQL statements from a string or file.
|
||||
*
|
||||
* @author Hans Lellelid <hans@xmpl.org>
|
||||
* @version $Revision: 1.5 $
|
||||
* @package creole.util.sql
|
||||
*/
|
||||
class Tools_SQLStatementExtractor {
|
||||
|
||||
protected static $delimiter = ';';
|
||||
|
||||
/**
|
||||
* Get SQL statements from file.
|
||||
*
|
||||
* @param string $filename Path to file to read.
|
||||
* @return array SQL statements
|
||||
*/
|
||||
public static function extractFile($filename) {
|
||||
$buffer = file_get_contents($filename);
|
||||
if ($buffer === false) {
|
||||
throw new Exception("Unable to read file: " . $filename);
|
||||
}
|
||||
return self::extractStatements(self::getLines($buffer));
|
||||
}
|
||||
|
||||
/**
|
||||
* Extract statements from string.
|
||||
*
|
||||
* @param string $txt
|
||||
* @return array
|
||||
*/
|
||||
public static function extract($buffer) {
|
||||
return self::extractStatements(self::getLines($buffer));
|
||||
}
|
||||
|
||||
/**
|
||||
* Extract SQL statements from array of lines.
|
||||
*
|
||||
* @param array $lines Lines of the read-in file.
|
||||
* @return string
|
||||
*/
|
||||
protected static function extractStatements($lines) {
|
||||
|
||||
$statements = array();
|
||||
$sql = "";
|
||||
|
||||
foreach($lines as $line) {
|
||||
|
||||
$line = trim($line);
|
||||
|
||||
if (self::startsWith("//", $line) ||
|
||||
self::startsWith("--", $line) ||
|
||||
self::startsWith("#", $line)) {
|
||||
continue;
|
||||
}
|
||||
|
||||
if (strlen($line) > 4 && strtoupper(substr($line,0, 4)) == "REM ") {
|
||||
continue;
|
||||
}
|
||||
|
||||
$sql .= " " . $line;
|
||||
$sql = trim($sql);
|
||||
|
||||
// SQL defines "--" as a comment to EOL
|
||||
// and in Oracle it may contain a hint
|
||||
// so we cannot just remove it, instead we must end it
|
||||
if (strpos($line, "--") !== false) {
|
||||
$sql .= "\n";
|
||||
}
|
||||
|
||||
if (self::endsWith(self::$delimiter, $sql)) {
|
||||
$statements[] = self::substring($sql, 0, strlen($sql)-1 - strlen(self::$delimiter));
|
||||
$sql = "";
|
||||
}
|
||||
}
|
||||
return $statements;
|
||||
}
|
||||
|
||||
//
|
||||
// Some string helper methods
|
||||
//
|
||||
|
||||
/**
|
||||
* Tests if a string starts with a given string.
|
||||
* @param string $check The substring to check.
|
||||
* @param string $string The string to check in (haystack).
|
||||
* @return boolean True if $string starts with $check, or they are equal, or $check is empty.
|
||||
*/
|
||||
protected static function startsWith($check, $string) {
|
||||
if ($check === "" || $check === $string) {
|
||||
return true;
|
||||
} else {
|
||||
return (strpos($string, $check) === 0) ? true : false;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Tests if a string ends with a given string.
|
||||
* @param string $check The substring to check.
|
||||
* @param string $string The string to check in (haystack).
|
||||
* @return boolean True if $string ends with $check, or they are equal, or $check is empty.
|
||||
*/
|
||||
protected static function endsWith($check, $string) {
|
||||
if ($check === "" || $check === $string) {
|
||||
return true;
|
||||
} else {
|
||||
return (strpos(strrev($string), strrev($check)) === 0) ? true : false;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* a natural way of getting a subtring, php's circular string buffer and strange
|
||||
* return values suck if you want to program strict as of C or friends
|
||||
*/
|
||||
protected static function substring($string, $startpos, $endpos = -1) {
|
||||
$len = strlen($string);
|
||||
$endpos = (int) (($endpos === -1) ? $len-1 : $endpos);
|
||||
if ($startpos > $len-1 || $startpos < 0) {
|
||||
trigger_error("substring(), Startindex out of bounds must be 0<n<$len", E_USER_ERROR);
|
||||
}
|
||||
if ($endpos > $len-1 || $endpos < $startpos) {
|
||||
trigger_error("substring(), Endindex out of bounds must be $startpos<n<".($len-1), E_USER_ERROR);
|
||||
}
|
||||
if ($startpos === $endpos) {
|
||||
return (string) $string{$startpos};
|
||||
} else {
|
||||
$len = $endpos-$startpos;
|
||||
}
|
||||
return substr($string, $startpos, $len+1);
|
||||
}
|
||||
|
||||
/**
|
||||
* Convert string buffer into array of lines.
|
||||
*
|
||||
* @param string $filename
|
||||
* @return array string[] lines of file.
|
||||
*/
|
||||
protected static function getLines($buffer) {
|
||||
$lines = preg_split("/\r?\n|\r/", $buffer);
|
||||
return $lines;
|
||||
}
|
||||
|
||||
}
|
||||
|
|
@ -1,94 +0,0 @@
|
|||
<?php
|
||||
|
||||
class TableExcelView {
|
||||
private $list = array();
|
||||
private $data = array();
|
||||
|
||||
function setColumns(array $list) {
|
||||
$this->list = $list;
|
||||
}
|
||||
|
||||
function makeTable() {
|
||||
$xls = new ExcelTable();
|
||||
$xls->setRow(1, 1, array_keys($this->list));
|
||||
|
||||
foreach($this->data as $n => $item) {
|
||||
$result = array();
|
||||
foreach($this->list as $key => $c) {
|
||||
if (is_callable($c)) {
|
||||
$result [] = call_user_func($c, $item, $n);
|
||||
} else {
|
||||
if (is_numeric($item[$c])) {
|
||||
$result [] = new Excel_Number($item[$c]);
|
||||
} else {
|
||||
$result [] = $item[$c];
|
||||
}
|
||||
}
|
||||
}
|
||||
$xls->addRow(1, $result);
|
||||
}
|
||||
|
||||
return $xls;
|
||||
}
|
||||
|
||||
function writeTable($data, $file) {
|
||||
$this->data = $data;
|
||||
|
||||
$xls = new ExcelDocument();
|
||||
$xls->addTable(array($this, 'makeTable'));
|
||||
$xls->save($file);
|
||||
}
|
||||
}
|
||||
|
||||
class TableHTMLView {
|
||||
private $list = array();
|
||||
private $stack = array();
|
||||
private $result = array();
|
||||
|
||||
function writeElement($name, $content) {
|
||||
echo "<".$name.">";
|
||||
echo $content;
|
||||
echo "</".$name.">";
|
||||
}
|
||||
|
||||
function startElement($name) {
|
||||
array_push($this->stack, $name);
|
||||
echo "<".$name.">";
|
||||
}
|
||||
|
||||
function endElement() {
|
||||
$name = array_pop($this->stack);
|
||||
echo "</".$name.">";
|
||||
}
|
||||
|
||||
function setColumns(array $list) {
|
||||
$this->list = $list;
|
||||
}
|
||||
|
||||
function writeTable($data) {
|
||||
$this->startElement('table');
|
||||
$this->startElement('thead');
|
||||
$this->startElement('tr');
|
||||
foreach($this->list as $key => $c) {
|
||||
$this->writeElement('th', $key);
|
||||
}
|
||||
$this->endElement();
|
||||
$this->endElement();
|
||||
|
||||
$this->startElement('tbody');
|
||||
foreach($data as $n => $item) {
|
||||
$this->startElement('tr');
|
||||
foreach($this->list as $key => $c) {
|
||||
if (is_callable($c)) {
|
||||
$this->writeElement('td', call_user_func($c, $item, $n));
|
||||
} else {
|
||||
$this->writeElement('td', $item[$c]);
|
||||
}
|
||||
}
|
||||
$this->endElement();
|
||||
}
|
||||
$this->endElement();
|
||||
$this->endElement();
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -1,636 +0,0 @@
|
|||
<?php
|
||||
//****************************************************************************
|
||||
// phpDBTree 1.4
|
||||
//****************************************************************************
|
||||
// Author: Maxim Poltarak <maxx at e dash taller dot net>
|
||||
// WWW: http://dev.e-taller.net/dbtree/
|
||||
// Category: Databases
|
||||
// Description: PHP class implementing a Nested Sets approach to storing
|
||||
// tree-like structures in database tables. This technique was
|
||||
// introduced by Joe Celko <http://www.celko.com/> and has some
|
||||
// advantages over a widely used method called Adjacency Matrix.
|
||||
//****************************************************************************
|
||||
// The lib is FREEWARE. That means you may use it anywhere you want, you may
|
||||
// do anything with it. The Author mentioned above is NOT responsible for any
|
||||
// consequences of using this library.
|
||||
// If you don't agree with this, you are NOT ALLOWED to use the lib!
|
||||
//****************************************************************************
|
||||
// You're welcome to send me all improvings, feature requests, bug reports...
|
||||
//****************************************************************************
|
||||
// SAMPLE DB TABLE STRUCTURE:
|
||||
//
|
||||
// CREATE TABLE categories (
|
||||
// cat_id INT UNSIGNED NOT NULL AUTO_INCREMENT,
|
||||
// cat_left INT UNSIGNED NOT NULL,
|
||||
// cat_right INT UNSIGNED NOT NULL,
|
||||
// cat_level INT UNSIGNED NOT NULL,
|
||||
// PRIMARY KEY(cat_id),
|
||||
// KEY(cat_left, cat_right, cat_level)
|
||||
// );
|
||||
//
|
||||
// This is believed to be the optimal Nested Sets use case. Use `one-to-one`
|
||||
// relations on `cat_id` field between this `structure` table and
|
||||
// another `data` table in your database.
|
||||
//
|
||||
// Don't forget to make a single call to clear()
|
||||
// to set up the Root node in an empty table.
|
||||
//
|
||||
//****************************************************************************
|
||||
// NOTE: Although you may use this library to retrieve data from the table,
|
||||
// it is recommended to write your own queries for doing that.
|
||||
// The main purpose of the library is to provide a simpler way to
|
||||
// create, update and delete records. Not to SELECT them.
|
||||
//****************************************************************************
|
||||
//
|
||||
// IMPORTANT! DO NOT create either UNIQUE or PRIMARY keys on the set of
|
||||
// fields (`cat_left`, `cat_right` and `cat_level`)!
|
||||
// Unique keys will destroy the Nested Sets structure!
|
||||
//
|
||||
//****************************************************************************
|
||||
// CHANGELOG:
|
||||
// 16-Apr-2003 -=- 1.1
|
||||
// - Added moveAll() method
|
||||
// - Added fourth parameter to the constructor
|
||||
// - Renamed getElementInfo() to getNodeInfo() /keeping BC/
|
||||
// - Added "Sample Table Structure" comment
|
||||
// - Now it trigger_error()'s in case of any serious error, because if not you
|
||||
// will lose the Nested Sets structure in your table
|
||||
// 19-Feb-2004 -=- 1.2
|
||||
// - Fixed a bug in moveAll() method?
|
||||
// Thanks to Maxim Matyukhin for the patch.
|
||||
// 13-Jul-2004 -=- 1.3
|
||||
// - Changed all die()'s for a more standard trigger_error()
|
||||
// Thanks to Dmitry Romakhin for pointing out an issue with
|
||||
// incorrect error message call.
|
||||
// 09-Nov-2004 -=- 1.4
|
||||
// - Added insertNear() method.
|
||||
// Thanks to Michael Krenz who sent its implementation.
|
||||
// - Removed IGNORE keyword from UPDATE clauses in insert() methods.
|
||||
// It was dumb to have it there all the time. Sorry. Anyway, you had
|
||||
// to follow the important note mencioned above. If you hadn't, you're
|
||||
// in problem.
|
||||
//
|
||||
//****************************************************************************
|
||||
// Note: For best viewing of the code Tab size 4 is recommended
|
||||
//****************************************************************************
|
||||
|
||||
function _case($c, $then, $else) {
|
||||
return " (CASE WHEN $c THEN $then ELSE $else END) ";
|
||||
}
|
||||
|
||||
function _between($a, $x, $y) {
|
||||
return " " . $a . " BETWEEN " . $x . " AND " . $y;
|
||||
}
|
||||
|
||||
function _inside($a, $x, $y) {
|
||||
return " " . $a . " > " . $x . " AND " . $a . " < " . $y;
|
||||
}
|
||||
|
||||
class Tree_DBTree
|
||||
{
|
||||
var $db; // CDatabase class to plug to
|
||||
var $table; // Table with Nested Sets implemented
|
||||
var $id; // Name of the ID-auto_increment-field in the table.
|
||||
// These 3 variables are names of fields which are needed to implement
|
||||
// Nested Sets. All 3 fields should exist in your table!
|
||||
// However, you may want to change their names here to avoid name collisions.
|
||||
var $left = 'cat_left';
|
||||
var $right = 'cat_right';
|
||||
var $level = 'cat_level';
|
||||
var $qryParams = '';
|
||||
var $qryFields = '';
|
||||
var $qryTables = '';
|
||||
var $qryWhere = '';
|
||||
var $qryGroupBy = '';
|
||||
var $qryHaving = '';
|
||||
var $qryOrderBy = '';
|
||||
var $qryLimit = '';
|
||||
var $sqlNeedReset = true;
|
||||
var $sql; // Last SQL query
|
||||
|
||||
//************************************************************************
|
||||
// Constructor
|
||||
// $DB : CDatabase class instance to link to
|
||||
// $tableName : table in database where to implement nested sets
|
||||
// $itemId : name of the field which will uniquely identify every record
|
||||
// $fieldNames : optional configuration array to set field names. Example:
|
||||
// array(
|
||||
// 'left' => 'cat_left',
|
||||
// 'right' => 'cat_right',
|
||||
// 'level' => 'cat_level'
|
||||
// )
|
||||
function CDBTree(&$DB, $tableName, $itemId, $seq, $fieldNames = array())
|
||||
{
|
||||
|
||||
if (empty($tableName)) trigger_error("phpDbTree: Unknown table", E_USER_ERROR);
|
||||
|
||||
if (empty($itemId)) trigger_error("phpDbTree: Unknown ID column", E_USER_ERROR);
|
||||
$this->seq = $seq;
|
||||
$this->db = $DB;
|
||||
$this->table = $tableName;
|
||||
$this->id = $itemId;
|
||||
|
||||
if (is_array($fieldNames) && sizeof($fieldNames))
|
||||
foreach($fieldNames as $k => $v) $this->$k = $v;
|
||||
}
|
||||
|
||||
//************************************************************************
|
||||
// Returns a Left and Right IDs and Level of an element or false on error
|
||||
// $ID : an ID of the element
|
||||
function getElementInfo($ID)
|
||||
{
|
||||
return $this->getNodeInfo($ID);
|
||||
}
|
||||
|
||||
function getNodeInfo($ID)
|
||||
{
|
||||
$this->sql = 'SELECT ' . $this->left . ',' . $this->right . ',' . $this->level . ' FROM ' . $this->table . ' WHERE ' . $this->id . '=\'' . $ID . '\'';
|
||||
// print_r($this->sql);
|
||||
|
||||
if (($query = $this->db->query($this->sql)) && ($this->db->num_rows($query) == 1) && ($Data = $this->db->fetch_array($query))) return array(
|
||||
(int)$Data[$this->left],
|
||||
(int)$Data[$this->right],
|
||||
(int)$Data[$this->level]
|
||||
);
|
||||
else trigger_error("phpDbTree error: " . $this->db->error() , E_USER_ERROR); // throw new Exception();
|
||||
}
|
||||
|
||||
//************************************************************************
|
||||
// Clears table and creates 'root' node
|
||||
// $data : optional argument with data for the root node
|
||||
function clear($data = array())
|
||||
{
|
||||
// clearing table
|
||||
|
||||
if ((!$this->db->query('TRUNCATE ' . $this->table)) && (!$this->db->query('DELETE FROM ' . $this->table))) trigger_error("phpDbTree error: " . $this->db->error() , E_USER_ERROR);
|
||||
// preparing data to be inserted
|
||||
|
||||
if (sizeof($data)) {
|
||||
$fld_names = implode(',', array_keys($data)) . ',';
|
||||
|
||||
if (sizeof($data)) $fld_values = '\'' . implode('\',\'', array_values($data)) . '\',';
|
||||
}
|
||||
$fld_names.= $this->left . ',' . $this->right . ',' . $this->level;
|
||||
$fld_values.= '1,2,0';
|
||||
// inserting new record
|
||||
$this->sql = 'INSERT INTO ' . $this->table . '(' . $fld_names . ') VALUES(' . $fld_values . ')';
|
||||
|
||||
if (!($this->db->query($this->sql))) trigger_error("phpDbTree error: " . $this->db->error() , E_USER_ERROR);
|
||||
return $this->db->insert_id($this->seq);
|
||||
}
|
||||
|
||||
//************************************************************************
|
||||
// Updates a record
|
||||
// $ID : element ID
|
||||
// $data : array with data to update: array(<field_name> => <fields_value>)
|
||||
function update($ID, $data)
|
||||
{
|
||||
$sql_set = '';
|
||||
|
||||
foreach($data as $k => $v) $sql_set.= ',' . $k . '=\'' . addslashes($v) . '\'';
|
||||
return $this->db->query('UPDATE ' . $this->table . ' SET ' . substr($sql_set, 1) . ' WHERE ' . $this->id . '=\'' . $ID . '\'');
|
||||
}
|
||||
|
||||
//************************************************************************
|
||||
// Inserts a record into the table with nested sets
|
||||
// $ID : an ID of the parent element
|
||||
// $data : array with data to be inserted: array(<field_name> => <field_value>)
|
||||
// Returns : true on success, or false on error
|
||||
function insert($ID, $data)
|
||||
{
|
||||
|
||||
if (!(list($leftId, $rightId, $level) = $this->getNodeInfo($ID))) trigger_error("phpDbTree error: " . $this->db->error() , E_USER_ERROR);
|
||||
// preparing data to be inserted
|
||||
|
||||
if (sizeof($data)) {
|
||||
$fld_names = implode(',', array_keys($data)) . ',';
|
||||
$fld_values = '\'' . implode('\',\'', array_values($data)) . '\',';
|
||||
}
|
||||
$fld_names.= $this->left . ',' . $this->right . ',' . $this->level;
|
||||
$fld_values.= ($rightId) . ',' . ($rightId+1) . ',' . ($level+1);
|
||||
// creating a place for the record being inserted
|
||||
|
||||
if ($ID) {
|
||||
$this->sql = 'UPDATE ' . $this->table . ' SET ' . $this->left . '=' . _case($this->left . '>' . $rightId, $this->left . '+2', $this->left) . ',' . $this->right . '=' . _case($this->right . '>=' . $rightId, $this->right . '+2', $this->right) . 'WHERE ' . $this->right . '>=' . $rightId;
|
||||
|
||||
if (!($this->db->query($this->sql))) trigger_error("phpDbTree error: " . $this->db->error() , E_USER_ERROR);
|
||||
}
|
||||
// inserting new record
|
||||
$this->sql = 'INSERT INTO ' . $this->table . '(' . $fld_names . ') VALUES(' . $fld_values . ')';
|
||||
|
||||
if (!($this->db->query($this->sql))) trigger_error("phpDbTree error: " . $this->db->error() , E_USER_ERROR);
|
||||
return $this->db->insert_id($this->seq);
|
||||
}
|
||||
|
||||
//************************************************************************
|
||||
// Inserts a record into the table with nested sets
|
||||
// $ID : ID of the element after which (i.e. at the same level) the new element
|
||||
// is to be inserted
|
||||
// $data : array with data to be inserted: array(<field_name> => <field_value>)
|
||||
// Returns : true on success, or false on error
|
||||
function insertNear($ID, $data)
|
||||
{
|
||||
|
||||
if (!(list($leftId, $rightId, $level) = $this->getNodeInfo($ID))) trigger_error("phpDbTree error: " . $this->db->error() , E_USER_ERROR);
|
||||
// preparing data to be inserted
|
||||
|
||||
if (sizeof($data)) {
|
||||
$fld_names = implode(',', array_keys($data)) . ',';
|
||||
$fld_values = '\'' . implode('\',\'', array_values($data)) . '\',';
|
||||
}
|
||||
$fld_names.= $this->left . ',' . $this->right . ',' . $this->level;
|
||||
$fld_values.= ($rightId+1) . ',' . ($rightId+2) . ',' . ($level);
|
||||
// creating a place for the record being inserted
|
||||
|
||||
if ($ID) {
|
||||
$this->sql = 'UPDATE ' . $this->table . ' SET ' . $this->left . '=' . _case($this->left . '>' . $rightId, $this->left . '+2', $this->left) . $this->right . '=' . _case($this->right . '>' . $rightId, $this->right . '+2', $this->right) . 'WHERE ' . $this->right . '>' . $rightId;
|
||||
|
||||
if (!($this->db->query($this->sql))) trigger_error("phpDbTree error:" . $this->db->error() , E_USER_ERROR);
|
||||
}
|
||||
// inserting new record
|
||||
$this->sql = 'INSERT INTO ' . $this->table . '(' . $fld_names . ') VALUES(' . $fld_values . ')';
|
||||
|
||||
if (!($this->db->query($this->sql))) trigger_error("phpDbTree error:" . $this->db->error() , E_USER_ERROR);
|
||||
return $this->db->insert_id($this->seq);
|
||||
}
|
||||
|
||||
//************************************************************************
|
||||
// Assigns a node with all its children to another parent
|
||||
// $ID : node ID
|
||||
// $newParentID : ID of new parent node
|
||||
// Returns : false on error
|
||||
function moveAll($ID, $newParentId)
|
||||
{
|
||||
|
||||
if (!(list($leftId, $rightId, $level) = $this->getNodeInfo($ID))) trigger_error("phpDbTree error: " . $this->db->error() , E_USER_ERROR);
|
||||
|
||||
if (!(list($leftIdP, $rightIdP, $levelP) = $this->getNodeInfo($newParentId))) trigger_error("phpDbTree error: " . $this->db->error() , E_USER_ERROR);
|
||||
|
||||
if ($ID == $newParentId || $leftId == $leftIdP || ($leftIdP >= $leftId && $leftIdP <= $rightId)) return false;
|
||||
// whether it is being moved upwards along the path
|
||||
|
||||
if ($leftIdP < $leftId && $rightIdP > $rightId && $levelP < $level-1) {
|
||||
$this->sql = 'UPDATE ' . $this->table . ' SET '
|
||||
. $this->level . '=' . _case($this->left . ' BETWEEN ' . $leftId . ' AND ' . $rightId, $this->level . sprintf('%+d', -($level-1) +$levelP) , $this->level) . ","
|
||||
. $this->right . '=' . _case($this->right . ' BETWEEN ' . ($rightId+1) . ' AND ' . ($rightIdP-1) , $this->right . '-' . ($rightId-$leftId+1)
|
||||
, _case($this->left . ' BETWEEN ' . ($leftId) . ' AND ' . ($rightId) , $this->right . '+' . ((($rightIdP-$rightId-$level+$levelP) /2) *2+$level-$levelP-1) , $this->right)) . ","
|
||||
. $this->left . '=' . _case($this->left . ' BETWEEN ' . ($rightId+1) . ' AND ' . ($rightIdP-1) , $this->left . '-' . ($rightId-$leftId+1) , _case($this->left . ' BETWEEN ' . $leftId . ' AND ' . ($rightId) , $this->left . '+' . ((($rightIdP-$rightId-$level+$levelP) /2) *2+$level-$levelP-1) , $this->left)) . 'WHERE ' . $this->left . ' BETWEEN ' . ($leftIdP+1) . ' AND ' . ($rightIdP-1);
|
||||
|
||||
} elseif ($leftIdP < $leftId) {
|
||||
$this->sql = 'UPDATE ' . $this->table . ' SET '
|
||||
. $this->level . '=' . _case($this->left . ' BETWEEN ' . $leftId . ' AND ' . $rightId, $this->level . sprintf('%+d', -($level-1) +$levelP) , $this->level) . ","
|
||||
. $this->left . '=' . _case($this->left . ' BETWEEN ' . $rightIdP . ' AND ' . ($leftId-1) , $this->left . '+' . ($rightId-$leftId+1)
|
||||
, _case($this->left . ' BETWEEN ' . $leftId . ' AND ' . $rightId, $this->left . '-' . ($leftId-$rightIdP) , $this->left)) . ","
|
||||
. $this->right . '=' . _case($this->right . ' BETWEEN ' . $rightIdP . ' AND ' . $leftId, $this->right . '+' . ($rightId-$leftId+1) , _case($this->right . ' BETWEEN ' . $leftId . ' AND ' . $rightId, $this->right . '-' . ($leftId-$rightIdP) , $this->right)) . 'WHERE ' . $this->left . ' BETWEEN ' . $leftIdP . ' AND ' . $rightId
|
||||
// !!! added this line (Maxim Matyukhin)
|
||||
. ' OR ' . $this->right . ' BETWEEN ' . $leftIdP . ' AND ' . $rightId;
|
||||
} else {
|
||||
$this->sql = 'UPDATE ' . $this->table . ' SET '
|
||||
. $this->level . '=' . _case($this->left . ' BETWEEN ' . $leftId . ' AND ' . $rightId, $this->level . sprintf('%+d', -($level-1) +$levelP) , $this->level) . ","
|
||||
. $this->left . '=' . _case($this->left . ' BETWEEN ' . $rightId . ' AND ' . $rightIdP, $this->left . '-' . ($rightId-$leftId+1)
|
||||
, _case($this->left . ' BETWEEN ' . $leftId . ' AND ' . $rightId, $this->left . '+' . ($rightIdP-1-$rightId), $this->left)) . ", "
|
||||
. $this->right . '=' . _case($this->right . ' BETWEEN ' . ($rightId+1) . ' AND ' . ($rightIdP-1) , $this->right . '-' . ($rightId-$leftId+1) , _case($this->right . ' BETWEEN ' . $leftId . ' AND ' . $rightId, $this->right . '+' . ($rightIdP-1-$rightId) , $this->right)) . 'WHERE ' . $this->left . ' BETWEEN ' . $leftId . ' AND ' . $rightIdP
|
||||
// !!! added this line (Maxim Matyukhin)
|
||||
. ' OR ' . $this->right . ' BETWEEN ' . $leftId . ' AND ' . $rightIdP;
|
||||
}
|
||||
return $this->db->query($this->sql) or trigger_error("phpDbTree error: " . $this->db->error() , E_USER_ERROR);
|
||||
}
|
||||
|
||||
// Перемещение всех детей ветки в другую ветку
|
||||
function moveChildren($ID, $newParentId)
|
||||
{
|
||||
|
||||
if (!(list($leftId, $rightId, $level) = $this->getNodeInfo($ID))) trigger_error("phpDbTree error: " . $this->db->error() , E_USER_ERROR);
|
||||
|
||||
if (!(list($leftIdP, $rightIdP, $levelP) = $this->getNodeInfo($newParentId))) trigger_error("phpDbTree error: " . $this->db->error() , E_USER_ERROR);
|
||||
|
||||
if ($ID == $newParentId || $leftId == $leftIdP || ($leftIdP >= $leftId && $leftIdP <= $rightId)) return false;
|
||||
// whether it is being moved upwards along the path
|
||||
|
||||
if ($leftIdP < $leftId && $rightIdP > $rightId && $levelP < $level-1) {
|
||||
// _update($this->table, array(), )
|
||||
$this->sql = 'UPDATE ' . $this->table . ' SET '
|
||||
// Меняем уровень
|
||||
. $this->level . '=' .
|
||||
_case(_between($this->left, $leftId, $rightId),
|
||||
$this->level . sprintf('%+d', -($level-1) +$levelP) , $this->level)
|
||||
// Меняем границы
|
||||
. $this->left . '=' .
|
||||
_case(_beetween($this->left, $rightId+1, $rightIdP-1), $this->left . '-' . $rightId-$leftId+1 ,
|
||||
_case(_between($this->left, $leftId, $rightId), $this->left . '+' . ((($rightIdP-$rightId-$level+$levelP) /2) *2+$level-$levelP-1) , $this->left))
|
||||
. $this->right . '=' .
|
||||
_case(_between($this->right, $rightId+1, $rightIdP-1), $this->right . '-' . ($rightId-$leftId+1) ,
|
||||
_case(_between($this->left, $leftId, $rightId), $this->right . '+' . ((($rightIdP-$rightId-$level+$levelP) /2) *2+$level-$levelP-1) , $this->right))
|
||||
. 'WHERE ' . _between($this->left, ($leftIdP+1), ($rightIdP-1));
|
||||
|
||||
} elseif ($leftIdP < $leftId) {
|
||||
$this->sql = 'UPDATE ' . $this->table . ' SET '
|
||||
. $this->level . '=' .
|
||||
_case(_between($this->left, $leftId, $rightId),
|
||||
$this->level . sprintf('%+d', -($level-1) +$levelP) , $this->level)
|
||||
. $this->left . '=' .
|
||||
_case(_between($this->left, $rightIdP, $leftId-1), $this->left . '+' . ($rightId-$leftId+1),
|
||||
_case(_between($this->left, $leftId, $rightId), $this->left . '-' . ($leftId-$rightIdP) , $this->left))
|
||||
. $this->right . '=' .
|
||||
_case(_between($this->right, $rightIdP, $leftId), $this->right . '+' . ($rightId-$leftId+1),
|
||||
_case(_between($this->right, $leftId, $rightId), $this->right . '-' . ($leftId-$rightIdP) , $this->right))
|
||||
. 'WHERE ' . _between($this->left, $leftIdP, $rightId)
|
||||
// !!! added this line (Maxim Matyukhin)
|
||||
. ' OR ' . _between($this->right, $leftIdP, $rightId);
|
||||
} else {
|
||||
$this->sql = 'UPDATE ' . $this->table . ' SET '
|
||||
. $this->level . '='
|
||||
. _case(_between($this->left, $leftId, $rightId),
|
||||
$this->level . sprintf('%+d', -($level-1) +$levelP) , $this->level)
|
||||
. $this->left . '=' .
|
||||
_case(_between($this->left, $rightId, $rightIdP), $this->left . '-' . ($rightId-$leftId+1),
|
||||
_case(_between($this->left, $leftId, $rightId), $this->left . '+' . ($rightIdP-1-$rightId), $this->left))
|
||||
. $this->right . '=' .
|
||||
_case(_between($this->right, $rightId+1, $rightIdP-1), $this->right . '-' . ($rightId-$leftId+1),
|
||||
_case(_between($this->right, $leftId, $rightId), $this->right . '+' . ($rightIdP-1-$rightId) , $this->right))
|
||||
. 'WHERE ' . _between($this->left, $leftId, $rightIdP)
|
||||
// !!! added this line (Maxim Matyukhin)
|
||||
. ' OR ' . _between($this->right, $leftId, $rightIdP);
|
||||
}
|
||||
return $this->db->query($this->sql) or trigger_error("phpDbTree error: " . $this->db->error() , E_USER_ERROR);
|
||||
|
||||
}
|
||||
|
||||
//************************************************************************
|
||||
// Deletes a record wihtout deleting its children
|
||||
// $ID : an ID of the element to be deleted
|
||||
// Returns : true on success, or false on error
|
||||
function delete($ID)
|
||||
{
|
||||
|
||||
if (!(list($leftId, $rightId, $level) = $this->getNodeInfo($ID))) trigger_error("phpDbTree error: " . $this->db->error() , E_USER_ERROR);
|
||||
// Deleting record
|
||||
$this->sql = 'DELETE FROM ' . $this->table . ' WHERE ' . $this->id . '=\'' . $ID . '\'';
|
||||
|
||||
if (!$this->db->query($this->sql)) trigger_error("phpDbTree error: " . $this->db->error() , E_USER_ERROR);
|
||||
// Clearing blank spaces in a tree
|
||||
$this->sql = 'UPDATE ' . $this->table . ' SET '
|
||||
. $this->left . '=' . _case($this->left . ' BETWEEN ' . $leftId . ' AND ' . $rightId, $this->left . '-1', $this->left) . ", "
|
||||
. $this->right . '=' . _case($this->right . ' BETWEEN ' . $leftId . ' AND ' . $rightId, $this->right . '-1', $this->right) . ", "
|
||||
. $this->level . '=' . _case($this->left . ' BETWEEN ' . $leftId . ' AND ' . $rightId, $this->level . '-1', $this->level) . ", "
|
||||
. $this->left . '=' . _case($this->left . '>' . $rightId, $this->left . '-2', $this->left) . ", "
|
||||
. $this->right . '=' . _case($this->right . '>' . $rightId, $this->right . '-2', $this->right)
|
||||
. ' WHERE ' . $this->right . '>' . $leftId;
|
||||
|
||||
if (!$this->db->query($this->sql)) trigger_error("phpDbTree error: " . $this->db->error() , E_USER_ERROR);
|
||||
return true;
|
||||
}
|
||||
|
||||
//************************************************************************
|
||||
// Deletes a record with all its children
|
||||
// $ID : an ID of the element to be deleted
|
||||
// Returns : true on success, or false on error
|
||||
function deleteAll($ID)
|
||||
{
|
||||
|
||||
if (!(list($leftId, $rightId, $level) = $this->getNodeInfo($ID))) trigger_error("phpDbTree error: " . $this->db->error() , E_USER_ERROR);
|
||||
// Deleteing record(s)
|
||||
$this->sql = 'DELETE FROM ' . $this->table . ' WHERE ' . $this->left . ' BETWEEN ' . $leftId . ' AND ' . $rightId;
|
||||
|
||||
if (!$this->db->query($this->sql)) trigger_error("phpDbTree error: " . $this->db->error() , E_USER_ERROR);
|
||||
// Clearing blank spaces in a tree
|
||||
$deltaId = ($rightId-$leftId) +1;
|
||||
$this->sql = 'UPDATE ' . $this->table . ' SET '
|
||||
. $this->left . '=' . _case($this->left . '>' . $leftId, $this->left . '-' . $deltaId, $this->left) . ", "
|
||||
. $this->right . '=' . _case($this->right . '>' . $leftId, $this->right . '-' . $deltaId, $this->right)
|
||||
. ' WHERE ' . $this->right . '>' . $rightId;
|
||||
|
||||
if (!$this->db->query($this->sql)) trigger_error("phpDbTree error: " . $this->db->error() , E_USER_ERROR);
|
||||
return true;
|
||||
}
|
||||
|
||||
//************************************************************************
|
||||
// Enumerates children of an element
|
||||
// $ID : an ID of an element which children to be enumerated
|
||||
// $start_level : relative level from which start to enumerate children
|
||||
// $end_level : the last relative level at which enumerate children
|
||||
// 1. If $end_level isn't given, only children of
|
||||
// $start_level levels are enumerated
|
||||
// 2. Level values should always be greater than zero.
|
||||
// Level 1 means direct children of the element
|
||||
// Returns : a result id for using with other DB functions
|
||||
function enumChildrenAll($ID)
|
||||
{
|
||||
return $this->enumChildren($ID, 1, 0);
|
||||
}
|
||||
|
||||
function enumChildren($ID, $start_level = 1, $end_level = 1)
|
||||
{
|
||||
if ($start_level < 0) trigger_error("phpDbTree error: " . $this->db->error() , E_USER_ERROR);
|
||||
// We could use sprintf() here, but it'd be too slow
|
||||
$whereSql1 = ' AND ' . $this->table . '.' . $this->level;
|
||||
$whereSql2 = '_' . $this->table . '.' . $this->level . '+';
|
||||
|
||||
if (!$end_level) $whereSql = $whereSql1 . '>=' . $whereSql2 . (int)$start_level;
|
||||
else {
|
||||
$whereSql = ($end_level <= $start_level) ? $whereSql1 . '=' . $whereSql2 . (int)$start_level : ' AND ' . $this->table . '.' . $this->level . ' BETWEEN _' . $this->table . '.' . $this->level . '+' . (int)$start_level . ' AND _' . $this->table . '.' . $this->level . '+' . (int)$end_level;
|
||||
}
|
||||
$this->sql = $this->sqlComposeSelect(array(
|
||||
'', // Params
|
||||
'', // Fields
|
||||
$this->table . ' _' . $this->table . ', ' . $this->table, // Tables
|
||||
'_' . $this->table . '.' . $this->id . '=\'' . $ID . '\'' . ' AND ' . $this->table . '.' . $this->left . ' BETWEEN _' . $this->table . '.' . $this->left . ' AND _' . $this->table . '.' . $this->right . $whereSql
|
||||
));
|
||||
return $this->db->query($this->sql);
|
||||
}
|
||||
|
||||
function enumChildrenArray($ID, $start_level = 1, $end_level = 1)
|
||||
{
|
||||
return $this->db->result2array($this->enumChildren($ID, $start_level, $end_level));
|
||||
}
|
||||
|
||||
//************************************************************************
|
||||
// Enumerates the PATH from an element to its top level parent
|
||||
// $ID : an ID of an element
|
||||
// $showRoot : whether to show root node in a path
|
||||
// Returns : a result id for using with other DB functions
|
||||
function enumPath($ID, $showRoot = false)
|
||||
{
|
||||
$this->sql = $this->sqlComposeSelect(array(
|
||||
'', // Params
|
||||
'', // Fields
|
||||
$this->table . ' _' . $this->table . ', ' . $this->table, // Tables
|
||||
'_' . $this->table . '.' . $this->id . '=\'' . $ID . '\'' . ' AND _' . $this->table . '.' . $this->left . ' BETWEEN ' . $this->table . '.' . $this->left . ' AND ' . $this->table . '.' . $this->right . (($showRoot) ? '' : ' AND ' . $this->table . '.' . $this->level . '>0') , // Where
|
||||
'', // GroupBy
|
||||
'', // Having
|
||||
$this->table . '.' . $this->left // OrderBy
|
||||
|
||||
));
|
||||
return $this->db->query($this->sql);
|
||||
}
|
||||
|
||||
function enumPathArray($ID, $showRoot = false)
|
||||
{
|
||||
return $this->db->result2array($this->enumPath($ID, $showRoot));
|
||||
}
|
||||
|
||||
//************************************************************************
|
||||
// Returns query result to fetch data of the element's parent
|
||||
// $ID : an ID of an element which parent to be retrieved
|
||||
// $level : Relative level of parent
|
||||
// Returns : a result id for using with other DB functions
|
||||
function getParent($ID, $level = 1)
|
||||
{
|
||||
|
||||
if ($level < 1) trigger_error("phpDbTree error: " . $this->db->error() , E_USER_ERROR);
|
||||
$this->sql = $this->sqlComposeSelect(array(
|
||||
'', // Params
|
||||
'', // Fields
|
||||
$this->table . ' _' . $this->table . ', ' . $this->table, // Tables
|
||||
'_' . $this->table . '.' . $this->id . '=\'' . $ID . '\'' . ' AND _' . $this->table . '.' . $this->left . ' BETWEEN ' . $this->table . '.' . $this->left . ' AND ' . $this->table . '.' . $this->right . ' AND ' . $this->table . '.' . $this->level . '=_' . $this->table . '.' . $this->level . '-' . (int)$level // Where
|
||||
|
||||
));
|
||||
$result = $this->db->result2array($this->db->query($this->sql));
|
||||
return (int)$result[0][$this->id];
|
||||
}
|
||||
//************************************************************************
|
||||
|
||||
function sqlReset()
|
||||
{
|
||||
$this->qryParams = '';
|
||||
$this->qryFields = '';
|
||||
$this->qryTables = '';
|
||||
$this->qryWhere = '';
|
||||
$this->qryGroupBy = '';
|
||||
$this->qryHaving = '';
|
||||
$this->qryOrderBy = '';
|
||||
$this->qryLimit = '';
|
||||
return true;
|
||||
}
|
||||
|
||||
//************************************************************************
|
||||
function sqlSetReset($resetMode)
|
||||
{
|
||||
$this->sqlNeedReset = ($resetMode) ? true : false;
|
||||
}
|
||||
|
||||
//************************************************************************
|
||||
function sqlParams($param = '')
|
||||
{
|
||||
return (empty($param)) ? $this->qryParams : $this->qryParams = $param;
|
||||
}
|
||||
|
||||
function sqlFields($param = '')
|
||||
{
|
||||
return (empty($param)) ? $this->qryFields : $this->qryFields = $param;
|
||||
}
|
||||
|
||||
function sqlSelect($param = '')
|
||||
{
|
||||
return $this->sqlFields($param);
|
||||
}
|
||||
|
||||
function sqlTables($param = '')
|
||||
{
|
||||
return (empty($param)) ? $this->qryTables : $this->qryTables = $param;
|
||||
}
|
||||
|
||||
function sqlFrom($param = '')
|
||||
{
|
||||
return $this->sqlTables($param);
|
||||
}
|
||||
|
||||
function sqlWhere($param = '')
|
||||
{
|
||||
return (empty($param)) ? $this->qryWhere : $this->qryWhere = $param;
|
||||
}
|
||||
|
||||
function sqlGroupBy($param = '')
|
||||
{
|
||||
return (empty($param)) ? $this->qryGroupBy : $this->qryGroupBy = $param;
|
||||
}
|
||||
|
||||
function sqlHaving($param = '')
|
||||
{
|
||||
return (empty($param)) ? $this->qryHaving : $this->qryHaving = $param;
|
||||
}
|
||||
|
||||
function sqlOrderBy($param = '')
|
||||
{
|
||||
return (empty($param)) ? $this->qryOrderBy : $this->qryOrderBy = $param;
|
||||
}
|
||||
|
||||
function sqlLimit($param = '')
|
||||
{
|
||||
return (empty($param)) ? $this->qryLimit : $this->qryLimit = $param;
|
||||
}
|
||||
|
||||
//************************************************************************
|
||||
function sqlComposeSelect($arSql)
|
||||
{
|
||||
$joinTypes = array(
|
||||
'join' => 1,
|
||||
'cross' => 1,
|
||||
'inner' => 1,
|
||||
'straight' => 1,
|
||||
'left' => 1,
|
||||
'natural' => 1,
|
||||
'right' => 1
|
||||
);
|
||||
$this->sql = 'SELECT ' . $arSql[0] . ' ';
|
||||
|
||||
if (!empty($this->qryParams)) $this->sql.= $this->sqlParams . ' ';
|
||||
|
||||
if (empty($arSql[1]) && empty($this->qryFields)) $this->sql.= $this->table . '.' . $this->id;
|
||||
else {
|
||||
|
||||
if (!empty($arSql[1])) $this->sql.= $arSql[1];
|
||||
|
||||
if (!empty($this->qryFields)) $this->sql.= ((empty($arSql[1])) ? '' : ',') . $this->qryFields;
|
||||
}
|
||||
$this->sql.= ' FROM ';
|
||||
// $tblAr = array(0 => 'join');
|
||||
$isJoin = ($tblAr = explode(' ', trim($this->qryTables)))
|
||||
&& /*($joinTypes[strtolower($tblAr[0]) ])*/ 1;
|
||||
|
||||
if (empty($arSql[2]) && empty($this->qryTables)) $this->sql.= $this->table;
|
||||
else {
|
||||
|
||||
if (!empty($arSql[2])) $this->sql.= $arSql[2];
|
||||
|
||||
if (!empty($this->qryTables)) {
|
||||
|
||||
if (!empty($arSql[2])) $this->sql.= (($isJoin) ? ' ' : ',');
|
||||
elseif ($isJoin) $this->sql.= $this->table . ' ';
|
||||
$this->sql.= $this->qryTables;
|
||||
}
|
||||
}
|
||||
|
||||
if ((!empty($arSql[3])) || (!empty($this->qryWhere))) {
|
||||
$this->sql.= ' WHERE ' . $arSql[3] . ' ';
|
||||
|
||||
if (!empty($this->qryWhere)) $this->sql.= (empty($arSql[3])) ? $this->qryWhere : 'AND(' . $this->qryWhere . ')';
|
||||
}
|
||||
|
||||
if ((!empty($arSql[4])) || (!empty($this->qryGroupBy))) {
|
||||
$this->sql.= ' GROUP BY ' . $arSql[4] . ' ';
|
||||
|
||||
if (!empty($this->qryGroupBy)) $this->sql.= (empty($arSql[4])) ? $this->qryGroupBy : ',' . $this->qryGroupBy;
|
||||
}
|
||||
|
||||
if ((!empty($arSql[5])) || (!empty($this->qryHaving))) {
|
||||
$this->sql.= ' HAVING ' . $arSql[5] . ' ';
|
||||
|
||||
if (!empty($this->qryHaving)) $this->sql.= (empty($arSql[5])) ? $this->qryHaving : 'AND(' . $this->qryHaving . ')';
|
||||
}
|
||||
|
||||
if ((!empty($arSql[6])) || (!empty($this->qryOrderBy))) {
|
||||
$this->sql.= ' ORDER BY ' . (isset($arSql[6]) ? $arSql[6] : '') . ' ';
|
||||
|
||||
if (!empty($this->qryOrderBy)) $this->sql.= (empty($arSql[6])) ? $this->qryOrderBy : ',' . $this->qryOrderBy;
|
||||
}
|
||||
|
||||
if (!empty($arSql[7])) $this->sql.= ' LIMIT ' . $arSql[7];
|
||||
elseif (!empty($this->qryLimit)) $this->sql.= ' LIMIT ' . $this->qryLimit;
|
||||
|
||||
if ($this->sqlNeedReset) $this->sqlReset();
|
||||
return $this->sql;
|
||||
}
|
||||
//************************************************************************
|
||||
|
||||
}
|
||||
|
|
@ -1,135 +0,0 @@
|
|||
<?php
|
||||
//****************************************************************************
|
||||
// phpDatabase 2.1
|
||||
//****************************************************************************
|
||||
// Author: Maxim Poltarak <maxx at e dash taller dot net>
|
||||
// Category: Databases
|
||||
//****************************************************************************
|
||||
// The lib is FREEWARE. This means you may use it anywhere you want, you may
|
||||
// do anything with it. The Author mentioned above is NOT responsible for any
|
||||
// consequences of using this library.
|
||||
// If you don't agree with this, you MAY NOT use the lib!
|
||||
//****************************************************************************
|
||||
// All improvings, feature requests, bug reports, etc. are gladly accepted.
|
||||
//****************************************************************************
|
||||
// Note: For best viewing of the code Tab size 4 is recommended
|
||||
//****************************************************************************
|
||||
|
||||
class Tree_Database
|
||||
{
|
||||
var $link;
|
||||
var $db;
|
||||
var $host, $user, $pass;
|
||||
|
||||
function CDatabase($db, $host = "localhost", $user = "", $pass = "")
|
||||
{
|
||||
$this->db = $db;
|
||||
$this->host = $host;
|
||||
$this->user = $user;
|
||||
$this->pass = $pass;
|
||||
$str = "host={$host} port=5432 dbname={$db} user={$user} password={$pass}";
|
||||
$this->link = pg_connect($str);
|
||||
}
|
||||
|
||||
function query($sql)
|
||||
{
|
||||
if (!$this->link) return 0;
|
||||
return pg_query($this->link, $sql);
|
||||
}
|
||||
|
||||
function affected_rows()
|
||||
{
|
||||
return pg_affected_rows($this->link);
|
||||
}
|
||||
|
||||
function num_rows($q)
|
||||
{
|
||||
return pg_num_rows($q);
|
||||
}
|
||||
|
||||
function fetch_array($q) // fetchAll
|
||||
{
|
||||
return pg_fetch_array($q, NULL);
|
||||
}
|
||||
|
||||
function fetch_object($q) // fetchObject
|
||||
{
|
||||
return pg_fetch_object($q);
|
||||
}
|
||||
/* function data_seek($q, $n) {
|
||||
return pg_data_seek($q, $n);
|
||||
}
|
||||
*/
|
||||
|
||||
function free_result($q)
|
||||
{
|
||||
return pg_free_result($q);
|
||||
}
|
||||
|
||||
function insert_id($seq)
|
||||
{
|
||||
$query = "SELECT currval('$seq')";
|
||||
$res = $this->query($query);
|
||||
$row = pg_fetch_array($res, NULL, PGSQL_ASSOC);
|
||||
pg_free_result($res);
|
||||
return ($row) ? $row['currval'] : 0;
|
||||
}
|
||||
|
||||
function error()
|
||||
{
|
||||
return pg_last_error($this->link);
|
||||
}
|
||||
|
||||
function error_die($msg = '')
|
||||
{
|
||||
die(((empty($msg)) ? '' : $msg . ': ') . $this->error());
|
||||
}
|
||||
|
||||
function sql2var($sql)
|
||||
{
|
||||
|
||||
if ((empty($sql)) || (!($query = $this->query($sql)))) return false;
|
||||
|
||||
if ($this->num_rows($query) < 1) return false;
|
||||
return $this->result2var($query);
|
||||
}
|
||||
|
||||
function result2var($q)
|
||||
{
|
||||
|
||||
if (!($Data = $this->fetch_array($q))) return false;
|
||||
$this->free_result($q);
|
||||
|
||||
foreach($Data as $k => $v) $GLOBALS[$k] = $v;
|
||||
return true;
|
||||
}
|
||||
|
||||
/*function sql2array($sql, $keyField = '')
|
||||
{
|
||||
|
||||
if ((empty($sql)) || (!($query = $this->query($sql)))) return false;
|
||||
|
||||
if ($this->num_rows($query) < 1) return false;
|
||||
return $this->result2array($query, $keyField);
|
||||
}*/
|
||||
|
||||
function result2array($q, $keyField = '')
|
||||
{
|
||||
$Result = array();
|
||||
while ($Data = $this->fetch_array($q))
|
||||
if (empty($keyField)) $Result[] = $Data;
|
||||
else $Result[$Data[$keyField]] = $Data;
|
||||
$this->free_result($q);
|
||||
return $Result;
|
||||
}
|
||||
|
||||
/*function list_tables()
|
||||
{
|
||||
return mysql_list_tables($this->db, $this->link);
|
||||
}
|
||||
|
||||
function list_fields($table_name)
|
||||
{
|
||||
return mysql_list_fields($this->db, $table_name, $this->link);
|
||||
}*/
|
||||
};
|
||||
|
|
@ -1,79 +0,0 @@
|
|||
<?php
|
||||
|
||||
/**
|
||||
* Сортировка дерева в представлении Nested Set
|
||||
* Для дерева которое хранится в базе данных используя представление Nested Set нет возможности отсортировать элементы дерева по
|
||||
* произвольному полю. Поэтому после извлечения дерева из базы данных оно преобразуется в обычное представление сортируется и обратно
|
||||
*
|
||||
* Пример:
|
||||
* $sort = new NestedSetSort();
|
||||
* $data = $sort->sortBy($data, 'name');
|
||||
*/
|
||||
class Tree_Sort {
|
||||
private $data = array();
|
||||
private $result = array();
|
||||
private $sortBy = '';
|
||||
|
||||
public function __construct() {
|
||||
}
|
||||
|
||||
// Преобразуем Nested Set в дерево и сортируем
|
||||
private function listTree(array $tree, $offset, $level) {
|
||||
$result = array();
|
||||
for ($i = $offset; $i < sizeof($tree); $i++) {
|
||||
$leaf = $tree[$i];
|
||||
$clevel = $leaf['cat_level'];
|
||||
if ($clevel == $level) {
|
||||
$result [] = array($i);
|
||||
} else if ($clevel > $level) {
|
||||
list($subtree, $i) = $this->listTree($tree, $i, $clevel);
|
||||
$i--;
|
||||
$result[sizeof($result) - 1][1] = $subtree;
|
||||
} else {
|
||||
$this->sortList($result, $tree);
|
||||
return array($result, $i);
|
||||
}
|
||||
}
|
||||
$this->sortList($result, $tree);
|
||||
return array($result, $i);
|
||||
}
|
||||
|
||||
// Сравнение двух элементов
|
||||
private function compare($a, $b) {
|
||||
$a1 = $this->data[$a[0]][$this->sortBy];
|
||||
$b1 = $this->data[$b[0]][$this->sortBy];
|
||||
return strcmp($a1, $b1);
|
||||
}
|
||||
|
||||
// Сортировка списка
|
||||
private function sortList(array &$list, $data) {
|
||||
usort($list, array($this, 'compare'));
|
||||
}
|
||||
|
||||
// Создает дерево в виде списка
|
||||
private function reorder(array $tree) {
|
||||
foreach($tree as $node) {
|
||||
$this->result[] = $this->data[$node[0]];
|
||||
if (isset($node[1])) {
|
||||
$this->reorder($node[1]);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public function sortBy0(array $data, $sortBy)
|
||||
{
|
||||
$this->data = $data;
|
||||
$this->sortBy = $sortBy;
|
||||
$order = $this->listTree($data, 0, 0);
|
||||
return $order[0];
|
||||
}
|
||||
|
||||
// Сортировка по заданному полю
|
||||
public function sortBy(array $data, $sortBy) {
|
||||
$this->data = $data;
|
||||
$this->sortBy = $sortBy;
|
||||
$order = $this->listTree($data, 0, 0);
|
||||
$this->reorder($order[0]);
|
||||
return $this->result;
|
||||
}
|
||||
}
|
||||
12
src/UTF8.php
Normal file
12
src/UTF8.php
Normal file
|
|
@ -0,0 +1,12 @@
|
|||
<?php
|
||||
|
||||
class UTF8 {
|
||||
static function str_split($str, $split_length = 1) {
|
||||
$split_length = (int) $split_length;
|
||||
|
||||
$matches = array();
|
||||
preg_match_all('/.{'.$split_length.'}|[^\x00]{1,'.$split_length.'}$/us', $str, $matches);
|
||||
|
||||
return $matches[0];
|
||||
}
|
||||
}
|
||||
14
src/Validator/Rule/FileName.php
Normal file
14
src/Validator/Rule/FileName.php
Normal file
|
|
@ -0,0 +1,14 @@
|
|||
<?php
|
||||
|
||||
class Validator_Rule_FileName extends Validator_Rule_Abstract {
|
||||
|
||||
public function getErrorMsg()
|
||||
{
|
||||
return 'Название файла может содержать только символы латиницы в нижнем регистре и цифры';
|
||||
}
|
||||
|
||||
public function isValid(Collection $container, $status = null)
|
||||
{
|
||||
return Path::isName($container->get($this->field));
|
||||
}
|
||||
}
|
||||
|
|
@ -1,5 +1,7 @@
|
|||
<?php
|
||||
|
||||
///<reference path="rule/notnull.php"/>
|
||||
|
||||
/**
|
||||
* Проверка коллекции
|
||||
*/
|
||||
|
|
@ -66,8 +68,7 @@ class Validator_Validator
|
|||
}
|
||||
}
|
||||
|
||||
public function addRule(&$rule)
|
||||
{
|
||||
public function addRule(/*.any.*/&$rule) {
|
||||
if (is_array($rule)) {
|
||||
$this->chain = array_merge($this->chain, $rule);
|
||||
} else {
|
||||
|
|
|
|||
73
src/View/Page.php
Normal file
73
src/View/Page.php
Normal file
|
|
@ -0,0 +1,73 @@
|
|||
<?php
|
||||
|
||||
class View_Page extends View_View
|
||||
{
|
||||
private $counter;
|
||||
public $text;
|
||||
|
||||
function __construct($data)
|
||||
{
|
||||
// Вставка компонентов на странице
|
||||
$pattern = '/<(\w+)(\s+[a-zA-Z\-]+=\"[^\"]*\")*\s+tal:replace="structure\s+component:([^\"]*)"[^>]*>/u';
|
||||
$matches = array();
|
||||
preg_match_all($pattern, $data, $matches, PREG_OFFSET_CAPTURE, 0);
|
||||
|
||||
$split = array();
|
||||
$offset = 0;
|
||||
foreach ($matches[0] as $key => $match) {
|
||||
$text = $this->fixHTML(substr($data, $offset, $match[1] - $offset));
|
||||
if (trim($text)) {
|
||||
$split[] = array('type' => 'page-text', 'content' => $text, 'component' => '', 'module' => '');
|
||||
}
|
||||
$offset = $match[1] + strlen($match[0]);
|
||||
$split[] = $this->replaceContent($matches[3][$key][0], $matches[3][$key][1]);
|
||||
}
|
||||
$text = $this->fixHTML(substr($data, $offset));
|
||||
if (trim($text)) {
|
||||
$split[] = array('type' => 'page-text', 'content' => $text, 'component' => '', 'module' => '');
|
||||
}
|
||||
|
||||
$this->text = $this->merge($split);
|
||||
}
|
||||
|
||||
function fixHTML($fragment) {
|
||||
return $fragment;
|
||||
}
|
||||
|
||||
function merge($data) {
|
||||
if (count($data) == 0) {
|
||||
$data[] = array('type' => 'page-text', 'content' =>"<p>Добавьте текст<p>", 'component' => '', 'module' => '');
|
||||
}
|
||||
$result = array();
|
||||
foreach($data as $key => $part) {
|
||||
$result[] = $part['content'];
|
||||
}
|
||||
return implode("", $result);
|
||||
}
|
||||
|
||||
function replaceContent($match, $offset)
|
||||
{
|
||||
//$result = phptal_component($match, $offset);
|
||||
|
||||
//*
|
||||
global $db, $registry; // Нужно как-то передавать параметры
|
||||
|
||||
$component = Controller_Component::loadComponent($match, $db, $registry);
|
||||
$req = new HttpRequest();
|
||||
unset($req['active_page']);
|
||||
|
||||
$info = $component->getInfo();
|
||||
$result = $component->execute($req);
|
||||
|
||||
if (is_string($result)) {
|
||||
return array('type' => 'page-component', 'content' => $result, 'component' => $match);
|
||||
} else {
|
||||
$this->setView('view' . $this->counter++, $result);
|
||||
return array('type' => 'page-component', 'content' => $result->execute(), 'component' => $match);
|
||||
}
|
||||
}
|
||||
|
||||
function execute() {
|
||||
return $this->text;
|
||||
}
|
||||
}
|
||||
48
src/View/Plain.php
Normal file
48
src/View/Plain.php
Normal file
|
|
@ -0,0 +1,48 @@
|
|||
<?php
|
||||
|
||||
// Класс отображения
|
||||
// CompositeView !! Composite pattern
|
||||
|
||||
/**
|
||||
* @package system.view
|
||||
*/
|
||||
class View_Plain
|
||||
{
|
||||
protected $document;
|
||||
protected $values = array();
|
||||
|
||||
public function __construct ($document)
|
||||
{
|
||||
$this->document = $document;
|
||||
}
|
||||
|
||||
public function set($key, $value)
|
||||
{
|
||||
$this->values[$key] = $value;
|
||||
}
|
||||
|
||||
public function import($list)
|
||||
{
|
||||
$this->values = array_merge($this->values, $list);
|
||||
}
|
||||
|
||||
public function __set($key, $value)
|
||||
{
|
||||
$this->set($key, $value);
|
||||
}
|
||||
|
||||
public function execute()
|
||||
{
|
||||
$result = $this->values;
|
||||
return self::getTemplateContent ($this->document, $result);
|
||||
}
|
||||
|
||||
static function getTemplateContent($document, $result)
|
||||
{
|
||||
ob_start ();
|
||||
include ($document);
|
||||
$content = ob_get_contents ();
|
||||
ob_clean ();
|
||||
return $content;
|
||||
}
|
||||
}
|
||||
|
|
@ -1,40 +1,203 @@
|
|||
<?php
|
||||
|
||||
// Класс отображения
|
||||
// CompositeView !! Composite pattern
|
||||
|
||||
// View_Top => View_Base + View_List + View_Template
|
||||
class View_View
|
||||
{
|
||||
protected $document;
|
||||
protected $values;
|
||||
protected $_section = array(); // Вложенные шаблоны
|
||||
// Блоки
|
||||
protected $_stylesheet = array(); // Массив стилей текущего шаблона
|
||||
protected $_script = array(); // Массив скриптов текущего шаблона
|
||||
protected $_scriptstring = array();
|
||||
protected $_startup = array();
|
||||
protected $_values = array();
|
||||
|
||||
public function __construct ($document)
|
||||
{
|
||||
$this->document = $document;
|
||||
protected $_title = null; // Заголовок текущего шаблона
|
||||
|
||||
public $active_module;
|
||||
public $module_action;
|
||||
|
||||
public $suggestions; //подсказки
|
||||
|
||||
public $alias = array();
|
||||
public $codeGenerator = null;
|
||||
public $parent_view = null;
|
||||
|
||||
function __construct() {
|
||||
}
|
||||
|
||||
public function set($key, $value)
|
||||
/**
|
||||
* Связывет переменную с вложенным шаблоном
|
||||
*
|
||||
* @param string $section переменная шаблона
|
||||
* @param CompositeView $view вложенный шаблон
|
||||
*/
|
||||
public function setView($section, View_View $view)
|
||||
{
|
||||
$this->values[$key] = $value;
|
||||
$this->_section [$section] = $view;
|
||||
$view->parent_view = $this;
|
||||
}
|
||||
|
||||
public function __set($key, $value)
|
||||
public function assignValues($values)
|
||||
{
|
||||
$this->set($key, $value);
|
||||
$this->_values = $values;
|
||||
$this->_values["suggestions"] = $this->suggestions;
|
||||
}
|
||||
|
||||
public function jGrowl($message, $args)
|
||||
{
|
||||
$this->addScriptRaw('$.jGrowl("' . $message . '", ' . json_encode($args) . ");\n", true);
|
||||
}
|
||||
|
||||
public function setGlobal($name, $args)
|
||||
{
|
||||
$this->addScriptRaw("var " . $name . " = " . json_encode($args) . ";\n", false);
|
||||
}
|
||||
|
||||
/**
|
||||
* Добавляет скипт к текущему шаблону
|
||||
*
|
||||
* @param string $name путь к скрипту
|
||||
*/
|
||||
public function addScript($name)
|
||||
{
|
||||
$output = $this->resolveName($this->alias, $name);
|
||||
$this->_script [] = $output;
|
||||
}
|
||||
|
||||
/**
|
||||
* Добавляет код скипта к текущему шаблону
|
||||
*
|
||||
* @param string $name строка javascript кода
|
||||
*/
|
||||
public function addScriptRaw($name, $startup = false)
|
||||
{
|
||||
if ($startup) {
|
||||
$this->_startup [] = $name;
|
||||
} else {
|
||||
$this->_scriptstring [] = $name;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Добавляет стили к текущему шаблону
|
||||
*
|
||||
* @param string $name путь к стилю
|
||||
*/
|
||||
public function addStyleSheet($name)
|
||||
{
|
||||
$output = $this->resolveName($this->alias, $name);
|
||||
$this->_stylesheet [] = $output;
|
||||
}
|
||||
|
||||
/**
|
||||
* Рекурсивно извлекает из значение свойства обьекта
|
||||
*
|
||||
* @param string $list Имя свойства
|
||||
* @param boolean $flatten
|
||||
*/
|
||||
protected function doTree($list, $flatten = true)
|
||||
{
|
||||
$result = ($flatten == true) ? $this->$list : array($this->$list);
|
||||
foreach ($this->_section as $value) {
|
||||
if (is_object($value)) {
|
||||
if ($list == '_script' || $list == '_stylesheet') {
|
||||
$result = array_merge($result, $value->doTree($list, $flatten));
|
||||
} else {
|
||||
$result = array_merge($value->doTree($list, $flatten), $result);
|
||||
}
|
||||
}
|
||||
}
|
||||
return $result;
|
||||
}
|
||||
|
||||
/*abstract*/ public function set($key, $value)
|
||||
{
|
||||
}
|
||||
|
||||
/**
|
||||
* Обработка всех вложенных шаблонов
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
public function execute()
|
||||
{
|
||||
$result = $this->values;
|
||||
return self::getTemplateContent ($this->document, $result);
|
||||
foreach ($this->_section as $key => $value) {
|
||||
$this->set($key, (is_object($value)) ? $value->execute() : $value); // ?
|
||||
}
|
||||
}
|
||||
|
||||
static function getTemplateContent($document, $result)
|
||||
/**
|
||||
* Установка заголовка шаблона
|
||||
*
|
||||
* @param string $title
|
||||
*/
|
||||
public function setTitle($title)
|
||||
{
|
||||
ob_start ();
|
||||
include ($document);
|
||||
$result = ob_get_contents ();
|
||||
ob_clean ();
|
||||
$this->_title = $title;
|
||||
}
|
||||
|
||||
protected function isNotNull($title)
|
||||
{
|
||||
return $title !== null;
|
||||
}
|
||||
|
||||
function setAlias($alias)
|
||||
{
|
||||
$this->alias = $alias;
|
||||
}
|
||||
|
||||
function addAlias($name, $path)
|
||||
{
|
||||
$this->alias[$name] = $path;
|
||||
$this->set($name, $path);
|
||||
}
|
||||
|
||||
function find_file($pathlist, $file) {
|
||||
foreach($pathlist as $key => $www) {
|
||||
if (file_exists($key . '/' . $file)) {
|
||||
return $www . '/' . $file;
|
||||
}
|
||||
}
|
||||
throw new Exception("file not found: $file");
|
||||
}
|
||||
|
||||
function resolveName($alias, $file) {
|
||||
list($type, $filename) = explode(":", $file, 2);
|
||||
|
||||
// Сделать поиск а не просто замену папки при совпадении имени
|
||||
if (is_array($alias[$type])) {
|
||||
$output = $this->find_file($alias[$type], $filename);
|
||||
} else {
|
||||
$output = $alias[$type] . '/' . $filename;
|
||||
}
|
||||
return $output;
|
||||
}
|
||||
|
||||
function loadImports($importFile)
|
||||
{
|
||||
$types = array(
|
||||
'js' => array($this, 'addScript'),
|
||||
'css' => array($this, 'addStyleSheet')
|
||||
);
|
||||
// Подключение стилей и скриптов
|
||||
if (file_exists($importFile)) {
|
||||
$files = file($importFile);
|
||||
foreach ($files as $file) {
|
||||
// Получить расширение вместо strpos
|
||||
$file = trim($file);
|
||||
if (!empty($file)) {
|
||||
$ext = pathinfo($file, PATHINFO_EXTENSION);
|
||||
call_user_func($types[$ext], $file);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public function resolveAllNames($alias, $list) {
|
||||
$result = array();
|
||||
foreach($list as $item) {
|
||||
$result [] = $this->resolveName($alias, $item);
|
||||
}
|
||||
return $result;
|
||||
}
|
||||
}
|
||||
13
src/View/list.php
Normal file
13
src/View/list.php
Normal file
|
|
@ -0,0 +1,13 @@
|
|||
<?php
|
||||
|
||||
class View_List extends View_View
|
||||
{
|
||||
function execute()
|
||||
{
|
||||
$result = array();
|
||||
foreach ($this->_section as $key => $value) {
|
||||
$result [] = $value->execute();
|
||||
}
|
||||
return $result;
|
||||
}
|
||||
}
|
||||
|
|
@ -1,26 +0,0 @@
|
|||
<?php
|
||||
|
||||
$settings = array
|
||||
(
|
||||
0 => '',
|
||||
1 => 'Город Ярославль',
|
||||
2 => 'Большесельский район',
|
||||
3 => 'Борисоглебский район',
|
||||
4 => 'Брейтовский район',
|
||||
5 => 'Гаврилов-Ямский район',
|
||||
6 => 'Даниловский район',
|
||||
7 => 'Любимский район',
|
||||
8 => 'Мышкинский район',
|
||||
9 => 'Некоузский район',
|
||||
10 => 'Некрасовский район',
|
||||
11 => 'Переславский район',
|
||||
12 => 'Первомайский район',
|
||||
13 => 'Пошехонский район',
|
||||
14 => 'Ростовский район',
|
||||
15 => 'Рыбинский район',
|
||||
16 => 'Тутаевский район',
|
||||
17 => 'Угличский район',
|
||||
18 => 'Ярославский район',
|
||||
19 => 'Город Переславль',
|
||||
20 => 'Город Рыбинск'
|
||||
);
|
||||
|
|
@ -1,14 +0,0 @@
|
|||
<?php
|
||||
|
||||
$settings = array(
|
||||
0 => '',
|
||||
1 => 'г.',
|
||||
2 => 'с.',
|
||||
3 => 'п.',
|
||||
4 => 'д.',
|
||||
5 => 'пгт.',
|
||||
6 => 'р.п.',
|
||||
7 => 'ст.',
|
||||
8 => 'а.'
|
||||
);
|
||||
|
||||
|
|
@ -1,14 +0,0 @@
|
|||
<?php
|
||||
|
||||
// Массив типов поселений
|
||||
$settings = array(
|
||||
// 0 => '',
|
||||
1 => 'город',
|
||||
2 => 'село',
|
||||
3 => 'поселок',
|
||||
4 => 'деревня',
|
||||
5 => 'поселок городского типа',
|
||||
6 => 'рабочий поселок',
|
||||
7 => 'станица',
|
||||
8 => 'аул'
|
||||
);
|
||||
|
|
@ -1,196 +0,0 @@
|
|||
<?php
|
||||
/**
|
||||
* http://www.w3schools.com/media/media_mimeref.asp
|
||||
*/
|
||||
|
||||
$settings = array (
|
||||
"" => "application/octet-stream",
|
||||
"323" => "text/h323",
|
||||
"acx" => "application/internet-property-stream",
|
||||
"ai" => "application/postscript",
|
||||
"aif" => "audio/x-aiff",
|
||||
"aifc" => "audio/x-aiff",
|
||||
"aiff" => "audio/x-aiff",
|
||||
"asf" => "video/x-ms-asf",
|
||||
"asr" => "video/x-ms-asf",
|
||||
"asx" => "video/x-ms-asf",
|
||||
"au" => "audio/basic",
|
||||
"avi" => "video/x-msvideo",
|
||||
"axs" => "application/olescript",
|
||||
"bas" => "text/plain",
|
||||
"bcpio" => "application/x-bcpio",
|
||||
"bin" => "application/octet-stream",
|
||||
"bmp" => "image/bmp",
|
||||
"c" => "text/plain",
|
||||
"cat" => "application/vnd.ms-pkiseccat",
|
||||
"cdf" => "application/x-cdf",
|
||||
"cer" => "application/x-x509-ca-cert",
|
||||
"class" => "application/octet-stream",
|
||||
"clp" => "application/x-msclip",
|
||||
"cmx" => "image/x-cmx",
|
||||
"cod" => "image/cis-cod",
|
||||
"cpio" => "application/x-cpio",
|
||||
"crd" => "application/x-mscardfile",
|
||||
"crl" => "application/pkix-crl",
|
||||
"crt" => "application/x-x509-ca-cert",
|
||||
"csh" => "application/x-csh",
|
||||
"css" => "text/css",
|
||||
"dcr" => "application/x-director",
|
||||
"der" => "application/x-x509-ca-cert",
|
||||
"dir" => "application/x-director",
|
||||
"dll" => "application/x-msdownload",
|
||||
"dms" => "application/octet-stream",
|
||||
"doc" => "application/msword",
|
||||
"dot" => "application/msword",
|
||||
"dvi" => "application/x-dvi",
|
||||
"dxr" => "application/x-director",
|
||||
"eps" => "application/postscript",
|
||||
"etx" => "text/x-setext",
|
||||
"evy" => "application/envoy",
|
||||
"exe" => "application/octet-stream",
|
||||
"fif" => "application/fractals",
|
||||
"flr" => "x-world/x-vrml",
|
||||
"gif" => "image/gif",
|
||||
"gtar" => "application/x-gtar",
|
||||
"gz" => "application/x-gzip",
|
||||
"h" => "text/plain",
|
||||
"hdf" => "application/x-hdf",
|
||||
"hlp" => "application/winhlp",
|
||||
"hqx" => "application/mac-binhex40",
|
||||
"hta" => "application/hta",
|
||||
"htc" => "text/x-component",
|
||||
"htm" => "text/html",
|
||||
"html" => "text/html",
|
||||
"htt" => "text/webviewhtml",
|
||||
"ico" => "image/x-icon",
|
||||
"ief" => "image/ief",
|
||||
"iii" => "application/x-iphone",
|
||||
"ins" => "application/x-internet-signup",
|
||||
"isp" => "application/x-internet-signup",
|
||||
"jfif" => "image/pipeg",
|
||||
"jpe" => "image/jpeg",
|
||||
"jpeg" => "image/jpeg",
|
||||
"jpg" => "image/jpeg",
|
||||
"js" => "application/x-javascript",
|
||||
"latex" => "application/x-latex",
|
||||
"lha" => "application/octet-stream",
|
||||
"lsf" => "video/x-la-asf",
|
||||
"lsx" => "video/x-la-asf",
|
||||
"lzh" => "application/octet-stream",
|
||||
"m13" => "application/x-msmediaview",
|
||||
"m14" => "application/x-msmediaview",
|
||||
"m3u" => "audio/x-mpegurl",
|
||||
"man" => "application/x-troff-man",
|
||||
"mdb" => "application/x-msaccess",
|
||||
"me" => "application/x-troff-me",
|
||||
"mht" => "message/rfc822",
|
||||
"mhtml" => "message/rfc822",
|
||||
"mid" => "audio/mid",
|
||||
"mny" => "application/x-msmoney",
|
||||
"mov" => "video/quicktime",
|
||||
"movie" => "video/x-sgi-movie",
|
||||
"mp2" => "video/mpeg",
|
||||
"mp3" => "audio/mpeg",
|
||||
"mpa" => "video/mpeg",
|
||||
"mpe" => "video/mpeg",
|
||||
"mpeg" => "video/mpeg",
|
||||
"mpg" => "video/mpeg",
|
||||
"mpp" => "application/vnd.ms-project",
|
||||
"mpv2" => "video/mpeg",
|
||||
"ms" => "application/x-troff-ms",
|
||||
"mvb" => "application/x-msmediaview",
|
||||
"nws" => "message/rfc822",
|
||||
"oda" => "application/oda",
|
||||
"p10" => "application/pkcs10",
|
||||
"p12" => "application/x-pkcs12",
|
||||
"p7b" => "application/x-pkcs7-certificates",
|
||||
"p7c" => "application/x-pkcs7-mime",
|
||||
"p7m" => "application/x-pkcs7-mime",
|
||||
"p7r" => "application/x-pkcs7-certreqresp",
|
||||
"p7s" => "application/x-pkcs7-signature",
|
||||
"pbm" => "image/x-portable-bitmap",
|
||||
"pdf" => "application/pdf",
|
||||
"pfx" => "application/x-pkcs12",
|
||||
"pgm" => "image/x-portable-graymap",
|
||||
"pko" => "application/ynd.ms-pkipko",
|
||||
"pma" => "application/x-perfmon",
|
||||
"pmc" => "application/x-perfmon",
|
||||
"pml" => "application/x-perfmon",
|
||||
"pmr" => "application/x-perfmon",
|
||||
"pmw" => "application/x-perfmon",
|
||||
"pnm" => "image/x-portable-anymap",
|
||||
"pot," => "application/vnd.ms-powerpoint",
|
||||
"ppm" => "image/x-portable-pixmap",
|
||||
"pps" => "application/vnd.ms-powerpoint",
|
||||
"ppt" => "application/vnd.ms-powerpoint",
|
||||
"prf" => "application/pics-rules",
|
||||
"ps" => "application/postscript",
|
||||
"pub" => "application/x-mspublisher",
|
||||
"qt" => "video/quicktime",
|
||||
"ra" => "audio/x-pn-realaudio",
|
||||
"ram" => "audio/x-pn-realaudio",
|
||||
"ras" => "image/x-cmu-raster",
|
||||
"rgb" => "image/x-rgb",
|
||||
"rmi" => "audio/mid",
|
||||
"roff" => "application/x-troff",
|
||||
"rtf" => "application/rtf",
|
||||
"rtx" => "text/richtext",
|
||||
"scd" => "application/x-msschedule",
|
||||
"sct" => "text/scriptlet",
|
||||
"setpay" => "application/set-payment-initiation",
|
||||
"setreg" => "application/set-registration-initiation",
|
||||
"sh" => "application/x-sh",
|
||||
"shar" => "application/x-shar",
|
||||
"sit" => "application/x-stuffit",
|
||||
"snd" => "audio/basic",
|
||||
"spc" => "application/x-pkcs7-certificates",
|
||||
"spl" => "application/futuresplash",
|
||||
"src" => "application/x-wais-source",
|
||||
"sst" => "application/vnd.ms-pkicertstore",
|
||||
"stl" => "application/vnd.ms-pkistl",
|
||||
"stm" => "text/html",
|
||||
"svg" => "image/svg+xml",
|
||||
"sv4cpio" => "application/x-sv4cpio",
|
||||
"sv4crc" => "application/x-sv4crc",
|
||||
"swf" => "application/x-shockwave-flash",
|
||||
"t" => "application/x-troff",
|
||||
"tar" => "application/x-tar",
|
||||
"tcl" => "application/x-tcl",
|
||||
"tex" => "application/x-tex",
|
||||
"texi" => "application/x-texinfo",
|
||||
"texinfo" => "application/x-texinfo",
|
||||
"tgz" => "application/x-compressed",
|
||||
"tif" => "image/tiff",
|
||||
"tiff" => "image/tiff",
|
||||
"tr" => "application/x-troff",
|
||||
"trm" => "application/x-msterminal",
|
||||
"tsv" => "text/tab-separated-values",
|
||||
"txt" => "text/plain",
|
||||
"uls" => "text/iuls",
|
||||
"ustar" => "application/x-ustar",
|
||||
"vcf" => "text/x-vcard",
|
||||
"vrml" => "x-world/x-vrml",
|
||||
"wav" => "audio/x-wav",
|
||||
"wcm" => "application/vnd.ms-works",
|
||||
"wdb" => "application/vnd.ms-works",
|
||||
"wks" => "application/vnd.ms-works",
|
||||
"wmf" => "application/x-msmetafile",
|
||||
"wps" => "application/vnd.ms-works",
|
||||
"wri" => "application/x-mswrite",
|
||||
"wrl" => "x-world/x-vrml",
|
||||
"wrz" => "x-world/x-vrml",
|
||||
"xaf" => "x-world/x-vrml",
|
||||
"xbm" => "image/x-xbitmap",
|
||||
"xla" => "application/vnd.ms-excel",
|
||||
"xlc" => "application/vnd.ms-excel",
|
||||
"xlm" => "application/vnd.ms-excel",
|
||||
"xls" => "application/vnd.ms-excel",
|
||||
"xlt" => "application/vnd.ms-excel",
|
||||
"xlw" => "application/vnd.ms-excel",
|
||||
"xof" => "x-world/x-vrml",
|
||||
"xpm" => "image/x-xpixmap",
|
||||
"xwd" => "image/x-xwindowdump",
|
||||
"z" => "application/x-compress",
|
||||
"zip" => "application/zip",
|
||||
);
|
||||
|
||||
|
|
@ -1,35 +0,0 @@
|
|||
<?php
|
||||
// В ОКАТО приняты следующие сокращения:
|
||||
// http://www.consultant.ru/online/base/?req=doc;base=LAW;n=62484
|
||||
|
||||
$settings = array (
|
||||
"р-н" => "район",
|
||||
"г" => "город",
|
||||
"пгт" => "поселок городского типа",
|
||||
"рп" => "рабочий поселок",
|
||||
"кп" => "курортный поселок",
|
||||
"к" => "кишлак",
|
||||
"пс" => "поселковый совет",
|
||||
"сс" => "сельсовет",
|
||||
"смн" => "сомон",
|
||||
"вл" => "волость",
|
||||
"дп" => "дачный поселковый совет",
|
||||
"п" => "поселок сельского типа",
|
||||
"нп" => "населенный пункт",
|
||||
"п. ст" => "поселок при станции",
|
||||
"ж/д ст" => "железнодорожная станция",
|
||||
"с" => "село",
|
||||
"м" => "местечко",
|
||||
"д" => "деревня",
|
||||
"сл" => "слобода",
|
||||
"ст" => "станция",
|
||||
"ст-ца" => "станица",
|
||||
"х" => "хутор",
|
||||
"у" => "улус",
|
||||
"рзд" => "разъезд",
|
||||
"клх" => "колхоз",
|
||||
"им" => "имени",
|
||||
"свх" => "совхоз",
|
||||
"зим" => "зимовье",
|
||||
);
|
||||
|
||||
|
|
@ -1,91 +0,0 @@
|
|||
<?php
|
||||
|
||||
$settings = array (
|
||||
0 => '',
|
||||
2 => 'Алтайский край',
|
||||
3 => 'Амурская область',
|
||||
4 => 'Архангельская область',
|
||||
5 => 'Астраханская область',
|
||||
6 => 'Белгородская область',
|
||||
7 => 'Брянская область',
|
||||
8 => 'Владимирская область',
|
||||
9 => 'Волгоградская область',
|
||||
10 => 'Вологодская область',
|
||||
11 => 'Воронежская область',
|
||||
12 => 'г. Москва',
|
||||
13 => 'г. Санкт-Петербург',
|
||||
14 => 'Еврейская автономная область',
|
||||
84 => 'Забайкальский край',
|
||||
15 => 'Ивановская область',
|
||||
16 => 'Иркутская область',
|
||||
17 => 'Кабардино-Балкарская Республика',
|
||||
18 => 'Калининградская область',
|
||||
19 => 'Калужская область',
|
||||
20 => 'Камчатский край',
|
||||
21 => 'Карачаево-Черкесская Республика',
|
||||
22 => 'Кемеровская область',
|
||||
23 => 'Кировская область',
|
||||
28 => 'Костромская область',
|
||||
29 => 'Краснодарский край',
|
||||
30 => 'Красноярский край',
|
||||
31 => 'Курганская область',
|
||||
32 => 'Курская область',
|
||||
33 => 'Ленинградская область',
|
||||
34 => 'Липецкая область',
|
||||
35 => 'Магаданская область',
|
||||
36 => 'Московская область',
|
||||
37 => 'Мурманская область',
|
||||
38 => 'Ненецкий автономный округ',
|
||||
39 => 'Нижегородская область',
|
||||
40 => 'Новгородская область',
|
||||
41 => 'Новосибирская область',
|
||||
42 => 'Омская область',
|
||||
43 => 'Оренбургская область',
|
||||
44 => 'Орловская область',
|
||||
45 => 'Пензенская область',
|
||||
46 => 'Пермский край',
|
||||
47 => 'Приморский край',
|
||||
48 => 'Псковская область',
|
||||
49 => 'Республика Адыгея',
|
||||
50 => 'Республика Алтай',
|
||||
51 => 'Республика Башкортостан',
|
||||
52 => 'Республика Бурятия',
|
||||
25 => 'Республика Дагестан',
|
||||
26 => 'Республика Ингушетия',
|
||||
53 => 'Республика Калмыкия',
|
||||
54 => 'Республика Карелия',
|
||||
55 => 'Республика Коми',
|
||||
56 => 'Республика Марий Эл',
|
||||
57 => 'Республика Мордовия',
|
||||
58 => 'Республика Саха(Якутия)',
|
||||
59 => 'Республика Северная Осетия-Алания',
|
||||
60 => 'Республика Татарстан',
|
||||
61 => 'Республика Тыва',
|
||||
62 => 'Республика Хакасия',
|
||||
63 => 'Ростовская область',
|
||||
64 => 'Рязанская область',
|
||||
65 => 'Самарская область',
|
||||
66 => 'Саратовская область',
|
||||
67 => 'Сахалинская область',
|
||||
68 => 'Свердловская область',
|
||||
69 => 'Смоленская область',
|
||||
70 => 'Ставропольский край',
|
||||
71 => 'Таймырский (Долгано-Ненецкий) автономный округ',
|
||||
72 => 'Тамбовская область',
|
||||
73 => 'Тверская область',
|
||||
74 => 'Томская область',
|
||||
75 => 'Тульская область',
|
||||
76 => 'Тюменская область',
|
||||
77 => 'Удмуртская Республика',
|
||||
78 => 'Ульяновская область',
|
||||
80 => 'Хабаровский край',
|
||||
81 => 'Ханты-Мансийский автономный округ',
|
||||
82 => 'Челябинская область',
|
||||
83 => 'Чеченская Республика',
|
||||
85 => 'Чувашская Республика',
|
||||
86 => 'Чукотский автономный округ',
|
||||
87 => 'Эвенкийский автономный округ',
|
||||
88 => 'Ямало-Ненецкий автономный округ',
|
||||
89 => 'Ярославская область'
|
||||
);
|
||||
|
||||
|
|
@ -1,32 +0,0 @@
|
|||
<?php
|
||||
|
||||
$settings = array (
|
||||
0 => array('title' => ''),
|
||||
1 => array(
|
||||
'title' => 'Центральный федеральный округ',
|
||||
'short' => 'ЦФО',
|
||||
'regions' => array(6, 7, 8, 11, 12, 15, 19, 28, 32, 34, 36, 44, 64, 69, 72, 73, 75, 89)),
|
||||
2 => array(
|
||||
'title' => 'Южный федеральный округ',
|
||||
'short' => 'ЮФО',
|
||||
'regions' => array(5, 9, 17, 21, 29, 49, 25, 26, 53, 59, 63, 70, 83)),
|
||||
3 => array(
|
||||
'title' => 'Северо-западный федеральный округ',
|
||||
'short' => 'СЗФО',
|
||||
'regions' => array(4, 10, 13, 18, 33, 37, 38, 40, 48, 54, 55)),
|
||||
4 => array(
|
||||
'title' => 'Дальневосточный федеральный округ',
|
||||
'short' => 'ДФО',
|
||||
'regions' => array(3, 14, 20, 35, 47, 58, 67, 80, 86)),
|
||||
5 => array(
|
||||
'title' => 'Сибирский федеральный округ',
|
||||
'short' => 'СФО',
|
||||
'regions' => array(2, 16, 22, 30, 41, 42, 50, 52, 61, 62, 71, 74, 84, 86, 87)),
|
||||
6 => array(
|
||||
'title' => 'Уральский федеральный округ',
|
||||
'short' => 'УФО',
|
||||
'regions' => array(31, 68, 76, 81, 82, 88)),
|
||||
7 => array(
|
||||
'title' => 'Приволжский федеральный округ',
|
||||
'short' => 'ПФО',
|
||||
'regions' => array(23, 39, 43, 45, 46, 51, 56, 57, 60, 65, 66, 77, 78, 85)));
|
||||
41
src/process.php
Normal file
41
src/process.php
Normal file
|
|
@ -0,0 +1,41 @@
|
|||
<?php
|
||||
|
||||
if (!function_exists('str_getcsv')) {
|
||||
function str_getcsv($input, $delimiter = ",", $enclosure = '"', $escape = "\\") {
|
||||
$fiveMBs = 1024;
|
||||
$fp = fopen("php://temp/maxmemory:$fiveMBs", 'r+');
|
||||
if (is_resource($fp)) {
|
||||
fputs($fp, $input);
|
||||
rewind($fp);
|
||||
$data = fgetcsv($fp, 1000, $delimiter, $enclosure);
|
||||
fclose($fp);
|
||||
}
|
||||
return $data;
|
||||
}
|
||||
}
|
||||
|
||||
function process_exists($pid) {
|
||||
if (PHP_OS == 'WINNT') {
|
||||
$processes = explode("\n", shell_exec("tasklist.exe /NH /FO CSV"));
|
||||
foreach($processes as $process) {
|
||||
if ($process != "") {
|
||||
$csv = str_getcsv($process);
|
||||
if ($pid == $csv[1]) return true;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
} else {
|
||||
return file_exists("/proc/$pid");
|
||||
}
|
||||
}
|
||||
|
||||
function create_single_proces($fpid, $fn) {
|
||||
if (file_exists($fpid)) {
|
||||
print_r(realpath($fpid));
|
||||
if (process_exists(file_get_contents($fpid))) {
|
||||
return 1;
|
||||
}
|
||||
}
|
||||
call_user_func($fn);
|
||||
return 0;
|
||||
}
|
||||
33
src/security.php
Normal file
33
src/security.php
Normal file
|
|
@ -0,0 +1,33 @@
|
|||
<?php
|
||||
|
||||
class Security {
|
||||
static function generatePassword($length = 9, $strength = 0) {
|
||||
$vowels = 'aeuy';
|
||||
$consonants = 'bdghjmnpqrstvz';
|
||||
if ($strength & 1) {
|
||||
$consonants .= 'BDGHJLMNPQRSTVWXZ';
|
||||
}
|
||||
if ($strength & 2) {
|
||||
$vowels .= "AEUY";
|
||||
}
|
||||
if ($strength & 4) {
|
||||
$consonants .= '23456789';
|
||||
}
|
||||
if ($strength & 8) {
|
||||
$consonants .= '@#$%';
|
||||
}
|
||||
|
||||
$password = '';
|
||||
$alt = time() % 2;
|
||||
for ($i = 0; $i < $length; $i++) {
|
||||
if ($alt == 1) {
|
||||
$password .= $consonants[(rand() % strlen($consonants))];
|
||||
$alt = 0;
|
||||
} else {
|
||||
$password .= $vowels[(rand() % strlen($vowels))];
|
||||
$alt = 1;
|
||||
}
|
||||
}
|
||||
return $password;
|
||||
}
|
||||
}
|
||||
|
|
@ -4,19 +4,20 @@
|
|||
* Преобразование дерева из модели Plain в массив массивов (Adjacency List)
|
||||
*/
|
||||
|
||||
require_once 'src/functions.php';
|
||||
require_once 'functions.php';
|
||||
|
||||
|
||||
/**
|
||||
* Обходит таблицу как дерево
|
||||
* @param $level Array Уровни вложенности
|
||||
* @param $table Таблица
|
||||
* @param $fn Функция которая применяется к каждой ветке дерева
|
||||
* $fn ($name, $index, $rows, $cc)
|
||||
* @param $name Ключ уровня
|
||||
* @param $index Значение ключа уровня
|
||||
* @param $rows Все столбцы текущго уровня
|
||||
* @parma $cc Столбцы более низкого уровня
|
||||
* $name Ключ уровня
|
||||
* $index Значение ключа уровня
|
||||
* $rows Все столбцы текущго уровня
|
||||
* $cc Столбцы более низкого уровня
|
||||
*
|
||||
* @param Array $level Уровни вложенности
|
||||
* @param array $table Таблица
|
||||
* @param Function $fn Функция которая применяется к каждой ветке дерева
|
||||
*/
|
||||
function tableTreeWalk($level, $table, $fn) {
|
||||
if (empty ($level)) return $table;
|
||||
|
|
|
|||
|
|
@ -47,10 +47,14 @@ function phptal_time ($e)
|
|||
function phptal_component ($expression) {
|
||||
global $db, $registry; // Нужно как-то передавать параметры
|
||||
|
||||
$begin = microtime(true);
|
||||
$component = Controller_Component::loadComponent($expression, $db, $registry);
|
||||
$req = new HttpRequest();
|
||||
|
||||
return $component->execute($req);
|
||||
$result = $component->execute($req);
|
||||
|
||||
echo "<!-- ", $expression, ", ", round(microtime(true) - $begin, 4), "sec -->";
|
||||
return $result;
|
||||
}
|
||||
|
||||
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue