diff --git a/composer.json b/composer.json index 25add6b..de9a023 100644 --- a/composer.json +++ b/composer.json @@ -8,11 +8,8 @@ } ], "autoload": { - "psr-4": { - "ctiso\\": "src/" + "psr-0": { + "": "src/" } - }, - "require": { - "phpmailer/phpmailer": "^6.8.0" } } diff --git a/config.php b/config.php deleted file mode 100644 index 502a2b4..0000000 --- a/config.php +++ /dev/null @@ -1,4 +0,0 @@ -adaptee = $adaptee; } - /** - * @param string $name - * @return mixed - */ public function get($name) { if (is_array ($this->adaptee)) { diff --git a/src/Arr.php b/src/Arr.php index 2fa9187..488d82c 100644 --- a/src/Arr.php +++ b/src/Arr.php @@ -1,16 +1,7 @@ $data - * @param string|int $key - * @param mixed $default - * @return mixed - */ static function get($data, $key, $default = null) { - return $data[$key] ?? $default; + return isset($data[$key]) ? $data[$key] : $default; } } diff --git a/src/Collection.php b/src/Collection.php index 430cc69..1370be3 100644 --- a/src/Collection.php +++ b/src/Collection.php @@ -1,20 +1,21 @@ + * */ -class Collection implements \ArrayAccess +class Collection implements ArrayAccess { - /** @var array */ - protected $data = []; + /** + * Holds collective request data + * + * @var array + */ + protected $data = array(); /** * Преобразование массива в коллекцию * * @param array $data - * @return bool */ public function import(array $data) { @@ -24,8 +25,6 @@ class Collection implements \ArrayAccess /** * Преобразование коллекции в массив - * - * @return array */ public function export() { @@ -33,13 +32,14 @@ class Collection implements \ArrayAccess } /** - + * Store "request data" in GPC order. + * * @param string $key * @param mixed $value * * @return void */ - public function set(string $key, mixed $value) + public function set($key/*: string*/, $value/*: any*/) { $this->data[$key] = $value; } @@ -48,7 +48,7 @@ class Collection implements \ArrayAccess * Read stored "request data" by referencing a key. * * @param string $key - * @param mixed $default + * * @return mixed */ public function get($key, $default = null) @@ -56,114 +56,44 @@ class Collection implements \ArrayAccess return isset($this->data[$key]) && $this->data[$key] != '' ? $this->data[$key] : $default; } - /** - * @param string $key - * @param int $default - * @return int - */ - public function getInt(string $key, int $default = 0): int + public function getInt($key, $default = 0) { - $value = $this->get($key); - - // Фильтруем как целое число - if (is_numeric($value)) { - // Приводим к int, но сначала проверим, что не float с дробной частью - $floatVal = (float)$value; - if (is_finite($floatVal) && floor($floatVal) === $floatVal) { - return (int)$floatVal; - } - } - - return $default; + return (int)$this->get($key, $default); } - /** - * @param string $key - * @param string $default - * @return string - */ - public function getString(string $key, string $default = ''): string + public function getString($key, $default = '') { - $value = $this->get($key); - - if (is_string($value)) { - return $value; - } - - if (is_numeric($value)) { - return (string)$value; - } - - return $default; + return ((string) $this->get($key, $default)); } - /** - * Получает булево значение - * Поддерживает: 1, '1', 'true', 'on', 'yes' → true - * Иначе → false - */ - public function getBool(string $key, bool $default = false): bool - { - $value = $this->get($key); - - if (is_bool($value)) { - return $value; - } - - if (is_string($value)) { - $value = strtolower(trim($value)); - return in_array($value, ['1', 'true', 'on', 'yes'], true); - } - - if (is_numeric($value)) { - return (bool)$value; - } - - return $default; - } - - function getArray(string $key, array $default = []): array { - $result = $this->get($key); - if (is_array($result)) { - return $result; - } - return $default; - } - - - /** - * @param string $key - * @param int $default - * @return int - */ - public function getNat(string $key, int $default = 1): int + public function getNat($key, $default = 1) { $result = (int)$this->get($key, $default); - return (($result > 0) ? $result : $default); + return (($result > 0) ? $result : $default); } - public function clear(): void + public function clear() { - $this->data = []; + $this->data = array(); } - public function offsetSet($key, $value): void + public function offsetSet($key, $value) { $this->data[$key] = $value; } - public function offsetExists($key): bool + public function offsetExists($key) { return isset($this->data[$key]); } - public function offsetUnset($key): void + public function offsetUnset($key) { unset($this->data[$key]); } - public function offsetGet($key): mixed + public function offsetGet($key) { - return $this->data[$key] ?? null; + return isset($this->data[$key]) ? $this->data[$key] : null; } } diff --git a/src/ComponentRequest.php b/src/ComponentRequest.php deleted file mode 100644 index 378c375..0000000 --- a/src/ComponentRequest.php +++ /dev/null @@ -1,51 +0,0 @@ -component_id = $c; - $this->r = $r; - } - - /** - * @param string $key - * @param mixed $default - * @return mixed - */ - function get($key, $default = null) { - if ($key == 'active_page') { - return $this->r->get($key); - } - $arr = $this->r->get($key); - if (!is_null($arr)) { - if (is_array($arr)) { - return Arr::get($arr, $this->component_id, $default); - } else { - return $arr; - } - } - return $default; - } - - /** - * @return string - */ - function getAction() { - return $this->r->getAction(); - } -} diff --git a/src/Connection/HttpRequest.php b/src/Connection/HttpRequest.php index 368feda..ce2f13b 100644 --- a/src/Connection/HttpRequest.php +++ b/src/Connection/HttpRequest.php @@ -1,39 +1,26 @@ method = self::GET; } - + /** * Возвращает заголовок соединения - * @return string */ public function getHeader() { @@ -46,58 +33,47 @@ class HttpRequest $result .= $this->data; return $result; } - + /** * Установка параметров запроса - * @param string $name - * @param string $value + * @parma string $name + * @parma string $value */ - public function setParameter($name, $value): void + public function setParameter($name, $value) { $this->param[$name] = $value; } /** * Метод запроса GET или POST - * @param string $method */ - public function setMethod($method): void + public function setMethod($method) { $this->method = $method; } - /** - * Установка URL - * @param string $url - */ - public function setUrl($url): void + public function setUrl($url) { $this->url = $url; - $host = parse_url($this->url, PHP_URL_HOST); - if (!$host) { - throw new \RuntimeException("Не удалось получить хост"); - } - $this->host = $host; + $this->host = parse_url($this->url, PHP_URL_HOST); } - public function getUrl(): string + public function getUrl() { return $this->url; } /** * Содержание запроса - * @param string $data */ - public function setContent($data): void + public function setContent($data) { - $this->setParameter("Content-length", (string)strlen($data)); + $this->setParameter ("Content-length", strlen($data)); $this->data = $data; } /** * Посылает запрос и возвращает страницу - * @return string|null */ public function getPage() { @@ -110,7 +86,7 @@ class HttpRequest $header = $this->getHeader(); fwrite($socket, $header); - $result = ''; + $result = null; while (! feof($socket)) { $result .= fgets($socket, 128); } @@ -120,12 +96,6 @@ class HttpRequest return null; } - /** - * Получение JSON - * @param string $url - * @param array $data - * @return array - */ static function getJSON($url, $data) { $query = http_build_query($data); $q = $url . '?' . $query; diff --git a/src/Connection/HttpResponse.php b/src/Connection/HttpResponse.php index fad35ab..7f78bb0 100644 --- a/src/Connection/HttpResponse.php +++ b/src/Connection/HttpResponse.php @@ -3,43 +3,32 @@ /** * Обрабатывает HTTP ответ */ -namespace ctiso\Connection; - -class HttpResponse +class Connection_HttpResponse { - /** @var int */ private $offset; - /** @var array */ - private $param = []; - /** @var int */ + private $param = array (); private $code; - /** @var string */ public $response; - /** @var string */ public $version; - /** @var string */ public $data; - /** - * @param string $response HTTP ответ - */ public function __construct($response) { $this->offset = 0; $this->response = $response; $this->parseMessage(); - } + } /** * Обработка HTTP ответа */ - private function parseMessage(): void + private function parseMessage() { $http = explode(" ", $this->getLine()); $this->version = $http[0]; - $this->code = (int)$http[1]; + $this->code = $http[1]; - $line = $this->getLine(); + $line = $this->getLine(); while ($offset = strpos($line, ":")) { $this->param[substr($line, 0, $offset)] = trim(substr($line, $offset + 1)); $line = $this->getLine(); @@ -47,12 +36,12 @@ class HttpResponse if (isset($this->param['Transfer-Encoding']) && $this->param['Transfer-Encoding'] == 'chunked') { //$this->data = substr($this->response, $this->offset); - $index = (int)hexdec($this->getLine()); - $chunk = []; - while ($index > 0) { - $chunk [] = substr($this->response, $this->offset, $index); - $this->offset += $index; - $index = (int)hexdec($this->getLine()); + $nline = hexdec($this->getLine()); + $chunk = array(); + while ($nline > 0) { + $chunk [] = substr($this->response, $this->offset, $nline); + $this->offset += $nline; + $nline = hexdec($this->getLine()); } $this->data = implode("", $chunk); @@ -64,33 +53,32 @@ class HttpResponse /** * Обработка строки HTTP ответа */ - private function getLine(): string + private function getLine() { $begin = $this->offset; $offset = strpos($this->response, "\r\n", $this->offset); - $result = substr($this->response, $begin, $offset - $begin); + $result = substr($this->response, $begin, $offset - $begin); $this->offset = $offset + 2; return $result; } /** * Значение параметра HTTP ответа - * @param string $name Имя параметра */ - public function getParameter($name): string + public function getParameter($name) { return $this->param[$name]; } - public function getData(): string + public function getData() { return $this->data; } /** - * Состояние + * Состояние */ - public function getCode(): int + public function getCode() { return $this->code; } diff --git a/src/Controller/Action.php b/src/Controller/Action.php index 84cf844..df0de65 100644 --- a/src/Controller/Action.php +++ b/src/Controller/Action.php @@ -1,139 +1,112 @@ part = new Url(); - } - - public function setUp(): void { - } + public $moduleTitle = ""; /** - * Загрузка файла настроек - * @param string $name - * @return array + * Соединение с базой данных */ - public function loadConfig($name) { - $basePath = $this->config->get('site', 'path'); + public $db; - $filename = Path::join($basePath, 'modules', $name); + // Фильтры + public $access = null; // Обьект хранит параметры доступа + public $logger = null; // Обьект для ведения лога + + private $factory = null; // Ссылка на обьект создания модели + private $helpers = array(); // Помошники для действий + public $param = array(); // Параметры для ссылки + + public $_registry/*: Registry*/; // Ссылка на реестр + public $_shortcut; + public $modulePrefix = ''; + public $iconPath = ''; + + // Для Widgets + public $view = null; + public $childNodes = array(); + public $ctrlValues = array(); + public $childViews = array(); + + function __construct() { + } + + public function setUp() { + } + + public function loadConfig($name) { + $filename = Shortcut::getUrl('config', $name); $settings = []; if (file_exists($filename)) { - $settings = include($filename); + include($filename); } else { throw new Exception('Невозможно загрузить файл настроек ' . $name); } return $settings; } - public function getConnection(): Database + public function getConnection() { return $this->db; } - /** - * Путь к установке модуля - * @param string $name - * @return string - */ public function installPath($name) { - $basePath = $this->config->get('system', 'path'); - return Path::join($basePath, "modules", $name); + return Path::join(CMS_PATH, "modules", $name); } - /** - * Добавляет подсказки - * @param View $view - * @param string $name - */ - public function addSuggest(View $view, $name): void { - $file = Path::join($this->modulePath, 'help', $name . '.suggest'); + public function addSuggest(View_View $view, $name) + { + $suggest = array(); + $file = Path::join($this->viewPath, 'help', $name . '.suggest'); if (file_exists($file)) { - $view->suggestions = include($file); + include($file); + $view->suggestions = $suggest; } } - /** - * Поиск иконки - * @param string $icon - * @param int $size - * @return string Путь к иконке - */ - function findIcon($icon, $size) { - $webPath = $this->config->get('site', 'web'); - return Path::join($webPath, 'icons', $size . 'x' . $size, $icon . '.png'); + function findIcon($icon, $size) + { + return Path::join($this->iconPath, $size . 'x' . $size, $icon . '.png'); } /** * Создает представление - * @param string $name - * @param class-string $viewClass - * @return Composite + * @param $name String + * @param $viewClass String + * @return View_Composite */ - public function getView($name, $viewClass = Composite::class) + public function getView($name, $viewClass = 'View_Composite') { $file = $name . self::TEMPLATE_EXTENSION; - $basePath = $this->config->get('system', 'path'); - $webPath = $this->config->get('system', 'web'); - - $list = [ - Path::join($this->modulePath, 'templates', $this->viewPathPrefix) - => Path::join($webPath, "modules", $this->name, 'templates', $this->viewPathPrefix), - Path::join($basePath, "templates") => Path::join($webPath, "templates") - ]; + $list = array( + Path::join($this->viewPath, TEMPLATES, $this->viewPathPrefix) => Path::join(WWW_PATH, "modules", $this->name, TEMPLATES, $this->viewPathPrefix), + Path::join(CMS_PATH, "templates") => Path::join(WWW_PATH, "templates") + ); // Поиск файла для шаблона foreach($list as $ospath => $path) { @@ -141,41 +114,34 @@ class Action implements ActionInterface if(file_exists($template)) { break; } } - /** @var \ctiso\View\Composite */ - $tpl = new $viewClass($template); - $tpl->config = $this->config; + $tpl/*: View_Composite*/ = new $viewClass($template); - $stylePath = Path::join($webPath, "assets", "css"); - $iconsPath = Path::join($webPath, 'icons'); - $scriptPath = Path::join($webPath, 'assets'); - - $tpl->set('icons', $iconsPath); // Путь к файлам текущей темы - $tpl->set('assets', $stylePath); - $tpl->set('script', $scriptPath); // Путь к файлам скриптов + $assets = Path::join(enableHttps(WWW_PATH), "assets", "css"); + $tpl->set('icons', $this->iconPath); // Путь к файлам текущей темы + $tpl->set('media', $this->themePath); // Путь к файлам текущей темы + $tpl->set('assets', $assets); + $tpl->set('script', $this->jsPath); // Путь к файлам скриптов $tpl->set('template', $path); // Путь к файлам текущего шаблона - $tpl->setAlias([ - 'assets' => $stylePath, - 'icons' => $iconsPath, - 'script' => $scriptPath, + $tpl->setAlias(array( + 'assets' => $assets, + 'icons' => $this->iconPath, + 'script' => $this->jsPath, // Для media и template поиск происходит как для файлов шаблонов 'media' => $list, 'template' => $list - ]); + )); + + $tpl->loadImports(Path::skipExtension($template) . ".import"); $this->addSuggest($tpl, $name); return $tpl; } - /** - * @template T - * @param class-string $name - * @return T - */ public function getModel($name) { if (!$this->factory) { - $this->factory = new Factory($this->db, $this->config, $this->user); + $this->factory = new Model_Factory($this->db, $this->_registry); } return $this->factory->getModel($name); } @@ -185,118 +151,125 @@ class Action implements ActionInterface * Т.к действия являются методами класса то * 1. Можно переопределить действия * 2. Использовать наследование чтобы добавить к старому обработчику новое поведение - * @param HttpRequest $request запроса - * @return View|string + * @param $request Обьект запроса */ - public function preProcess(HttpRequest $request) + public function preprocess(HttpRequest $request) { $action = self::ACTION_PREFIX . ucfirst($request->getAction()); if (!method_exists($this, $action)) { $action = "actionIndex"; } $view = $this->forward($action, $request); - if ($view instanceof View) { - $view->active_module = get_class($this); - $view->module_action = $action; - } - return $view; + if ($view instanceof View_View) { + $view->active_module = get_class($this); + $view->module_action = $action; + } + return $view; } - - /** - * Выполнение действия - * @param HttpRequest $request - * @return View|string|false - */ + public function execute(HttpRequest $request) { - $result = $this->preProcess($request); - return $result; + $result = $this->preprocess($request); + if (!empty($result)) { + $this->view = $result; + } + $text = $this->render(); + return $text; } - /** - * Перенаправление на другой контроллер - * @param string $action - * @param HttpRequest $args - * @return mixed - */ public function forward($action, HttpRequest $args) { - $actionFn = [$this, $action]; - if (!is_callable($actionFn)) { - return false; - } - $value = call_user_func($actionFn, $args); + $value = call_user_func(array($this, $action), $args); return $value; } /** * Страница по умолчанию - * @param HttpRequest $request - * @return string|false */ public function actionIndex(HttpRequest $request) { return ""; } - /** - * Добавление части ссылки - * @param string $key - * @param string $value - */ - public function addUrlPart($key, $value): void { - $this->part->addQueryParam($key, $value); + public function postUrl($name, $param) + { + $uri = array_merge(array('module' => + strtr($this->modulePrefix . strtolower(get_class($this)), array('module_' => '')), "action" => $name), + $this->param, $param); + + return "?" . http_build_query($uri); } /** * Генерация ссылки c учетом прав пользователя на ссылки - * @param string $actionName Действие + * @param string $name Действие * @param array $param Дополнительные параметры * 'mode' означает что элемент до отправки обрабатывается javascript - * @return Url|null + * @return array|null */ - public function nUrl($actionName, array $param = []) + public function nUrl($name, array $param = array()) { - $access = $this->access; - $url = new Url(); + $access/*: Filter_ActionAccess*/ = $this->access; - if ($access == null || $access->checkAction($actionName)) { - $moduleName = explode("\\", strtolower(get_class($this))); - if (count($moduleName) > 2) { - array_shift($moduleName); - if ($moduleName[0] == $moduleName[1]) { - array_shift($moduleName); - } - } - $param = array_merge(['module' => implode("\\", $moduleName), "action" => $actionName], $param); - - $url->setParent($this->part); - $url->setQuery($param); + if ($access == null || $access->checkAction($name)) { + return Functions::lcurry(array($this, 'postUrl'), $name, $param); } + return null; + } - return $url; + public function fUrl($name, array $param = array()) + { + return forceUrl($this->nUrl($name, $param)); + } + + /** + * Добавляет параметр для всех ссылок создаваемых функцией nUrl, aUrl + */ + public function addParameter($name, $value) + { + if ($value) { + $this->param [$name] = $value; + } } /** * Генерация ссылки на действие контроллера * Ajax определяется автоматически mode = ajax используется для смены layout - * @param string $name + * @param $name * @param array $param - * @return Url|null + * @return array|null * * @example ?action=$name&mode=ajax * {$param[i].key = $param[i].value} */ - public function aUrl($name, array $param = []) + public function aUrl($name, array $param = array()) { - return $this->nUrl($name, array_merge(['mode' => 'ajax'], $param)); + return $this->nUrl($name, array_merge(array('mode' => 'ajax'), $param)); // FIXME + } + + /** + * Добавление помошника контроллера + */ + public function addHelper($class) + { + $this->helpers [] = $class; + } + + /** + * Вызов помошников контроллера + */ + public function callHelpers(HttpRequest $request) + { + $action = self::ACTION_PREFIX . $request->getAction(); + foreach ($this->helpers as $helper) { + if (method_exists($helper, $action)) { + return call_user_func(array($helper, $action), $request, $this); + } else { + return $helper->actionIndex($request, $this); // Вместо return response ??? + } + } } /** * Загрузка файла класса - * @deprecated Веместо его нужно использовать автозагрузку - * @param string $path - * @param mixed $setup - * @param string $prefix - * @return mixed */ public function loadClass($path, $setup = null, $prefix = '') { @@ -308,11 +281,6 @@ class Action implements ActionInterface throw new Exception("NO CLASS $path"); } - /** - * Загрузка настроек - * @param string $path - * @return array - */ public function loadSettings($path) { $result = new Settings($path); @@ -320,22 +288,70 @@ class Action implements ActionInterface return $result->export(); } + public function setView($name) + { + $this->view = $this->getView($name); + } + /** - * Установка идентификатора страницы - * @return int + * Установка заголовка для отображения + */ + public function setTitle($title) + { + $this->view->setTitle($title); + } + + /** + * Добавление widget к отображению */ - function getPageId(HttpRequest $request) { - $pageId = time(); + public function addChild(/*Widget*/ $section, $node) + { + $this->childNodes[$section] = $node; + } + + public function setValue(/*Widget*/ $name, $value) + { + $this->ctrlValues[$name] = $value; + } + + /** + * Добавление дочернего отображения к текущему отображению + */ + public function addView(/*CompositeView*/ $section, $node) + { + $this->childViews[$section] = $node; + } + + /** + * Генерация содержания + * Путаница c execute и render + */ + public function render() + { + if ($this->view instanceof View_View) { + $this->view->assignValues($this->ctrlValues); + + $node/*: Widgets_Widget*/ = null; + foreach ($this->childNodes as $name => $node) { + $node->make($this); + $this->view->setView($name, $node->view); + } + + foreach ($this->childViews as $name => $node) { + $this->view->setView($name, $node); + } + } + return $this->view; + } + + function getPageId(HttpRequest $request) + { + $pageId = time(); $request->session()->set('page', $pageId); return $pageId; } - /** - * Проверка идентификатора страницы - * @param int $page Идентификатор страницы - * @return bool - */ - function checkPageId(HttpRequest $request, $page) + function checkPageId(HttpRequest $request, $page) { if ($request->get('__forced__')) { return true; @@ -346,15 +362,19 @@ class Action implements ActionInterface return $result; } - /** - * @return State - */ - function _getActionPath() { - return new State('index'); + function _getActionPath() + { + return new Controller_State('index'); } - function redirect(string $action): void { - header('location: ' . $action); + // Тоже убрать в метод Controller_Model + function getActionPath(HttpRequest $request, $action = null) + { + $this->_getActionPath()->getPath($this, ($action) ? $action : $request->getAction()); + } + + function redirect($action) { + header('location: ' . $this->fUrl($action)); exit(); } } diff --git a/src/Controller/ActionInterface.php b/src/Controller/ActionInterface.php deleted file mode 100644 index 4c8dbf6..0000000 --- a/src/Controller/ActionInterface.php +++ /dev/null @@ -1,28 +0,0 @@ - $class - * @return \ctiso\View\View - */ - function getView($name, $class); - /** - * @param string $key - * @param string $value - */ - function addUrlPart($key, $value): void; -} \ No newline at end of file diff --git a/src/Controller/Component.php b/src/Controller/Component.php index 124d4e5..7077175 100644 --- a/src/Controller/Component.php +++ b/src/Controller/Component.php @@ -1,90 +1,72 @@ ]*>/u', 'replaceContent', $text); +} + +class ComponentRequest { + public $component_id; + public $component_title; + public $r; + + function __construct($c, HttpRequest $r) { + $this->component_id = $c; + $this->r = $r; + } + + function get($key, $default = null) { + if ($key == 'active_page') { + return $this->r->get($key); + } + $arr = $this->r->get($key); + if ($arr !== NULL) { + if (is_array($arr)) { + return Arr::get($arr, $this->component_id, $default); + } else { + return $arr; + } + } + return $default; + } + + function getAction() { + return $this->r->getAction(); + } +} /** * Класс компонента */ -class Component +class Controller_Component { - /** @var string[] */ - public $viewPath = []; - /** @var string[] */ - public $webPath = []; + public $viewPath = array(); + public $webPath = array(); - /** @var ?string */ public $template = null; - public string $templatePath; + public $templatePath; - /** @var int */ public $component_id; - /** @var string */ public $component_title; - /** @var string */ public $COMPONENTS_WEB; - public Registry $config; - public Database $db; - public Collection $parameter; + public $registry/*: Settings*/; + public $db/*: Database*/; + public $parameter/*: Collection*/; - /** @var string */ - public $output = 'html'; - - /** @var string */ public $module; - /** @var string */ public $item_module; - /** - * @var SiteInterface $site - */ - public $site; - - function before(): void { + function before() { } - /** - * @param string $match - * @return string - */ - static function replaceContent($match) { - return \ctiso\Tales::phptal_component(htmlspecialchars_decode($match[3])); + function get($request, $key, $default) { } - /** - * @param string $text - * @return string - */ - static function applyComponents($text) { - $callback = fn($x) => self::replaceContent($x); - return preg_replace_callback('/<(\w+)(\s+[a-zA-Z\-]+=\"[^\"]*\")*\s+tal:replace="structure\s+component:([^\"]*)"[^>]*>/u', - $callback, $text); - } - - /** - * Выполняет запрос компонента и возвращает результат - * Результат может быть строкой или View для обычных компонентов, или массивом для использования в сервисах - * - * @param HttpRequest $request - * @param bool $has_id - * @return mixed - */ function execute(HttpRequest $request, $has_id = true) { $crequest = new ComponentRequest($this->component_id, $request); @@ -94,74 +76,53 @@ class Component } else { $action = 'action' . ucfirst($_action); } - + $this->before(); - $actionMethod = [$this, $action]; - if (is_callable($actionMethod)) { - return call_user_func($actionMethod, $crequest); + if (method_exists($this, $action)) { + return call_user_func(array($this, $action), $crequest); + } else { + return $this->actionIndex($crequest); } - - return $this->actionIndex($crequest); } - /** - * Получить имя шаблона - * @param Registry $_registry - * @return string - */ - public function getTemplateName($_registry) { - return (isset($_COOKIE['with_template']) && preg_match('/^[\w\d-]{3,20}$/', $_COOKIE['with_template'])) - ? $_COOKIE['with_template'] : ($_registry ? $_registry->get('site', 'template') : 'modern'); - } + public function getTemplateName($_registry/*: Settings*/) { + return (isset($_COOKIE['with_template']) && preg_match('/^[\w\d-]{3,20}$/', $_COOKIE['with_template'])) ? $_COOKIE['with_template'] : $_registry->readKey(array('system', 'template')); + } - /** - * Получить шаблон - * @param string $name - * @return PHPTAL|JsonView - */ public function getView($name) { - if ($this->output === 'json') { - return new JsonView($name); - } - - /** @var Registry $config */ - $config = $this->config; - $default = $config->get('site', 'template'); - $template = ($this->template) ? $this->template : $this->getTemplateName($config); + // + $registry/*: Settings*/ = $this->registry; + $template = ($this->template) ? $this->template : $this->getTemplateName($registry); $selected = null; - $tpl = null; foreach ($this->viewPath as $index => $viewPath) { // Загружать шаблон по умолчанию если не найден текущий - $dir = Path::join($this->viewPath[$index], 'templates', $template); - if (is_dir($dir)) { + if(is_dir(Path::join($this->viewPath[$index], 'templates', $template))) { $tpl = new PHPTAL(Path::join($this->viewPath[$index], 'templates', $template, $name)); $tpl->setPhpCodeDestination(PHPTAL_PHP_CODE_DESTINATION); $selected = $index; break; - } + } } if ($selected === null) { - // Последний вариант viewPath, путь к папке компонента - $selected = count($this->viewPath) - 1; - $tpl = new PHPTAL(Path::join($this->viewPath[$selected], 'templates', 'modern', $name)); + $tpl = new PHPTAL(Path::join($this->viewPath[0], 'templates', 'modern', $name)); $tpl->setPhpCodeDestination(PHPTAL_PHP_CODE_DESTINATION); $template = 'modern'; + $selected = 0; } $tpl->stripComments(true); - $tpl->addPreFilter(new \PHPTAL_PreFilter_Normalize()); + $tpl->addPreFilter(new PHPTAL_PreFilter_Normalize()); - $tpl->set('common', Path::join($this->config->get('system', 'web'), '../', 'common')); - $tpl->set('script', Path::join($this->config->get('system', 'web'), 'js')); - $tpl->set('media', Path::join($this->config->get('system', 'templates.web'), $template)); - - if ($default) { - $tpl->set('site_template', Path::join($this->config->get('site', 'templates.web'), $default)); + $tpl->set('common', Path::join(WWW_PATH, '../', 'common')); + $tpl->set('script', Path::join(WWW_PATH, 'js')); + $tpl->set('media', Path::join(TEMPLATE_WEB, $template)); + if ($registry) { + $tpl->set('site_template', SITE_WWW_PATH . '/templates' . $registry->readKey(array('system', 'template'))); } - $tpl->set('base', $this->config->get('site', 'web')); + $tpl->set('base', SITE_WWW_PATH); $tpl->set('component_base', $this->webPath[$selected]); $tpl->set('component', Path::join($this->webPath[$selected], 'templates', $template)); @@ -170,122 +131,69 @@ class Component return $tpl; } - /** - * Возвращает путь к шаблону по умолчанию - * @return string - */ - function _getDefaultPath() { - return $this->viewPath[count($this->viewPath) - 1]; - } - - /** - * Возвращает путь к шаблону - * @param string $name - * @return string - */ public function getTemplatePath($name) { - $registry = $this->config; + $registry/*: Settings*/ = $this->registry; // Брать настройки из куков если есть $template = ($this->template) ? $this->template : $this->getTemplateName($registry); - foreach ($this->viewPath as $index => $_) { + foreach ($this->viewPath as $index => $viewPath) { if(is_dir(Path::join($this->viewPath[$index], 'templates', $template))) { return Path::join($this->viewPath[$index], 'templates', $template, $name); } } - - return Path::join($this->viewPath[count($this->viewPath) - 1], 'templates', 'modern', $name); + + return Path::join($this->viewPath[0], 'templates', 'modern', $name); } - /** - * Возвращает путь к шаблонам - * @return string - */ public function getTemplateWebPath() { - return Path::join($this->webPath[count($this->webPath) - 1], 'templates', 'modern'); + return Path::join($this->webPath[0], 'templates', 'modern'); } /** * Создает модель - * - * @template T - * @param class-string $modelName - * @return T + * @param string $name + * @return model */ - public function getModel($modelName) + public function getModel($name) { + $modelName = "Mapper_" . $name; $model = new $modelName(); - $model->config = $this->config; $model->db = $this->db; return $model; } - /** - * @param string $key - * @param string $val - * @param PDOStatement $res - * @return array{value: string, name: string}[] - */ - public function options(string $key, string $val, $res) { - $result = []; + public function options($key, $val, $res/*: Database_PDOStatement*/) { + $result = array(); while($res->next()) { - $result[] = ['value' => $res->getString($key), 'name' => $res->getString($val)]; + $result[] = array('value' => $res->getString($key), 'name' => $res->getString($val)); } return $result; } - /** - * @param array $list - * @param bool $selected - * @return array{value: string, name: string, selected: bool}[] - */ - public function optionsPair(array $list, $selected = false) { - $result = []; + public function optionsPair($list, $selected = false) { + $result = array(); foreach ($list as $key => $value) { - $result [] = ['value' => $key, 'name' => $value, 'selected' => $key == $selected]; + $result [] = array('value' => $key, 'name' => $value, 'selected' => $key == $selected); } return $result; } - /** - * Найти файл по пути - * @param string[] $pathList - * @param string $name - * @return string|null - */ - function findFile(array $pathList, string $name) { - foreach($pathList as $item) { - $filename = Path::join($item, $name); - if (file_exists($filename)) { - return $filename; - } - } - return null; - } - - /** - * Получить информацию о параметрах - * @return array - */ function getInfo() { - $filename = Path::join($this->viewPath[count($this->viewPath) - 1], 'install.json'); + $filename = Path::join($this->viewPath[0], 'install.json'); if (file_exists($filename)) { $settings = json_decode(File::getContents($filename), true); - if ($settings) { - return $settings; - } + return $settings; } - return ['parameter' => []]; + return array(); } /** * Генерация интерфейса для выбора галлереи фотографии - * @param Composite $view - * @param ?\ctiso\Form\OptionsFactory $options */ - public function setParameters(Composite $view, $options = null): void + public function setParameters($view/*: View_Composite*/) { - $form = new Form(); + $form = new Form_Form(); + $options = new Form_OptionFactory($this->db, $this->registry); $settings = $this->getInfo(); $form->addFieldList($settings['parameter'], $options); @@ -295,94 +203,56 @@ class Component $view->component_title = $settings['title']; } - /** - * @param \ctiso\Form\OptionsFactory $options - * @return array - */ - public function getFields($options = null) { - $form = new Form(); - $settings = $this->getInfo(); - $form->addFieldList($settings['parameter'], $options); - - return $form->field; - } - - /** - * Обьеденить с ComponentFactory - * @param string $expression - * @param SiteInterface $site - * @return Component - */ - static function loadComponent(string $expression, $site) + static function loadComponent($expression, Database $db, $registry/*: Registry*/) { + $expression = htmlspecialchars_decode($expression); $offset = strpos($expression, '?'); $url = parse_url($expression); - - $arguments = []; - $path = $expression; - if (is_int($offset)) { + + $arguments = array(); + if ($offset === false) { + $path = $expression; + } else if (is_int($offset)) { $path = substr($expression, 0, $offset); $query = substr($expression, $offset + 1); parse_str($query, $arguments); } $name = $path; - $config = $site->getConfig(); - // FIXME: Если имя для компонента не задано то возвращаем пустой компонент - // Нужно дополнительно проверить и файл или в autoloader просто не найдет файл копонента - if (!$name) { - return new Component(); - } + $path = Path::join (BASE_PATH, 'components', $name, $name . '.php'); + $className = 'Component_' . $name; - $filename = ucfirst($name); - $path = Path::join ($config->get('site', 'components'), $name, $filename . '.php'); - $className = implode("\\", ['Components', ucfirst($name), $filename]); - - $component = null; + $component/*: Controller_Component*/ = null; + if (file_exists($path)) { - /** @var Component $component */ - $component = new $className(); + require_once ($path); - $component->viewPath = [$config->get('site', 'components') . '/' . $name . '/']; - $component->webPath = [$config->get('site', 'components.web') . '/' . $name]; - $component->COMPONENTS_WEB = $config->get('site', 'web') . '/components/'; + $component = new $className(); + $component->db = $db; + $component->registry = $registry; + + $component->viewPath = array(BASE_PATH . '/components/' . $name . '/'); + $component->webPath = array(SITE_WWW_PATH . '/components/' . $name); + + $component->COMPONENTS_WEB = SITE_WWW_PATH . '/components/'; } else { - /** @var Component $component */ + $path = Path::join (COMPONENTS, $name, $name . '.php'); + require_once ($path); $component = new $className(); - $template = $component->getTemplateName($site->getConfig()); + $component->db = $db; + $component->registry = $registry; - $component->viewPath = [ - // Сначало ищем локально - $config->get('site', 'templates') . '/'. $template . '/_components/' . $name . '/', - $config->get('site', 'components') . '/' . $name . '/', - // Потом в общем хранилище - $config->get('system', 'templates'). '/' . $template . '/_components/' . $name . '/', - $config->get('system', 'components') . '/' . $name . '/', - ]; + $component->viewPath = array(COMPONENTS . '/' . $name . '/', BASE_PATH . '/components/' . $name . '/'); if (defined('COMPONENTS_WEB')) { - $component->webPath = [ - // Сначало локально - $config->get('site', 'templates.web') . '/' . $template . '/_components/' . $name, - $config->get('site', 'components.web') . '/' . $name, - // Потом в общем хранилище - $config->get('system', 'templates.web') . '/' . $template . '/_components/' . $name, - $config->get('system', 'components.web') . '/' . $name, - ]; - $component->COMPONENTS_WEB = $config->get('system', 'components.web'); + $component->webPath = array(COMPONENTS_WEB . '/' . $name, SITE_WWW_PATH . '/components/' . $name); + $component->COMPONENTS_WEB = COMPONENTS_WEB; } else { - $component->webPath = ['', $config->get('site', 'components.web') . '/' . $name, '', '']; + $component->webPath = array('', SITE_WWW_PATH . '/components/' . $name, ''); } - } - - // Вынести в отдельную функцию - $db = $site->getDatabase(); - - $component->db = $db; - $component->config = $site->getConfig(); - $component->site = $site; - + } + $stmt = $db->prepareStatement("SELECT * FROM component WHERE code = ?"); $stmt->setString(1, $expression); $cid = $stmt->executeQuery(); @@ -390,7 +260,6 @@ class Component $component->component_id = $cid->getInt('id_component'); } else { $last = $db->getIdGenerator(); - $result = null; if ($last->isBeforeInsert()) { $result = $last->getId('component_id_component_seq'); @@ -410,40 +279,38 @@ class Component $params = new Collection(); $params->import(array_merge($_GET, $arguments)); - $component->parameter = $params; $component->template = $params->get('template', false); $editor = $component->getEditUrl(); if ($editor) { - $site->addComponentConfig($editor); + if(class_exists("Controller_Site")){ //Если мы в CMS2 + $instance = Controller_Site::getInstance(); + $instance->componentsConfig[] = $editor; + } else { + global $componentsConfig; + $componentsConfig[] = $editor; + } } return $component; } - /** - * @return ?array{name: string, url: string} - */ function getEditUrl() { return null; } - /** - * @param ComponentRequest $request - * @return array - */ - function raw_query($request) + function raw_query($request/*: ComponentRequest*/) { $arr = $request->r->export('get'); - $param = []; - $parameter = $this->parameter; + $param = array(); + $parameter/*: Collection*/ = $this->parameter; foreach($parameter->export() as $key => $value) { $param[$key] = $value; } - $data = []; + $data = array(); foreach($arr as $key => $value) { if (is_array($value)) { $data[$key] = Arr::get($value, $this->component_id); @@ -456,12 +323,7 @@ class Component } - /** - * @param ComponentRequest $request - * @param array $list - * @return string - */ - function query($request, $list) + function query($request/*: ComponentRequest*/, $list) { $arr = $request->r->export('get'); @@ -474,27 +336,14 @@ class Component } /** - * @param string $name - * @param string $path - * @param array $shim - */ - function addRequireJsPath($name, $path, $shim = null): void { - $this->site->addRequireJsPath($name, $path, $shim); + * @deprecated В CMS2 перенесено в контроллер сайта! + */ + + function addRequireJsPath($name, $path, $shim = null) { + Controller_Site::addRequireJsPath($name, $path, $shim); } - /** - * @param ComponentRequest $request - * @return mixed - */ - function actionIndex($request) { - return ""; - } - - /** - * @param HttpRequest $request - * @return array - */ - function getDefaultPageEnvironment($request) { - return []; + function actionIndex($request/*: ComponentRequest*/) { } } + diff --git a/src/Controller/Front.php b/src/Controller/Front.php index b799f40..ed5aee2 100644 --- a/src/Controller/Front.php +++ b/src/Controller/Front.php @@ -4,119 +4,107 @@ * Первичный контроллер контроллер страниц * @package system.controller */ -namespace ctiso\Controller; - -use ctiso\Controller\Action; -use ctiso\Registry; -use ctiso\Database; -use ctiso\Filter\ActionAccess; -use ctiso\Filter\ActionLogger; -use ctiso\Path; -use ctiso\UserMessageException; -use ctiso\HttpRequest; -use ctiso\Role\User; - -class Front extends Action +class Controller_Front extends Controller_Action { - /** - * Параметр по которому выбирается модуль - * @var string - */ - protected $_param; - /** - * Значение параметра по умолчанию - * @var string - */ - protected $default; + /** @var Shortcut */ + protected $shortcut; // Ярлык к модулю + protected $_param; // Параметр по которому выбирается модуль + protected $default; // Значение параметра по умолчанию - /** @var array */ - protected $modules = []; + protected $modules = array(); /** - * @param string $default + * @param Settings $_registry + * @param Shortcut $_shortcut */ - public function __construct(Database $db, Registry $config, User $user, $default) { + public function __construct(Settings $_registry, $_shortcut) // $db, $installer, $shortcut + { parent::__construct(); - $this->config = $config; - $this->db = $db; - $this->user = $user; - $this->default = $default; + $registry = $_registry; + $this->_registry = $_registry; + $this->_shortcut = $_shortcut; // $cc->newShortcut(); + + $dsn = $registry->readKey(array('system', 'dsn')); + $this->db = Database::getConnection($dsn); // $cc->newConnection(); } - /** - * Проверяет загружен ли модуль - * @param string $name Имя модуля - * @return bool - */ - public function isLoaded($name): bool + public function isLoaded($name) { return isset($this->modules[$name]); } /** * Создает экземпляр модуля и выполняет действия для него - * @param string $name Имя модуля - * @param HttpRequest $request - * @return string + * @param string $name Имя модуля + * @param request $request Имя модуля + * @return string */ - public function loadModule($name, HttpRequest $request) + public function loadModule($name, Collection $request, $controller = false) { if ($this->isLoaded($name)) { $module = $this->modules[$name]; return $module->access->execute($request); } - $parts = explode('\\', $name); + $suffix = ($controller) ? $controller : $name; + $moduleFile = Shortcut::getUrl($this->shortcut, $name, $suffix); // ModuleLoader (2) - $config = $this->config; + $module = $this->loadClass($moduleFile, null, 'Module_'); + if ($module) { + // Инициализация модуля + $module->front = $this; + $module->viewPath = Shortcut::getUrl('modulepath', $name); + $module->name = $name; - $moulesPath = Path::join($config->get('system', 'path'), 'modules'); - $logPath = Path::join($config->get('site', 'path'), $config->get('system', 'access.log')); + $module->param = $this->param; + // + $module->_registry = $this->_registry; + $module->_shortcut = $this->_shortcut; - $first = $parts[0]; - $second = (count($parts) >= 2) ? $parts[1] : $parts[0]; + $module->iconPath = $this->iconPath; // -> Registry + $module->themePath = $this->themePath; // -> Registry + $module->jsPath = $this->jsPath; // -> Registry + $module->db = $this->db; + // Не для всех приложений нужно вести лог действий + // Ведение лога + $logger = $this->loadClass(__DIR__ . '/../Filter/ActionLogger.php', $module, 'Filter_'); + $logger->before = $this->loadSettings(Shortcut::getUrl('logger', $name)); + // Управление доступом + $module->access = $this->loadClass(__DIR__ . '/../Filter/ActionAccess.php', $logger, 'Filter_'); + $module->access->name = $suffix; + $module->access->access = $this->loadSettings(Shortcut::getUrl('access', $name)); - $ucname = ucfirst($first); - $ucpart = ucfirst($second); - - $moduleClass = "Modules\\$ucname\\$ucpart"; - /** @var Action $module */ - $module = new $moduleClass(); - - // Инициализация модуля - $modPath = Path::join($moulesPath, $first); - $module->modulePath = $modPath; - $module->name = $name; - // - $module->config = $this->config; - $module->db = $this->db; - $module->user = $this->user; - $module->front = $this; - // Ведение лога - $logger = new ActionLogger($module, $logPath, $this->user); - $filename = Path::join($modPath, 'filters', 'logger.json'); - $logger->before = $this->loadSettings($filename); - // Управление доступом - $module->access = new ActionAccess($logger, $this->user); - $module->access->access = $this->loadSettings(Path::join($modPath, 'filters', 'access.json')); - - $module->setUp(); - - $this->modules[$name] = $module; - $result = $module->access->execute($request); - return $result; + $module->setUp(); + + $this->modules[$name] = $module; + $result = $module->access->execute($request); + return $result; + } + return null; // throw new FileNotFoundException(); } + public function setParameter($shortcut, $param, $name) + { + $this->shortcut = $shortcut; + // Параметр + $this->_param = $param; + $this->default = $name; + } public function execute(HttpRequest $request) { - $name = $request->getString('module', $this->default); - try { - return $this->loadModule($name, $request); + $name = explode("_", $request->get($this->_param, $this->default)); + if (count($name) >= 2) { + $controller = $name[1]; + } else { + $controller = false; + } + try{ + return $this->loadModule($name[0], $request, $controller); } catch (UserMessageException $ex) { //Исключение с понятным пользователю сообщением $mode = $request->get('mode'); - if ($mode == 'ajax' || $mode == 'json') { + if($mode == 'ajax' || $mode == 'json'){ return json_encode(['result'=>'fail', 'message'=> $ex->userMessage]); } else { return $ex->userMessage; diff --git a/src/Controller/Installer.php b/src/Controller/Installer.php index 79b08f2..d20a93d 100644 --- a/src/Controller/Installer.php +++ b/src/Controller/Installer.php @@ -1,67 +1,36 @@ _registry = $_registry; } - - /** - * Устанавливает параметры - * @param Manager $db_manager - * @param callable $installPath - */ - public function setUp($db_manager, $installPath): void + + public function setUp($db_manager, $installPath) { $this->db_manager = $db_manager; $this->installPath = $installPath; } - /** - * Получение пути к файлу install.json - * @param string $name - * @return string - */ function getSetupFile($name) { $setup = Path::join(call_user_func($this->installPath, $name), "install.json"); - return $setup; + return $setup; } - /** - * Получение пути к файлу unisntall.json - * @param string $name - * @return string - */ - function getUninstallFile($name) - { + function getUninstallFile($name){ return Path::join(call_user_func($this->installPath, $name), "sql", "uninstall.json"); } - /** - * Проверка версии обновления - * @param string $name - * @return bool - */ + // Проверка версии обновления function isChanged($name) // Информация о модулях { - $item = $this->_registry->get($name); + $item = $this->_registry->readKey(array($name)); if ($item) { $setup = $this->getSetupFile($name); if (file_exists($setup) && (filemtime($setup) > $item['time'])) { @@ -72,18 +41,10 @@ class Installer return true; } - /** - * Устанавливает SQL - * @param array $sql - * @param string $version_new - * @param string $version_old - * @param string $name - * @return array - */ function installSQL(array $sql, $version_new, $version_old, $name) { $result = []; - $json_installer = new JsonInstall($this->db_manager); + $json_installer = new Database_JsonInstall($this->db_manager); foreach ($sql as $version => $install) { if (version_compare($version, $version_new, "<=") && version_compare($version, $version_old, ">")) { $file = Path::join(call_user_func($this->installPath, $name), "sql", $install); @@ -94,78 +55,60 @@ class Installer return $result; } - /** - * @param string $name - * @return void - */ - function uninstall($name): void - { + function uninstall($name){ $uninstall = $this->getUninstallFile($name); if (file_exists($uninstall)) { - $json_installer = new JsonInstall($this->db_manager); - $json_installer->install($uninstall, null); + $json_installer = new Database_JsonInstall($this->db_manager); + $json_installer->install($uninstall,null); } $this->_registry->removeKey($name); $this->_registry->write(); } - /** - * Устанавливает обновления если есть - * @param string $name - * @param bool $force - * @return array - */ - function doUpdates($name, $force = false) + // Устанавливает обновления если есть + function doUpdates($name, $force = false) // Установка модуля { - $result = []; + $result = array(); $setup = $this->getSetupFile($name); if (file_exists($setup) && ($this->isChanged($name) || $force)) { $registry = $this->_registry; - $settings = new Settings($setup); $settings->read(); - $item = $registry->get($name); + $item = $registry->readKey(array($name)); $version_new = $settings->get('version'); if ($item) { - $version_old = $item['version']; + $version_old = $item['version']; } else { $version_old = "0.0"; - $registry->writeKey([$name], []); + $registry->writeKey(array($name), array()); } if (version_compare($version_old, $settings->get('version'), "!=")) { $sql = $settings->get('sql'); if (is_array($sql)) { $res = $this->installSQL($sql, $version_new, $version_old, $name); - if ($res) { - $result[] = $res; + if($res){ + $result[]=$res; } } - } - // Обновление версии меню - $registry->removeKey($name); - $registry->set($name, [ - 'version' => $version_new, - 'time' => filemtime($setup) - ]); - // $registry->writeKey([$name], $settings->export()); + // Обновление версии меню + $registry->removeKey($name); + $registry->writeKey(array($name), $settings->get('settings')); + $registry->writeKey(array($name), + array('version' => $version_new, + 'time' => filemtime($setup))); + } $registry->write(); } return $result; } - /** - * Устанавливает базу данных - * @param string $dbinit_path - * @param string|null $dbfill_path - */ - function install($dbinit_path, $dbfill_path = null): void - { - $json_installer = new JsonInstall($this->db_manager); + function install($dbinit_path, $dbfill_path = null) { + $json_installer = new Database_JsonInstall($this->db_manager); $json_installer->install($dbinit_path, $dbfill_path); } } diff --git a/src/Controller/Request.php b/src/Controller/Request.php index 4a4293e..6567ad7 100644 --- a/src/Controller/Request.php +++ b/src/Controller/Request.php @@ -1,33 +1,19 @@ r = $request; $this->id = $id; } - /** - * @param string $name - * @param mixed $def - * @return mixed - */ function get($name, $def = null) { $v = $this->r->get($name); $id = $this->id; if ($id && is_array($v)) { - return $v[$id] ?? $def; + return isset($v[$id]) ? $v[$id] : $def; } return $v; } diff --git a/src/Controller/Service.php b/src/Controller/Service.php index e4d7fb9..a1f7185 100644 --- a/src/Controller/Service.php +++ b/src/Controller/Service.php @@ -3,101 +3,72 @@ /** * Класс сервиса = Упрощенный компонент */ -namespace ctiso\Controller; - -use ctiso\Path; -use ctiso\Model\BaseMapper; -use ctiso\File; -use ctiso\Registry; -use ctiso\Database\PDOStatement; -use ctiso\Database; - -class Service +class Controller_Service { - /** @var array */ public $viewPath = []; - /** @var array */ public $webPath = []; - /** @var Registry */ - public $config; - /** @var string */ + public $registry; // Registry->getInstance public $template; - /** @var string */ public $templatePath; - /** @var string */ public $COMPONENTS_WEB; - /** @var Database */ + public $db; - /** - * Возвращает путь к шаблонам - * @param string $name Имя шаблона - * @return string - */ public function getTemplatePath($name) { return Path::join($this->viewPath[0], 'templates', 'modern', $name); } - /** - * Возвращает путь к шаблонам - * @return string - */ public function getTemplateWebPath() { return Path::join($this->webPath[0], strtolower(get_class($this)), 'templates', 'modern'); } /** - * Создает модель - * @param class-string $modelName - * @return BaseMapper + * @param $name Имя модели */ - public function getModel($modelName) + private function getModelPath($name) { - /** @var BaseMapper */ - $model = new $modelName(); + return Path::join (CMS_PATH, "model", $name . ".php"); + } + + /** + * Создает модель + * @param string $name + * @return model + */ + public function getModel($name) + { + require_once ($this->getModelPath ($name)); + $modelName = $name . "Mapper"; + $model = new $modelName (); $model->db = $this->db; return $model; } - /** - * @param string $key - * @param string $val - * @param PDOStatement $res - * @return array - */ public function options($key, $val, $res) { - $result = []; + $result = array(); while($res->next()) { - $result[] = ['value' => $res->getInt($key), 'name' => $res->getString($val)]; + $result[] = array('value' => $res->getInt($key), 'name' => $res->getString($val)); } return $result; } - /** - * @param array $list - * @param bool $selected - * @return array - */ public function optionsPair($list, $selected = false) { - $result = []; + $result = array(); foreach ($list as $key => $value) { - $result [] = ['value' => $key, 'name' => $value, 'selected' => $key == $selected]; + $result [] = array('value' => $key, 'name' => $value, 'selected' => $key == $selected); } return $result; } - - /** - * @return array - */ + function getInfo() { $filename = Path::join($this->viewPath[0], 'install.json'); if (file_exists($filename)) { $settings = json_decode(File::getContents($filename), true); return $settings; } - return []; + return array(); } } diff --git a/src/Controller/SiteInterface.php b/src/Controller/SiteInterface.php deleted file mode 100644 index 92c06a5..0000000 --- a/src/Controller/SiteInterface.php +++ /dev/null @@ -1,41 +0,0 @@ -action = $action; + } + + static function make($action) + { + return new Controller_State($action); + } + + public function addTitle($name, $url = array()) + { + $this->titles [] = array($name, $url); + return $this; + } + + public function addState(Controller_State $state) + { + $this->states [$state->getAction()] = $state; + return $this; + } + + public function getAction() + { + return $this->action; + } + + function checkAction($action, &$list) + { + if ($this->action == $action) { + array_push($list, $this); + return true; + } else { + foreach ($this->states as $state) { + if ($state->checkAction($action, $list)) { + array_push($list, $this); + return true; + } + } + } + return false; + } + + function makeTitle(Controller_Action $module) + { + foreach ($this->titles as $item) { + $module->path->addMenuItem($module->nUrl($this->action, $item[1]), $item[0]); + } + } + + function getPath($module, $action) + { + $list = array(); + if ($this->checkAction($action, $list)) { + foreach (array_reverse($list) as $item) { + $item->makeTitle($module); + } + } else { + $this->makeTitle($module); + } + } +} diff --git a/src/Database.php b/src/Database.php index ab2a233..acd8c59 100644 --- a/src/Database.php +++ b/src/Database.php @@ -1,280 +1,190 @@ +require_once "Database/PDOStatement.php"; + +/** + * Класс оболочка для PDO для замены Creole + */ +class Database/**/ extends PDO +{ + + public $dsn; + public function __construct($dsn, $username = null, $password = null) + { + parent::__construct($dsn, $username, $password); + $this->setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION); + $this->setAttribute(PDO::ATTR_DEFAULT_FETCH_MODE, PDO::FETCH_ASSOC); + $this->setAttribute(PDO::ATTR_STATEMENT_CLASS, array('Database_PDOStatement', array())); + } + + function prepare($sql, $args = []) { + $result = parent::prepare($sql, $args); + return $result; } -} - -namespace ctiso { - - use PDO; - use ctiso\Database\Statement; - use ctiso\Database\PDOStatement; - use ctiso\Database\IdGenerator; + public function getDSN() + { + return $this->dsn; + } + public function isPostgres(){ + return ($this->dsn["phptype"] == "pgsql"); + } /** - * Класс оболочка для PDO для замены Creole - * @phpstan-type DSN = array{phptype: string, hostspec: string, database: string, username: string, password: string} + * Создает соединение с базой данных */ - class Database extends PDO + static function getConnection(array $dsn) { - /** @var DSN */ - public $dsn; - - /** - * Создает соединение с базой данных - * @param string $dsn - DSN - * @param string|null $username - имя пользователя - * @param string|null $password - пароль - */ - public function __construct($dsn, $username = null, $password = null) - { - parent::__construct($dsn, $username, $password); - $this->setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION); - $this->setAttribute(PDO::ATTR_DEFAULT_FETCH_MODE, PDO::FETCH_ASSOC); - $this->setAttribute(PDO::ATTR_STATEMENT_CLASS, [PDOStatement::class, []]); + if ($dsn['phptype'] == 'pgsql' || $dsn['phptype'] == 'mysql') { + $port = (isset($dsn['port'])) ? "port={$dsn['port']};" : ""; + $connection/*: Database*/ = new static("{$dsn['phptype']}:host={$dsn['hostspec']}; $port dbname={$dsn['database']}", $dsn['username'], $dsn['password']); + if ($dsn['phptype'] == 'pgsql') { + $connection->query('SET client_encoding="UTF-8"'); + } + + if (isset($dsn['schema'])) { + $connection->query('SET search_path TO ' . $dsn['schema']); + } } + if ($dsn['phptype'] == 'sqlite') { + $connection/*: Database*/ = new static("{$dsn['phptype']}:{$dsn['database']}"); + $connection->setAttribute(PDO::ATTR_TIMEOUT, 5); + $mode = defined('SQLITE_JOURNAL_MODE') ? SQLITE_JOURNAL_MODE : 'WAL'; + $connection->query("PRAGMA journal_mode=$mode"); - /** - * prepare возвращает только PDOStatement т.к установлен PDO::ERRMODE_EXCEPTION - */ - function prepare(string $sql, array $options = []): PDOStatement - { - /** @var PDOStatement */ - $result = parent::prepare($sql, $options); - return $result; - } - - function query($query, $fetchMode = PDO::FETCH_INTO, mixed $_arg1 = null, mixed $_arg2 = null): PDOStatement { - /** @var PDOStatement */ - $result = parent::query($query, $fetchMode); - return $result; - } - - /** - * Возвращает DSN - * @return DSN - */ - public function getDSN() - { - return $this->dsn; - } - - /** - * Возвращает true, если база данных Postgres - * @return bool - */ - public function isPostgres() - { - return ($this->dsn["phptype"] == "pgsql"); - } - /** - * Создает соединение с базой данных - * @param array $dsn - DSN - * @return Database|null - */ - static function getConnection(array $dsn) - { - - /** @var ?Database */ - $connection = null; - if ($dsn['phptype'] == 'pgsql' || $dsn['phptype'] == 'mysql') { - $port = (isset($dsn['port'])) ? "port={$dsn['port']};" : ""; - $connection = new self("{$dsn['phptype']}:host={$dsn['hostspec']}; $port dbname={$dsn['database']}", $dsn['username'], $dsn['password']); - if ($dsn['phptype'] == 'pgsql') { - $connection->query('SET client_encoding="UTF-8"'); + if(!function_exists('sqliteLower')){ + function sqliteLower($str) { + return mb_strtolower($str, 'UTF-8'); } - - if (isset($dsn['schema'])) { - $connection->query('SET search_path TO ' . $dsn['schema']); - } - } elseif ($dsn['phptype'] == 'sqlite::memory') { - $connection = new self("{$dsn['phptype']}:"); - $connection->sqliteCreateFunction('LOWER', 'sqliteLower', 1); - } elseif ($dsn['phptype'] == 'sqlite') { - $connection = new self("{$dsn['phptype']}:{$dsn['database']}"); - $connection->setAttribute(PDO::ATTR_TIMEOUT, 5); - $mode = defined('SQLITE_JOURNAL_MODE') ? \SQLITE_JOURNAL_MODE : 'WAL'; - $connection->query("PRAGMA journal_mode=$mode"); $connection->sqliteCreateFunction('LOWER', 'sqliteLower', 1); } - $connection->dsn = $dsn; - return $connection; } + $connection->dsn = $dsn; + return $connection; + } - /** - * Выполняет запрос к базе данных - * @param string $query - запрос - * @param ?array $values - значения - */ - public function executeQuery($query, $values = null): PDOStatement - { - $stmt = $this->prepare($query); + public function executeQuery($query, $values=null) + { + $stmt/*: Database_PDOStatement*/ = $this->prepare($query); - $stmt->execute($values); - $stmt->cache = $stmt->fetchAll(PDO::FETCH_ASSOC); - return $stmt; - } + $stmt->execute($values); + $stmt->cache = $stmt->fetchAll(PDO::FETCH_ASSOC); + return $stmt; + } - /** - * Создает подготовленный запрос - * @param string $query - запрос - * @return Statement - */ - public function prepareStatement($query) - { - return new Statement($query, $this); - } + public function prepareStatement($query) + { + return new Database_Statement($query, $this); + } - /** - * Извлекает из базы все элементы по запросу (Для совместимости со старым представлением баз данных CIS) - * @param string $query - запрос - * @param ?array $values - значения - * @return array> - */ - public function fetchAllArray($query, $values = null) - { - $sth = $this->prepare($query); - $prep = $this->prepareValues($values); - $sth->execute($prep); - return $sth->fetchAll(PDO::FETCH_ASSOC); - } + // Для совместимости со старым представлением баз данных CIS + /** + * Извлекает из базы все элементы по запросу + */ + public function fetchAllArray($query, $values = null) + { + $sth/*: Database_PDOStatement*/ = $this->prepare($query); + $prep = $this->prepareValues($values); + $sth->execute($prep); + return $sth->fetchAll(PDO::FETCH_ASSOC); + } - /** - * Извлекает из базы первый элемент по запросу - * @param string $query - запрос - * @param ?array $values - значения - * @return array|false - */ - public function fetchOneArray($query, $values = null) - { - $sth = $this->prepare($query); - $prep = $this->prepareValues($values); - $sth->execute($prep); - return $sth->fetch(PDO::FETCH_ASSOC); - } + /** + * Извлекает из базы первый элемент по запросу + */ + public function fetchOneArray($query, $values = null) + { + $sth/*: Database_PDOStatement*/ = $this->prepare($query); + $prep = $this->prepareValues($values); + $sth->execute($prep); + return $sth->fetch(PDO::FETCH_ASSOC); + } - /** - * Преобразует значения в подготовленные значения - * @param array $values - значения - * @return ?array - */ - private function prepareValues($values) - { - if (!$values) { - return null; - } - $pg = $this->isPostgres(); - $prep = []; - foreach ($values as $key => $value) { - $result = null; - if (is_bool($value)) { - if ($pg) { - $result = $value ? 'true' : 'false'; - } else { - $result = $value ? 1 : 0; - } - } else { - $result = $value; - } - $prep[":" . $key] = $result; - } - return $prep; - } + private static function assignQuote($x, $y) + { + return $x . "=" . $this->quote($y); + } - /** - * Создает INSERT запрос - * @param string $table - таблица - * @param array $values - значения - * @param bool $return_id - возвращать id - * @param string $index - индекс - * @return int|null - */ - function insertQuery($table, array $values, $return_id = false, $index = null) - { - $prep = $this->prepareValues($values); - - $sql = "INSERT INTO $table (" . implode(",", array_keys($values)) - . ") VALUES (" . implode(",", array_keys($prep)) . ")"; - if ($return_id) { - if ($this->isPostgres()) { - $sql .= " RETURNING $index"; - } - } - $stmt = $this->prepare($sql); - $stmt->setFetchMode(PDO::FETCH_ASSOC); - $stmt->execute($prep); - $result = $stmt->fetch(); - if ($return_id) { - if ($this->isPostgres()) { - return $result[$index]; - } else { - $result = $this->fetchOneArray("SELECT $index AS lastid FROM $table WHERE OID = last_insert_rowid()"); - if ($result === false) { - throw new \RuntimeException("Ошибка получения идентификатора"); - } - return $result['lastid']; - } - } + private function prepareValues($values) + { + if (!$values) { return null; } - - /** - * Создает UPDATE запрос - * @param string $table - таблица - * @param array $values - значения - * @param string $cond - условие - */ - function updateQuery($table, array $values, $cond): void - { - $prep = $this->prepareValues($values); - $sql = "UPDATE $table SET " . implode( - ",", - array_map(function ($k, $v) { - return $k . "=" . $v; }, array_keys($values), array_keys($prep)) - ) . " WHERE $cond"; - - $stmt = $this->prepare($sql); - $stmt->setFetchMode(PDO::FETCH_ASSOC); - $stmt->execute($prep); - } - - /** - * Создает генератор идентификаторов - * @return IdGenerator - */ - function getIdGenerator() - { - return new IdGenerator($this); - } - - /** - * Замечание: Только для Postgres SQL - * @param string $seq Имя последовательности для ключа таблицы - * @return int Идентефикатор следующей записи - */ - function getNextId($seq) - { - $result = $this->fetchOneArray("SELECT nextval('$seq')"); - if ($result === false) { - throw new \RuntimeException("Ошибка получения следующего идентификатора"); + $pg = $this->isPostgres(); + $prep = array(); + foreach ($values as $key => $value) { + $result = null; + if(is_bool($value)) { + if ($pg) { + $result = $value ? 'true' : 'false'; + } else { + $result = $value ? 1 : 0; + } + } else { + $result = $value; } - return $result['nextval']; + $prep[":" . $key] = $result; } + return $prep; + } + /** + * Создает INSERT запрос + */ + function insertQuery($table, array $values, $return_id = false, $index = null) + { + $prep = $this->prepareValues($values); - /** - * Закрывает соединение с базой данных - */ - function close(): void - { + $sql = "INSERT INTO $table (" . implode(",", array_keys($values)) + . ") VALUES (" . implode(",", array_keys($prep)). ")"; + if ($return_id) { + if ($this->isPostgres()){ + $sql = $sql." RETURNING $index"; + } + } + $stmt = $this->prepare($sql); + $stmt->setFetchMode(PDO::FETCH_ASSOC); + $stmt->execute($prep); + $result = $stmt->fetch(); + if ($return_id) { + if ($this->isPostgres()) { + return $result[$index]; + } else { + $result = $this->fetchOneArray("SELECT $index AS lastid FROM $table WHERE OID = last_insert_rowid()"); + return $result['lastid']; + } } } + + /** + * Создает UPDATE запрос + */ + function updateQuery($table, array $values, $cond) + { + $prep = $this->prepareValues($values); + $sql = "UPDATE $table SET " . implode(",", + array_map(function($k,$v){return $k."=".$v;}, array_keys($values), array_keys($prep))) . " WHERE $cond"; + + $stmt = $this->prepare($sql); + $stmt->setFetchMode(PDO::FETCH_ASSOC); + $stmt->execute($prep); + } + + function getIdGenerator() { + return new Database_IdGenerator($this); + } + + /** + * Замечание: Только для Postgres SQL + * @param string $seq Имя последовательности для ключа таблицы + * @return int Идентефикатор следующей записи + */ + function getNextId($seq) { + $result = $this->fetchOneArray("SELECT nextval('$seq')"); + return $result['nextval']; + } + + function close() + { + return null; + } } diff --git a/src/Database/IdGenerator.php b/src/Database/IdGenerator.php index 6cad31a..045ec86 100644 --- a/src/Database/IdGenerator.php +++ b/src/Database/IdGenerator.php @@ -1,43 +1,26 @@ db = $db; } - /** - * @return bool - */ function isBeforeInsert() { - return false; - } + return false; + } - /** - * @return bool - */ function isAfterInsert() { - return true; + return true; } - - /** - * @param string $seq - * @return int - */ + function getId($seq) { if ($this->db->isPostgres()) { $result = $this->db->fetchOneArray("SELECT nextval('$seq') AS nextval"); } else { $result = $this->db->fetchOneArray("SELECT last_insert_rowid() AS nextval"); - } - if (!$result) { - throw new \Exception("nextval failed"); - } - return (int)$result['nextval']; + } + return intval($result['nextval']); } } diff --git a/src/Database/JsonInstall.php b/src/Database/JsonInstall.php index f7842fb..078113b 100644 --- a/src/Database/JsonInstall.php +++ b/src/Database/JsonInstall.php @@ -1,175 +1,143 @@ db_manager = $db_manager; - } + public function __construct(Database_Manager $db_manager) { + $this->db_manager = $db_manager; + } - /** - * Установить базу данных - * @param string $dbinit_path - * @param ?string $dbfill_path - * @return int - */ - function install($dbinit_path, $dbfill_path = null) { - $dbinit_file = file_get_contents($dbinit_path); - if (is_string($dbinit_file)) { - $initActions = json_decode($dbinit_file, true); - if (!$initActions) { - echo "Invalid ".$dbinit_path; - return 0; - } - } else { - echo "No ".$dbinit_path; - return 0; - } + function install($dbinit_path, $dbfill_path = null) { + $dbinit_file = file_get_contents($dbinit_path); + if (is_string($dbinit_file)) { + $initActions = json_decode($dbinit_file, true); + if (!$initActions) { + echo "Invalid ".$dbinit_path; + return 0; + } + } else { + echo "No ".$dbinit_path; + return 0; + } - $this->initDataBase($initActions, $dbinit_path); - if ($dbfill_path) { - $this->fillDataBase($dbfill_path); - } - $this->makeConstraints($initActions); - return 1; - } + $this->initDataBase($initActions, $dbinit_path); + if ($dbfill_path) { + $this->fillDataBase($dbfill_path); + } + $this->makeConstraints($initActions); + } - /** - * Получить список таблиц, которые не существуют в базе данных - * @param array $tables - * @return array - */ - function missingTables($tables) { - $actual_tables = $this->db_manager->getAllTableNames(); - $missingTables = []; - foreach ($tables as $table) { - if (!in_array($table, $actual_tables)) - $missingTables[] = $table; - } - return $missingTables; - } + function missingTables($tables) { + $actual_tables = $this->db_manager->GetAllTableNames(); + $missingTables = []; + foreach ($tables as $table) { + if (!in_array($table, $actual_tables)) + $missingTables[] = $table; + } + return $missingTables; + } - /** - * Создать таблицы - * @param array $initActions - * @param string $dbinit_path - * @return void - */ - function initDataBase(array $initActions, $dbinit_path) { - $pg = $this->db_manager->db->isPostgres(); - if (!$pg) { - $refs = []; - //В sqlite нет alter reference. Референсы надо создавать при создании таблицы. - foreach ($initActions as $action) { - if ($action["type"] == "alterReference") { - if (!isset($refs[$action["table"]])) - $refs[$action["table"]] = []; - $refs[$action["table"]][]=$action;//добавить к списку референсов для таблицы - } - } - } + //Создать таблицы + function initDataBase($initActions/*: array*/, $dbinit_path) { + $pg = $this->db_manager->db->isPostgres(); + if (!$pg) { + $refs = []; + //В sqlite нет alter reference. Референсы надо создавать при создании таблицы. + foreach ($initActions as $action) { + if ($action["type"] == "alterReference") { + if (!isset($refs[$action["table"]])) + $refs[$action["table"]] = []; + $refs[$action["table"]][]=$action;//добавить к списку референсов для таблицы + } + } + } - foreach ($initActions as $action) { - if (!$pg) { - if ($action["type"] == "createTable") { - $table_name = $action["table_name"]; - if (isset($refs[$table_name])) { - foreach ($refs[$table_name] as $value) { - $action['fields'][$value['column']]['references'] = [ - "refTable" => $value['refTable'], - 'refColumn' => $value['refColumn'] - ]; - } - } + foreach ($initActions as $action) { + if (!$pg) { + if ($action["type"] == "createTable") { + $table_name = $action["table_name"]; + if (isset($refs[$table_name])) { + foreach ($refs[$table_name] as $value) { + $action['fields'][$value['column']]['references'] = + $value['refTable']."(".$value['refColumn'].")"; + } + } - } - } - if ($action["type"] != "alterReference") { - $this->db_manager->executeAction($action, $dbinit_path); - } - } + } + } + if ($action["type"] != "alterReference") { + $this->db_manager->ExecuteAction($action, $dbinit_path); + } + } - //Запомнить все колонки serial - $this->serialColumns = []; - if ($pg) { - foreach ($initActions as $action) { - if ($action["type"] == "createTable") { - foreach ($action["fields"] as $name => $field) { - if ($field["type"]=="serial") { - $this->serialColumns[] = [ + //Запомнить все колонки serial + $this->serialColumns = []; + if ($pg) { + foreach ($initActions as $action) { + if ($action["type"] == "createTable") { + foreach ($action["fields"] as $name => $field) { + if ($field["type"]=="serial") { + $this->serialColumns[] = [ "table"=>$action["table_name"], - "column"=>$name + "column"=>$name ]; - } - } - } - } - } - } + } + } + } + } + } + } - /** - * Заполнить данными - * @param string $dbfill_file_path - * @return void - */ - function fillDataBase($dbfill_file_path) { - $dbfill_file = file_get_contents($dbfill_file_path); - if (is_string($dbfill_file)) { - $actions = json_decode($dbfill_file,true); - if ($actions) { - - //Проверка что упоминаемые в списке действий таблицы уже есть в базе - $affected_tables = []; - foreach ($actions as $action) { - if ($action["table_name"]) { - $affected_tables[$action["table_name"]] = 1; + //Заполнить данными + function fillDataBase($dbfill_file_path) { + $dbfill_file = file_get_contents($dbfill_file_path); + if (is_string($dbfill_file)) { + $actions = json_decode($dbfill_file,true); + if ($actions) { + + //Проверка что упоминаемые в списке действий таблицы уже есть в базе + $affected_tables = []; + foreach ($actions as $action) { + if ($action["table_name"]) { + $affected_tables[$action["table_name"]] = 1; } } - $missing = $this->missingTables(array_keys($affected_tables)); - if (!empty($missing)) { - echo "dbfill error. Missing tables: ".implode(" ", $missing); - return; + $missing = $this->missingTables(array_keys($affected_tables)); + if (!empty($missing)) { + echo "dbfill error. Missing tables: ".implode(" ", $missing); + return; + } + + //Выполнение действий + foreach ($actions as $action) { + $this->db_manager->ExecuteAction($action, $dbfill_file_path); + } + } else { + echo "Invalid dbfill.json"; + } + } else { + echo "No dbfill.json"; + } + } + + //Обновить ключи serial и создать ограничения + function makeConstraints($initActions) { + $pg = $this->db_manager->db->isPostgres(); + if ($pg) { + foreach ($this->serialColumns as $serialColumn) { + $this->db_manager->UpdateSerial($serialColumn["table"], $serialColumn["column"]); + } + + + foreach ($initActions as $action) { + if ($action["type"] == "alterReference") { + $this->db_manager->ExecuteAction($action); } - - //Выполнение действий - foreach ($actions as $action) { - $this->db_manager->executeAction($action, $dbfill_file_path); - } - } else { - echo "Invalid dbfill.json"; - } - } else { - echo "No dbfill.json"; - } - } - - /** - * Обновить ключи serial и создать ограничения - * @param array $initActions - * @return void - */ - function makeConstraints($initActions) { - $pg = $this->db_manager->db->isPostgres(); - if ($pg) { - foreach ($this->serialColumns as $serialColumn) { - $this->db_manager->updateSerial($serialColumn["table"], $serialColumn["column"]); - } - - - foreach ($initActions as $action) { - if ($action["type"] == "alterReference") { - $this->db_manager->executeAction($action); - } - } - } - } + } + } + } } \ No newline at end of file diff --git a/src/Database/Manager.php b/src/Database/Manager.php index ff8211e..f5bdaf0 100644 --- a/src/Database/Manager.php +++ b/src/Database/Manager.php @@ -1,397 +1,221 @@ -, type: string}|string, - * fields:array, - * } - * - * @phpstan-type AddColumnAction array{ - * type:"addColumn", - * table_name:string, - * column_name:string, - * field:ColumnProps - * } - * - * @phpstan-type AlterReferenceAction array{ - * type:"alterReference", - * table:string, - * column:string, - * refTable:string, - * refColumn:string - * } - * - * @phpstan-type RenameColumnAction array{ - * type:"renameColumn", - * table:string, - * old_name:string, - * new_name:string - * } - * - * @phpstan-type ExecuteFileAction array{ - * type:"executeFile", - * source:string, - * pgsql:?string - * } - * - * @phpstan-type CreateViewAction array{ - * type:"createView", - * view:string, - * select:string - * } - * - * @phpstan-type InsertAction array{ - * type:"insert", - * table_name:string, - * values:array - * } - * - * @phpstan-type Action DropAction - * | CreateAction - * | AddColumnAction - * | AlterReferenceAction - * | RenameColumnAction - * | ExecuteFileAction - * | CreateViewAction - * | InsertAction - * - * @phpstan-type ColumnProps array{ - * name:string, - * type:string, - * not_null:bool, - * default:?string, - * references:?array{refTable:string,refColumn:string} - * } - */ -class Manager +class Database_Manager { - /** @var Database */ - public $db; + public $db/*: Database*/; - public function __construct(Database $db) - { - $this->db = $db; - } + function __construct(Database $db) { + $this->db = $db; + } - /** - * Выполняет действие - * @param Action $action - * @param string $db_file - * @throws Exception - */ - public function executeAction(array $action, $db_file = ""): void - { - switch ($action["type"]) { - case "dropTable": - $this->dropTableQuery($action["table_name"], true); - break; - case "createTable": - $constraints = $action["constraints"] ?? null; - $this->createTableQuery($action["table_name"], $action["fields"], $constraints); - break; + public function ExecuteAction($action/*: array*/, $db_file = "") { + switch($action["type"]) { + case "dropTable": + $this->DropTableQuery($action["table_name"], true); + break; + case "createTable": + $constraints = isset($action["constraints"]) ? $action["constraints"] : NULL; + $this->CreateTableQuery($action["table_name"], $action["fields"], $constraints); + break; case "addColumn": - $this->addColumn($action["table_name"], $action["column_name"], $action["field"]); + $this->AddColumn($action["table_name"], $action["column_name"], $action["field"]); + break; + case "insert": + $this->db->insertQuery($action["table_name"], $action["values"]); + break; + case "alterReference": + $this->AlterReference($action["table"], $action["column"], $action["refTable"], $action["refColumn"]); + break; + case "renameColumn": + $this->RenameColumn($action["table"], $action["old_name"], $action["new_name"]); break; - case "insert": - $this->db->insertQuery($action["table_name"], $action["values"]); - break; - case "alterReference": - $this->alterReference($action["table"], $action["column"], $action["refTable"], $action["refColumn"]); - break; - case "renameColumn": - $this->renameColumn($action["table"], $action["old_name"], $action["new_name"]); - break; - case "createView": - $this->recreateView($action["view"], $action["select"]); - break; - case "executeFile": + case "executeFile": if ($this->db->isPostgres() && isset($action["pgsql"])) { - $file = $action["pgsql"]; + $file = $action["pgsql"]; } else { - $file = $action["source"]; + $file = $action["source"]; } - $stmtList = SQLStatementExtractor::extractFile(Path::join(dirname($db_file), $file)); - foreach ($stmtList as $stmt) { + $stmtList = Tools_SQLStatementExtractor::extractFile(Path::join(dirname($db_file), $file)); + foreach($stmtList as $stmt) { $this->db->executeQuery($stmt); } break; - default: - throw new Exception("unknown action " . $action["type"] . PHP_EOL); - } - } + default: + throw new Exception("unknown action ". $action["type"] . PHP_EOL); + } + } - /** - * Дропает и создаёт SQL VIEW - * @param string $viewName - * @param string $selectStatement - */ - public function recreateView($viewName, $selectStatement): void - { - $this->db->query("DROP VIEW " . $viewName); - $this->db->query("CREATE VIEW " . $viewName . " AS " . $selectStatement); - } + public function DropTableQuery($table, $cascade=false) { + $statement = "DROP TABLE IF EXISTS ".$table; + if ($this->db->isPostgres()&&$cascade) { + $statement = $statement." CASCADE"; + } + $this->db->query($statement); + } - /** - * Дропает таблицу - * @param string $table - * @param bool $cascade - */ - public function dropTableQuery($table, $cascade = false): void - { - $statement = "DROP TABLE IF EXISTS " . $table; - if ($this->db->isPostgres() && $cascade) { - $statement .= " CASCADE"; - } - $this->db->query($statement); - } + public function AlterReference($table,$column,$refTable,$refColumn) { + $this->db->query("ALTER TABLE ".$table." ADD CONSTRAINT ".$table."_".$column."fk"." FOREIGN KEY (".$column.") REFERENCES ".$refTable." (".$refColumn.")"); + } - /** - * Добавляет ссылку на другую таблицу - * @param string $table - * @param string $column - * @param string $refTable - * @param string $refColumn - */ - public function alterReference($table, $column, $refTable, $refColumn): void - { - $this->db->query("ALTER TABLE " . $table . " ADD CONSTRAINT " . $table . "_" . $column . "fk" . " FOREIGN KEY (" . $column . ") REFERENCES " . $refTable . " (" . $refColumn . ") ON DELETE CASCADE ON UPDATE CASCADE"); - } - - /** - * Извлечение информации о полях таблицы - * @param string $table - * @return array{type:string,not_null:bool,constraint:?string}[]|null - */ - public function tableInfo($table) - { - $pg = $this->db->isPostgres(); - if ($pg) { - throw new Exception("Not implemented for postgres"); - } else { - $results = $this->db->fetchAllArray("PRAGMA table_info(" . $table . ");"); - if (empty($results)) { - return null; + //Извлечение информации о полях таблицы + public function TableInfo($table) { + $pg = $this->db->isPostgres(); + if ($pg) { + throw new Exception("Not implemented for postgres"); + } else { + $results = $this->db->fetchAllArray("PRAGMA table_info(".$table.");"); + if (empty($results)) { + return null; } - $fields = []; - foreach ($results as $result) { - $fields[$result["name"]] = [ - "type" => $result["type"], - "not_null" => boolval($result["notnull"]), - "constraint" => ((bool) $result["pk"]) ? "PRIMARY KEY" : null + $fields = []; + foreach ($results as $result) { + $fields[$result["name"]] = [ + "type"=> $result["type"], + "not_null"=> boolval($result["notnull"]), + "constraint"=> ((boolean) $result["pk"]) ? "PRIMARY KEY" : null ]; - } - return $fields; - } - } + } + return $fields; + } + } - /** - * Переименование столбца в таблице - * @param string $table - * @param string $old_name - * @param string $new_name - */ - public function renameColumn($table, $old_name, $new_name): void - { - $pg = $this->db->isPostgres(); - if ($pg) { - $this->db->query("ALTER TABLE " . $table . " RENAME COLUMN " . $old_name . " TO " . $new_name); - } else { - $tmp_table = "tmp_" . $table; - $this->dropTableQuery($tmp_table); - $table_info = $this->tableInfo($table); + public function RenameColumn($table, $old_name, $new_name) { + $pg = $this->db->isPostgres(); + if ($pg) { + $this->db->query("ALTER TABLE ".$table." RENAME COLUMN ".$old_name." TO ".$new_name); + } else { + $tmp_table = "tmp_" . $table; + $this->DropTableQuery($tmp_table); + $table_info = $this->TableInfo($table); - if (isset($table_info[$new_name])) { - return; + if (isset($table_info[$new_name])) { + return; } - $data = $this->dumpTable($table); + $data/*: array*/ = $this->DumpTable($table); - $this->db->query("ALTER TABLE " . $table . " RENAME TO " . $tmp_table . ";"); - $table_info[$new_name] = $table_info[$old_name]; - unset($table_info[$old_name]); - $this->createTableQuery($table, $table_info, null); + $this->db->query("ALTER TABLE ".$table." RENAME TO ".$tmp_table.";"); + $table_info[$new_name] = $table_info[$old_name]; + unset($table_info[$old_name]); + $this->CreateTableQuery($table,$table_info,null); - foreach ($data as $row) { - $values = $row['values']; - $values[$new_name] = $values[$old_name]; - unset($values[$old_name]); - $this->db->insertQuery($table, $values); - } - $this->dropTableQuery($tmp_table); - } - } + foreach ($data as $row) { + $values = $row['values']; + $values[$new_name] = $values[$old_name]; + unset($values[$old_name]); + $this->db->insertQuery($table, $values); + } + $this->DropTableQuery($tmp_table); + } + } - /** - * Обновление ключа serial после ручной вставки - * @param string $table - * @param string $column - */ - public function updateSerial($table, $column): void - { - $this->db->query("SELECT setval(pg_get_serial_sequence('" . $table . "', '" . $column . "'), coalesce(max(" . $column . "),0) + 1, false) FROM " . $table); - } + //Обновление ключа serial после ручной вставки + public function UpdateSerial($table,$column) { + $this->db->query("SELECT setval(pg_get_serial_sequence('".$table."', '".$column."'), coalesce(max(".$column."),0) + 1, false) FROM ".$table); + } - /** - * Возвращает определение столбца - * @param string $name - * @param ColumnProps $data - * @param bool $pg - * @return string - */ - public function columnDefinition($name, $data, $pg) - { - $constraint = isset($data['constraint']) ? " " . $data['constraint'] : ""; - $references = ""; - if (isset($data['references'])) { - $references = " REFERENCES " . $data['references']['refTable'] . '(' . $data['references']['refColumn'] . ')'; - } - if (isset($data["not_null"]) && $data["not_null"]) { - $constraint .= " NOT NULL"; - } - $type = $data['type']; - if (!$pg) { - if (strtolower($type) == "serial") { - $type = "integer"; - } - } - return $name . " " . $type . $references . $constraint; - } + public function Column_Definition($name,$data,$pg){ + $constraint = isset($data['constraint'])?" ".$data['constraint']:""; + $references = ""; + if (isset($data['references'])) { + $references = " REFERENCES ".$data['references']; + } + if (isset($data["not_null"]) && $data["not_null"]) + $constraint .=" NOT NULL"; + $type = $data['type']; + if (!$pg) { + if (strtolower($type)=="serial") + $type = "integer"; + //if (strtolower($type)=="boolean") + // $type = "integer"; + } + return $name." ".$type.$references.$constraint; + } - /** - * Добавляет столбец в таблицу - * @param string $table_name - * @param string $column_name - * @param ColumnProps $field - */ - public function addColumn($table_name, $column_name, $field): void - { - $pg = $this->db->isPostgres(); - $q = "ALTER TABLE " . $table_name . " ADD COLUMN " . - $this->columnDefinition($column_name, $field, $pg); - $this->db->query($q); - } + public function AddColumn($table_name,$column_name,$field){ + $pg = $this->db->isPostgres(); + $q = "ALTER TABLE ".$table_name." ADD COLUMN ". + $this->Column_Definition($column_name, $field, $pg); + $this->db->query($q); + } - /** - * Возвращает определение ограничения - * @param array{fields: string[], type: string} $c - * @return string - */ - public function getConstraintDef(array $c) - { + function getConstraintDef($c/*: array*/) { if ($c['type'] == 'unique') { return "UNIQUE(" . implode(", ", $c['fields']) . ")"; } return ""; } - - /** - * Создает таблицу - * @example createTableQuery('users',['id'=>['type'=>'integer','constraint'=>'PRIMARY KEY']]) - * @param string $table - * @param array $fields - * @param array{fields: array, type: string}|string|null $constraints - */ - public function createTableQuery($table, $fields, $constraints): void - { - $pg = $this->db->isPostgres(); - if ($constraints) { + //CreateTableQuery('users',['id'=>['type'=>'integer','constraint'=>'PRIMARY KEY']]) + public function CreateTableQuery($table, $fields, $constraints) { + $pg = $this->db->isPostgres(); + if ($constraints) { if (is_array($constraints)) { $constraints = $this->getConstraintDef($constraints); } - $constraints = ", " . $constraints; + $constraints = ", " . $constraints; } - $statement = "CREATE TABLE $table (" . implode( - ",", - array_map(function ($name, $data) use ($pg) { - return $this->columnDefinition($name, $data, $pg); - }, array_keys($fields), array_values($fields)) - ) . " " . $constraints . ")"; - $this->db->query($statement); - } + $statement = "CREATE TABLE $table (" . implode(",", + array_map(function($name,$data) use ($pg) { + return $this->Column_Definition($name,$data,$pg); + }, array_keys($fields), array_values($fields)) + ) . " " . $constraints . ")"; + $this->db->query($statement); + } - /** - * Возвращает дамп таблицы - * @param string $table_name - * @return array - */ - public function dumpTable($table_name) - { - $pg = $this->db->isPostgres(); + public function DumpTable($table_name) { + $pg = $this->db->isPostgres(); - $result = []; - $data = $this->db->fetchAllArray("SELECT * FROM " . $table_name . ";"); + $result/*: array*/ = array(); + $data/*: array*/ = $this->db->fetchAllArray("SELECT * FROM ".$table_name.";"); - if (!$pg) { - $table_fields = $this->tableInfo($table_name); - foreach ($table_fields as $name => $value) { - $type = strtolower($value['type']); - if ($type == "boolean") { - foreach ($data as &$row) { - if (isset($row[$name])) { - $row[$name] = boolval($row[$name]); - } - } - } - } - } - foreach ($data as $r) { - $result[] = [ + if (!$pg) { + $table_fields = $this->TableInfo($table_name); + foreach ($table_fields as $name => $value) { + $type = strtolower($value['type']); + if ($type == "boolean") { + foreach ($data as &$row) { + $row/*: array*/ = $row; + if (isset($row[$name])) { + $row[$name] = boolval($row[$name]); + } + } + } + } + } + foreach ($data as $r) { + $result[] = array( "type" => "insert", - "table_name" => $table_name, - "values" => $r - ]; - } - return $result; - } + "table_name" => $table_name, + "values" => $r + ); + } + return $result; + } - /** - * Возвращает все имена таблиц - * @return list - */ - public function getAllTableNames() - { - $result = []; - if ($this->db->isPostgres()) { - $query = "SELECT table_name as name FROM information_schema.tables WHERE table_schema='public'"; - } else { - $query = "SELECT * FROM sqlite_master WHERE type='table'"; + public function GetAllTableNames() { + $result = []; + if ($this->db->isPostgres()) { + $query = "SELECT table_name as name FROM information_schema.tables WHERE table_schema='public'"; + } else { + $query = "SELECT * FROM sqlite_master WHERE type='table'"; } - $tables = $this->db->fetchAllArray($query); - foreach ($tables as $table) { - $result[] = $table['name']; + $tables = $this->db->fetchAllArray($query); + foreach ($tables as $table) { + $result[] = $table['name']; } - return $result; - } + return $result; + } - /** - * Возвращает дамп всех таблиц - * @return array - */ - public function dumpInserts() - { - $table_names = $this->getAllTableNames(); - $result = []; - foreach ($table_names as $table_name) { - $result = array_merge($result, $this->dumpTable($table_name)); - } - return $result; - } -} + public function DumpInserts() { + $table_names = $this->GetAllTableNames(); + $result = array(); + foreach ($table_names as $table_name) { + $result = array_merge($result, $this->DumpTable($table_name)); + } + return $result; + } +} \ No newline at end of file diff --git a/src/Database/PDOStatement.php b/src/Database/PDOStatement.php index 69a1c49..11ccdd9 100644 --- a/src/Database/PDOStatement.php +++ b/src/Database/PDOStatement.php @@ -1,67 +1,48 @@ - */ -class PDOStatement extends \PDOStatement implements \IteratorAggregate +class Database_PDOStatement extends PDOStatement implements IteratorAggregate { - /** @var int */ protected $cursorPos = 0; - /** @var array */ - public $cache = []; - /** @var ?array */ + public $cache = array(); public $fields; - function getIterator(): \Iterator { - return new StatementIterator($this); + function getIterator(): Iterator { + return new Database_StatementIterator($this); } - protected function __construct() { + protected function __construct() { } - function rewind(): void { + function rewind() { $this->cursorPos = 0; } - /** - * @param int $rownum - * @return bool - */ - public function seek($rownum): bool { - if ($rownum < 0) { - return false; - } + public function seek($rownum) { + if ($rownum < 0) { + return false; + } + + // PostgreSQL rows start w/ 0, but this works, because we are + // looking to move the position _before_ the next desired position + $this->cursorPos = $rownum; + return true; + } - // PostgreSQL rows start w/ 0, but this works, because we are - // looking to move the position _before_ the next desired position - $this->cursorPos = $rownum; - return true; + function valid() { + return true; } - function valid(): bool { - return true; - } - /** - * @return bool - */ public function first() { - if ($this->cursorPos !== 0) { $this->seek(0); } + if($this->cursorPos !== 0) { $this->seek(0); } return $this->next(); } - function next(): bool{ + function next() { if ($this->getRecordCount() > $this->cursorPos) { if (!isset($this->cache[$this->cursorPos])) { $this->cache[$this->cursorPos] = $this->fetch(PDO::FETCH_ASSOC); - } + } $this->fields = $this->cache[$this->cursorPos]; $this->cursorPos++; @@ -72,87 +53,50 @@ class PDOStatement extends \PDOStatement implements \IteratorAggregate } } - function key(): int { + function key() { return $this->cursorPos; } - /** - * @return mixed - */ function current() { return $this->cache[$this->cursorPos]; } - /** - * @return array|null - */ function getRow() { return $this->fields; } - /** - * @param string $name - * @return int - */ - function getInt($name): int { + function getInt($name) { if (!$this->fields) { - throw new \Exception('no fields'); + throw new Error('no fields'); } return (int)$this->fields[$name]; } - /** - * @param string $name - * @return string - */ function getBlob($name) { return $this->fields[$name]; } - /** - * @param string $name - * @return string - */ function getString($name) { - return $this->fields[$name] ?? null; + return isset($this->fields[$name]) ? $this->fields[$name]: null; } - /** - * @param string $name - * @return bool - */ function getBoolean($name) { return (bool)$this->fields[$name]; } - /** - * @param string $name - * @return mixed - */ function get($name) { return $this->fields[$name]; } - /** - * @param string $name - * @return array - */ function getArray($name) { - return StringUtil::strToArray($this->fields[$name]); + return Tools_String::strToArray($this->fields[$name]); } - /** - * @return int - */ function getRecordCount() { return count($this->cache); } - - /** - * @param array $args - * @return bool - */ - function execute($args = null): bool { + + function execute($args = null) { $result = parent::execute($args); return $result; } diff --git a/src/Database/Statement.php b/src/Database/Statement.php index e270822..ae42fc7 100644 --- a/src/Database/Statement.php +++ b/src/Database/Statement.php @@ -1,83 +1,47 @@ query = $query; $this->conn = $conn; } - - /** - * @param int|string $n - * @param int $value - */ - function setInt($n, $value): void { - $this->binds [] = [$n, $value, PDO::PARAM_INT]; + + function setInt($n, $value) { + $this->binds [] = array($n, $value, PDO::PARAM_INT); } - /** - * @param int|string $n - * @param string $value - */ - function setString($n, $value): void { - $this->binds [] = [$n, $value, PDO::PARAM_STR]; + function setString($n, $value) { + $this->binds [] = array($n, $value, PDO::PARAM_STR); } - /** - * @param int|string $n - * @param mixed $value - */ - function setBlob($n, $value): void { - $this->binds [] = [$n, $value, PDO::PARAM_LOB]; + function setBlob($n, $value) { + $this->binds [] = array($n, $value, PDO::PARAM_LOB); } - /** - * @param int $limit - */ - function setLimit($limit): void { + function setLimit($limit) { $this->limit = $limit; } - /** - * @param int $offset - */ - function setOffset($offset): void { + function setOffset($offset) { $this->offset = $offset; } - /** - * @return PDOStatement - */ function executeQuery() { if ($this->limit) { $this->query .= " LIMIT {$this->limit} OFFSET {$this->offset}"; } - $stmt = $this->conn->prepare($this->query); + $stmt/*: Database_PDOStatement*/ = $this->conn->prepare($this->query); foreach ($this->binds as $bind) { list($n, $value, $type) = $bind; $stmt->bindValue($n, $value, (int) $type); diff --git a/src/Database/StatementIterator.php b/src/Database/StatementIterator.php index 43f82e9..8e6c970 100644 --- a/src/Database/StatementIterator.php +++ b/src/Database/StatementIterator.php @@ -1,59 +1,46 @@ - */ -class StatementIterator implements \Iterator +class Database_StatementIterator implements Iterator { - /** @var PDOStatement */ + private $result; - /** @var int */ private $pos = 0; - /** @var int */ + private $fetchmode; private $row_count; - - /** - * @param PDOStatement $rs - */ - public function __construct($rs) { + + public function __construct($rs/*: Database_PDOStatement*/) { $this->result = $rs; - $this->row_count = $rs->getRecordCount(); + $this->row_count = $rs->getRecordCount(); } - - function rewind(): void{ + + function rewind() { $this->pos = 0; } - - function valid(): bool { - return ($this->pos < $this->row_count); + + function valid() { + return ($this->pos < $this->row_count); } - - function key(): mixed { + + function key() { return $this->pos; } - - function current(): mixed{ + + function current() { if (!isset($this->result->cache[$this->pos])) { $this->result->cache[$this->pos] = $this->result->fetch(PDO::FETCH_ASSOC); - } + } return $this->result->cache[$this->pos]; } - - function next(): void { + + function next() { $this->pos++; } - /** - * @param int $index - */ - function seek($index): void { - $this->pos = $index; + function seek($index) { + $this->pos = $index; } - function count(): int { - return $this->row_count; + function count() { + return $this->row_count; } } diff --git a/src/Excel/DataTime.php b/src/Excel/DataTime.php index 7a910df..0536cbd 100644 --- a/src/Excel/DataTime.php +++ b/src/Excel/DataTime.php @@ -1,22 +1,16 @@ value = (int)$value; + $this->value = intval($value); } - function getString(): string + function getString() { return date('Y-m-d\TH:i:s.u', $this->value); - } + } } diff --git a/src/Excel/Document.php b/src/Excel/Document.php index 4a9480c..4600fad 100644 --- a/src/Excel/Document.php +++ b/src/Excel/Document.php @@ -3,45 +3,33 @@ /** * Документ */ -namespace ctiso\Excel; -use XMLWriter, - Exception; - -class Document { - /** @var string */ +class Excel_Document { static $ns = "urn:schemas-microsoft-com:office:spreadsheet"; - /** @var list */ - private $table = []; - /** @var array */ - protected $styles = []; + private $table = array (); + protected $styles = array(); - /** - * Добавление таблицы в документ - * @param Table|callable $table Таблица или функция, возвращающая таблицу - */ - function addTable($table): void { + function addTable($table) { $this->table [] = $table; } /** - * Добавление стиля к документу - * @param string $name string Имя стиля - * @param array $values array Параметры стиля - * @param string $type Тип стиля + * Добавление стиля к документу + * @param $name string Имя стиля + * @param $values array Параметры стиля + * @param $type Тип стиля */ - function setStyle ($name, array $values, $type = 'Interior'): void + function setStyle ($name, array $values, $type = 'Interior') { if(!isset($this->styles[$name])) { - $this->styles[$name] = []; - } + $this->styles[$name] = array(); + } $this->styles[$name][$type] = $values; } /** - * Генерация стилей + * Генерация стилей */ - private function createStyles (XMLWriter $doc): void - { + private function createStyles (XMLWriter $doc) { $doc->startElement('Styles'); foreach ($this->styles as $name => $sn) { $doc->startElement('Style'); @@ -51,6 +39,7 @@ class Document { if ($type == 'Borders') { $doc->startElement('Borders'); foreach ($s as $border) { + $border/*: array*/ = $border; $doc->startElement('Border'); foreach ($border as $key => $value) { $doc->writeAttribute('ss:' . $key, $value); @@ -73,25 +62,21 @@ class Document { /** * Преобразует переводы строки в спец символы - * @param string $s - * @return string */ function clean ($s) { - return strtr($s, ["\n" => " "]); - } + assert(is_string($s)); - /** + return strtr($s, array ("\n" => " ")); + } + + /** * Сохраняет таблицу в формате Office 2003 XML * http://en.wikipedia.org/wiki/Microsoft_Office_XML_formats - * - * @param string $filename - * @throws Exception - * @return void */ - function save($filename): void + function save($filename) { $doc = new XMLWriter(); - if (!$doc->openUri($filename)) { + if (!$doc->openURI($filename)) { throw new Exception("unknown file " . $filename); } $doc->setIndent(false); @@ -101,9 +86,9 @@ class Document { $doc->writeAttribute('xmlns:ss', self::$ns); $this->createStyles($doc); - + foreach ($this->table as $table) { - if ($table instanceof Table) { + if ($table instanceof Excel_Table) { $table->createTable($doc); } else { $table_data = call_user_func($table); diff --git a/src/Excel/Number.php b/src/Excel/Number.php index 3df78bb..dfc220a 100644 --- a/src/Excel/Number.php +++ b/src/Excel/Number.php @@ -1,23 +1,17 @@ value = (int)($value); } - function getString(): string + function getString() { - return (string) $this->value; - } + return $this->value; + } } diff --git a/src/Excel/Table.php b/src/Excel/Table.php index 395253e..6bc61db 100644 --- a/src/Excel/Table.php +++ b/src/Excel/Table.php @@ -1,25 +1,14 @@ value = $value; @@ -27,86 +16,65 @@ class TableCell } /** - * Ряд таблицы + * Ряд таблицы */ class TableRow { - /** @var string|false */ public $style = false; - /** @var TableCell[] */ - public $cells = []; - /** @var int|false */ + public $cells = array(); public $height = false; - - /** - * Устанавливает значение для клетки - * @param int $y Номер столбца - * @param string $value Значение клетки - */ - function setCell($y, $value): void + + function setCell($y, $value) { $this->cells[$y] = new TableCell($value); } - - /** - * Устанавливает стиль для клетки - * @param int $y Номер столбца - * @param string $name Имя стиля - */ - function setCellStyle($y, $name): void + + function setCellStyle($y, $name) { $this->cells[$y]->style = $name; } } /** - * Таблица + * Таблица */ -class Table +class Excel_Table { - /** @var int */ static $index; - /** @var string */ private $name; - /** @var TableRow[] */ - protected $rows = []; + private $style; + protected $rows = array(); - /** @var int|false */ protected $_splitVertical = false; - /** @var int|false */ protected $_splitHorizontal = false; function __construct() { - $this->name = "Page " . ((int)self::$index ++); + $this->name = "Page " . intval(self::$index ++); } /** - * Записать значение в клетку с заданными координатами - * @param int $x Номер ряда - * @param int $y Номер столбца - * @param string $value Значение клетки + * Записать значение в клетку с заданными координатами */ - function setCell(int $x, int $y, $value): void + function setCell($x, $y, $value) { - assert($x > 0); - assert($y > 0); + assert(is_numeric($x) && $x > 0); + assert(is_numeric($y) && $y > 0); if(! isset($this->rows[$x])) { $this->rows[$x] = new TableRow(); } - - $row = $this->rows[$x]; + $row/*: TableRow*/ = $this->rows[$x]; $row->setCell($y, $value); } /** * Заполняет ряд начиная с указанного столбца значениями из массива */ - function setRow(int $row, int $index, array $data): void + function setRow($row, $index, array $data) { - assert($index > 0); - assert($row > 0); + assert(is_numeric($index) && $index > 0); + assert(is_numeric($row) && $row > 0); reset($data); for ($i = $index; $i < $index + count($data); $i++) { @@ -117,125 +85,115 @@ class Table /** * Устанавливает высоту ряда - * @param int $row Номер ряда - * @param int $value Высота ряда + * @param $row integer Номер ряда + * @parma $value real Высота ряда */ - function setRowHeight (int $row, $value): void + function setRowHeight ($row, $value) { - assert($row > 0); + assert(is_numeric($row) && $row > 0); $this->rows[$row]->height = $value; } /** * Устанавливает стиль ряда - * @param int $row Номер ряда - * @param string $name Имя стиля + * @param $row integer Номер ряда + * @parma $name string Имя стиля */ - function setRowStyle(int $row, $name): void + function setRowStyle ($row, $name) { - assert($row > 0); + assert(is_numeric($row) && $row > 0); $this->rows[$row]->style = $name; } /** * Обьединяет клетки в строке - * @param int $x Номер ряда - * @param int $cell Номер столбца - * @param bool $merge Количество клеток для обьединения + * @param $row Номер ряда + * @param $cell Номер столбца + * @param $merge Количество клеток для обьединения */ - function setCellMerge(int $x, int $cell, $merge): void + function setCellMerge($x, $cell, $merge) { - assert($x > 0); - assert($cell > 0); + assert(is_numeric($x) && $x > 0); + assert(is_numeric($cell) && $cell > 0); - $row = $this->rows[$x]; + $row/*: TableRow*/ = $this->rows[$x]; $row->cells[$cell]->merge = $merge; } /** * Устанавливает стиль для клеток ряда - * @param int $row Номер ряда - * @param int $y Номер столбца - * @param string $name Имя стиля + * @param $row integer Номер ряда + * @param $y integer Номер столбца + * @parma $name string Имя стиля */ - function setCellStyle ($row, $y, $name): void + function setCellStyle ($row, $y, $name) { - if (isset($this->rows[$row])) { + if (isset($this->rows[$row])) $this->rows[$row]->setCellStyle($y, $name); - } } /** * Добавляет строку к таблице - * @return int Номер добавленной строки - */ - function addRow(int $index = 1, array $data = [""]) + */ + function addRow($index = 1, array $data = array("")) { - assert($index > 0); + assert(is_numeric($index) && $index > 0); $offset = $this->getRows() + 1; - + $this->setRow($offset, $index, $data); return $offset; - } + } /** * Количество строк в таблице * * @return int - */ + */ function getRows() { - // Высчитываем максимальный индекс, массив может быть разрежен поэтому используем array_keys - $keys = array_keys($this->rows); - return $keys === [] ? 0 : max($keys); + $keys/*: array*/ = array_keys($this->rows); + return max($keys); } - + /** * Количество столбцов в строке - * - * @return int + * + * @return int */ function getRowCells(TableRow $row) { - $keys = array_keys($row->cells); - return $keys === [] ? 0 :max($keys); - } + $keys/*: array*/ = array_keys($row->cells); + return max($keys); + } /** * Разделяет таблицу на две части по вертикали - * @param int $n Количество столбцов слева + * @param $n integer Количество столбцов слева */ - function splitVertical($n): void { + function splitVertical($n) { $this->_splitVertical = $n; } /** * Разделяет таблицу на две части по горизонтали - * @param int $n Количество столбцов сверху + * @param $n integer Количество столбцов сверху */ - function splitHorizontal($n): void { + function splitHorizontal($n) { $this->_splitHorizontal = $n; } /** * Количество столбцов в таблице - * + * * @return int - */ + */ function getColumns() { - $columns = array_map($this->getRowCells(...), $this->rows); - return $columns === [] ? 0 : max($columns); + return max(array_map(array($this, 'getRowCells'), $this->rows)); } - /** - * Кодирование строки - * @deprecated Можно заменить на значение - * @param string $s Строка - * @return string - */ function encode($s) { return $s; @@ -243,13 +201,8 @@ class Table /** * Генерация клетки таблицы (Переработать) - * @param TableCell $ncell Клетка таблицы - * @param XMLWriter $doc XMLWriter - * @param int $j Индекс клетки - * @param mixed $value Значение клетки - * @param bool $setIndex Устанавливать индекс клетки в атрибут ss:Index */ - function createCell (TableCell $ncell, XMLWriter $doc, $j, mixed $value, $setIndex): void { + function createCell (TableCell $ncell, XMLWriter $doc, $j, $value/*: any*/, $setIndex) { $doc->startElement("Cell"); if ($ncell->style) { @@ -257,11 +210,11 @@ class Table } if ($ncell->merge) { - $doc->writeAttribute('ss:MergeAcross', (string)$ncell->merge); + $doc->writeAttribute('ss:MergeAcross', $ncell->merge); } if ($setIndex) { - $doc->writeAttribute('ss:Index', (string)$j); + $doc->writeAttribute('ss:Index', $j); } $doc->startElement("Data"); @@ -270,23 +223,23 @@ class Table $doc->text($value->getString()); } else if ($value instanceof Excel_Number) { $doc->writeAttribute('ss:Type', "Number"); - $doc->text($value->getString()); + $doc->text($value->getString()); } else { if (is_string($value)) { $doc->writeAttribute('ss:Type', "String"); } else { $doc->writeAttribute('ss:Type', "Number"); } - $doc->writeCdata($value); - } - $doc->endElement(); + $doc->writeCData($this->encode($value)); + } $doc->endElement(); + $doc->endElement(); } - + /** - * Генерация таблицы + * Генерация таблицы */ - public function createTable (XMLWriter $doc): void { + public function createTable (XMLWriter $doc) { $doc->startElement('Worksheet'); $doc->writeAttribute('ss:Name', $this->name); @@ -294,8 +247,8 @@ class Table $rows = $this->getRows(); $doc->startElement('Table'); - $doc->writeAttribute('ss:ExpandedColumnCount', (string)$columns); - $doc->writeAttribute('ss:ExpandedRowCount', (string)$rows); + $doc->writeAttribute('ss:ExpandedColumnCount', $columns); + $doc->writeAttribute('ss:ExpandedRowCount', $rows); // Переписать цыкл !!!!!!! for ($i = 1; $i <= $rows; $i++) { @@ -306,26 +259,26 @@ class Table } if ($this->rows[$i]->height) { - $doc->writeAttribute('ss:Height', (string)$this->rows[$i]->height); + $doc->writeAttribute('ss:Height', $this->rows[$i]->height); } - /** @var TableRow $nrow */ - $nrow = $this->rows[$i]; + + $nrow/*: TableRow*/ = $this->rows[$i]; // Флаг индикатор подстановки номера столбца $setIndex = false; for ($j = 1; $j <= $columns; $j++) { - + $value = null; if (isset($nrow->cells[$j])) { $value = $nrow->cells[$j]->value; } - + if (!empty($value)) { $this->createCell($nrow->cells[$j], $doc, $j, $value, $setIndex); $setIndex = false; } else { $setIndex = true; } - } + } } $doc->endElement(); } @@ -334,24 +287,25 @@ class Table $doc->endElement(); } - protected function splitPane (XMLWriter $doc): void { - $doc->startElement('WorksheetOptions'); + protected function splitPane (XMLWriter $doc) { + $doc->startElement('WorksheetOptions'); $doc->writeAttribute('xmlns', 'urn:schemas-microsoft-com:office:excel'); $doc->writeElement('FrozenNoSplit'); if ($this->_splitVertical) { - $doc->writeElement('SplitVertical', (string) $this->_splitVertical); - $doc->writeElement('LeftColumnRightPane', (string) $this->_splitVertical); + $doc->writeElement('SplitVertical', $this->_splitVertical); + $doc->writeElement('LeftColumnRightPane', $this->_splitVertical); } if ($this->_splitHorizontal) { - $doc->writeElement('SplitHorizontal', (string) $this->_splitHorizontal); - $doc->writeElement('TopRowBottomPane', (string) $this->_splitHorizontal); + $doc->writeElement('SplitHorizontal', $this->_splitHorizontal); + $doc->writeElement('TopRowBottomPane', $this->_splitHorizontal); } if ($this->_splitHorizontal && $this->_splitVertical) { - $doc->writeElement('ActivePane', (string) 0); + $doc->writeElement('ActivePane', 0); } else if($this->_splitHorizontal) { - $doc->writeElement('ActivePane', (string) 2); + $doc->writeElement('ActivePane', 2); } $doc->endElement(); } } + diff --git a/src/File.php b/src/File.php index 8ee2eae..27ca254 100644 --- a/src/File.php +++ b/src/File.php @@ -1,16 +1,8 @@ processor = $processor; - $this->user = $user; } /** * Проверка доступных действий для пользователя * !! Реализация класса проверки действий не должна быть внутри Контроллера!!! * Информация о доступе может быть в файле, базе данных и т.д. - * - * @param string $action - * @return bool */ function checkAction($action) { // Импликация !! http://ru.wikipedia.org/wiki/Импликация - return (!isset($this->access[$action]) || in_array($this->user->access, $this->access[$action])); + $name = $this->name; + return (!isset($this->access[$name][$action]) || in_array(Filter_UserAccess::$access, $this->access[$name][$action])); } - /** - * @param HttpRequest $request - * @return mixed - */ function execute(HttpRequest $request) { $action = $request->getAction(); if(! $this->checkAction($action)) { diff --git a/src/Filter/ActionLogger.php b/src/Filter/ActionLogger.php index ee94839..5a2cbab 100644 --- a/src/Filter/ActionLogger.php +++ b/src/Filter/ActionLogger.php @@ -1,44 +1,21 @@ processor = $processor; - $this->user = $user; - - $file = fopen($logPath, "a"); - if (is_resource($file)) { - $this->file = $file; - } else { - throw new \Exception('Ошибка открытия файла ' . $logPath); - } + $this->file = fopen(Shortcut::getUrl('access.log'), "a"); } function execute(HttpRequest $request) { $action = $request->getAction(); if(in_array($action, $this->before)) { - $line = ['time' => time(), 'user' => $this->user->getName(), 'sid' => session_id(), 'query' => array_merge($_POST, $_GET)]; + $line = ['time' => time(), 'user' => Filter_UserAccess::$name, 'sid' => session_id(), 'query' => array_merge($_POST, $_GET)]; fwrite($this->file, json_encode($line) . "\n"); } return $this->processor->execute($request); diff --git a/src/Filter/Authorization.php b/src/Filter/Authorization.php index 2421212..5afd556 100644 --- a/src/Filter/Authorization.php +++ b/src/Filter/Authorization.php @@ -1,24 +1,10 @@ group = $group; - } - - /** - * @param string $group - */ - static function isLogged($group = 'access'): bool { + static function isLogged($group = 'access') { // echo session_status(); if (session_status() == PHP_SESSION_NONE) { session_start(); @@ -30,45 +16,37 @@ class Authorization { // UserAccess::getUserById($_SESSION ['access']); // Поиск по идентификатору return true; } else { - return false; + return false; } } return false; } - /** - * @param int $id - * @param string $group - */ - static function enter($id, $group = 'access'): void { + static function enter($id, $group = 'access') + { // $db->executeQuery("UPDATE visitor SET sid = '' WHERE id_visitor = " . $result->getInt('id_user')); // session_register("access"); // session_register("time"); - $_SESSION [$group] = $id; +// $_SESSION ["group"] = $result->getInt('access'); + $_SESSION [$group] = $id; // id_user $_SESSION [self::SESSION_BROWSER_SIGN_KEYNAME] = self::getBrowserSign(); - $_SESSION ["sign"] = self::getRawSign(); - $_SESSION ["time"] = time(); + $_SESSION ["time"] = time(); } - static function getRawSign(): string + private static function getBrowserSign() { $rawSign = self::SESSION_BROWSER_SIGN_SECRET; - $signParts = ['HTTP_USER_AGENT']; +// $signParts = array('HTTP_USER_AGENT', 'HTTP_ACCEPT_ENCODING'); + $signParts = array(); foreach ($signParts as $signPart) { - $rawSign .= '::' . ($_SERVER[$signPart] ?? 'none'); + $rawSign .= '::' . (isset($_SERVER[$signPart]) ? $_SERVER[$signPart] : 'none'); } - - return $rawSign; + return md5($rawSign); } - static function getBrowserSign(): string - { - return md5(self::getRawSign()); - } - - function logout(): void { + static function logout() { session_destroy(); } } diff --git a/src/Filter/Filter.php b/src/Filter/Filter.php index 57d8e7c..645f624 100644 --- a/src/Filter/Filter.php +++ b/src/Filter/Filter.php @@ -3,46 +3,26 @@ /** * Попытка реализовать фильтр для запросов */ -namespace ctiso\Filter; - -use ctiso\Database; -use ctiso\HttpRequest; -use ctiso\Controller\ActionInterface; - -class Filter implements ActionInterface +class Filter_Filter { - /** @var ActionInterface */ public $processor; - - /** - * @param ActionInterface $processor - */ - public function __construct($processor) + public function __construct($processor/*: Controller_Action*/) { $this->processor = $processor; } - + public function execute(HttpRequest $request) { return $this->processor->execute($request); } - /** - * @param string $name - * @param class-string<\ctiso\View\View> $class - * @return \ctiso\View\View - */ - public function getView($name, $class = \ctiso\View\Top::class) + public function getView($name, $class = 'View_Top') { return $this->processor->getView($name, $class); } - public function getConnection(): Database + public function getConnection() { return $this->processor->getConnection(); } - - public function addUrlPart($key, $value): void { - $this->processor->addUrlPart($key, $value); - } } diff --git a/src/Filter/FilterInterface.php b/src/Filter/FilterInterface.php deleted file mode 100644 index aee34a9..0000000 --- a/src/Filter/FilterInterface.php +++ /dev/null @@ -1,12 +0,0 @@ -getString('password'); + if (Filter_UserAccess::$access == 'site_root' && defined('PARENT_PATH')) { + $s = new Settings(PARENT_PATH . '/settings.json'); + $s->read(); + $dsn = $s->readKey(array('system', 'dsn')); - function __construct($processor, User $role, Registry $config) { - parent::__construct($processor); - $this->role = $role; - $this->config = $config; + $db = Database::getConnection($dsn); + $user = $db->fetchOneArray("SELECT * FROM users WHERE login = :login", ['login' => $login]); + $userPassword = $user['password']; + } /*else if (time() - $result->getInt('lastupdate') > 60*60*24*60) { + // Проверить давность пароля, 60 дней + $request->set('error', true); + $request->set('lastupdate', true); + return false; + }*/ + + // Извлечение пользователя из родительской CMS, для проверки пароля + if (md5($password) == $userPassword) { // password + $this->enter($db, $result); + return true; + } + } + return false; } - /** * Проверка авторизации - * @param HttpRequest $request - * @return bool Авторизовани пользователь или нет + * @return Boolean Авторизован пользователь или нет */ public function isLoggin(HttpRequest $request) { // Авторизация session_start(); + $db = $this->getConnection(); + Filter_UserAccess::setUp($db); // Соединение + switch ($request->getAction()) { // Авторизация по постоянному паролю + case 'api_key': case 'login': - $login = $request->getString('login', '') ; - $password = $request->getString('password'); - - $result = $this->role->getUserByLogin($login); // Поиск по логину - if ($result) { - $userPassword = $this->role->getUserPassword($result); - if ($this->role->access == 'site_root' && defined('PARENT_PATH')) { - $s = new Settings(PARENT_PATH . '/settings.json'); - $s->read(); - $dsn = $s->readKey(['system', 'dsn']); - - $db = Database::getConnection($dsn); - $user = $db->fetchOneArray("SELECT * FROM users WHERE login = :login", ['login' => $login]); - if ($user === false) { - return false; - } - $userPassword = $user['password']; - } /*else if (time() - $result->getInt('lastupdate') > 60*60*24*60) { - // Проверить давность пароля, 60 дней - $request->set('error', true); - $request->set('lastupdate', true); - return false; - }*/ - // Проверка на количества попыток авторизации - $lastAttempt = $result; - - if ($lastAttempt->get('trie_count') >= self::AUTH_MAX_ATTEMPT /*&& time() - $lastAttempt['trie_time'] < self::AUTH_LAST_ATTEMPT_TIMER*/) { - if (time() - $lastAttempt->get('trie_time') < self::AUTH_LAST_ATTEMPT_TIMER) { - $request->set('timeout_error', true); - break; - } else { - $this->role->resetTries($request->getString('login')); - } - } - // Извлечнеие пользователя из родительской CMS, для проверки пароля - if (md5($password) == $userPassword) { // password - $this->enter($result); - return true; - } else { - // Обновление количества неудачных попыток входа - $this->role->updateTries($login); - } + $login = $request->get('login'); + $password = $request->get('password'); + if($this->checkLoginPasswordPair($db,$login,$password)==true){ + return true; } $request->set('error', true); break; @@ -103,22 +75,22 @@ class Login extends Filter case 'enter': $login = $request->get('login'); $password = $request->get('sid'); - $result = $this->role->getUserByLogin($login); // Поиск по логину + $result = Filter_UserAccess::getUserByLogin($login); // Поиск по логину if ($result) { $temp = md5($result->getString('password') . $result->getString('login') . $result->getString('sid')); if ($password == $temp) { - $this->enter($result); + $this->enter($db, $result); return true; } } break; */ default: - $hash = Authorization::getBrowserSign(); + $hash = $this->getBrowserSign(); // Если $hash не совпадает $_SESSION['hash'] то удаляем сессию if (isset($_SESSION ['access']) && isset($_SESSION[self::SESSION_BROWSER_SIGN_KEYNAME])) { if ($hash == $_SESSION[self::SESSION_BROWSER_SIGN_KEYNAME]) { - $this->user = $user = $this->role->getUserById($_SESSION['access']); // Поиск по идентификатору + $this->user = $user = Filter_UserAccess::getUserById($_SESSION['access']); // Поиск по идентификатору if ($user && isset($_SESSION['random']) && ($user->get('sid') == $_SESSION['random'])) { return true; } @@ -131,34 +103,41 @@ class Login extends Filter return false; } - /** - * Вход в систему - * @param PDOStatement $result - */ - private function enter($result): void + private 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); + } + + private function enter($db, $result) { $this->user = $result; $random = rand(0, 1024 * 1024); - $this->role->setSID((string)$random, $result); + $db->executeQuery("UPDATE users SET sid = '$random' WHERE id_user = " . $result->getInt('id_user')); $_SESSION["group"] = $result->getInt('access'); $_SESSION["access"] = $result->getInt('id_user'); // id_user $_SESSION["random"] = $random; // id_user - $_SESSION[self::SESSION_BROWSER_SIGN_KEYNAME] = Authorization::getBrowserSign(); + $_SESSION[self::SESSION_BROWSER_SIGN_KEYNAME] = $this->getBrowserSign(); $_SESSION["time"] = time(); } - /** - * @return mixed - */ - public function execute(HttpRequest $request): mixed + public function execute(HttpRequest $request) { - $logged = $this->isLoggin($request); - if ($request->getString('action') == 'user_access') { + $logged = $this->isLoggin($request); +// return json_encode(["logged"=>$logged]); + if ($request->get('action') == 'user_access') { if ($logged) { - $result = []; + $result = array(); $result['fullname'] = $this->user->getString('patronymic') . " " . $this->user->getString('firstname'); $result['email'] = $this->user->getString('email'); + $result['site'] = 187; $result['hash'] = sha1(self::SESSION_BROWSER_SIGN_SECRET . $this->user->getString('email')); return json_encode($result); } else { @@ -166,32 +145,34 @@ class Login extends Filter } } - if ($request->getString('action') == 'relogin') { + if($logged && ($request->get('action') == 'api_key')) { + $result['key'] = Security::generateAPIKey(strval(time())); + return json_encode($result); + } + + if ($request->get('action') == 'relogin') { if ($logged) { - return json_encode(['result' => 'ok', 'message' => "Авторизация успешна"]); + return json_encode(array('result' => 'ok', 'message' => "Авторизация успешна")); } else { - return json_encode(['result' => 'fail', 'message' => "Неправильное имя пользователя или пароль"]); + return json_encode(array('result' => 'fail', 'message' => "Неправильное имя пользователя или пароль")); } } if (!$logged) { // Параметры при неправильной авторизации // Действия по умолчанию !! Возможно переход на форму регистрации - if ($request->getString('mode') == 'ajax') { - if (!$this->requestIsWhite($request)) { - return json_encode(['result' => 'fail', 'message' =>"NOT_AUTHORIZED"]); + if ($request->get('mode') == 'ajax') { + if ((!$this->requestIsWhite($request))&&(!$this->APIKeyCheck($request))) { + return json_encode(array('result' => 'fail', 'message' =>"NOT_AUTHORIZED")); } } else { $request->set('module', 'login'); $request->set('mode', $this->mode); } } else if (isset($_SERVER['HTTP_REFERER'])) { - $arr = []; - parse_str(parse_url($_SERVER['HTTP_REFERER'] ?? '', PHP_URL_QUERY) ?: '', $arr); - if (isset($arr['back_page']) - && is_string($arr['back_page']) - && $request->getString('mode') != 'ajax') - { + $arr = array(); + parse_str(parse_url($_SERVER['HTTP_REFERER'], PHP_URL_QUERY), $arr); + if (isset($arr['back_page']) && $request->get('mode') != 'ajax') { $request->redirect($arr['back_page']); } } @@ -200,27 +181,69 @@ class Login extends Filter return $text; } - /** + /* --------------------- * Проверка на попадание реквеста в белый список - */ - public function requestIsWhite(Collection $request): bool { + */ + + public function requestIsWhite(Collection $request) { $module = $request->get('module'); $action = $request->get('action'); - $moduleDir = explode('\\',$module)[0]; - // TODO: Параметр для белого списка перенести в install.json - $file = Path::join($this->config->get('system', 'path'), 'modules', $moduleDir, 'filters', 'white.json'); + $moduleDir = explode('_',$module)[0]; + $file = Path::join(CMS_PATH, 'modules', $moduleDir, 'filters', 'white.json'); if (file_exists($file)) { - $text = file_get_contents($file); - if (!$text) { - return false; - } - $whiteList = json_decode($text, true); - if (is_array($whiteList) && in_array($action, $whiteList, true)) { + $whiteList = json_decode(file_get_contents($file), true); + + if (in_array($action, $whiteList)) { return true; } } return false; } + + /* --------------------- + * Проверка на попадание реквеста в API_key_allowed и проверка ключа API + */ + + public function APIKeyCheck(Collection $request) { + $key = $request->get('api_key'); + if(!is_string($key)) { + return false; + } + $module = $request->get('module'); + $action = $request->get('action'); + + $moduleDir = explode('_',$module)[0]; + $file = Path::join(CMS_PATH, 'modules', $moduleDir, 'filters', 'api_key.json'); + if (file_exists($file)) { + $whiteList = json_decode(file_get_contents($file), true); + + if (in_array($action, $whiteList)) { + if($this->isValidAPIKey($key)) { + return true; + } + } + } + + return false; + } + /** + * ключ API имеет вид [unixTime]_[hash(unixTime,WWW_PATH)] + */ + public function isValidAPIKey(String $key) { + $parts = explode('_',$key,2); + if(count($parts)!=2) { + return false; + } + $timestamp = intval($parts[0]); + $timediff = time()-$timestamp; + if(($timediff<0)||($timediff>60*60*24)) { // key is valid for 24 hours + return false; + } + if($key != Security::generateAPIKey($timestamp)){ + return false; + } + return true; + } } diff --git a/src/Filter/UserAccess.php b/src/Filter/UserAccess.php new file mode 100644 index 0000000..fbf97b4 --- /dev/null +++ b/src/Filter/UserAccess.php @@ -0,0 +1,69 @@ +executeQuery(); + if ($result->next()) { + self::$access = $GROUPS[$result->getString('access')]; + self::$name = $result->getString('login'); + self::$id = $result->getInt('id_user'); + self::$password = $result->getString('password'); + self::$fullname = implode(' ', array( + $result->getString('surname'), + $result->getString('firstname'), + $result->getString('patronymic'))); + return $result; + } + return null; + } + + public static function getUserByLogin($login) + { + $stmt = self::$db->prepareStatement("SELECT * FROM users WHERE login = ?"); + $stmt->setString(1, $login); + $result = self::getUserByQuery($stmt); + if ($result) { + $time = time(); + $id = self::$id; + self::$db->executeQuery("UPDATE users SET lasttime = $time WHERE id_user = $id"); // Время входа + } + return $result; + } + + public static function getUserById($id) + { + $stmt = self::$db->prepareStatement("SELECT * FROM users WHERE id_user = ?"); + $stmt->setInt(1, $_SESSION ['access']); + $result = self::getUserByQuery($stmt); + if ($result) { + $lasttime = $result->getInt('lasttime'); + $time = time(); + if ($time - $lasttime > self::LIFE_TIME) return null; // Вышло время сессии + $id = self::$id; + // self::$db->executeQuery("UPDATE users SET lasttime = $time WHERE id_user = $id"); // Время последнего обращения входа + } + return $result; + } +} diff --git a/src/Form/BrowserInput.php b/src/Form/BrowserInput.php deleted file mode 100644 index f6e1e69..0000000 --- a/src/Form/BrowserInput.php +++ /dev/null @@ -1,6 +0,0 @@ -value = $value; - $this->checked = $value; - } -} diff --git a/src/Form/Color.php b/src/Form/Color.php index 17a9caf..c7c0d2d 100644 --- a/src/Form/Color.php +++ b/src/Form/Color.php @@ -3,9 +3,6 @@ /** * Поле с цветом */ -namespace ctiso\Form; -use ctiso\Form\Field; - -class Color extends Field +class Form_Color extends Form_Field { } \ No newline at end of file diff --git a/src/Form/Date.php b/src/Form/Date.php index 3b1c526..42f8b00 100644 --- a/src/Form/Date.php +++ b/src/Form/Date.php @@ -2,8 +2,5 @@ /** * Поле с датой */ -namespace ctiso\Form; -use ctiso\Form\Field; - -class Date extends Field { +class Form_Date extends Form_Field { } \ No newline at end of file diff --git a/src/Form/DateTime.php b/src/Form/DateTime.php deleted file mode 100644 index 4f995fb..0000000 --- a/src/Form/DateTime.php +++ /dev/null @@ -1,7 +0,0 @@ -default = null; if (isset($input['validate'])) { $this->require = strpos($input['validate'], 'require') !== false; @@ -57,22 +31,19 @@ class Field $this->fieldset = $input['fieldset']; } // Инициализация свойст обьетка - foreach (['label', 'name', 'type', 'description', 'maxlength'] as $name) { + foreach (array('label', 'name', 'type', 'description') as $name) { if (isset($input[$name])) { $this->$name = $input[$name]; } } } - /** - * @param mixed $value - */ - function setValue($value): void + function setValue($value/*: any*/) { $this->value = $value; } - function getId(): string + function getId() { return $this->name . '_label'; } diff --git a/src/Form/Form.php b/src/Form/Form.php index a425af1..898e18d 100644 --- a/src/Form/Form.php +++ b/src/Form/Form.php @@ -4,100 +4,115 @@ * При рендеринге каждому классу соответствует шаблон (см. themes/maxim/templates/macros.html) */ -namespace ctiso\Form; +class TCheckbox extends Form_Field +{ + public $checked = false; + function setValue($value) + { + $this->value = $value; + $this->checked = $value; + } +} -use ctiso\Form\Field; -use ctiso\Form\Select; -use ctiso\Form\Input; -use ctiso\Validator\Validator; -use ctiso\HttpRequest; +class TQuestionType extends Form_Select +{ + function setValue($value) + { + // Установить selected у options + $this->value = $value; + foreach ($this->options as &$option) { + $option['selected'] = ($option['value'] == $value); + } + } +} + +class TDateTime extends Form_Input { +} + +/** + * Поле для ввода пароля + */ +class TSecret extends Form_Field { +} + +class TUpload extends Form_Field { +} + +class THidden extends Form_Input { + public $hidden = true; +} + +class TComponentBrowserInput extends Form_Input { +} /** * Форма для ввода */ -class Form { - /** @var array */ - public $field = []; //Поля формы - /** @var array */ - public $fieldsets = []; //Группы полей (fieldset). Некоторые поля могут не принадлежать никаким группам +class Form_Form extends View_View { + public $field = array(); //Поля формы + public $fieldsets = array(); //Группы полей (fieldset). Некоторые поля могут не принадлежать никаким группам - /** @var string */ public $action = ""; - /** @var string */ public $method = 'post'; - /** @var string */ public $header; - /** @var array */ protected $replace; - /** @var array */ protected $before; - /** @var array */ - public $_title = []; - /** @var array */ - public $alias = []; - /** @var class-string[] */ - private $constructor = []; - + public $_title = array(); + public $alias = array(); + public $constructor = array(); + /** * Строим форму по ее структуре. Каждому типу соответствует определенный класс. */ public function __construct() { - $this->constructor = [ - 'input' => Input::class, - // input с проверкой на заполненность - 'inputreq' => Input::class, - 'date' => Date::class, - 'datereq' => Date::class, - 'datetime' => DateTime::class, + $this->constructor = array( + 'input' => 'Form_Input', + 'inputreq' => 'Form_Input', // input с проверкой на заполненность - 'color' => Color::class, - 'textarea' => TextArea::class, - 'text' => TextArea::class, - 'multiselect' => SelectMany::class, - 'select1' => SelectOne::class, - 'select' => SelectOne::class, + 'date' => 'Form_Date', + 'datereq' => 'Form_Date', + 'datetime' => 'TDateTime', - 'questiontype'=> QuestionType::class, - 'secret' => Secret::class, - 'upload' => Upload::class, - 'image' => Upload::class, - 'checkbox' => CheckBox::class, - 'checkmany' => SelectMany::class, - 'hidden' => Hidden::class, - 'radio' => SelectOne::class, - 'filebrowser' => BrowserInput::class, - 'documents' => BrowserInput::class, - 'chooser' => Input::class, - 'select_chooser' => SelectOne::class, - 'html_text' => HtmlText::class - ]; + 'color' => 'Form_Color', + 'textarea' => 'Form_TextArea', + 'text' => 'Form_TextArea', + 'multiselect' => 'Form_SelectMany', +// 'selectmany' => 'TSelectMany', + 'select1' => 'Form_SelectOne', + 'select' => 'Form_SelectOne', + 'questiontype'=> 'TQuestionType', + 'secret' => 'TSecret', + 'upload' => 'TUpload', + 'image' => 'TUpload', + 'checkbox' => 'TCheckbox', + 'checkmany' => 'Form_SelectMany', + 'hidden' => 'THidden', + 'radio' => 'Form_SelectOne', + 'filebrowser' => 'TComponentBrowserInput', + 'documents' => 'TComponentBrowserInput', + 'chooser' => 'Form_Input', + 'select_chooser' => 'Form_SelectOne' + ); } - function getId(): string + function getId() { return '_form_edit'; } - /** - * Добавление конструкторя для поля формы - * @param string $name Краткое название поля - * @param class-string $class - */ - public function addFieldClass($name, $class): void + public function addFieldClass($name, $class) { $this->constructor [$name] = $class; } - + /** * Добавляет одно поле ввода на форму - * @param array{ type: string, name: string, hint?: string } $init - * @param OptionsFactory|null $factory */ - public function addField(array $init, $factory = null): Field + public function addField(array $init, $factory = null) { assert(isset($init['type'])); assert(isset($init['name'])); @@ -111,15 +126,16 @@ class Form { if(isset($init['hint'])) { $el->hint = $init['hint']; } - - $this->field[$init['name']] = $el; + + $this->field [$init['name']] = $el; return $el; } /** * Добавление fieldset на форму */ - public function addFieldSet(array $fieldset): void + + public function addFieldSet(array $fieldset) { $this->fieldsets[$fieldset['name']] = $fieldset; } @@ -127,7 +143,8 @@ class Form { /** * Добавление массива fieldset на форму */ - public function addFieldSetList(array $list): void + + public function addFieldSetList(array $list) { foreach ($list as $fieldset) { $this->addFieldSet($fieldset); @@ -136,10 +153,9 @@ class Form { /** * Добавляет список полей для формы - * @param array $list - * @param OptionsFactory|null $factory + * @param array $list */ - public function addFieldList(array $list, $factory = null): void + public function addFieldList(array $list, $factory = null) { foreach ($list as $init) { $this->addField($init, $factory); @@ -149,7 +165,7 @@ class Form { /** * Устанавливает ошибки после проверки */ - function setError(Validator $validator): void + function setError(Validator_Validator $validator) { foreach ($validator->getErrorMsg() as $name => $error) { @@ -158,12 +174,7 @@ class Form { } } - /** - * Устанавливает ошибку для поля - * @param string $name - * @param string $message - */ - function setFieldError($name, $message): void + function setFieldError($name, $message) { $this->field[$name]->error = true; $this->field[$name]->error_msg = $message; @@ -171,41 +182,33 @@ class Form { /** * Устанавливает значения из масива - */ - function setValues(HttpRequest $request): void { - foreach ($this->field as $key => $_) { + */ + function setValues(HttpRequest $request) { + foreach ($this->field as $key => $el) { $value = $request->getRawData($this->method, $key); $this->field[$key]->setValue($value); } } /** - * Заполняет форму данными из обьекта + * Заполняет форму данными из обьекта * @param object $data - * @param array $schema Связь между элементами формы и свойствами обьекта + * @param array $schema Связь между элементами формы и свойствами обьекта */ - public function fill($data, array $schema): void + public function fill($data, array $schema) { foreach ($schema as $key => $conv) { list($value, $type) = $conv; - $convertFn = [\ctiso\Primitive::class, 'from_' . $type]; - if (!is_callable($convertFn)) { - throw new \Exception('Не найден метод преобразования ' . $type); - } - $this->field[$key]->setValue(call_user_func($convertFn, $data->$value)); + $this->field [$key]->setValue(call_user_func(array('Primitive', 'from_' . $type), $data->$value)); } } - /** - * @param string $name - * @param mixed $value - */ - public function set($name, $value): void + public function set($name, $value) { $this->field[$name]->setValue($value); } - function execute(): self + function execute() { return $this; } diff --git a/src/Form/Hidden.php b/src/Form/Hidden.php deleted file mode 100644 index 6e3df61..0000000 --- a/src/Form/Hidden.php +++ /dev/null @@ -1,9 +0,0 @@ -db = $db; + $this->registry = $registry; + } + + function create(Form_Select $field, $input) { + if (isset($input['options.resid'])) { + $type = $input['options.resid']; + + $res = new Model_Resources($this->db); + $field->options = $this->optionsArray('id_section', 'title', $res->getSubsections('', $type)); + + } else if (isset($input['options.res'])) { + $type = $input['options.res']; + + $res = new Model_Resources($this->db); + $field->options = $this->optionsArray('path', 'title', $res->getSubsections('', $type)); + + } else if (isset($input['options.all_res'])) { + $type = $input['options.all_res']; + + $res = new Model_Resources($this->db); + $field->options = $this->optionsArray('id_resource', 'subtitle', $res->getAllResource($type)); + + } else if (isset($input['options.db'])) { + list($table, $keyvalue) = explode(":", $input['options.db']); + list($key, $value) = explode(",", $keyvalue); + try { + $query_result = $this->db->executeQuery("SELECT * FROM $table"); + $field->options = $this->optionsDB($key, $value, $query_result); + } catch(Exception $ex) { + $field->options = []; + } + } elseif (isset($input['options.pair'])) { + $field->options = $this->optionsPair($input['options.pair']); + } elseif (isset($input['options.model'])) { + $factory = new Model_Factory($this->db, $this->registry); + $model = $factory->getModel($input['options.model']); + $field->options = $model->getAllAsOptions(); + } else { + $field->options = $input['options']; + } + if (isset($input['default'])) { + array_unshift($field->options, ['value' => 0, 'name' => $input['default']]); + } + + // Ставим корневой каталог в начало списка (скорее всего он будет в конце массива) + if ($field->options) + { + $root_elem = array_pop($field->options); + if ($root_elem['value'] == '/') + array_unshift($field->options, $root_elem); + else + array_push($field->options, $root_elem); + } + } + + public function optionsDB($key, $val, $res) { + $result = array(); + while($res->next()) { + $result[] = array('value' => $res->getInt($key), 'name' => $res->getString($val)); + } + return $result; + } + + public function optionsArray($key, $val, $res) { + $result = array(); + foreach($res as $item) { + $result[] = array('value' => $item->{$key}, 'name' => $item->{$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; + } +} diff --git a/src/Form/OptionsFactory.php b/src/Form/OptionsFactory.php deleted file mode 100644 index 79be2e0..0000000 --- a/src/Form/OptionsFactory.php +++ /dev/null @@ -1,7 +0,0 @@ -value = $value; - foreach ($this->options as &$option) { - $option['selected'] = ($option['value'] == $value); - } - } -} diff --git a/src/Form/Secret.php b/src/Form/Secret.php deleted file mode 100644 index ce0175a..0000000 --- a/src/Form/Secret.php +++ /dev/null @@ -1,10 +0,0 @@ -create($this, $input); @@ -32,15 +21,10 @@ class Select extends Field } } - /** - * @param string[] $list - * @param bool $selected - * @return Option[] - */ public function optionsPair($list, $selected = false) { - $result = []; + $result = array(); foreach ($list as $key => $value) { - $result [] = ['value' => $key, 'name' => $value, 'selected' => $key == $selected]; + $result [] = array('value' => $key, 'name' => $value, 'selected' => $key == $selected); } return $result; } diff --git a/src/Form/SelectMany.php b/src/Form/SelectMany.php index 9ca752d..339ceac 100644 --- a/src/Form/SelectMany.php +++ b/src/Form/SelectMany.php @@ -1,14 +1,11 @@ value = $value; foreach ($this->options as &$option) { $option['selected'] = (in_array($option['value'], $value)); diff --git a/src/Form/SelectOne.php b/src/Form/SelectOne.php index d631d81..32fdeab 100644 --- a/src/Form/SelectOne.php +++ b/src/Form/SelectOne.php @@ -3,12 +3,9 @@ /** * Выбор из одного элемента */ -namespace ctiso\Form; -use ctiso\Form\Select; - -class SelectOne extends Select +class Form_SelectOne extends Form_Select { - function setValue($value): void + function setValue($value) { // Установить selected у options $this->value = $value; diff --git a/src/Form/TextArea.php b/src/Form/TextArea.php index 01e60e0..dfc3e9f 100644 --- a/src/Form/TextArea.php +++ b/src/Form/TextArea.php @@ -1,13 +1,10 @@ value = $value; } diff --git a/src/Form/Upload.php b/src/Form/Upload.php deleted file mode 100644 index 7cd38b8..0000000 --- a/src/Form/Upload.php +++ /dev/null @@ -1,7 +0,0 @@ -values[$name] = $value; } - /** - * Возвращает значение - * @param string ...$args - * @return mixed - */ - function get(...$args) + function get($_rest) { + $args = func_get_args(); $result = $this->values; foreach ($args as $name) { if (!isset($result[$name])) { @@ -38,28 +26,16 @@ class ViewState // extends Collection return $result; } - /** - * Сохраняет состояние - * @return string - */ - function saveState(): string + function saveState() { return base64_encode(serialize($this->values)); } - /** - * Восстанавливает состояние - * @param string $value - */ - function restoreState($value): void + function restoreState($value) { $this->values = unserialize(base64_decode($value)); } - /** - * Возвращает состояние - * @return array - */ function export() { return $this->values; diff --git a/src/Functions.php b/src/Functions.php index bd7fead..b7b6d99 100644 --- a/src/Functions.php +++ b/src/Functions.php @@ -1,84 +1,59 @@ */ - protected $params; - /** @var callable */ +class __right { + protected $params; protected $fn; - - /** - * @param array $params - */ + public function __construct($params) { $this->fn = array_shift($params); $this->params = $params; } - - /** - * Применение функции - * @param mixed ...$params - * @return mixed - */ - function apply(...$params) { + + function apply() { + $params = func_get_args(); array_splice($params, count($params), 0, $this->params); return call_user_func_array($this->fn, $params); - } + } } -class left { - /** @var array */ - protected $params; - /** @var callable */ +class __left { + protected $params; protected $fn; - - /** - * @param array $params - */ + public function __construct($params) { $this->fn = array_shift($params); $this->params = $params; } - /** - * Применение функции - * @param mixed ...$params - * @return mixed - */ - function apply(...$params) { + function apply() { + $params = func_get_args(); array_splice ($params, 0, 0, $this->params); return call_user_func_array ($this->fn, $params); } } define('__', '_ARGUMENT_PLACE_'); -class partial { - /** @var array */ - protected $params; - /** @var callable */ +class __partial { + protected $params; protected $fn; - - /** - * @param array $params - */ + public function __construct($params) { $this->fn = array_shift($params); $this->params = $params; } - /** - * Применение функции - * @param mixed ...$params - * @return mixed - */ - function apply(...$params) { - $result = []; - $count = count($this->params); - for($i = 0, $j = 0; $i < $count; $i++) { + function apply() { + $params = func_get_args(); + $result = array(); + for($i = 0, $j = 0; $i < count($this->params); $i++) { if ($this->params[$i] == __) { $result [] = $params[$j]; $j++; @@ -88,31 +63,21 @@ class partial { } return call_user_func_array ($this->fn, $result); } -} +} /** * Композиция функций */ -class compose { - /** @var array */ +class __compose { protected $fns; - - /** - * @param array $list - */ function __construct($list) { $this->fns = array_reverse($list); } - /** - * Применение функций - * @param mixed ...$params - * @return mixed - */ - function apply (...$params) { + function apply () { + $params = func_get_args (); $result = call_user_func_array($this->fns[0], $params); - $count = count($this->fns); - for ($i = 1; $i < $count; $i++) { + for ($i = 1; $i < count($this->fns); $i++) { $result = call_user_func($this->fns[$i], $result); } return $result; @@ -121,57 +86,54 @@ class compose { class Functions { - /** - * Частичное применение функции - * @param mixed ...$args - * @return mixed - */ - static function partial(...$args) { - $closure = new partial($args); - return [$closure, 'apply']; + static function partial() { + $closure = new __partial(func_get_args()); + return array($closure, 'apply'); } /** * Композиция функций - * @param mixed ...$args - * @return mixed + * @param mixed $a + * @param mixed $b + * + * @return array[int]mixed */ - static function compose(...$args) { - $closure = new compose($args); - return [$closure, 'apply']; + static function compose() { + $closure = new __compose(func_get_args()); + return array($closure, 'apply'); } /** * Карирование справа - * @param mixed ...$args - * @return mixed + * + * @return array[int]mixed */ - static function rcurry(...$args) { - $closure = new right($args); - return [$closure, 'apply']; + static function rcurry($_rest) { + $closure = new __right(func_get_args ()); + return array($closure, 'apply'); } /** * Карирование слева - * @param mixed ...$args - * @return mixed + * + * @return array[int]mixed */ - static function lcurry(...$args) { - $closure = new left($args); - return [$closure, 'apply']; + static function lcurry($_rest) { + $closure = new __left(func_get_args ()); + return array($closure, 'apply'); } /** * Разделение массива на два по условию * @param mixed $pred Условие по которому разделяется массив - * @param array $lst + * @param array $lst * - * @return mixed + * @return array[int]mixed */ static function partition($pred, $lst) { - $left = []; - $right = []; + $left = array (); + $right = array (); foreach ($lst as $n) { if (call_user_func($pred, $n) !== false) { $left [] = $n; @@ -179,37 +141,29 @@ class Functions { $right [] = $n; } } - return [$left, $right]; + return array ($left, $right); } /** - * @deprecated - * @param array $value - * @param string $name + * @param array $value + * @param string $name * * @return mixed */ static function __key($value, $name) { return $value[$name]; } - - /** - * @deprecated - * @param mixed $value - * - * @return mixed - */ + static function identity($value) { return $value; } - + /** - * @deprecated use fn and <=> operator * @param array $a * @param array $b - * @param string|int $key + * @param $key * - * @return int + * @return int */ static function __cmp($a, $b, $key) { if ($a[$key] == $b[$key]) { @@ -217,133 +171,108 @@ class Functions { } return ($a[$key] > $b[$key]) ? -1 : 1; } - - /** - * @deprecated use fn and <=> operator - * @param array $a - * @param array $b - * @param string|int $key - * - * @return int - */ + static function __cmp_less($a, $b, $key) { if ($a[$key] == $b[$key]) { return 0; } return ($a[$key] < $b[$key]) ? -1 : 1; } - - /** - * @param string ...$args - * @return string - */ - static function concat(...$args) { + + // Сравнение по ключу массиве + static function __index($n, $key, $row) { + return ($row[$key] == $n); + } + + static function __div($x, $y) { + return $x / $y; + } + + static function __self($name, $o) { + return call_user_func(array($o, $name)); + } + + static function concat(/* $args ...*/) { + $args = func_get_args(); return implode("", $args); } - - /** - * @param mixed $x - * @return bool - */ + static function __empty($x) { return empty($x); } - + + // Отрицание + static function __not($x) { + return !$x; + } + + // Не равно + static function __neq($x, $y) { + return $x != $y; + } + + // Равно + static function __eq($x, $y) { + return $x == $y; + } + /** * Извлекает из многомерого массива значения с определенным ключом * @example key_values('a', array(1 => array('a' => 1, 'b' => 2))) => array(1) * - * @param string $key - * @param list|\ArrayIterator $array * @return mixed */ - static function key_values($key, $array) { - $result = []; - + static function key_values($key, /*array|ArrayIterator*/ $array) { + $result = array(); + foreach($array as $item) { $result[] = $item[$key]; } return $result; } - - /** - * @param string $key - * @param array|\ArrayIterator $array - * @return array - */ - static function key_values_object($key, $array) { - $result = []; - + + static function key_values_object($key, /*array|ArrayIterator*/ $array) { + $result = array(); + foreach($array as $item) { $result[] = $item->{$key}; } return $result; } - - /** - * @param string $key - * @param string $value - * @param array>|\ArrayIterator $array - * @return array - */ + static function assoc_key_values($key, $value, $array) { - $result = []; + $result = array(); foreach ($array as $item) { $result[$item[$key]] = $item[$value]; } return $result; } - - /** - * @param string $key - * @param array>|\ArrayIterator $array - * @return array - */ + static function assoc_key($key, $array) { - $result = []; + $result = array(); foreach ($array as $item) { $result[$item[$key]] = $item; } return $result; } - - /** - * Возвращает значение по ключу - * @param string $key - * @param mixed $value - * @param array $array - * @return mixed - */ - static function _get($key, $value, $array) { + + static function _get($key, $value/*: any*/, $array/*: array*/) { foreach ($array as $item) { - if ($item[$key] == $value) { - return $item; - } + if ($item[$key] == $value) return $item; } - return null; + return null; } - - /** - * Возвращает ключ по значению - * @param string $key - * @param mixed $value - * @param array $array - * @return mixed - */ + static function _get_key($key, $value, $array) { foreach ($array as $name => $item) { - if ($item[$key] == $value) { - return $name; - } + if ($item[$key] == $value) return $name; } - return null; + return null; } - - + + /** * Логическа операция && ко всем элементам массива - * @param array $array Массив - * @param callable $callback Функция * @return bool */ static function every(array $array, $callback) { @@ -354,14 +283,17 @@ class Functions { } return true; } - + /** * Логическа операция || ко всем элементам массива - * @param array $array Массив - * @param callable $callback Функция + * @param array $array + * @param mixed $callback + * * @return mixed */ - static function some(array $array, callable $callback) { + static function some(array $array, $callback) { + assert(is_callable($callback)); + foreach ($array as $key => $value) { if (call_user_func($callback, $value) === true) { return $key; @@ -369,107 +301,80 @@ class Functions { } return false; } - - /** - * Разбивает массив на массивы определенной длины - * @template T - * @param int $length Длина массива - * @param T[] $array Массив - * @return T[][] - */ - static function span(int $length, array $array) { - $result = []; - $count = count($array); - for($i = 0; $i < $count; $i += $length) { + + static function span($length, array $array) { + assert(is_int($length)); + + $result = array(); + for($i = 0; $i < count($array); $i += $length) { $result [] = array_slice($array, $i, $length); } return $result; } - - /** - * Возвращает значение массива - * @param array $data Массив - * @param string|int $n Ключ - * @return mixed - */ - static function array_ref(array $data, string|int $n) { + + static function array_ref($data, $n) { return $data[$n]; } - - /** - * Вызывает функцию с аргументами - * @param mixed ...$args Аргументы - * @return mixed - */ - static function call(...$args) { + + static function call() { + $args = func_get_args(); $name = array_shift($args); return call_user_func_array($name, $args); } - + /** * Поиск элемента в массиве - * @param callable $cb сравнение с элементом массива + * @param function $cb сравнение с элементом массива * @param array $hs массив в котором ищется значение - * @param bool $strict * - * @return int|string|null ключ найденого элемента в массиве + * @return int|string ключ найденого элемента в массиве */ static function array_usearch($cb, array $hs, $strict = false) { - foreach($hs as $key => $value) { - if (call_user_func_array($cb, [$value, $key, $strict])) { - return $key; - } - } - return null; - } - + foreach($hs as $key => $value) if (call_user_func_array($cb, array($value, $key, $strict))) return $key; + } + /** * Выбирает все сроки из таблицы с уникальными значениями ключа + * @param $name Имя ключа + * @param $table Двухмерный массив * @example * key_unique_values ('name', array (array ('name' => 1), array ('name' => 2), array ('name' => 1))) - * => array (1, 2) - * - * @param string $name Имя ключа - * @param array $table Двухмерный массив - * @return array Массив с уникальными значениями ключа + => array (1, 2) + * @end example */ static function key_unique_values ($name, $table) { - // Ищем уникальные значения для заданного ключа - $keys = []; + // Ищем уникальные значения для заданного ключа + $keys = array (); foreach ($table as $row) { - if (!in_array ($row[$name], $keys)) { + if (!in_array ($row[$name], $keys)) $keys[] = $row[$name]; - } } return $keys; } - + /** * Сортировка двумерного массива по заданному ключу - * @param array $array Массив - * @param string $key Имя ключа по значению которого будет идти сравнение - * @param callable $fn Функция сравнения - * @return array Отсортированный массив + * @param $array Массив + * @param $key Имя ключа по значению которого будет идти сравнение + * @return Отсортированный массив */ - static function sortOn($array, $key, $fn = '\\ctiso\\Functions::__cmp') { + static function sortOn($array, $key, $fn = 'Functions::__cmp') { usort ($array, Functions::rcurry($fn, $key)); //usort ($array, create_function ('$x,$y', 'return __cmp ($x, $y, "'.$key.'");')); return $array; } /** - * Преобразует ключи элементов для многомерного массива - * @param string $key_name Имя ключа - * @param array $array Многомерный массив + * Преобразует ключи элементов для многомерного массива * @return mixed */ - static function hash_key ($key_name, $array) { - $result = []; + static function hash_key ($key_name,$array/*: array*/) { + $result = array(); foreach($array as $value) { - $result[$value[$key_name]] = $value; + $result[$value[$key_name]] = $value; } - return $result; + return $result; } } diff --git a/src/HttpRequest.php b/src/HttpRequest.php index a24e60f..25890a5 100644 --- a/src/HttpRequest.php +++ b/src/HttpRequest.php @@ -1,22 +1,17 @@ $_REQUEST, - 'get' => $_GET, - 'post' => $_POST, + 'data' => $_REQUEST, + 'get' => $_GET, + 'post' => $_POST, 'cookie' => $_COOKIE ]; @@ -42,77 +37,37 @@ class HttpRequest extends Collection parent::set('files', $data); } - /** - * @param string $key - * @return Collection - */ function _get($key) { return parent::get($key); } - /** - * @param string $key - * @param mixed $default - * @return null|string|array - */ function get($key, $default = null) { return parent::get('data')->get($key, $default); } - - function getString(string $key, string $default = ''): string - { - return parent::get('data')->getString($key, $default); - } - - function getInt(string $key, int $default = 0): int - { - return parent::get('data')->getInt($key, $default); - } - - function getNat(string $key, int $default = 1): int - { - return parent::get('data')->getNat($key, $default); - } - - function getBool(string $key, bool $default = false): bool - { - return parent::get('data')->getBool($key, $default); - } - - function getArray(string $key, array $default = []): array - { - return parent::get('data')->getArray($key, $default); - } - - function session(?Session $value = null): ?Session + + function session(Session $value = null) { if ($value) { - $this->_session = $value; + $this->_session = $value; } return $this->_session; } - function set(string $key, mixed $value): void + function set($key, $value/*: any*/) { - parent::get('data')->set($key, $value); + return parent::get('data')->set($key, $value); } - /** - * @param string $key - * @return array - */ - function export(string $key = 'data') + function export($key = 'data') { return parent::get($key)->export(); } - function clear(): void + function clear() { - /** @var Collection */ - $collection = parent::get('data'); - $collection->clear(); + return parent::get('data')->clear(); } /** @@ -122,7 +77,7 @@ class HttpRequest extends Collection * @param string $key * @return mixed */ - public function getRawData(string $var, $key) + public function getRawData($var, $key) { $data = parent::get(strtolower($var)); if ($data) { @@ -131,12 +86,6 @@ class HttpRequest extends Collection return null; } - /** - * @param string $var - * @param string $key - * @param mixed $val - * @return mixed - */ public function setRawData($var, $key, $val) { $data = parent::get(strtolower($var)); @@ -145,34 +94,37 @@ class HttpRequest extends Collection } } - /** - * @param string $name - */ - public function setAction($name): void - { + public function setAction($name) + { $this->setRawData('get', 'action', $name); } - public function getAction(): string + public function getAction() { $result = $this->getRawData('get', 'action'); return ($result) ? $result : 'index'; } - public function isAjax(): bool + public function isAjax() { return isset($_SERVER['HTTP_X_REQUESTED_WITH']) && ($_SERVER['HTTP_X_REQUESTED_WITH'] == 'XMLHttpRequest'); } - /** - * @param string $url - */ - public function redirect($url): void { + public function redirect($url) { header('location: ' . $url); exit(); } - static function getProtocol(): string { - return (!empty($_SERVER['HTTPS']) && $_SERVER['HTTPS'] !== 'off' || $_SERVER['SERVER_PORT'] == 443) ? "https://" : "http://"; + + public function offsetSet($key, $value) { + } + + public function offsetExists($key) { + } + + public function offsetUnset($key) { + } + + public function offsetGet($key) { } } diff --git a/src/Layout/Blank.php b/src/Layout/Empty.php similarity index 57% rename from src/Layout/Blank.php rename to src/Layout/Empty.php index 8a0d0ff..a7f99b8 100644 --- a/src/Layout/Blank.php +++ b/src/Layout/Empty.php @@ -3,15 +3,8 @@ /** * Самый простой макет */ -namespace ctiso\Layout; -use ctiso\Filter\Filter, - ctiso\HttpRequest; - -class Blank extends Filter +class Layout_Empty extends Filter_Filter { - /** - * @return mixed - */ function execute(HttpRequest $request) { $text = $this->processor->execute($request); diff --git a/src/Layout/Manager.php b/src/Layout/Manager.php index 26537b0..942a8fd 100644 --- a/src/Layout/Manager.php +++ b/src/Layout/Manager.php @@ -4,44 +4,32 @@ * Выбор макета страницы. * Выбор оформления страницы осуществляется если было совпадение с каким либо условием */ -namespace ctiso\Layout; - -use ctiso\Filter\Filter; -use ctiso\HttpRequest; - -class Manager extends Filter +class Layout_Manager extends Filter_Filter { - /** - * Массив условий с их макетами - * @var list - */ - protected $condition = []; + // Массив условий с их макетами + protected $condition = array(); /** * Функция которая добавляет условие для проверки параметров $_GET - * @param array|true $get Ассоциативный массив ключей и значений для $_GET - * @param Filter $layout Макет + * @param $get array() | true Ассоциативный массив ключей и значений для $_GET + * + * @example + * addConditionGet(array('module' => 'personal'), 'personal') + * addConditionGet(array('module' => 'login'), 'login') */ - public function addConditionGet($get, Filter $layout): void + public function addConditionGet($get, Filter_Filter $layout) { - $this->addCondition(fn(HttpRequest $request) => $this->checkGet($request, $get), $layout); + $this->addCondition(Functions::rcurry(array($this, 'checkGet'), $get), $layout); } /** - * Условие для аякс запросов. Тоже самое что и addConditionGet но еще проверяется является ли запрос ajax - * @param array|true $get Ассоциативный массив ключей и значений для $_GET - * @param Filter $layout Макет + * Условие для аякс запросов. Тоже самое что и addConditionGet но еще проверяется является ли запрос ajax */ - public function addConditionXHR($get, Filter $layout): void + public function addConditionXHR($get, Filter_Filter $layout) { - $this->addCondition(fn(HttpRequest $request) => $this->checkXHR($request, $get), $layout); + $this->addCondition(Functions::rcurry(array($this, 'checkXHR'), $get), $layout); } - /** - * @param HttpRequest $request - * @param array|true $get - * @return bool - */ public function checkGet($request, $get) { if (is_array($get)) { @@ -54,44 +42,38 @@ class Manager extends Filter return true; } - /** - * @param HttpRequest $request - * @param array|true $get - * @return bool - */ - public function checkXHR($request, $get): bool + public function checkXHR($request, $get) { return $request->isAjax() && $this->checkGet($request, $get); } /** * Добавляет условие в общем виде - * @param callable $get Функция - * @param Filter $layout Макет + * @parma $get function(HttpRequest) Функция + * @parma $layout Layout Макет */ - public function addCondition($get, Filter $layout): void - { - $this->condition [] = [$get, $layout]; + public function addCondition($get, Filter_Filter $layout) + { + $this->condition [] = array($get, $layout); } /** * Выбирает и применяет макет для страницы - * @return mixed */ - public function execute(HttpRequest $request): mixed + public function execute(HttpRequest $request) { foreach ($this->condition as $condition) { if (call_user_func($condition[0], $request)) { $layout = $condition[1]; $view = $layout->execute($request); if (is_object($view)) { - return $view->execute(); + echo $view->render(); } else { - return $view; + echo $view; } + return null; } } - return ''; } } diff --git a/src/Mail.php b/src/Mail.php index 848c645..1f4eda4 100644 --- a/src/Mail.php +++ b/src/Mail.php @@ -4,75 +4,55 @@ * Класс для работы с почтой * http://en.wikipedia.org/wiki/MIME */ - -namespace ctiso; - -use ctiso\Path, - Exception; - class Mail { - /** @var string */ public $_from; - /** @var string */ public $_to; - /** @var string */ public $_subject; - /** @var string */ public $content; - /** @var string */ public $copy; - /** @var string */ - private $encoding; - /** @var string */ + private $encoding; private $_notify = null; - /** @var array */ - protected $attachment = array(); - /** @var string */ + protected $attachment = array (); protected $uniqid; - /** @var string */ protected $type = "text/plain"; - function __construct() - { + function __construct() { $this->setEncoding("UTF-8"); - $this->uniqid = strtoupper(uniqid((string)time())); // Идентефикатор разделителя + $this->uniqid = strtoupper(uniqid(time())); // Идентефикатор разделителя } /** * Установка отправителя */ - function from(string $name): void + function from($name) { - // filter_var($name, FILTER_VALIDATE_EMAIL); $this->_from = $name; - } + } /** * Установка получателя */ - function to(string $name): void + function to($name) // recipient { $this->_to = $name; } - /** - * @param string $name - */ - function replyTo($name): void - {} + function replyTo($name) // recipient + { + } /** * Установка получателей копии */ - function copy(string $name): void + function copy($name) // recipient cc { $this->copy = $name; } - - function notify(string $notify): void + + function notify($notify) { $this->_notify = $notify; } @@ -80,70 +60,59 @@ class Mail /** * Тема письма */ - function subject(string $subject): void + function subject($subject) { - $this->_subject = $subject; + $this->_subject = $subject; } /** * Текст письма */ - function setContent(string $text): void + function setContent($text) { $this->content = $text; } - + /** * Кодировка текста в письме */ - function setEncoding(string $encoding): void + function setEncoding($encoding) { $this->encoding = $encoding; } /** * Добавление вложения из файла - * @param string $filename - * @param string|false $name */ - function addAttachment(string $filename, $name = false): void + function addAttachment($filename, $name = false) { - if (file_exists($filename)) { + assert(is_string($filename)); + + if(file_exists($filename)) { // assert ?? $file = fopen($filename, "rb"); if (is_resource($file)) { - $size = filesize($filename); - if ($size !== false && $size > 0) { - $data = fread($file, $size); - $this->attachment[] = ($name) ? [$data, $name] : [$data, basename($filename)]; - } + $data = fread($file, filesize($filename)); + $this->attachment [] = ($name) ? array($data, $name) : array($data, basename($filename)); } } } - /** - * Установка типа содержимого - * @param string $type - */ - function setType($type): void + function setType($type) { $this->type = $type; } /** * Добавление вложения из строки с указанием имени файла - * @param string $data - * @param string $name */ - function addAttachmentRaw($data, string $name): void + function addAttachmentRaw($data, $name) { - $this->attachment[] = [$data, $name]; + assert(is_string($name)); + + $this->attachment [] = array($data, $name); } - /** - * @param string $var - * @param string $val - */ - function quote($var, $val): string + function quote($var, $val) { return ";" . PHP_EOL . "\t" . $var . "=\"" . $val . "\""; } @@ -151,48 +120,44 @@ class Mail /** * Общий формат тегов MIME * @see http://tools.ietf.org/html/rfc2045 - * - * @param string $name - * @param string $value - * @param array $args */ - function mimeTag($name, $value, array $args = []): string + function mimeTag($name, $value, array $args = array()) { - assert(is_string($name)); - assert(is_string($value)); + assert (is_string($name)); + assert (is_string($value)); - return $name . ": " . $value . implode("", array_map([$this, 'quote'], array_keys($args), array_values($args))) . PHP_EOL; + return $name . ": " . $value . implode("", array_map(array($this, 'quote'), array_keys($args), array_values($args))) . PHP_EOL; } /** - * - * @see http://tools.ietf.org/html/rfc2047 + * + * @see http://tools.ietf.org/html/rfc2047 */ - function encodedWord(string $text, string $encoding = 'B'): string + function encodedWord($text, $encoding = 'B') { - return "=?{$this->encoding}?$encoding?" . base64_encode($text) . "?="; + return "=?{$this->encoding}?$encoding?".base64_encode($text)."?="; } /** * Тело сообщения */ - function getMessage(): string + function getMessage() { - $message = "--" . $this->uniqid . PHP_EOL; - $message .= $this->mimeTag("Content-Type", $this->type, ['charset' => $this->encoding]); + $message = "--".$this->uniqid . PHP_EOL; + $message .= $this->mimeTag("Content-Type", $this->type, array ('charset' => $this->encoding)); $message .= $this->mimeTag("Content-Transfer-Encoding", "8bit"); $message .= PHP_EOL . $this->content . PHP_EOL . PHP_EOL; /* - * Вложения + * Вложения * http://tools.ietf.org/html/rfc2046#section-5.1.3 */ foreach ($this->attachment as $value) { list($data, $name) = $value; $message .= "--" . $this->uniqid . PHP_EOL; - $message .= $this->mimeTag("Content-Type", "application/octet-stream", ['name' => basename($name)]); + $message .= $this->mimeTag("Content-Type", "application/octet-stream", array ('name' => basename($name))); $message .= $this->mimeTag("Content-Transfer-Encoding", "base64"); - $message .= $this->mimeTag("Content-Disposition", "attachment", ['filename' => basename($name)]); + $message .= $this->mimeTag("Content-Disposition", "attachment", array ('filename' => basename($name))); $message .= PHP_EOL . chunk_split(base64_encode($data)) . PHP_EOL; } @@ -202,7 +167,7 @@ class Mail /** * Заголовок сообщения */ - function getHeader(): string + function getHeader() { $head = $this->mimeTag("MIME-Version", "1.0"); $head .= $this->mimeTag("From", $this->_from); @@ -211,7 +176,7 @@ class Mail if (is_string($this->_notify)) { $head .= $this->mimeTag("Disposition-Notification-To", "\"" . $this->_notify . "\" <" . $this->_from . ">"); } - $head .= $this->mimeTag("Content-Type", "multipart/mixed", ["boundary" => $this->uniqid]); + $head .= $this->mimeTag("Content-Type", "multipart/mixed", array ("boundary" => $this->uniqid)); if ($this->copy) { $head .= $this->mimeTag("BCC", $this->copy); } @@ -219,7 +184,7 @@ class Mail return $head; } - function getSubject(): string + function getSubject() { return $this->encodedWord($this->_subject); } @@ -227,29 +192,28 @@ class Mail /** * Вывод строки для сохранения в формате .eml */ - function eml(): string + function eml() { return "To: " . $this->_to . PHP_EOL . "Subject: {$this->getSubject()}" . PHP_EOL . $this->getHeader() . $this->getMessage(); } /** - * Отправка почты + * Отправка почты */ - function send(): bool + function send() { $result = mail($this->_to, $this->getSubject(), $this->getMessage(), $this->getHeader()); - if (! $result) { + if(! $result) { file_put_contents(Path::resolveFile("send.eml"), $this->eml()); - throw new Exception('Невозможно отправить почту'); + throw new Exception('Невозможно отправить почту'); } return $result; } - function clear(): void - { + function clear() { foreach ($this->attachment as $key => &$value) { - unset($this->attachment[$key]); + unset($this->attachment[$key]); } - $this->attachment = []; + $this->attachment = array(); } } diff --git a/src/MailAlt.php b/src/MailAlt.php index c9cae8a..098d921 100644 --- a/src/MailAlt.php +++ b/src/MailAlt.php @@ -1,15 +1,9 @@ mailer->setFrom($name); - } + } /** * Установка получателя */ - function to(string $name): void // recipient + function to($name) // recipient { $this->mailer->addAddress($name); } - function replyTo(string $name): void // recipient + function replyTo($name) // recipient { - $this->mailer->addReplyTo($name); + $this->mailer->AddReplyTo($name); } /** * Установка получателей копии - * @param string $name */ - function copy(string $name): void // recipient cc + function copy($name) // recipient cc { $this->mailer->addCC($name); } - - function notify(string $notify): void + + function notify($notify) { $this->_notify = $notify; } /** * Тема письма - * @param string $subject */ - function subject(string $subject): void + function subject($subject/*: string*/) { - $this->mailer->Subject = $subject; + $this->mailer->Subject = $subject; } /** * Текст письма - * @param string $text */ - function setContent(string $text): void + function setContent($text) { $this->mailer->Body = $text; } - function setType(string $text): void + function setType($text) { $this->mailer->isHTML($text == 'text/html'); } - + /** * Кодировка текста в письме */ - function setEncoding(string $encoding): void + function setEncoding($encoding) { $this->encoding = $encoding; } @@ -86,20 +77,20 @@ class MailAlt /** * Добавление вложения из файла */ - function addAttachment(string $filename, ?string $name = null): void + function addAttachment($filename, $name = null) { $this->mailer->addAttachment($filename, $name); } /** - * Отправка почты + * Отправка почты */ - function send(): bool + function send() { return $this->mailer->send(); } - function eml(): string { + function eml() { return $this->mailer->getSentMIMEMessage(); } } diff --git a/src/Model/BaseMapper.php b/src/Model/BaseMapper.php deleted file mode 100644 index 37831a0..0000000 --- a/src/Model/BaseMapper.php +++ /dev/null @@ -1,12 +0,0 @@ -db = $db; - $this->config = $config; - $this->user = $user; + $this->_registry = $_registry; } - + /** * Создает модель - * @template T - * @param class-string $modelName - * @return T + * @param string $name + * @return model */ - public function getModel($modelName) + public function getModel ($name) { + $modelName = "Mapper_" . $name; $model = new $modelName(); $model->db = $this->db; $model->factory = $this; - $model->config = $this->config; - $model->user = $this->user; + $model->_registry = $this->_registry; $model->setUp(); // return $model; diff --git a/src/Numbers.php b/src/Numbers.php index 5d92be2..c0a39c7 100644 --- a/src/Numbers.php +++ b/src/Numbers.php @@ -1,30 +1,24 @@ url = parse_url($path) ?: []; +// assert(is_string($path)); + + $this->url = parse_url($path); if (isset($this->url['path'])) { $path = $this->url['path']; @@ -36,18 +33,18 @@ class Path $this->path = self::optimize($list); } - } + } - static function factory(string $path): Path { + static function factory($path) { return new Path($path); } - public function getParts(): array + public function getParts() { return $this->path; } - public static function normalize(string $pathName): string + public static function normalize($pathName) { $path = new Path($pathName); return $path->__toString(); @@ -55,12 +52,12 @@ class Path /** * Базовое имя - * @param string $path - * @return string + * @param $path + * @return mixed */ public static function basename($path) { - $list = preg_split('#\\\\|/#s', $path) ?: ['']; + $list = preg_split('#\\\\|/#s', $path); return end($list); } @@ -68,19 +65,16 @@ class Path * Возвращает расширение файла * * @param string $fileName Полное имя файла + * * @return string */ static function getExtension($fileName) { + assert(is_string($fileName) || is_null($fileName)); + return pathinfo($fileName, PATHINFO_EXTENSION); } - /** - * Проверяет расширение файла - * @param string $fileName Полное имя файла - * @param string|array $extension Расширение файла - * @return bool - */ static function isType($fileName, $extension) { if (is_array($extension)) { @@ -92,11 +86,17 @@ class Path /** * Полное имя файла без расширения + * + * @param string $fileName Имя файла + * + * @return string */ - static function skipExtension(string $fileName): string + static function skipExtension($fileName) { + assert(is_string($fileName)); + $path = pathinfo($fileName); - if (!isset($path['dirname']) || $path['dirname'] === ".") { + if ($path['dirname'] == ".") { return $path['filename']; } else { return self::join($path['dirname'], $path['filename']); @@ -107,10 +107,13 @@ class Path * Возвращает имя файла без расширения * * @param string $fileName Полное имя файла + * * @return string */ - static function getFileName(string $fileName) + static function getFileName($fileName) { + assert(is_string($fileName)); + return pathinfo($fileName, PATHINFO_FILENAME); } @@ -120,47 +123,47 @@ class Path * Преобразует строку пути в массив * * @param string $path Путь - * @return list + * + * @return array */ - public static function listFromString(string $path): array + public static function listFromString($path) { + assert(is_string($path)); + $list = preg_split('#\\\\|/#s', $path); - return $list ?: []; + + return $list; } /** - * Преобразует относительный путь в абсолютный - * @param array $path Путь - * @return array + * Преобразует относительный путь в абсолютный */ - public static function optimize($path) // + public static function optimize($path) // { - $result = []; + $result = array(); foreach ($path as $n) { switch ($n) { // Может быть относительным или абсолютным путем - case "": case ".": break; + case "": break; + case ".": break; case "..": - if (count($result) > 0 && $result[count($result) - 1] != '..') { - array_pop($result); break; + if (count($result) > 0 && $result[count($result) - 1] != '..') { + array_pop($result); break; } default: - $result[] = $n; + array_push($result, $n); } } return $result; } - /** - * Сравнение двух путей на равентство - */ - public function equal(Path $path): bool + // Сравнение двух путей на равентство + public function equal($path/*: Path*/) { - $count = count($this->path); - if ($count == count($path->path)) { - for ($i = 0; $i < $count; $i++) { + if (count($this->path) == count($path->path)) { + for ($i = 0; $i < count($this->path); $i++) { if ($this->path[$i] != $path->path[$i]) { - return false; + return false; } } return true; @@ -168,29 +171,27 @@ class Path return false; } - /** - * Преобразует путь в строку - * @param array{ host?: string, path?: string, query?: string, fragment?: string, scheme?: string, user?: string, pass?: string, port?: int} $path Путь - */ - public static function makeUrl($path): string + public static function makeUrl($path) { - $slash = (isset($path['host']) && isset($path['path']) && (strlen($path['path']) > 0) && ($path['path'][0] != '/')) ? '/' : ''; - $scheme = isset($path['scheme']) ? $path['scheme'] . ':/' : ''; - $user = isset($path['user']) ? $path['user'] . (isset($path['pass']) ? ':' . $path['pass'] : '') . '@' : ''; - - $port = isset($path['port']) ? ':' . $path['port'] : ''; - $host = isset($path['host']) ? ('/' . $user . $path['host'] . $port) : ''; - - $query = isset($path['query']) ? '?' . $path['query'] : ''; - $fragment = isset($path['fragment']) ? '#' . $path['fragment'] : ''; - - return $scheme . $host . $slash . ($path['path'] ?? '') . $query . $fragment; + $slash = (isset($path['host']) && (strlen($path['path']) > 0) && ($path['path'][0] != '/')) ? '/' : ''; + + return (isset($path['scheme']) ? $path['scheme'] . ':/' : '') + . (isset($path['host']) ? ('/' + . (isset($path['user']) ? $path['user'] . (isset($path['pass']) ? ':' . $path['pass'] : '') . '@' : '') + . $path['host'] + . (isset($path['port']) ? ':' . $path['port'] : '')) : '') + . $slash + . $path['path'] + . (isset($path['query']) ? '?' . $path['query'] : '') + . (isset($path['fragment']) ? '#' . $path['fragment'] : ''); } /** * Преобразует путь в строку + * + * @return string */ - public function __toString(): string + public function __toString() { $result = (($this->absolute) ? '/' : '') . implode(self::SEPARATOR, $this->path); $this->url['path'] = $result; @@ -200,16 +201,17 @@ class Path /** * Проверяет является ли папка родительской для другой папки * - * @param Path $path + * @parma Path $path + * + * @return boolean */ - public function isParent($path): bool + public function isParent($path/*: Path*/) { - if (isset($this->url['host']) && isset($path->url['host']) + if (isset($this->url['host']) && isset($path->url['host']) && ($this->url['host'] != $path->url['host'])) return false; - $count = count($this->path); - if (count($path->path) > $count) { - for ($i = 0; $i < $count; $i++) { + if (count($path->path) > count($this->path)) { + for ($i = 0; $i < count($this->path); $i++) { if ($path->path[$i] != $this->path[$i]) { return false; } @@ -219,16 +221,17 @@ class Path return false; } - public static function _isParent(string $path1, string $path2): bool + public static function _isParent($path1, $path2) { $path = new Path($path1); return $path->isParent(new Path($path2)); } - + /** * Находит путь относительно текущего путя + * + * @param string $name Полный путь к файлу * - * @param string $name Полный путь к файлу * @return string Относительный путь к файлу */ public function relPath($name) @@ -243,12 +246,7 @@ class Path return $path->__toString(); } - /** - * Вычисляет относительный путь в виде строки - * @param string $rpath Путь относительно которого вычисляется относительный путь - * @param string $lpath Путь к которому вычисляется относительный путь - * @return string Относительный путь - */ + // Вычисляет относительный путь в виде строки static function relative($rpath, $lpath) { // Нужно проверять диск!! $self = new Path($rpath); @@ -256,28 +254,21 @@ class Path $self_path = $self->getParts(); $list_path = $list->getParts(); - $result = []; - $count = count($list_path); - for ($i = 0; $i < $count; $i++) { - if (($i >= count($self_path)) || $list_path[$i] != $self_path[$i]) { - break; + $result = array(); + for ($i = 0; $i < count($list_path); $i++) { + if (($i >= count($self_path)) || $list_path[$i] != $self_path[$i]) { + break; } - } - $list_count = count($list_path); - for($j = $i; $j < $list_count; $j++) { + } + for($j = $i; $j < count($list_path); $j++) { array_push($result, '..'); } - $self_count = count($self_path); - for($j = $i; $j < $self_count; $j++) { + for($j = $i; $j < count($self_path); $j++) { array_push($result, $self_path[$j]); } return implode("/", $result); } - /** - * @param string $path - * @return string - */ public function append($path) { $base = $this->__toString(); @@ -287,11 +278,11 @@ class Path /** * Обьединяет строки в Path соединяя необходимым разделителем * fixme не обрабатывает параметры урла, решение Path::join(SITE_WWW_PATH) . '?param=pampam' - * @param string ...$args - * @return string + * @return string */ - static function fromJoin(...$args) { - $result = []; + static function fromJoin($_rest) { + $args = func_get_args(); + $result = array(); $parts0 = new Path(array_shift($args)); $result [] = $parts0->getParts(); foreach ($args as $file) { @@ -300,7 +291,7 @@ class Path } // При обьединении ссылок можно обьеденить path, query, fragment - $path = implode(self::SEPARATOR, self::optimize(call_user_func_array('array_merge', $result))); + $path = implode(self::SEPARATOR, self::optimize(call_user_func_array('array_merge', $result))); $parts0->url['path'] = ($parts0->isAbsolute()) ? '/' . $path : $path; return $parts0; } @@ -308,33 +299,32 @@ class Path /** * Обьединяет строки в строку пути соединяя необходимым разделителем * fixme не обрабатывает параметры урла, решение Path::join(SITE_WWW_PATH) . '?param=pampam' - * @param string ...$args - * @return string + * @return string */ - static function join(...$args) + static function join($_rest) { - $path = call_user_func_array([self::class, "fromJoin"], $args); + $args = func_get_args(); + $path = call_user_func_array("self::fromJoin", $args); return self::makeUrl($path->url); } // Проверка структуры имени файла - static function checkName(string $name, string $extension): bool + static function checkName($name, $extension) { return (strlen(pathinfo($name, PATHINFO_FILENAME)) > 0) && (pathinfo($name, PATHINFO_EXTENSION) == $extension); } - static function isCharName(string $char): bool + static function isCharName($char) { $ch = ord($char); return ((($ch >= ord('a')) && ($ch <= ord('z'))) || (strpos('-._', $char) !== false) || (($ch >= ord('0')) && ($ch <= ord('9')))); } - // Проверка имени файла - static function isName(string $name): bool - { + // Проверка имени файла + static function isName($name) { if (strlen(trim($name)) == 0) { return false; - } + } for ($i = 0; $i < strlen($name); $i++) { if (!self::isCharName($name[$i])) { return false; @@ -343,7 +333,7 @@ class Path return true; } - public function isAbsolute(): bool + public function isAbsolute() { return $this->absolute; } @@ -352,6 +342,7 @@ class Path * Подбирает новое временное имя для файла * * @param string $dst Предпологаемое имя файла + * * @return string Новое имя файла */ static function resolveFile($dst) @@ -368,49 +359,41 @@ class Path } - /** - * Список файлов в директории + /** + * Список файлов в директории * - * @param ?string[] $allow массив расширений для файлов - * @param string[] $ignore массив имен пааок которые не нужно обрабатывать + * @param array $allow массив расширений для файлов + * @param array $ignore массив имен пааок которые не нужно обрабатывать * - * @return string[] + * @returnarray */ - public function getContent(?array $allow = null, array $ignore = []) + public function getContent($allow = null, $ignore = array()) { - $ignore = array_merge([".", ".."], $ignore); + $ignore = array_merge(array(".", ".."), $ignore); return self::fileList($this->__toString(), $allow, $ignore); } /** * Обьединяет строки в путь соединяя необходимым разделителем + * + * @param array $allow массив расширений разрешеных для файлов + * @param array $ignore массив имен пааок которые не нужно обрабатывать * - * @param ?string[] $allow массив расширений разрешеных для файлов - * @param string[] $ignore массив имен папок которые не нужно обрабатывать - * - * @return string[] - */ - function getContentRec(?array $allow = null, array $ignore = []) + * @return array + */ + function getContentRec($allow = null, $ignore = array()) { - $result = []; - $ignore = array_merge([".", ".."], $ignore); + $result = array (); + $ignore = array_merge(array (".", ".."), $ignore); self::fileListAll($result, $this->__toString(), $allow, $ignore); return $result; } - /** - * Список файлов в директории - * - * @param string $base Базовый путь - * @param ?string[] $allow массив расширений для файлов - * @param string[] $ignore массив имен папок которые не нужно обрабатывать - * - * @return string[] - */ - protected static function fileList(string $base, ?array &$allow, array &$ignore): array + // Использовать SPL ??? + protected static function fileList($base, &$allow, &$ignore) { if ($base == '') $base = '.'; - $result = []; + $result = array (); $handle = opendir($base); if (is_resource($handle)) { while (true) { @@ -419,7 +402,7 @@ class Path if (! in_array($file, $ignore)) { $isDir = is_dir(Path::join($base, $file)); if ($isDir || ($allow == null) || in_array(self::getExtension($file), $allow)) { - $result[] = $file; + $result[] = $file; } } continue; @@ -431,8 +414,8 @@ class Path // При обьединении ссылок можно обьеденить path, query, fragment return $result; } - - protected static function fileListAll(array &$result, string $base, ?array &$allow, array &$ignore): void + + protected static function fileListAll(&$result, $base, &$allow, &$ignore) { $files = self::fileList($base, $allow, $ignore); foreach ($files as $name) { @@ -452,7 +435,7 @@ class Path * * @return void */ - static function prepare(string $dst, bool $filename = true) + static function prepare($dst, $filename = true) { if ($filename) { $path_dst = pathinfo($dst, PATHINFO_DIRNAME); @@ -466,29 +449,29 @@ class Path /** * Обновить относительную ссылку при переносе файла - * - * @param string $relativePath - относительная ссылка до переноса - * @param string $srcFile - абсолютный путь к папке содержащей файл со ссылкой до переноса - * @param string $dstFile - абсолютный путь к папке содержащей файл со ссылкой после переноса - * - * @return string + * + * @param String $relativePath - относительная ссылка до переноса + * @param String $srcFile - абсолютный путь к папке содержащей файл со ссылкой до переноса + * @param String $dstFile - абсолютный путь к папке содержащей файл со ссылкой после переноса + * + * @return String */ - static function updateRelativePathOnFileMove(string $relativePath, string $srcFile, string $dstFile) { + static function updateRelativePathOnFileMove($relativePath, $srcFile, $dstFile) { $srcToDst = self::relative($srcFile, $dstFile); return self::normalize(self::join($srcToDst, $relativePath)); } /** * Обновить относительную ссылку в файле при переносе папки - * - * @param string $relativePath относительная ссылка до переноса - * @param string $fileDir абсолютный путь к директории файла содержащего ссылку до переноса - * @param string $srcDir абсолютный путь к переносимой директории до переноса - * @param string $dstDir абсолютный путь к переносимой директории после переноса - * - * @return string + * + * @param String $relativePath - относительная ссылка до переноса + * @param String $fileDir - абсолютный путь к директории файла содержащего ссылку до переноса + * @param String $srcDir - абсолютный путь к переносимой директории до переноса + * @param String $dstDir - абсолютный путь к переносимой директории после переноса + * + * @return */ - static function updateRelativePathOnDirectoryMove(string $relativePath, string $fileDir, string $srcDir, string $dstDir) { + static function updateRelativePathOnDirectoryMove($relativePath, $fileDir, $srcDir, $dstDir) { $relativePath = self::normalize($relativePath); $fileDir = self::normalize($fileDir); $srcDir = self::normalize($srcDir); diff --git a/src/Primitive.php b/src/Primitive.php index ce1482a..aec45fd 100644 --- a/src/Primitive.php +++ b/src/Primitive.php @@ -3,117 +3,80 @@ /** * Преобразование типов !!! Пересмотреть использование классов!! * Класс преобразования типа значения поля класса в тип поля таблицы + * @package system */ -namespace ctiso; - class Primitive { - /** - * @param mixed $value - */ - public static function to_varchar($value): string + // varchar + public static function to_varchar($value) { return ((string) $value); } - /** - * @param mixed $value - * @return mixed - */ public static function from_varchar($value) { return $value; } - /** - * @param mixed $value - */ - public static function to_bool($value): bool + // int + public static function to_bool($value) { - return filter_var($value, FILTER_VALIDATE_BOOLEAN); + return filter_var($value, FILTER_VALIDATE_BOOLEAN);//(int)((bool) $value); } - /** - * Преобразование значения в булевое значение - * @param string $value - * @return bool - */ - public static function from_bool($value): bool + public static function from_bool($value) { return ((bool) $value); } - /** - * Преобразование значения в целое число - * @param string $value - * @return int - */ - public static function to_int($value): int + // int + public static function to_int($value) { return ((int) $value); } - /** - * @param mixed $value - */ - public static function from_int($value): string + public static function from_int($value) { return ((string) $value); } - - /** - * Преобразование даты dd/mm/yy в unix timestamp - * @param string $value - * @return int - */ - public static function to_date($value): int + + // date + public static function to_date($value) { $result = 0; - $tmp = explode("/", $value ?? '', 3); + $tmp = explode("/", $value, 3); + if (!empty($tmp)) { + if (count($tmp) != 3) return $result; - if (count($tmp) != 3) { - return $result; - } + $year = intval($tmp[2]); + $month = intval($tmp[1]); + $day = intval($tmp[0]); - $year = (int)$tmp[2]; - $month = (int)$tmp[1]; - $day = (int)$tmp[0]; - - if ($month != 0 && $day != 0 && $year != 0) { - if (checkdate($month, $day, $year)) { - return mktime(0, 0, 0, $month, $day, $year) ?: 0; - } else { - return 0; + if ($month != 0 && $day != 0 && $year != 0) { + if (checkdate($month, $day, $year)) { + return mktime(0, 0, 0, $month, $day, $year); + } else { + return 0; + } } } - return $result; } - /** - * Преобразование даты ISO 8601 в unix timestamp - * @param string $value - * @return int - */ - public static function to_datetime($value): int + public static function to_datetime($value) { $result = 0; - $tmp = []; + $tmp = array(); if (preg_match('/(\d+)-(\d+)-(\d+)T(\d+):(\d+)Z/', $value, $tmp)) { - if (checkdate((int)$tmp[2], (int)$tmp[3], (int)$tmp[1])) { - $result = mktime((int)$tmp[4], (int)$tmp[5], 0, (int)$tmp[2], (int)$tmp[3], (int)$tmp[1]) ?: 0; + if (checkdate($tmp[2], $tmp[3], $tmp[1])) { + $result = mktime($tmp[4], $tmp[5], 0, $tmp[2], $tmp[3], $tmp[1]); } } return $result; } - /** - * Преобразование даты в формат dd/mm/yyyy - * @param int $value - * @return string - */ - public static function from_date($value): string + public static function from_date($value) { if ($value > 0) { return date("d/m/Y", $value); @@ -121,12 +84,7 @@ class Primitive { return ''; } - /** - * Преобразование даты в формат ISO 8601 - * @param int $value - * @return string - */ - public static function from_datetime($value): string + public static function from_datetime($value) { if ($value > 0) { return date("Y-m-d\TH:i\Z", $value); @@ -135,45 +93,24 @@ class Primitive { } - /** - * @deprecated - * @template T - * @param T $value - * @return T - */ + // secure public static function to_secure($value) { // Значение приабразуется во время сохранения в базе данных return $value; } - /** - * @deprecated - * @template T - * @param T $value - * @return T - */ public static function from_secure($value) { return $value; } - /** - * Преобразование значения в массив - * @param mixed $value - * @return array - */ - public static function to_array($value) + // array + public static function to_array($value) { - return (is_array($value)) ? $value : []; + return (is_array($value)) ? $value : array(); } - /** - * @deprecated - * @template T - * @param T $value - * @return T - */ public static function from_array($value) { return $value; diff --git a/src/Process.php b/src/Process.php deleted file mode 100644 index ce1c177..0000000 --- a/src/Process.php +++ /dev/null @@ -1,68 +0,0 @@ - -class Registry { - /** @var array */ - private array $namespace = []; +/** + * http://www.patternsforphp.com/wiki/Registry + * http://www.patternsforphp.com/wiki/Singleton + * http://www.phppatterns.com/docs/design/the_registry?s=registry + */ - function importFile(string $namespace, ?string $filePath = null): void { - $data = json_decode(File::getContents($filePath), true); - $data['_file'] = $filePath; - $this->namespace[$namespace] = [ - 'path' => $filePath, - 'data' => $data - ]; - } - - function importArray(string $namespace, array $data = []): void { - if (isset($this->namespace[$namespace])) { - $data = array_merge($this->namespace[$namespace]['data'], $data); +class Registry extends Settings +{ + static $instance = null; + + /** + */ + static public function getInstance() + { + if (self::$instance == null) { + self::$instance = new Registry(); } - $this->namespace[$namespace] = [ - 'path' => null, - 'data' => $data - ]; + return self::$instance; } /** - * @param string $ns - * @param string $key - * @return mixed - * @throws Exception + * Список модулей */ - public function get(string $ns, string $key) { - if (isset($this->namespace[$ns]['data'][$key])) { - return $this->namespace[$ns]['data'][$key]; - } - throw new Exception('Unknown key ' . $ns . '::' . $key); + public function getModules() + { + return array_keys($this->data); } /** - * @param string $ns - * @param string $key - * @return mixed|null + * Проверка наличия модуля */ - public function getOpt(string $ns, string $key) { - if (isset($this->namespace[$ns]['data'][$key])) { - return $this->namespace[$ns]['data'][$key]; - } - return null; - } - - public function has(string $ns, string $key): bool { - return isset($this->namespace[$ns]['data'][$key]); - } - - function set(string $ns, string $key, mixed $value): void { - $this->namespace[$ns]['data'][$key] = $value; + public function hasModule($name) + { + return isset($this->data[$name]); } } diff --git a/src/Role/User.php b/src/Role/User.php deleted file mode 100644 index 78f2923..0000000 --- a/src/Role/User.php +++ /dev/null @@ -1,128 +0,0 @@ -db = $db; - $this->groups = $groups; - } - - public function setDB(Database $db): void { - $this->db = $db; - } - - public function getName(): string { - return $this->name; - } - - /** - * @return bool - */ - function isLogged() { - return \ctiso\Filter\Authorization::isLogged(); - } - - public function getUserByQuery(Statement $stmt): ?PDOStatement - { - $result = $stmt->executeQuery(); - if ($result->next()) { - $this->access = $this->groups[$result->getString('access')]; - $this->name = $result->getString('login'); - $this->id = $result->getInt('id_user'); - $this->password = $result->getString('password'); - $this->fullname = implode(' ', [ - $result->getString('surname'), - $result->getString('firstname'), - $result->getString('patronymic')]); - return $result; - } - return null; - } - - /** - * @param PDOStatement $result - * @return string - */ - function getUserPassword($result) { - return $result->get('password'); - } - - public function getUserByLogin(string $login): ?PDOStatement - { - $stmt = $this->db->prepareStatement("SELECT * FROM users WHERE login = ?"); - $stmt->setString(1, $login); - $result = $this->getUserByQuery($stmt); - if ($result) { - $time = time(); - $id = $this->id; - $this->db->executeQuery( - "UPDATE users SET lasttime = :time WHERE id_user = :id", - ['time' => $time, 'id' => $id]); // Время входа - } - return $result; - } - - public function getUserById(int $id): ?PDOStatement - { - $stmt = $this->db->prepareStatement("SELECT * FROM users WHERE id_user = ?"); - $stmt->setInt(1, $_SESSION ['access']); - $result = $this->getUserByQuery($stmt); - if ($result) { - $lasttime = $result->getInt('lasttime'); - $time = time(); - if ($time - $lasttime > self::LIFE_TIME) return null; // Вышло время сессии - $id = $this->id; - } - return $result; - } - - /** - * @param string $random - * @param PDOStatement $result - * @return PDOStatement|bool - */ - function setSID(string $random, $result) - { - return $this->db->executeQuery("UPDATE users SET sid = :sid, trie_count = 0 WHERE id_user = :user", [ - 'user' => $result->getInt('id_user'), - 'sid' => $random - ]); - } - - function resetTries(string $login): void { - $this->db->executeQuery( - "UPDATE users SET trie_count = :count WHERE login = :login", - ['count' => 0, 'login' => $login] - ); - } - - function updateTries(string $login): void { - $user = $this->db->fetchOneArray("SELECT id_user, trie_count FROM users WHERE login = :login", ['login' => $login]); - if ($user === false) { - return; - } - $this->db->executeQuery( - "UPDATE users SET trie_time = :cur_time, trie_count = :count WHERE id_user = :id_user", - ['cur_time' => time(), 'count' => $user['trie_count']+1, 'id_user' => $user['id_user']] - ); - } -} diff --git a/src/Role/UserInterface.php b/src/Role/UserInterface.php deleted file mode 100644 index a69d9b7..0000000 --- a/src/Role/UserInterface.php +++ /dev/null @@ -1,19 +0,0 @@ - parameters1, 'name2' => parameters1, ... ) * - * name1, name2 ... - Имена модулей + * name1, name2 ... - Имена модулей * parameters1, parameters1 - Массивы с параметрами модуля * Имя необходимо чтобы потом легко было удалить ненужные ветки дерева */ -class Settings +class Settings extends Collection { - /** @var array */ - public $data = []; - /** @var string */ protected $file; - /** @var string */ protected $format = 'php'; - /** @var bool */ - protected $is_read = false; - /** - * Конструктор - * @param string $file Путь к файлу - * @param 'php'|'json'|false $format Формат файла - */ public function __construct ($file = null, $format = false) { $fileFormat = ['theme' => 'json']; $extname = pathinfo($file, PATHINFO_EXTENSION); - $this->format = $format ?: Arr::get($fileFormat, $extname, $extname); + $this->format = $format ? $format : Arr::get($fileFormat, $extname, $extname); $this->file = $file; } @@ -42,48 +27,43 @@ class Settings * Чтение настроек из файла * @return Boolean */ - public function read(): bool + public function read() { if (!file_exists ($this->file)) { - $this->is_read = true; return false; } // Не include_once т.к читать настройки можно несколько раз - $settings = []; + $settings = array(); if ($this->format == 'json') { $settings = json_decode(File::getContents($this->file), true); } else { - $settings = include ($this->file); + include ($this->file); } if (!is_array($settings)) { - throw new Exception('no data in ' . $this->file); + throw new Exception($this->file); } - - $this->is_read = true; - $this->data = $settings; - return true; + return $this->import($settings); } /** - * Запись ключа в реестр (Реестр это многомерный массив) - * @param array $key Путь к значению ключа - * @param mixed $value Значение - * @return void + * Запись ключа в реестр (Реестр это могомерный массив) */ - public function writeKey(array $key, $value) + public function writeKey(array $key, $value) { +// assert(count($key) >= 1); $data = &$this->data; while (count($key) > 1) { $name = array_shift($key); $data = &$data[$name]; - } - + } + +// assert(count($key) == 1); $name = array_shift($key); if (is_array($value)) { if (!isset($data[$name])) { - $data[$name] = []; + $data[$name] = array(); } $this->merge($data[$name], $value); } else { @@ -93,14 +73,12 @@ class Settings /** * Обновляет массив в соответствии со значением - * @param array $data Массив - * @param mixed $value Значение */ - protected function merge(array &$data, $value): void + protected function merge(array &$data, $value) { foreach ($value as $key => $subvalue) { if (is_array($subvalue)) { - if (! isset($data[$key])) $data[$key] = []; + if (! isset($data[$key])) $data[$key] = array(); $this->merge($data[$key], $subvalue); } else { $data[$key] = $subvalue; @@ -109,23 +87,17 @@ class Settings } /** - * Чтение ключа из реестра - * @param array $key Путь к значению ключа - * @return mixed + * Чтение ключа из реестра + * @param $args Путь к значению ключа */ public function readKey(array $key) { return $this->readKeyData($key, $this->data); } - /** - * Чтение ключа из реестра - * @param array $key Путь к значению ключа - * @param array $data - * @return mixed - */ protected function readKeyData(array $key, $data) { +// assert(count($key) >= 1); while (count($key) > 1) { $name = array_shift($key); if (isset($data[$name])) { @@ -133,8 +105,9 @@ class Settings } else { return null; } - } - + } + +// assert(count($key) == 1); $name = array_shift($key); if (isset($data[$name])) { return $data[$name]; @@ -145,12 +118,12 @@ class Settings /** * Чтение ключа из реестра (Собирает все ключи с определенным значением во всех модулях) - * @param mixed $key Путь к значению ключа внутри модуля - * @return array + * @param $key Путь к значению ключа внутри модуля */ - public function readKeyList(...$key) + public function readKeyList($_rest) { - $result = []; + $key = func_get_args(); + $result = array(); foreach ($this->data as $name => $value) { $output = $this->readKeyData($key, $value); if ($output) { @@ -160,17 +133,13 @@ class Settings return $result; } - /** - * Удаление ключа из реестра - * @param string $name Имя ключа - */ - public function removeKey($name): void + public function removeKey($name) { unset($this->data[$name]); } - public function removeNode(array $key): void + public function removeNode(array $key) { $data = &$this->data; while (count($key) > 1) { @@ -181,80 +150,26 @@ class Settings unset($data[$name]); } + public function getOwner() + { + return array_keys($this->data); + } + /** * Запись настроек в файл (Может переименовать в store) * - * @param string $file + * @param File $file + * * @return void */ public function write($file = null) { - if (!$this->is_read) { - throw new Exception('read settings before write'); - } - if ($this->format == 'json') { $result = json_encode($this->data, JSON_PRETTY_PRINT | JSON_UNESCAPED_UNICODE); } else { $result = var_export($this->data, true); - $result = ""; + $result = ""; } - file_put_contents(($file) ? $file : $this->file, $result); - } - - /** - * Установка значения ключа - * @param string $key Ключ - * @param mixed $value Значение - */ - public function set($key, $value): void { - $this->data[$key] = $value; - } - - /** - * Получение значения ключа - * @param string $key Ключ - * @param mixed $default Значение по умолчанию - * @return mixed - */ - public function get($key, $default = null) - { - return isset($this->data[$key]) && $this->data[$key] != '' ? $this->data[$key] : $default; - } - - /** - * Получение всех данных - * @return array - */ - function export() { - return $this->data; - } - - /** - * Импорт данных - * @param array $data Данные - * @return void - */ - function import($data) { - $this->data = $data; - } - - /** - * Список модулей/ключей - * @return array - */ - public function getKeys() - { - return array_keys($this->data); - } - - /** - * Проверка наличия ключа - * @param string $name Ключ - * @return bool - */ - public function hasKey($name) - { - return isset($this->data[$name]); + file_put_contents (($file) ? $file : $this->file, $result); } } diff --git a/src/Setup.php b/src/Setup.php index e3538be..6e5dfa9 100644 --- a/src/Setup.php +++ b/src/Setup.php @@ -6,104 +6,58 @@ * $setup->set('target', 'dst'); * $setup->executeActions('install'); * - */ -namespace ctiso; -use ctiso\Tools\SQLStatementExtractor; -use ctiso\Path; -use ctiso\File; -use SimpleXMLElement; - -class FakeZipArchive { - /** @var string */ - public $base; - - function open(string $path): void { - $this->base = $path; - } - - /** - * Возвращает содержимое файла - * @param string $file - * @return string - */ - function getFromName($file) { - return File::getContents(Path::join($this->base, $file)); - } -} - -class Setup + */ +class Setup { - /** @var array */ - protected $actions = []; - /** @var array */ - public $context = []; - /** @var string */ + protected $actions = array(); + public $context = array(); protected $file; - /** @var string */ protected $action; - /** @var SimpleXMLElement */ protected $node; - /** @var array */ - protected $stack = []; - - /** @var FakeZipArchive */ + protected $stack = array(); + public $zip; - /** @var string */ public $target; - /** @var string */ public $source; - /** - * @param string $file - */ public function __construct($file) { $this->file = $file; - $node = simplexml_load_file($file); - if ($node === false) { - throw new \RuntimeException("Can't load file $file"); - } - $this->node = $node; + $this->node = simplexml_load_file($file); $this->target = ''; $this->source = ''; - $this->zip = new FakeZipArchive(); - $this->zip->open(dirname($this->file) . '/' . $this->node->attributes()['dir']); + $this->zip = new ZipArchive(); + $this->zip->open(strtr($file, array('.xml' => '.zip'))); + array_push($this->stack, $this->node); - $this->registerAction('copy', [$this, 'copyFile']); - $this->registerAction('make-directory', [$this, 'makeDirectory']); - $this->registerAction('make-link', [$this, 'makeLink']); - $this->registerAction('include', [$this, 'includeFile']); - $this->registerAction('when', [$this, 'testWhen']); + $this->registerAction('copy', array($this, 'copyFile')); + $this->registerAction('make-directory', array($this, 'makeDirectory')); + $this->registerAction('make-link', array($this, 'makeLink')); + $this->registerAction('include', array($this, 'includeFile')); + $this->registerAction('when', array($this, 'testWhen')); } /** - * Регистрация новых действия для установки - * @param string $name - * @param callable $action + * Регистрация новых действия для установки */ - public function registerAction(string $name, $action): void + public function registerAction($name, $action) { $this->actions[$name] = $action; } /** * Установка переменных для шаблона - * @param string $name - * @param mixed $value */ - public function set(string $name, $value): void + public function set($name, $value) { $this->context[$name] = $value; } - /** - * @return string - */ - function replaceFn(array $matches) { + function replaceFn($matches) { if (isset($this->context[$matches[2]])) { $v = $this->context[$matches[2]]; } else { @@ -116,14 +70,14 @@ class Setup return $v; } - public function fileContent(string $file, array $tpl): string - { + public function fileContent($file, array $tpl) + { $result = $this->zip->getFromName($file); - $result = preg_replace_callback('/\{\{\s*(\*?)(\w+)\s*\}\}/', [$this, 'replaceFn'], $result); + $result = preg_replace_callback('/\{\{\s*(\*?)(\w+)\s*\}\}/', array($this, 'replaceFn'), $result); return $result; } - function callAction(string $name, array $attributes): void + function callAction($name, array $attributes) { if(isset($this->actions[$name])) { call_user_func_array($this->actions[$name], $attributes); @@ -132,8 +86,6 @@ class Setup /** * Заменяет переменные на их значения в строке - * @param array $match массив совпадения - * @return string */ function replaceVariable(array $match) { @@ -145,55 +97,48 @@ class Setup /** * Для всех аттрибутов заменяет переменные на их значения - * @param SimpleXMLElement $attributes аттрибуты - * @return array */ - function resolve(SimpleXMLElement $attributes): array - { - $result = []; + function resolve($attributes) + { + $result = array(); foreach ($attributes as $key => $value) { - $result[$key] = preg_replace_callback("/\\\${(\w+)}/", $this->replaceVariable(...), $value); + $result [$key] = preg_replace_callback("/\\\${(\w+)}/", array($this, 'replaceVariable'), $value); } return $result; } - + /** * Выполняет список действий если для действия не указан аттрибут when то оно выполняется всегда - * - * @param string $action специальное действие - * @return void + * + * @param $action специальное действие */ function executeActions($action = "install") { - $this->action = $action; + $this->action = $action; if ($this->stack[count($this->stack) - 1] === false) { return; } - /** @var \SimpleXMLElement */ - $item = $this->stack[count($this->stack) - 1]; + $item/*: SimpleXMLElement*/ = $this->stack[count($this->stack) - 1]; $root = $item->children(); foreach ($root as $node) - { + { $attributes = $node->attributes(); array_push($this->stack, $node); - $this->callAction($node->getName(), [$this->resolve($attributes)]); + $this->callAction($node->getName(), array($this->resolve($attributes))); array_pop($this->stack); } - } - + } + /** - * Копирования файла - * preserve - Не переписывать файл если он существует - * template Файл является шаблоном подставить параметры до копирования - * src Исходный файл - * dst Новый файл - * - * @param array{preserve?: string, template: string, src: string, dst: string} $attributes - * @return void + * Копирования файла + * @param preserve Не переписывать файл если он существует + * @param template Файл является шаблоном подставить параметры до копирования + * @param src Исходный файл + * @param dst Новый файл */ public function copyFile(array $attributes) - { + { $path = $this->targetPath($attributes['dst']); if (!(file_exists($path) && isset($attributes['preserve']))) { @@ -203,9 +148,9 @@ class Setup /** * Создает символическую ссылку на папку/файл - * @param array{target: string, link: string} $attributes + * @param dst Имя папки */ - public function makeLink(array $attributes): void + public function makeLink(array $attributes) { if (function_exists('symlink')) { symlink($attributes['target'], $attributes['link']); @@ -213,37 +158,35 @@ class Setup } /** - * Подключение файла установки - * @param array{file: string} $attributes Имя подключаемого файла + * Подключение файла установки + * @param file Имя подключаемого файла */ - public function includeFile(array $attributes): void + public function includeFile(array $attributes) { $file = basename($this->file) . "/" . $attributes['file']; $setup = new Setup($file); - $setup->context = $this->context; + $setup->context = $this->context; $setup->executeActions(); } - function targetPath(string $s): string { + function targetPath($s) { return $this->target . '/' . $s; } /** * Создает новую папку - * dst Имя папки - * - * @param array{dst:string} $attributes + * @param dst Имя папки */ - public function makeDirectory(array $attributes): void + public function makeDirectory(array $attributes) { $path = $this->targetPath($attributes['dst']); if (!file_exists($path)) { mkdir($path); } - } + } - function testWhen(array $attributes): void + function testWhen(array $attributes) { if (!isset($attributes['test']) || $attributes['test'] == $this->action) { $this->executeActions($this->action); @@ -251,26 +194,19 @@ class Setup } /** - * Выполнение Списка SQL команд из ZIP файла - * @param Database $conn - * @param string $file - */ - function batchSQLZip($conn, $file): void + * Выполнение Списка SQL команд + */ + function batchSQLZip($conn/*: Database*/, $file) { - $stmtList = SQLStatementExtractor::extract($this->zip->getFromName($file)); + $stmtList = Tools_SQLStatementExtractor::extract($this->zip->getFromName($file)); foreach ($stmtList as $stmt) { $conn->executeQuery ($stmt); } } - /** - * Выполнение Списка SQL команд - * @param Database $conn - * @param string $file - */ - static function batchSQL($conn, $file): void + static function batchSQL($conn/*: Database*/, $file) { - $stmtList = SQLStatementExtractor::extractFile($file); + $stmtList = Tools_SQLStatementExtractor::extractFile($file); foreach ($stmtList as $stmt) { $conn->executeQuery ($stmt); } diff --git a/src/Shortcut.php b/src/Shortcut.php new file mode 100644 index 0000000..4e24046 --- /dev/null +++ b/src/Shortcut.php @@ -0,0 +1,66 @@ +list[$prefix] = $path; + } + + /** + * + */ + public function addVar($name, $value) + { + $this->variables['$' . $name] = $value; + } + + /** + * Возвращает путь по имени ярлыка + */ + static function getUrl($prefix, $name = null, $name1 = null) + { + $shortcut = self::getInstance(); + + $names = $shortcut->variables; + if ($name) { + $names['$name'] = $name; + } + if ($name1) { + $names['$name1'] = $name1; + } + + if (isset($shortcut->list[$prefix])) { + return strtr($shortcut->list[$prefix], $names); + } + return null; + } + + static function expand($path) + { + $shortcut = self::getInstance(); + $names = $shortcut->variables; + return strtr($path, $names); + } + +} diff --git a/src/SortRecord.php b/src/SortRecord.php index 84604ea..24c054b 100644 --- a/src/SortRecord.php +++ b/src/SortRecord.php @@ -1,24 +1,19 @@ key = $key; $this->order = ((boolean)($order) === false) ? 1 : -1; + $this->mode = $mode; } - /** - * @template T - * @param array $a - * @param array $b - */ - function compare(array $a, array $b): int + function compare($a, $b) { if($a[$this->key] == $b[$this->key]) { return 0; @@ -26,7 +21,7 @@ class SortRecord return ($a[$this->key] > $b[$this->key]) ? $this->order : -$this->order; } - function compareKeys(object $a, object $b): int + function compareKeys($a, $b) { if($a->{$this->key} == $b->{$this->key}) { return 0; @@ -34,23 +29,23 @@ class SortRecord return ($a->{$this->key} > $b->{$this->key}) ? $this->order : -$this->order; } - function sort(array &$list): bool + function sort(&$list) { - return usort($list, [$this, 'compare']); + return usort($list, array($this, 'compare')); } - function sortKeys(array &$list): bool + function sortKeys(&$list) { - return usort($list, [$this, 'compareKeys']); + return usort($list, array($this, 'compareKeys')); } - function group(array &$list, string $key, array $types): void + function group(&$list, $key, $types) { - $groups = []; + $groups = array(); foreach ($types as $name) { - $groups[$name] = []; + $groups[$name] = array(); } - $groups['_any_'] = []; + $groups['_any_'] = array(); foreach ($list as $item) { if (isset($groups[$item[$key]])) { $groups[$item[$key]][] = $item; @@ -58,10 +53,10 @@ class SortRecord $groups['_any_'][] = $item; } } - $result = []; + $result = array(); foreach ($groups as $value) { $result = array_merge($result, $value); } - $list = $result; + $list = $result; } } diff --git a/src/TableTree.php b/src/TableTree.php deleted file mode 100644 index d09eac3..0000000 --- a/src/TableTree.php +++ /dev/null @@ -1,40 +0,0 @@ -addStyleSheet($s); - return ""; - } - - /** - * Функция подключения компонента - * @param string $expression - * @return string - */ - static function phptal_component($expression): string { - $begin = floatval(microtime(true)); - /** @var Component */ - $component = self::$site->loadComponent($expression); - $req = new HttpRequest(); - $result = $component->execute($req); - - echo ""; - return $result; - } - - - static function register(?SiteInterface $site): void { - self::$site = $site; - - /* Регистрация нового префикса для подключения компонента */ - $tales = PHPTAL_TalesRegistry::getInstance(); - $tales->registerPrefix('component', [\ctiso\Tales_Component::class, 'component']); - $tales->registerPrefix('date', [\ctiso\Tales_DateTime::class, 'date']); - $tales->registerPrefix('time', [\ctiso\Tales_DateTime::class, 'time']); - $tales->registerPrefix('assets', [\ctiso\Tales_Assets::class, 'assets']); - } -} diff --git a/src/Tools/Drawing.php b/src/Tools/Drawing.php index 8a7568e..e13a323 100644 --- a/src/Tools/Drawing.php +++ b/src/Tools/Drawing.php @@ -1,130 +1,86 @@ > $rgb - */ - static function drawRectangle(GdImage &$image, int $left, int $top, int $width, int $height, array $rgb): void + + static function drawrectnagle(&$image, $left, $top, $width, $height, $rgb) { $color = imagecolorallocate($image, $rgb[0], $rgb[1], $rgb[2]); - if ($color === false) { - throw new \RuntimeException("Can't allocate color"); - } $right = $left + $width; $bottom = $top + $height; - imageline($image, $left, $top, $right, $top, $color); - imageline($image, $right, $top, $right, $bottom, $color); + imageline($image, $left, $top, $right, $top, $color); + imageline($image, $right,$top, $right, $bottom, $color); imageline($image, $left, $bottom, $right, $bottom, $color); - imageline($image, $left, $top, $left, $bottom, $color); + imageline($image, $left, $top, $left, $bottom, $color); } /** - * http://ru2.php.net/imagettftext - * - * @param GdImage $image - * @param int $size - * @param float $angle - * @param int $left - * @param int $top - * @param int $color - * @param string $font - * @param string $text - * @param int $max_width - * @param int $max_height - * @param string $align - * @param string $valign + * http://ru2.php.net/imagettftext */ - static function imagettftextbox( - GdImage &$image, - int $size, - float $angle, - $left, - $top, - $color, - $font, - $text, - $max_width, - $max_height, - $align, - $valign - ): float { - // echo $left,"\n", $top, "\n"; - // echo $max_width,"\n", $max_height, "\n"; - // self::drawrectnagle($image, $left, $top, $max_width, $max_height, array(0xFF,0,0)); + static function imagettftextbox(&$image, $size, $angle, $left, $top, $color, $font, $text, + $max_width, $max_height, $align, $valign) + { +// echo $left,"\n", $top, "\n"; +// echo $max_width,"\n", $max_height, "\n"; +// self::drawrectnagle($image, $left, $top, $max_width, $max_height, array(0xFF,0,0)); $text_lines = explode("\n", $text); // Supports manual line breaks! - - $lines = []; - $line_widths = []; - - $largest_line_height = 0; + + $lines = array(); + $line_widths = array(); + + $largest_line_height = 0; foreach ($text_lines as $block) { - $current_line = ''; // Reset current line - $words = explode(' ', $block); // Split the text into an array of single words + $current_line = ''; // Reset current line + $words = explode(' ', $block); // Split the text into an array of single words $first_word = true; - - $last_width = 0; - $count = count($words); - $item = ''; - for ($i = 0; $i < $count; $i++) { + + $last_width = 0; + for ($i = 0; $i < count($words); $i++) { $item = $words[$i]; $dimensions = imagettfbbox($size, $angle, $font, $current_line . ($first_word ? '' : ' ') . $item); - if ($dimensions === false) { - continue; - } $line_width = $dimensions[2] - $dimensions[0]; $line_height = $dimensions[1] - $dimensions[7]; - + $largest_line_height = max($line_height, $largest_line_height); - + if ($line_width > $max_width && !$first_word) { $lines[] = $current_line; - - $line_widths[] = $last_width ?: $line_width; + + $line_widths[] = $last_width ? $last_width : $line_width; $current_line = $item; } else { $current_line .= ($first_word ? '' : ' ') . $item; } - + if ($i == count($words) - 1) { - $lines[] = $current_line; + $lines[] = $current_line; $line_widths[] = $line_width; } - - $last_width = $line_width; + + $last_width = $line_width; $first_word = false; } - + if ($current_line) { $current_line = $item; } } - + // vertical align $top_offset = 0; if ($valign == self::ALIGN_CENTER) { $top_offset = ($max_height - $largest_line_height * count($lines)) / 2; } elseif ($valign == self::ALIGN_BOTTOM) { $top_offset = $max_height - $largest_line_height * count($lines); - } - + } + $top += $largest_line_height + $top_offset; - + $i = 0; foreach ($lines as $line) { // horizontal align @@ -134,23 +90,28 @@ class Drawing } elseif ($align == self::ALIGN_RIGHT) { $left_offset = ($max_width - $line_widths[$i]); } - + imagettftext($image, $size, $angle, $left + $left_offset, $top + ($largest_line_height * $i), $color, $font, $line); $i++; } - + return $largest_line_height * count($lines); } - function imagettftextSp(GdImage $image, float $size, float $angle, int $x, int $y, int $color, string $font, string $text, int $spacing = 0): void - { - if ($spacing == 0) { + + function imagettftextSp($image, $size, $angle, $x, $y, $color, $font, $text, $spacing = 0) + { + if ($spacing == 0) + { imagettftext($image, $size, $angle, $x, $y, $color, $font, $text); - } else { + } + else + { $temp_x = $x; - for ($i = 0; $i < mb_strlen($text); $i++) { + for ($i = 0; $i < mb_strlen($text); $i++) + { $bbox = imagettftext($image, $size, $angle, $temp_x, $y, $color, $font, $text[$i]); - $temp_x += $spacing + ($bbox !== false ? ($bbox[2] - $bbox[0]) : 0); + $temp_x += $spacing + ($bbox[2] - $bbox[0]); } } } diff --git a/src/Tools/Image.php b/src/Tools/Image.php index dd3ebd4..e750540 100644 --- a/src/Tools/Image.php +++ b/src/Tools/Image.php @@ -1,16 +1,8 @@ 1 && !$force) { - $percent = 1; - } - $new_width = max(1, (int)($width * $percent)); - $new_height = max(1, (int)($height * $percent)); + if ($percent > 1 && !$force) $percent = 1; + $new_width = $width * $percent; + $new_height = $height * $percent; + $image_p = imagecreatetruecolor($new_width, $new_height); imagecopyresampled($image_p, $image, 0, 0, 0, 0, $new_width, $new_height, $width, $height); return $image_p; } - /** - * @param GdImage $image - * @param string $uri - * @return bool - */ - static function save($image, $uri): bool + static function save($image, $uri) { $e = strtolower(pathinfo($uri, PATHINFO_EXTENSION)); switch ($e) { @@ -51,6 +35,5 @@ class Image case 'png': imagepng($image, $uri); break; case 'gif': imagegif($image, $uri); break; } - return false; } } \ No newline at end of file diff --git a/src/Tools/SQLStatementExtractor.php b/src/Tools/SQLStatementExtractor.php index 5041e69..fd4e068 100644 --- a/src/Tools/SQLStatementExtractor.php +++ b/src/Tools/SQLStatementExtractor.php @@ -18,7 +18,7 @@ * and is licensed under the LGPL. For more information please see * . */ - + /** * Static class for extracting SQL statements from a string or file. * @@ -26,157 +26,139 @@ * @version $Revision: 1.5 $ * @package creole.util.sql */ - -namespace ctiso\Tools; - -use Exception; - -class SQLStatementExtractor -{ - - /** @var string */ +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) - { + public static function extractFile($filename) { $buffer = file_get_contents($filename); if ($buffer !== false) { - return self::extractStatements(self::getLines($buffer)); + return self::extractStatements(self::getLines($buffer)); } throw new Exception("Unable to read file: " . $filename); } - + /** * Extract statements from string. - * - * @param string $buffer + * + * @param string $txt * @return array */ - public static function extract($buffer) - { + public static function extract($buffer) { return self::extractStatements(self::getLines($buffer)); } - + /** * Extract SQL statements from array of lines. * - * @param string[] $lines Lines of the read-in file. - * @return string[] SQL statements + * @param array $lines Lines of the read-in file. + * @return string */ - protected static function extractStatements($lines) - { - - $statements = []; + 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; + } - foreach ($lines as $line) { - $line = trim($line); + $sql .= " " . $line; + $sql = trim($sql); - if ( - self::startsWith("//", $line) || - self::startsWith("--", $line) || - self::startsWith("#", $line) - ) { - continue; + // 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 = ""; + } } - - 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; + 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) - { + protected static function startsWith($check, $string) { if ($check === "" || $check === $string) { return true; } else { return (strpos($string, $check) === 0); } } - + /** * 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(string $check, string $string) - { + protected static function endsWith($check/*: string*/, $string) { if ($check === "" || $check === $string) { return true; } else { return (strpos(strrev($string), strrev($check)) === 0); } - } + } /** * 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 - * @param string $string The string to get the substring from. - * @param int $startpos The start position of the substring. - * @param int $endpos The end position of the substring. - * @return string The substring. + * return values suck if you want to program strict as of C or friends */ - protected static function substring(string $string, int $startpos, int $endpos = -1) - { + protected static function substring($string, $startpos, $endpos = -1) { $len = strlen($string); - $endpos = (int) (($endpos === -1) ? $len - 1 : $endpos); - if ($startpos > $len - 1 || $startpos < 0) { + $endpos = (int) (($endpos === -1) ? $len-1 : $endpos); + if ($startpos > $len-1 || $startpos < 0) { trigger_error("substring(), Startindex out of bounds must be 0 $len - 1 || $endpos < $startpos) { - trigger_error("substring(), Endindex out of bounds must be $startpos $len-1 || $endpos < $startpos) { + trigger_error("substring(), Endindex out of bounds must be $startpos 0) { // already in sub-array? + $subarr[$in_subarr][] = $tok; + if ('}' === substr($tok, -1, 1)) { // check to see if we just added last component + $res[] = static::strToArray(implode(',', $subarr[$in_subarr])); + $in_subarr--; + } + } elseif ($tok[0] === '{') { // we're inside a new sub-array + if ('}' !== substr($tok, -1, 1)) { + $in_subarr++; + // if sub-array has more than one element + $subarr[$in_subarr] = array(); + $subarr[$in_subarr][] = $tok; + } else { + $res[] = static::strToArray($tok); + } + } else { // not sub-array + $val = trim($tok, '"'); // remove " (surrounding strings) + // perform type castng here? + $res[] = $val; + } + } + + return $res; + } + + //Нормализация строк на русском + static function normalizeRussian($str) { + $result = preg_replace('/\s+/',' ', $str); + if (is_string($result)) { + $result = trim($result); //Замена длинных пробелов на одинарные, пробелы по краям + $result = mb_strtolower($result); + $result = preg_replace('/ё/','е', $str); //е на ё + } + return $result; + } + + //Проверка равенства двух строк на русском языке. + static function equalRussianCheck($str1,$str2) { + return self::normalizeRussian($str1) == self::normalizeRussian($str2); + } + + + /** + * Попадает ли строка в список вариантов + * input: $str="foo1" $variants="foo1|foo2|foo3" + * output: true + * input: $str="foo" $variants="foo1|foo2|foo3" + * output: false +*/ + static function compare_string_to_variants($str, $variants){ + $variants_array = explode('|', $variants); + $founded = false; + foreach ($variants_array as $variant) { + $founded = $founded || self::equalRussianCheck($variant, $str); + } + return $founded; + } + + static function mb_str_split($str) { + return preg_split('~~u', $str, null, PREG_SPLIT_NO_EMPTY); + } + + static function mb_strtr($str, $from, $to) { + return str_replace(self::mb_str_split($from), self::mb_str_split($to), $str); + } + + static function encodestring($st) { + $st = self::mb_strtr($st,"абвгдеёзийклмнопрстуфхъыэ !+()", "abvgdeeziyklmnoprstufh_ie_____"); + $st = self::mb_strtr($st,"АБВГДЕЁЗИЙКЛМНОПРСТУФХЪЫЭ", "ABVGDEEZIYKLMNOPRSTUFH_IE"); + $st = strtr($st, array( + " " => '_', + "." => '_', + "," => '_', + "?" => '_', + "\"" => '_', + "'" => '_', + "/" => '_', + "\\" => '_', + "%" => '_', + "#" => '_', + "*" => '_', + "ж"=>"zh", "ц"=>"ts", "ч"=>"ch", "ш"=>"sh", + "щ"=>"shch","ь"=>"", "ю"=>"yu", "я"=>"ya", + "Ж"=>"ZH", "Ц"=>"TS", "Ч"=>"CH", "Ш"=>"SH", + "Щ"=>"SHCH","Ь"=>"", "Ю"=>"YU", "Я"=>"YA", + "Й"=>"i", "й"=>"ie", "ё"=>"Ye", + "№"=>"N" + )); + return strtolower($st); + } + + static function validate_encoded_string($st) { + $enc_st = self::encodestring($st); + return preg_match('/^[\w_-]+(\.[\w_-]+)?$/', $enc_st); + } +} \ No newline at end of file diff --git a/src/Tools/StringUtil.php b/src/Tools/StringUtil.php deleted file mode 100644 index a5a37ce..0000000 --- a/src/Tools/StringUtil.php +++ /dev/null @@ -1,168 +0,0 @@ - 0) { // already in sub-array? - $subarr[$in_subarr][] = $tok; - if ('}' === substr($tok, -1, 1)) { // check to see if we just added last component - $res[] = static::strToArray(implode(',', $subarr[$in_subarr])); - $in_subarr--; - } - } elseif ($tok[0] === '{') { // we're inside a new sub-array - if ('}' !== substr($tok, -1, 1)) { - $in_subarr++; - // if sub-array has more than one element - $subarr[$in_subarr] = []; - $subarr[$in_subarr][] = $tok; - } else { - $res[] = static::strToArray($tok); - } - } else { // not sub-array - $val = trim($tok, '"'); // remove " (surrounding strings) - // perform type castng here? - $res[] = $val; - } - } - - return $res; - } - - /** - * Нормализация строк на русском - * @param string $str - * @return string - */ - static function normalizeRussian(string $str): string - { - $result = preg_replace('/\s+/', ' ', $str); - if (is_string($result)) { - $result = trim($result); //Замена длинных пробелов на одинарные, пробелы по краям - $result = mb_strtolower($result); - $result = preg_replace('/ё/', 'е', $str); //е на ё - } - return $result; - } - - /** - * Проверка равенства двух строк на русском языке. - * @param string $str1 - * @param string $str2 - * @return bool - */ - static function equalRussianCheck($str1, $str2): bool - { - return self::normalizeRussian($str1) == self::normalizeRussian($str2); - } - - /** - * Попадает ли строка в список вариантов - * input: $str="foo1" $variants="foo1|foo2|foo3" - * output: true - * input: $str="foo" $variants="foo1|foo2|foo3" - * output: false - * - * @param string $str - * @param string $variants - * @return bool - */ - static function compare_string_to_variants($str, string $variants) - { - $variants_array = explode('|', $variants); - $founded = false; - foreach ($variants_array as $variant) { - $founded = $founded || self::equalRussianCheck($variant, $str); - } - return $founded; - } - - /** - * Разбивает строку на массив символов - * @param string $str - * @return array - */ - static function mb_str_split(string $str): array - { - return preg_split('~~u', $str, -1, PREG_SPLIT_NO_EMPTY) ?: []; - } - - /** - * Заменяет символы в строке на символы из другой строки - * @param string $str - * @param string $from - * @param string $to - * @return string - */ - static function mb_strtr($str, $from, $to) - { - return str_replace(self::mb_str_split($from), self::mb_str_split($to), $str); - } - - static function encodestring(string $st): string - { - $st = self::mb_strtr($st, "абвгдеёзийклмнопрстуфхъыэ !+()", "abvgdeeziyklmnoprstufh_ie_____"); - $st = self::mb_strtr($st, "АБВГДЕЁЗИЙКЛМНОПРСТУФХЪЫЭ", "ABVGDEEZIYKLMNOPRSTUFH_IE"); - $st = strtr($st, [ - " " => '_', - "." => '_', - "," => '_', - "?" => '_', - "\"" => '_', - "'" => '_', - "/" => '_', - "\\" => '_', - "%" => '_', - "#" => '_', - "*" => '_', - "ж" => "zh", - "ц" => "ts", - "ч" => "ch", - "ш" => "sh", - "щ" => "shch", - "ь" => "", - "ю" => "yu", - "я" => "ya", - "Ж" => "ZH", - "Ц" => "TS", - "Ч" => "CH", - "Ш" => "SH", - "Щ" => "SHCH", - "Ь" => "", - "Ю" => "YU", - "Я" => "YA", - "Й" => "i", - "й" => "ie", - "ё" => "Ye", - "№" => "N" - ]); - return strtolower($st); - } - - /** - * Проверяет, является ли строка кодированной - * @param string $st - * @return int|false - */ - static function validate_encoded_string(string $st): int|false - { - $enc_st = self::encodestring($st); - return preg_match('/^[\w_-]+(\.[\w_-]+)?$/', $enc_st); - } -} diff --git a/src/Tools/TemplateImage.php b/src/Tools/TemplateImage.php index cb0ad0d..cdf97ca 100644 --- a/src/Tools/TemplateImage.php +++ b/src/Tools/TemplateImage.php @@ -3,18 +3,10 @@ /** * Формат для композиции изображений */ - -namespace ctiso\Tools; - -use ctiso\Tools\Drawing; -use GdImage; - -class TemplateImage +class Tools_TemplateImage { - /** @var array */ - static array $listfiles = array('jpg' => 'jpeg', 'gif' => 'gif', 'png' => 'png', 'bmp' => 'wbmp'); - /** @var array */ - static array $listfonts = array( + static $listfiles = array('jpg' => 'jpeg', 'gif' => 'gif', 'png' => 'png', 'bmp' => 'wbmp'); + static $listfonts = array( 'georgia' => 'georgia.ttf', 'georgiabd' => 'georgiab.ttf', 'georgiaz' => 'georgiaz.ttf', @@ -29,29 +21,27 @@ class TemplateImage '' => 'arial.ttf', 'dejavu' => 'DejaVuCondensedSerif.ttf', 'dejavubd' => 'DejaVuCondensedSerifBold.ttf', - 'dejavuz' => 'DejaVuCondensedSerifBoldItalic.ttf', + 'dejavuz' =>'DejaVuCondensedSerifBoldItalic.ttf', 'dejavui' => 'DejaVuCondensedSerifItalic.ttf', 'miriad' => 'MyriadPro-Cond.ttf', 'miriadbd' => 'MyriadPro-BoldCond.ttf' ); - /** @var string */ protected $src; - protected array $context = []; - protected array $data = []; - protected string $base = "c:\\windows\\fonts\\"; - protected GdImage $image; - /** @var bool */ - protected $_prepare = true; - /** @var bool */ + protected $context = array(); + protected $data = array(); + protected $base = "c:\\windows\\fonts\\"; + protected $image; + protected $prepare = true; public $debug = false; - public string $resource; - public string $filename; + public $filename; + public $resource; - function __construct(?array $template = null) + function __construct ($template = false) { - if ($template) { +// assert(is_string($src)); + if($template) { $this->data = $template; } } @@ -59,166 +49,132 @@ class TemplateImage /** * Путь к изображению */ - function resourcePath(string $path): void + function resourcePath($path) { + assert(is_string($path)); + $this->resource = $path; } /** * Путь у шрифтам */ - function fontPath(string $path): void + function fontPath($path) { + assert(is_string($path)); + $this->base = $path; } - /** - * @param string $name - * @param mixed $value - */ - function set(string $name, $value): void + function set($name, $value) { - $this->context['[' . $name . ']'] = $value; + assert(is_string($name)); + + $this->context['['.$name.']'] = $this->encode($value); } - function setImage(string $name): void + function setImage($name) { $this->filename = $name; $this->image = $this->imagefromfile($name); } - /** - * Создает пустое изображение - * @param int<1, max> $width - * @param int<1, max> $height - */ - function setEmptyImage($width, $height): void + function setEmptyImage($width, $height) { $this->image = imagecreatetruecolor($width, $height); } /** * Создает изображение из файла - * @param string $file - * @return GdImage|null */ - function imagefromfile(string $file) + function imagefromfile($file) { + assert(is_string($file)); + $suffix = pathinfo($file, PATHINFO_EXTENSION); if (array_key_exists($suffix, self::$listfiles)) { - $imageFn = 'imagecreatefrom' . self::$listfiles[$suffix]; - if (!is_callable($imageFn)) { - return null; - } - return call_user_func($imageFn, $file); + return call_user_func('imagecreatefrom' . self::$listfiles[$suffix], $file); } return null; } - function getFontFile(string $name): string + function getFontFile($name) { - if (array_key_exists(strtolower($name), self::$listfonts)) { + assert(is_string($name)); + + if(array_key_exists(strtolower($name), self::$listfonts)) { return $this->base . self::$listfonts[$name]; } return $this->base . 'arial.ttf'; } - function fontSuffix(array $style): string + function fontSuffix($style) { - if ($style[0] && $style[1]) return "z"; + if($style[0] && $style[1]) return "z"; - if ($style[0]) return "bd"; - if ($style[1]) return "i"; + if($style[0]) return "bd"; + if($style[1]) return "i"; return ""; } - /** - * @param string $text - * @param object{ - * fontFamily: string, - * fontSize: int, - * fontStyle: array{string, string}, - * color: string, - * align: array, - * valign: array, - * left: int, - * top: int, - * width: int, - * height: int - * } $value - */ - function imageText(string $text, object $value): void + function imageText($text, $value/*: stdClass*/) { + assert(is_string($text)); + $text = strtr($text, $this->context); $size = $value->fontSize; $fontfile = $this->getFontFile($value->fontFamily . $this->fontSuffix($value->fontStyle)); $color = intval(substr($value->color, 1), 16); if ($value->align[0]) { - $align = Drawing::ALIGN_LEFT; + $align = Tools_Drawing::ALIGN_LEFT; } elseif ($value->align[2]) { - $align = Drawing::ALIGN_RIGHT; + $align = Tools_Drawing::ALIGN_RIGHT; } else { - $align = Drawing::ALIGN_CENTER; + $align = Tools_Drawing::ALIGN_CENTER; } if ($value->valign[0]) { - $valign = Drawing::ALIGN_TOP; - } elseif ($value->valign[1]) { - $valign = Drawing::ALIGN_CENTER; + $valign = Tools_Drawing::ALIGN_TOP; + } elseif ($value->valign[1]) { + $valign = Tools_Drawing::ALIGN_CENTER; } else { - $valign = Drawing::ALIGN_BOTTOM; + $valign = Tools_Drawing::ALIGN_BOTTOM; } - Drawing::imagettftextbox( - $this->image, - $size, - 0, - $value->left, - $value->top, - $color, - $fontfile, - $text, - $value->width, - $value->height, - $align, - $valign - ); + Tools_Drawing::imagettftextbox($this->image, $size, 0, $value->left, $value->top, $color, $fontfile, $text, + $value->width, $value->height, + $align, $valign); } /** * Перекодировка текста - * @deprecated Можно заменить encode($x) -> $x */ - function encode(string $text): string + function encode($text) { - return $text; + assert(is_string($text)); + return $text; //iconv("WINDOWS-1251", "UTF-8", $text); } - /** - * @param int<1,max> $new_width - * @param ?int<1,max> $new_height - */ - function setSize(int $new_width, ?int $new_height = null): void + function setSize($new_width, $new_height) { $width = imagesx($this->image); $height = imagesy($this->image); - if ($new_height == null) { - $new_height = max(1, (int)ceil($height * $new_width / $width)); + if($new_height == false) { + $new_height = ceil($height * $new_width / $width); } // Resample $image_p = imagecreatetruecolor($new_width, $new_height); imagecopyresampled($image_p, $this->image, 0, 0, 0, 0, $new_width, $new_height, $width, $height); - // imagecopyresized($image_p, $this->image, 0, 0, 0, 0, $new_width, $new_height, $width, $height); +// imagecopyresized($image_p, $this->image, 0, 0, 0, 0, $new_width, $new_height, $width, $height); $this->image = $image_p; } - function prepare(): void - { - if ($this->_prepare) { - $this->_prepare = false; + function prepare() { + if($this->prepare) { + $this->prepare = false; foreach ($this->data as $value) { $this->imageText($value->text, $value); // break; } @@ -228,8 +184,10 @@ class TemplateImage /** * Генерирует изображение из шаблона */ - function render(?string $file = null): string|bool + function render($file = null) { + assert(is_string($file) || is_null($file)); + $this->prepare(); if ($file == null) { diff --git a/src/UTF8.php b/src/UTF8.php index 4eab203..3cc68b8 100644 --- a/src/UTF8.php +++ b/src/UTF8.php @@ -1,21 +1,12 @@ - */ - static function str_split(string $str, int $split_length = 1): array - { - $split_length = (int) $split_length; - - $matches = []; - preg_match_all('/.{' . $split_length . '}|[^\x00]{1,' . $split_length . '}$/us', $str, $matches); - - return $matches[0]; +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]; } -} +} \ No newline at end of file diff --git a/src/Url.php b/src/Url.php deleted file mode 100644 index 83ce86b..0000000 --- a/src/Url.php +++ /dev/null @@ -1,31 +0,0 @@ - */ - public array $parts = []; - public ?Url $parent; - - /** - * @param Url|null $parent - */ - function setParent($parent): void { - $this->parent = $parent; - } - - /** - * @param string[] $parts - */ - function setQuery(array $parts): void { - $this->parts = $parts; - } - - function addQueryParam(string $key, ?string $value): void { - $this->parts[$key] = $value; - } - - function toString(): string { - return '?' . http_build_query(array_merge($this->parts, $this->parent ? $this->parent->parts : [])); - } -} \ No newline at end of file diff --git a/src/UserMessageException.php b/src/UserMessageException.php index 1638288..88286de 100644 --- a/src/UserMessageException.php +++ b/src/UserMessageException.php @@ -1,16 +1,15 @@ userMessage = $message; diff --git a/src/Validator/Rule/Abstract.php b/src/Validator/Rule/Abstract.php new file mode 100644 index 0000000..40f5acc --- /dev/null +++ b/src/Validator/Rule/Abstract.php @@ -0,0 +1,45 @@ +field = $field; + $this->errorMsg = $errorMsg; + } + + public function setName($field) + { + $this->field = $field; + return $this; + } + + public function setErrorMsg($errorMsg) + { + $this->errorMsg = $errorMsg; + return $this; + } + + public function getErrorMsg() + { + return $this->errorMsg; + } + + public function isValid(Collection $container, $status = null) + { + return true; + } + + function skipEmpty() { + return true; + } + + public function setContext($ctx) + { + $this->ctx = $ctx; + } +} diff --git a/src/Validator/Rule/AbstractRule.php b/src/Validator/Rule/AbstractRule.php deleted file mode 100644 index 706d8b6..0000000 --- a/src/Validator/Rule/AbstractRule.php +++ /dev/null @@ -1,58 +0,0 @@ -field = $field; - $this->errorMsg = $errorMsg; - } - - public function setName(string $field): self - { - $this->field = $field; - return $this; - } - - public function setErrorMsg(?string $errorMsg): self - { - $this->errorMsg = $errorMsg; - return $this; - } - - public function getErrorMsg(): string - { - return $this->errorMsg; - } - - /** - * @param Collection $container - * @param bool|null $status - * @return bool - */ - public function isValid(Collection $container, $status = null): bool - { - return true; - } - - function skipEmpty(): bool { - return true; - } - - /** - * @param RuleContext $ctx - */ - public function setContext($ctx): void - { - $this->ctx = $ctx; - } -} diff --git a/src/Validator/Rule/Alpha.php b/src/Validator/Rule/Alpha.php index 2f13230..2443da1 100644 --- a/src/Validator/Rule/Alpha.php +++ b/src/Validator/Rule/Alpha.php @@ -3,19 +3,14 @@ /** * Проверка на число */ -namespace ctiso\Validator\Rule; - -use ctiso\Validator\Rule\AbstractRule; -use ctiso\Collection; - -class Alpha extends AbstractRule +class Validator_Rule_Alpha extends Validator_Rule_Abstract { - public function getErrorMsg(): string - { + public function getErrorMsg() + { return "Поле должно содержать только буквы"; } - public function isValid(Collection $container, $status = null): bool + public function isValid(Collection $container, $status = null) { return ctype_alpha($container->get($this->field)); } diff --git a/src/Validator/Rule/Code.php b/src/Validator/Rule/Code.php index 30f6e5e..2bcfbf8 100644 --- a/src/Validator/Rule/Code.php +++ b/src/Validator/Rule/Code.php @@ -3,17 +3,14 @@ /** * Проверка формата электронной почты */ -namespace ctiso\Validator\Rule; -use ctiso\Validator\Rule\AbstractRule, - ctiso\Collection; - -class Code extends AbstractRule +class Validator_Rule_Code extends Validator_Rule_Abstract { - public function getErrorMsg(): string { + public function getErrorMsg() + { return "Неправильно указан персональный код"; } - function checkCode(array $code): bool { + function checkCode($code) { foreach($code as $c) { if (empty($c)) { return false; @@ -22,38 +19,37 @@ class Code extends AbstractRule return true; } - public function isValid(Collection $container, $status = null): bool + public function isValid(Collection $container, $status = null) { if ($status == 'update') return true; $name = $this->field; if (is_array($_POST[$name . '_code_genre'])) { - $count = count($_POST[$name . '_code_genre']); - for($n = 0; $n < $count; $n++) { - $code = [ - $_POST[$name . '_code_genre'][$n], - $_POST[$name . '_code_f'][$n], - $_POST[$name . '_code_i'][$n], - $_POST[$name . '_code_o'][$n], - $_POST[$name . '_code_year'][$n], - $_POST[$name . '_code_month'][$n], - $_POST[$name . '_code_day'][$n] - ]; + for($n = 0; $n < count($_POST[$name . '_code_genre']); $n++) { + $code = array( + $_POST[$name . '_code_genre'][$n], + $_POST[$name . '_code_f'][$n], + $_POST[$name . '_code_i'][$n], + $_POST[$name . '_code_o'][$n], + $_POST[$name . '_code_year'][$n], + $_POST[$name . '_code_month'][$n], + $_POST[$name . '_code_day'][$n] + ); if (!$this->checkCode($code)) { return false; } } return true; - } else { - $code = [ - $_POST[$name . '_code_genre'], - $_POST[$name . '_code_f'], - $_POST[$name . '_code_i'], - $_POST[$name . '_code_o'], - $_POST[$name . '_code_year'], - $_POST[$name . '_code_month'], + } else { + $code = array( + $_POST[$name . '_code_genre'], + $_POST[$name . '_code_f'], + $_POST[$name . '_code_i'], + $_POST[$name . '_code_o'], + $_POST[$name . '_code_year'], + $_POST[$name . '_code_month'], $_POST[$name . '_code_day'] - ]; + ); return $this->checkCode($code); } diff --git a/src/Validator/Rule/Count.php b/src/Validator/Rule/Count.php index fa650a8..2afd612 100644 --- a/src/Validator/Rule/Count.php +++ b/src/Validator/Rule/Count.php @@ -3,38 +3,30 @@ /** * Проверка формата даты */ -namespace ctiso\Validator\Rule; -use ctiso\Validator\Rule\AbstractRule, - ctiso\Collection; - -class Count extends AbstractRule +class Validator_Rule_Count extends Validator_Rule_Abstract { - public int $size = 1; - public ?int $max = null; + public $size = 1; + public $max = false; - public function getErrorMsg(): string - { + public function getErrorMsg() + { return "Количество записей должно быть не менне {$this->size} и не более {$this->max}"; } - /** - * @param string $s - * @return bool - */ - function notEmpty($s): bool { + function not_empty($s) { return $s != ""; } - - public function isValid(Collection $container, $status = null): bool + + public function isValid(Collection $container, $status = null) { if (!$this->max) { $this->max = $this->size; - } - $count = count(array_filter(array_map('trim', - explode(";", $container->get($this->field))), [$this, 'notEmpty'])); + } + $count = count(array_filter(array_map('trim', + explode(";", $container->get($this->field))), array($this, 'not_empty'))); - return $count >= $this->size && $count <= ((int)$this->max); + return $count >= $this->size && $count <= $this->max; } } diff --git a/src/Validator/Rule/Date.php b/src/Validator/Rule/Date.php index a53975d..166907a 100644 --- a/src/Validator/Rule/Date.php +++ b/src/Validator/Rule/Date.php @@ -3,23 +3,21 @@ /** * Проверка формата даты */ -namespace ctiso\Validator\Rule; -use ctiso\Validator\Rule\AbstractRule, - ctiso\Collection; - -class Date extends AbstractRule +class Validator_Rule_Date extends Validator_Rule_Abstract { - public function getErrorMsg(): string - { + private $split = "\\/"; + + public function getErrorMsg() + { return "Неверный формат даты"; } - - public function isValid(Collection $container, $status = null): bool + + public function isValid(Collection $container, $status = null) { $pattern = "/^([0-9]{1,2})\/([0-9]{1,2})\/([0-9]{4})$/"; $matches = []; - return (preg_match($pattern, $container->get($this->field), $matches) - && checkdate((int)$matches[2], (int)$matches[1], (int)$matches[3])); + return (preg_match($pattern, $container->get($this->field), $matches) + && checkdate($matches[2], $matches[1], $matches[3])); } } diff --git a/src/Validator/Rule/Email.php b/src/Validator/Rule/Email.php index ebbdc17..dd2b0e0 100644 --- a/src/Validator/Rule/Email.php +++ b/src/Validator/Rule/Email.php @@ -3,21 +3,23 @@ /** * Проверка формата электронной почты */ -namespace ctiso\Validator\Rule; -use ctiso\Validator\Rule\AbstractRule, - ctiso\Collection; - -class Email extends AbstractRule +class Validator_Rule_Email extends Validator_Rule_Abstract { - public function getErrorMsg(): string - { + public function getErrorMsg() + { return "Неверный формат электронной почты"; } - public function isValid(Collection $container, $status = null): bool + public function isValid(Collection $container, $status = null) { + $user = '[a-zA-Z0-9_\-\.\+\^!#\$%&*+\/\=\?\|\{\}~\']+'; + $doIsValid = '(?:[a-zA-Z0-9]|[a-zA-Z0-9][a-zA-Z0-9\-]*[a-zA-Z0-9]\.?)+'; + $ipv4 = '[0-9]{1,3}(\.[0-9]{1,3}){3}'; + $ipv6 = '[0-9a-fA-F]{1,4}(\:[0-9a-fA-F]{1,4}){7}'; + $emails = explode(",", $container->get($this->field)); foreach ($emails as $email) { +// if (! preg_match("/^$user@($doIsValid|(\[($ipv4|$ipv6)\]))$/", $email)) return false; if (! filter_var($email, FILTER_VALIDATE_EMAIL)) return false; } diff --git a/src/Validator/Rule/EmailList.php b/src/Validator/Rule/EmailList.php index 068becf..98ac122 100644 --- a/src/Validator/Rule/EmailList.php +++ b/src/Validator/Rule/EmailList.php @@ -3,20 +3,22 @@ /** * Проверка формата электронной почты */ -namespace ctiso\Validator\Rule; -use ctiso\Validator\Rule\AbstractRule, - ctiso\Collection; - -class EmailList extends AbstractRule +class Validator_Rule_EmailList extends Validator_Rule_Abstract { - public function getErrorMsg(): string - { + public function getErrorMsg() + { return "Неверный формат электронной почты"; } - public function isValid(Collection $container, $status = null): bool { + public function isValid(Collection $container, $status = null) { + $user = '[a-zA-Z0-9_\-\.\+\^!#\$%&*+\/\=\?\|\{\}~\']+'; + $doIsValid = '(?:[a-zA-Z0-9]|[a-zA-Z0-9][a-zA-Z0-9\-]*[a-zA-Z0-9]\.?)+'; + $ipv4 = '[0-9]{1,3}(\.[0-9]{1,3}){3}'; + $ipv6 = '[0-9a-fA-F]{1,4}(\:[0-9a-fA-F]{1,4}){7}'; + $emails = $container->get($this->field); foreach ($emails as $email) { +// if (! preg_match("/^$user@($doIsValid|(\[($ipv4|$ipv6)\]))$/", $email)) return false; if (! filter_var($email, FILTER_VALIDATE_EMAIL)) return false; } return true; diff --git a/src/Validator/Rule/FileName.php b/src/Validator/Rule/FileName.php index 5f4410f..87732b3 100644 --- a/src/Validator/Rule/FileName.php +++ b/src/Validator/Rule/FileName.php @@ -1,18 +1,13 @@ get($this->field)); } diff --git a/src/Validator/Rule/IsFile.php b/src/Validator/Rule/IsFile.php index 37115f8..b724754 100644 --- a/src/Validator/Rule/IsFile.php +++ b/src/Validator/Rule/IsFile.php @@ -3,48 +3,44 @@ /** * Проверка формата времени */ -namespace ctiso\Validator\Rule; -use ctiso\Validator\Rule\AbstractRule, - ctiso\Collection; - -class IsFile extends AbstractRule +class Validator_Rule_IsFile extends Validator_Rule_Abstract { - private array $type = []; - private int $maxsize = 1024; + private $type = array(); + private $maxsize = 1024; - function skipEmpty(): bool { + function skipEmpty() { return false; } - function setSize(int $size): void { + function setSize($size) { $this->maxsize = $size; } - function setType(array $type): void { + function setType(array $type) { $this->type = $type; } - public function isValid(Collection $container, $status = null): bool + public function isValid(Collection $container, $status = null) { if (!isset($_FILES[$this->field]) || $_FILES[$this->field]['error'] == UPLOAD_ERR_NO_FILE) { $this->setErrorMsg('Файл не загружен'); - return false; + return false; } if ($_FILES[$this->field]['error'] == UPLOAD_ERR_INI_SIZE) { $this->setErrorMsg('Превышен размер файла'); - return false; + return false; } $tmp = $_FILES[$this->field]; if (!in_array($tmp['type'], $this->type)) { $this->setErrorMsg('Неверный формат файла'); - return false; + return false; } if (((int)$tmp['size']) > $this->maxsize*1024) { $this->setErrorMsg('Неверный размер файла'); - return false; + return false; } return true; diff --git a/src/Validator/Rule/MatchRule.php b/src/Validator/Rule/Match.php similarity index 59% rename from src/Validator/Rule/MatchRule.php rename to src/Validator/Rule/Match.php index b0db64b..eb37a82 100644 --- a/src/Validator/Rule/MatchRule.php +++ b/src/Validator/Rule/Match.php @@ -3,22 +3,16 @@ /** * Проверка на равентство двух полей */ -namespace ctiso\Validator\Rule; -use ctiso\Validator\Rule\AbstractRule, - ctiso\Collection; - -class MatchRule extends AbstractRule +class Validator_Rule_Match extends Validator_Rule_Abstract { - /** @var string */ public $same; - public function getErrorMsg(): string - { + public function getErrorMsg() + { return "Поля не совпадают"; } - public function isValid(Collection $container, $status = null): bool - { + public function isValid(Collection $container, $status = null) { return (strcmp($container->get($this->field), $container->get($this->same)) == 0); } } diff --git a/src/Validator/Rule/Notnull.php b/src/Validator/Rule/Notnull.php index 2a146e2..2b0c3cb 100644 --- a/src/Validator/Rule/Notnull.php +++ b/src/Validator/Rule/Notnull.php @@ -1,21 +1,17 @@ get($this->field); if (is_array($data)) { diff --git a/src/Validator/Rule/Numeric.php b/src/Validator/Rule/Numeric.php index 1fe5b0d..2d080e7 100644 --- a/src/Validator/Rule/Numeric.php +++ b/src/Validator/Rule/Numeric.php @@ -3,18 +3,14 @@ /** * Проверка на число */ -namespace ctiso\Validator\Rule; -use ctiso\Validator\Rule\AbstractRule, - ctiso\Collection; - -class Numeric extends AbstractRule +class Validator_Rule_Numeric extends Validator_Rule_Abstract { - public function getErrorMsg(): string - { + public function getErrorMsg() + { return "Значение поля должно быть числом"; } - public function isValid(Collection $container, $status = null): bool + public function isValid(Collection $container, $status = null) { return (is_numeric($container->get($this->field))); } diff --git a/src/Validator/Rule/PregMatch.php b/src/Validator/Rule/PregMatch.php deleted file mode 100644 index 71e4252..0000000 --- a/src/Validator/Rule/PregMatch.php +++ /dev/null @@ -1,20 +0,0 @@ -pattern, $container->get($this->field)) !== false; - } -} diff --git a/src/Validator/Rule/RuleContext.php b/src/Validator/Rule/RuleContext.php deleted file mode 100644 index e5be2fc..0000000 --- a/src/Validator/Rule/RuleContext.php +++ /dev/null @@ -1,10 +0,0 @@ - -1 && $hour < 24 && $minute > -1 && $minute < 60) { return true; } - return false; } - public function isValid(Collection $container, $status = null): bool + public function isValid(Collection $container, $status = null) { - /** @var list */ $tmp = explode($this->split, $container->get($this->field), 2); - if (self::checktime ((int)$tmp[0], (int)$tmp[1])) { - return true; + if ($tmp) { + if (self::checktime ($tmp[0], $tmp[1])) { + return true; + } } - return false; } } diff --git a/src/Validator/Rule/Unique.php b/src/Validator/Rule/Unique.php index 37dfccf..e458b8d 100644 --- a/src/Validator/Rule/Unique.php +++ b/src/Validator/Rule/Unique.php @@ -2,21 +2,16 @@ /** */ -namespace ctiso\Validator\Rule; - -use ctiso\Validator\Rule\AbstractRule; -use ctiso\Collection; - -class Unique extends AbstractRule +class Validator_Rule_Unique extends Validator_Rule_Abstract { - public function getErrorMsg(): string + public function getErrorMsg() { return $this->ctx->getMessage(); } - public function isValid(Collection $container, $status = null): bool + public function isValid(Collection $container, $status = null) { - return $this->ctx->isUnique($container->getString($this->field), $status, $container); + return $this->ctx->isUnique($container->get($this->field), $status, $container); } } diff --git a/src/Validator/Validator.php b/src/Validator/Validator.php index 2225479..d01c001 100644 --- a/src/Validator/Validator.php +++ b/src/Validator/Validator.php @@ -1,71 +1,43 @@ /** - * @phpstan-type Rule array{ - * validate?:string, // Описание правила см. формат правила ниже - * name:string, // Имя переменой для проверки - * context?:RuleContext - * } + * Проверка коллекции */ -class Validator +class Validator_Validator { - /** @var AbstractRule[] */ - protected array $chain = []; // Массив правил - /** @var array */ - protected array $errorMsg = []; // Массив ошибок + protected $chain = array(); // Массив правил + protected $errorMsg = array(); // Массив ошибок - /** - * Поля по умолчанию - * @var array> - */ - protected $type = [ - 'date' => Rule\Date::class, - 'email' => Rule\Email::class, - 'emaillist'=> Rule\EmailList::class, - 'match' => Rule\MatchRule::class, - 'time' => Rule\Time::class, - 'alpha' => Rule\Alpha::class, - 'require' => Rule\Notnull::class, - 'numeric' => Rule\Numeric::class, - 'unique' => Rule\Unique::class, - 'filename' => Rule\FileName::class, - 'count' => Rule\Count::class, - 'isfile' => Rule\IsFile::class, - 'code' => Rule\Code::class, - 'reg' => Rule\PregMatch::class, - ]; - - /** - * @param Rule[] $rules - */ - function __construct($rules = []) { + function __construct($rules = array()) { $this->addRuleList($rules); } - /** - * Добавление правила в список - * @param string $name - * @param class-string $className - */ - function addRuleType(string $name, string $className): void { - $this->type[$name] = $className; - } - /** * Добавление списка правил в специальном формате - * @param Rule[] $input + * array(array('name' => fieldname, 'validate' => ruletext), ...) + * fieldname - Имя переменой для проверки + * ruletext - Описание правила см. формат правила ниже */ - public function addRuleList(array $input): void + public function addRuleList(array $input) { + $type = array( + 'date' => 'Validator_Rule_Date', + 'email' => 'Validator_Rule_Email', + 'emaillist'=> 'Validator_Rule_EmailList', + 'match' => 'Validator_Rule_Match', + 'time' => 'Validator_Rule_Time', + 'alpha' => 'Validator_Rule_Alpha', + 'require' => 'Validator_Rule_Notnull', + 'numeric' => 'Validator_Rule_Numeric', + 'unique' => 'Validator_Rule_Unique', + 'filename' => 'Validator_Rule_FileName', + 'count' => 'Validator_Rule_Count', + 'isfile' => 'Validator_Rule_IsFile', + 'code' => 'Validator_Rule_Code' + ); + // Разбор правила проверки // Формат правила 'rule1|rule2,param1=value1|rule3,param1=value1,param2=value2' foreach ($input as $value) { @@ -78,8 +50,8 @@ class Validator $rule_param = explode(",", $rule); $name = array_shift($rule_param); - if (isset($this->type[$name])) { - $constructor = $this->type[$name]; + if (isset($type[$name])) { + $constructor = $type[$name]; $ruleObj = new $constructor($value['name'], false); // Нужны шаблонные сообщения для правил if (isset($value['context'])) { $ruleObj->setContext($value['context']); @@ -97,46 +69,33 @@ class Validator } } - public function addRule(array|AbstractRule $rule): void { + public function addRule($rule/*: any*/) { if (is_array($rule)) { $this->chain = array_merge($this->chain, $rule); } else { $this->chain[] = $rule; } } - - /** - * @param AbstractRule $rule - */ - public function skip($rule, Collection $container): bool + + public function skip($rule/*: Validator_Rule_Abstract*/, $container/*: Collection*/) // -> Rule_Abstract { if ($rule->skipEmpty()) { $data = $container->get($rule->field); if (!is_array($data)) { - $value = trim($data ?: ''); + $value = trim($data); return $value == ''; } - } + } return false; } - - function reset(): void { - $this->errorMsg = []; - } - - /** - * @param Collection $container - * @param AbstractRule[]|null $rules - * @param bool|null $status - * @return bool - */ - public function validate(Collection $container, $rules = null, $status = null): bool + + public function validate(Collection $container, $rule = null, $status = null) { - $fields = []; - if ($rules) { - $this->chain = $rules; + $fields = array(); + if ($rule) { + $this->chain = $rule; } - + $this->errorMsg = array(); foreach ($this->chain as $rule) { //echo $key; if (!in_array($rule->field, $fields) && !$this->skip($rule, $container) && !$rule->isValid($container, $status)) { @@ -148,25 +107,22 @@ class Validator return $this->isValid(); } - public function addError(string $name, string $message): void + public function addError($name, $message) { $this->errorMsg[$name] = $message; } - public function isError(): bool + public function isError() { return !empty($this->errorMsg); } - public function isValid(): bool + public function isValid() { return empty($this->errorMsg); } - /** - * @return array - */ - public function getErrorMsg(): array + public function getErrorMsg() { return $this->errorMsg; } diff --git a/src/View/Composite.php b/src/View/Composite.php index edfaafb..812ee48 100644 --- a/src/View/Composite.php +++ b/src/View/Composite.php @@ -1,46 +1,45 @@ tal = new PHPTAL($file); $this->tal->setPhpCodeDestination(PHPTAL_PHP_CODE_DESTINATION); - $this->tal->setEncoding(PHPTAL_DEFAULT_ENCODING); + $this->tal->setEncoding(PHPTAL_DEFAULT_ENCODING); // PHPTAL_DEFAULT_ENCODING !! $this->tal->setTemplateRepository(PHPTAL_TEMPLATE_REPOSITORY); $this->tal->setOutputMode(PHPTAL::HTML5); $this->tal->stripComments(true); // $this->tal->addPreFilter(new PHPTAL_PreFilter_Normalize()); } - function set(string $key, mixed $val): void { + function set($key, $val) { if ($key == 'title') { $this->setTitle($val); } $this->tal->set($key, $val); } - function __set(string $key, mixed $val): void { + function __set($key, $val) { $this->tal->set($key, $val); } - function execute(): string + function execute() { - $this->processChild(); + parent::execute(); + // postProcess return $this->tal->execute(); } - function setTranslator(PHPTAL_TranslationService $t): void { + function setTranslator($t) { $this->tal->setTranslator($t); } } diff --git a/src/View/JsonView.php b/src/View/JsonView.php deleted file mode 100644 index 3ba8fd4..0000000 --- a/src/View/JsonView.php +++ /dev/null @@ -1,40 +0,0 @@ -_name = $name; - } - - /** - * @param string $key - * @param mixed $value - */ - function set($key, $value): void { - $this->_data[$key] = $value; - } - - /** - * @param string $key - * @param mixed $value - */ - function __set($key, $value): void { - $this->_data[$key] = $value; - } - - /** - * @return string - */ - function execute() { - return json_encode($this->_data) ?: ''; - } -} diff --git a/src/View/List.php b/src/View/List.php new file mode 100644 index 0000000..8522b32 --- /dev/null +++ b/src/View/List.php @@ -0,0 +1,13 @@ +_section as $key => $value) { + $result [] = $value->execute(); + } + return $result; + } +} diff --git a/src/View/Pages.php b/src/View/Pages.php index a64873d..704629a 100644 --- a/src/View/Pages.php +++ b/src/View/Pages.php @@ -1,71 +1,57 @@ $n) $page = $n; if ($page < 1) $page = 1; $url = 'page='; - $result = []; + $result = array(); for ($i = max($page - self::$range, 1); $i <= min($n, $page + self::$range); $i++) { - $result [] = ['page' => $i, 'href' => ($i != $page) ? self::href($prefix, $url . $i) : false]; + $result [] = array('page' => $i, 'href' => ($i != $page) ? self::href($prefix, $url . $i) : false); } - return [ + return array( 'all' => ($n > 1), - 'list' => $result, - 'first' => self::href($prefix, $url . 1), - 'last' => self::href($prefix, $url . $n), - 'next' => ($page == $n)? false : self::href($prefix, $url . ($page + 1)) , - 'prev' => ($page == 1)? false : self::href($prefix, $url . ($page - 1))]; + 'list' => $result, + 'first' => self::href($prefix, $url . 1), + 'last' => self::href($prefix, $url . $n), + 'next' => ($page == $n)? false : self::href($prefix, $url . ($page + 1)) , + 'prev' => ($page == 1)? false : self::href($prefix, $url . ($page - 1))); } /** * @deprecated - * @param int $page номер страницы - * @param int $onpage количество элем на странице + * @param $page int номер страницы + * @param $onpage int количество элем на странице * @return string */ - static function getLimit(int $page, int $onpage) { + static function getLimit($page/*: number*/, $onpage/*: number*/) { if ($page <= 0) { $page = 1; } return "LIMIT $onpage OFFSET " . ($page - 1) * $onpage; } /** - * @param int $page номер страницы - * @param int $onpage количество элем на странице + * @param $page int номер страницы + * @param $onpage int количество элем на странице * @return array */ - static function _getLimit(int $page, int $onpage) { + static function _getLimit($page, $onpage) { if ($page <= 0) { $page = 1; } - return [ + return array( 'count' => $onpage, 'start' => ($page - 1) * $onpage, - ]; + ); } - /** - * @param string $prefix префикс - * @param string $x строка - * @return string - */ - static function href($prefix, $x) { - return $prefix . $x; + static function href($prefix, $x) { + return $prefix . $x; } + } diff --git a/src/View/Plain.php b/src/View/Plain.php index f070d3d..67d4521 100644 --- a/src/View/Plain.php +++ b/src/View/Plain.php @@ -1,76 +1,48 @@ document = $document; } - /** - * Установка значения - * @param string $key ключ - * @param mixed $value значение - */ - public function set($key, $value): void + public function set($key, $value) { $this->values[$key] = $value; } - /** - * Импорт значений - * @param array $list список значений - */ - public function import($list): void + public function import($list) { $this->values = array_merge($this->values, $list); } - /** - * @param string $key ключ - * @param mixed $value значение - */ - public function __set($key, $value): void + public function __set($key, $value) { $this->set($key, $value); } - /** - * Выполнение шаблона - * @return string - */ public function execute() { $result = $this->values; return self::getTemplateContent ($this->document, $result); } - /** - * Получение содержимого шаблона - * @param string $document шаблон - * @param array $result результат - * @return string содержимое шаблона - */ - static function getTemplateContent(string $document, $result): string + static function getTemplateContent($document, $result) { ob_start (); - include ($document); + include ($document); $content = ob_get_contents (); ob_clean (); - return $content === false ? '' : $content; + return $content; } } diff --git a/src/View/Top.php b/src/View/Top.php index 2a7d7fe..75667e1 100644 --- a/src/View/Top.php +++ b/src/View/Top.php @@ -1,120 +1,131 @@ doTree('_title', false), [$this, 'isNotNull'])); + return implode(" - ", array_filter($this->doTree('_title', false), array($this, 'isNotNull'))); } - /** - * Идентификатор - * - * @param string $pref - * @return string - */ - function getId($pref) + private function findGroup($groups, $file) { - $this->mid++; - return $pref . $this->mid; + foreach($groups as $key => $group) { + if(in_array($file, $group)) { + return $key; + } + } + return false; } + private function groupFiles(array $list, $debugMode = true) + { + $debug = ($debugMode) ? 'debug=1' : ''; + $path = parse_url(WWW_PATH, PHP_URL_PATH); + + $groups = array(); + $use = array(); + + $result = array(); + foreach ($list as $file) { + $name = $this->findGroup($groups, $file); + if($name) { + $use[$name] = 1; + } else { + $result[] = $file; + } + } + $list = array(); + foreach ($use as $name => $value) { + $list[] = $groups[$name]; + } + + return array_merge($list, $result); + } + + + function getId($pref) { + $this->mid++; + return $pref.$this->mid; + } + /** * Обработка шаблона * * @return string */ - #[\Override] - public function execute(): string + public function render() { - $this->doTree('alias'); + $alias = $this->doTree('alias'); // Скрипты и стили $this->set('scriptstring', $this->getScriptRaw()); - $this->set('scripts', array_unique($this->getScripts())); - $this->set('stylesheet', array_unique($this->getStyleSheet())); + $this->set('scripts', array_unique($this->groupFiles($this->getScripts(), false))); + $this->set('stylesheet', array_unique($this->groupFiles($this->getStyleSheet(), false))); - $this->require = ['admin' => 'ma']; - $this->deps = []; + $this->require = array('admin' => 'ma'); + $this->deps = array(); - $startup = []; - foreach ($this->_section as $s) { + $startup = array(); + foreach($this->_section as $s) { if (is_string($s)) { continue; } - $moduleName = explode('_', $s->active_module ?: '', 2); + $moduleName = explode('_', $s->active_module, 2); if (count($moduleName) < 2) { continue; } $module = $moduleName[1]; - $name = mb_strtolower($module); - $fname = $name . '/' . $name; + $name = mb_strtolower($module); + $fname = $name . '/' . $name; - $current = $this->getId('m'); - $this->require[$fname] = $current; + $current = $this->getId('m'); + $this->require[$fname] = $current; - $value = $this->getId('v'); + $value = $this->getId('v'); - $script = "var " . $value . " = new " . $current . '.' . $module . "();\n"; - foreach ($s->_values as $key => $v) { - $script .= $value . "." . $key . " = " . json_encode($v /*, JSON_PRETTY_PRINT*/) . ";\n"; - } + $script = "var " . $value . " = new " . $current . '.' . $module . "();\n"; + foreach($s->_values as $key => $v) { + $script .= $value . "." . $key . " = " . json_encode($v/*, JSON_PRETTY_PRINT*/) . ";\n"; + } - $init = []; - /** @var View $item */ + $init = array(); + foreach($s->_section as $key => $item) { + $ss/*: View_View*/ = $item; + if ($ss->codeGenerator !== null) { + // функцию которая вычисляет а не результат + $part = call_user_func($ss->codeGenerator, $this, $key, $value); + $init [] = $part; + } + } - foreach ($s->_section as $key => $item) { - if ($item->codeGenerator !== null) { - // функцию которая вычисляет а не результат - $part = call_user_func($item->codeGenerator, $this, $key, $value); - $init[] = $part; - } - } - - $script .= $value . ".execute('" . $s->module_action . "', " . json_encode($init) . ");\n"; - $startup[] = $script; - } + $script .= $value . ".execute('" . $s->module_action . "', " . json_encode($init) .");\n"; + $startup[] = $script; + } $this->set('startup', implode("", $startup) . $this->getScriptStartup()); - $this->set('require', implode(",", array_map(function ($x) { - return "'$x'"; }, array_keys($this->require)))); + $this->set('require', implode(",", array_map(function ($x) { return "'$x'";}, array_keys($this->require)))); $this->set('deps', implode(",", array_values($this->require))); $this->set('title', $this->getTitle()); - $this->set('jspath', $this->config->get('system', 'web')); - // - return parent::execute(); // execute+phptal ?? + $this->set('jspath', enableHttps(WWW_PATH)); + // + return $this->execute(); // execute+phptal ?? } /** * Массив имен файлов скриптов * - * @return array + * return array */ public function getScripts() { @@ -131,11 +142,6 @@ class Top extends Composite return implode("\n", $this->doTree('_scriptstring')); } - /** - * Строка со скриптом - * - * @return string - */ public function getScriptStartup() { return implode("\n", $this->doTree('_startup')); @@ -144,10 +150,11 @@ class Top extends Composite /** * Массив имен файлов стилей * - * @return array + * return array */ public function getStyleSheet() { return $this->doTree('_stylesheet'); } -} \ No newline at end of file + +} diff --git a/src/View/View.php b/src/View/View.php index 7d7776e..b54079e 100644 --- a/src/View/View.php +++ b/src/View/View.php @@ -1,39 +1,24 @@ Вложенные шаблоны */ - protected array $_section = []; + protected $_section = array(); // Вложенные шаблоны + // Блоки + protected $_stylesheet = array(); // Массив стилей текущего шаблона + protected $_script = array(); // Массив скриптов текущего шаблона + protected $_scriptstring = array(); + protected $_startup = array(); + protected $_values = array(); - /** @var string[] $_stylesheet Массив стилей текущего шаблона */ - protected array $_stylesheet = []; - /** @var string[] $_script Массив скриптов текущего шаблона */ - protected array $_script = []; - /** @var string[] $_scriptstring */ - public array $_scriptstring = []; - /** @var string[] $_startup */ - protected array $_startup = []; + protected $_title = null; // Заголовок текущего шаблона - protected array $_values = []; + public $active_module; + public $module_action; - protected ?string $_title = null; // Заголовок текущего шаблона + public $suggestions; //подсказки - public ?string $active_module = null; - public string $module_action; - - /** @var string[] */ - public array $prefix; - - /** @var string[] */ - public array $suggestions = []; //подсказки - - /** @var array> */ - public array $alias = []; - // public $codeGenerator = null; - /** @var View|null */ + public $alias = array(); + public $codeGenerator = null; public $parent_view = null; function __construct() { @@ -43,74 +28,77 @@ class View extends \stdClass * Связывет переменную с вложенным шаблоном * * @param string $section переменная шаблона - * @param View|string $view вложенный шаблон + * @param CompositeView $view вложенный шаблон */ - public function setView($section, $view): void + public function setView($section, /*View_View|string*/ $view) { - $this->_section[$section] = $view; + $this->_section [$section] = $view; if (is_object($view)) { $view->parent_view = $this; } } - /** - * @param array $values - */ - public function assignValues($values): void + public function assignValues($values) { $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 путь к скрипту + * + * @param string $name путь к скрипту */ - public function addScript(string $name): void + public function addScript($name) { - $output = $this->resolveName($this->alias, $name . '?' . http_build_query($this->prefix)); + $output = $this->resolveName($this->alias, $name); $this->_script [] = $output; } /** * Добавляет код скипта к текущему шаблону * - * @param string $code строка javascript кода + * @param string $name строка javascript кода */ - public function addScriptRaw(string $code, bool $startup = false): void + public function addScriptRaw($name, $startup = false) { if ($startup) { - $this->_startup [] = $code; + $this->_startup [] = $name; } else { - $this->_scriptstring [] = $code; + $this->_scriptstring [] = $name; } } - public function setPrefix(string $name, string $val): void { - $this->prefix[$name] = $val; - } - /** * Добавляет стили к текущему шаблону - * + * * @param string $name путь к стилю */ - public function addStyleSheet(string $name): void + public function addStyleSheet($name) { - $output = $this->resolveName($this->alias, $name . '?' . http_build_query($this->prefix)); + $output = $this->resolveName($this->alias, $name); $this->_stylesheet [] = $output; } - /** + /** * Рекурсивно извлекает из значение свойства обьекта * * @param string $list Имя свойства - * @param bool $flatten + * @param boolean $flatten */ - protected function doTree($list, bool $flatten = true): array + protected function doTree($list, $flatten = true) { - $result = ($flatten == true) ? $this->$list : [$this->$list]; + $result = ($flatten == true) ? $this->$list : array($this->$list); foreach ($this->_section as $value) { if (is_object($value)) { if ($list == '_script' || $list == '_stylesheet') { @@ -123,22 +111,16 @@ class View extends \stdClass return $result; } - /* - function getTitleArray(): array { - return array_reduce($this->_section, fn ($result, $item) => - is_object($item) ? array_merge($result, $item->getTitleArray()) : $result, []); - } - */ - - - /*abstract*/ public function set(string $key, mixed $value): void + /*abstract*/ public function set($key, $value) { } - + /** * Обработка всех вложенных шаблонов + * + * @return string */ - public function processChild(): void + public function execute() { foreach ($this->_section as $key => $value) { $this->set($key, (is_object($value)) ? $value->execute() : $value); // ? @@ -147,35 +129,31 @@ class View extends \stdClass /** * Установка заголовка шаблона + * + * @param string $title */ - public function setTitle(string $title): void + public function setTitle($title) { - $this->_title = $title; + $this->_title = $title; } - protected function isNotNull(?string $title): bool + protected function isNotNull($title) { - return $title !== null; + return $title !== null; } - /** - * @param array> $alias - */ - function setAlias($alias): void + function setAlias($alias) { $this->alias = $alias; } - function addAlias(string $name, string $path): void + function addAlias($name, $path) { $this->alias[$name] = $path; $this->set($name, $path); } - /** - * @param string[] $pathlist - */ - function findFile(array $pathlist, string $file): string { + function find_file($pathlist, $file) { foreach($pathlist as $key => $www) { if (file_exists($key . '/' . $file)) { @@ -183,45 +161,45 @@ class View extends \stdClass } } throw new Exception("file not found: $file"); - } + } - - /** - * FIXME: Префикс, конфликтует с протоколом - * @param string[]|string[][] $alias - */ - function resolveName($alias, string $file): string { + function resolveName($alias, $file) { list($type, $filename) = explode(":", $file, 2); - - // Сделать поиск а не просто замену папки при совпадении имени - if (isset($alias[$type])) { - if (is_array($alias[$type])) { - $output = $this->findFile($alias[$type], $filename); - } else { - $output = $alias[$type] . '/' . $filename; - } - return $output; + + // Сделать поиск а не просто замену папки при совпадении имени + if (is_array($alias[$type])) { + $output = $this->find_file($alias[$type], $filename); + } else { + $output = $alias[$type] . '/' . $filename; } - return $file; + return $output; } - /** - * @param string[][] $alias - * @param string[] $list - * @return string[] - */ - public function resolveAllNames($alias, array $list): array { - $result = []; + 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; } - - /** - * Шаблон всегда возвращает строку - */ - function execute(): string { - return ''; - } -} +} \ No newline at end of file diff --git a/src/WrongRequestException.php b/src/WrongRequestException.php deleted file mode 100644 index 34863be..0000000 --- a/src/WrongRequestException.php +++ /dev/null @@ -1,7 +0,0 @@ - - */ - private $ignore = ['.', '..']; + private $ignore = array('.', '..'); - public function addIgnore(string $name): void + public function addIgnore($name) { $this->ignore [] = $name; } - private function addDirDo(string $location, string $name): void + private function addDirDo($location, $name) { + assert(is_string($location) && is_string($name)); + $name .= '/'; $location .= '/'; $file = null; // Read all Files in Dir $dir = opendir($location); - if (!$dir) { - throw new \RuntimeException("Enable to open dir '$dir'"); - } while (($file = readdir($dir)) !== false) { if (in_array($file, $this->ignore)) continue; // Rekursiv, If dir: FlxZipArchive::addDir(), else ::File(); - $call = (is_dir($location . $file)) ? $this->addDir(...) : $this->addFile(...); - call_user_func($call, $location . $file, $name . $file); + $call = (is_dir($location . $file)) ? 'addDir' : 'addFile'; + call_user_func(array($this, $call), $location . $file, $name . $file); } } - public function addDir(string $location, string $name): void + public function addDir($location, $name) { + assert(is_string($location) && is_string($name)); + $this->addEmptyDir($name); $this->addDirDo($location, $name); } diff --git a/src/config.php b/src/config.php new file mode 100644 index 0000000..86c7dfb --- /dev/null +++ b/src/config.php @@ -0,0 +1,9 @@ +execute($req); + + echo ""; + return $result; +} + + +/* Регистрация нового префикса для подключения компонента */ +$tales = PHPTAL_TalesRegistry::getInstance(); +$tales->registerPrefix('component', array('Component_Tales', 'component')); +$tales->registerPrefix('date', array('DateTime_Tales', 'date')); +$tales->registerPrefix('time', array('DateTime_Tales', 'time')); +