diff --git a/src/Adapter.php b/src/Adapter.php index 6ab0934..2ba68f9 100644 --- a/src/Adapter.php +++ b/src/Adapter.php @@ -8,21 +8,12 @@ namespace ctiso; */ class Adapter { - /** @var array|object */ protected $adaptee; - - /** - * @param array|object $adaptee - */ public function __construct ($adaptee) { $this->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..38cbb35 100644 --- a/src/Arr.php +++ b/src/Arr.php @@ -4,12 +4,6 @@ namespace ctiso; class Arr { - /** - * @param array $data - * @param string|int $key - * @param mixed $default - * @return mixed - */ static function get($data, $key, $default = null) { return $data[$key] ?? $default; } diff --git a/src/Collection.php b/src/Collection.php index 430cc69..2f7cea3 100644 --- a/src/Collection.php +++ b/src/Collection.php @@ -3,18 +3,21 @@ namespace ctiso; /** * Коллекция - * @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 +27,6 @@ class Collection implements \ArrayAccess /** * Преобразование коллекции в массив - * - * @return array */ public function export() { @@ -33,13 +34,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 +50,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,93 +58,23 @@ 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); } - public function clear(): void + public function clear() { $this->data = []; } diff --git a/src/ComponentRequest.php b/src/ComponentRequest.php index 378c375..6bc7dbc 100644 --- a/src/ComponentRequest.php +++ b/src/ComponentRequest.php @@ -2,31 +2,19 @@ namespace ctiso; -use ctiso\HttpRequest; -use ctiso\Arr; +use ctiso\HttpRequest, + ctiso\Arr; class ComponentRequest { - /** @var int */ public $component_id; - /** @var string */ public $component_title; - /** @var HttpRequest */ public $r; - /** - * @param int $c - * @param HttpRequest $r - */ function __construct($c, HttpRequest $r) { $this->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); @@ -42,9 +30,6 @@ class ComponentRequest { return $default; } - /** - * @return string - */ function getAction() { return $this->r->getAction(); } diff --git a/src/Connection/HttpRequest.php b/src/Connection/HttpRequest.php index 368feda..006cc63 100644 --- a/src/Connection/HttpRequest.php +++ b/src/Connection/HttpRequest.php @@ -3,37 +3,27 @@ namespace ctiso\Connection; use ctiso\File; -class HttpRequest +class HttpRequest { const POST = "POST"; const GET = "GET"; - /** @var array Параметры запроса */ - private $param = []; - /** @var string Содержание */ - public $data = null; - /** @var string Адресс */ - public $url; - /** @var string Метод */ - public $method; - /** @var int */ + private $param = array(); // Параметры запроса + public $data = null; // Содержание + public $url; // Адресс + public $method; // Метод public $port = 80; - /** @var string */ public $host = ""; - /** @var ?string */ public $proxy_host = null; - /** @var ?int */ public $proxy_port = null; - /** @var string */ public $http_version = 'HTTP/1.1'; function __construct() { $this->method = self::GET; } - + /** * Возвращает заголовок соединения - * @return string */ public function getHeader() { @@ -46,58 +36,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 +89,7 @@ class HttpRequest $header = $this->getHeader(); fwrite($socket, $header); - $result = ''; + $result = null; while (! feof($socket)) { $result .= fgets($socket, 128); } @@ -120,12 +99,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..1da2036 100644 --- a/src/Connection/HttpResponse.php +++ b/src/Connection/HttpResponse.php @@ -7,39 +7,30 @@ namespace ctiso\Connection; class 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 +38,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()); + $index = hexdec($this->getLine()); $chunk = []; while ($index > 0) { $chunk [] = substr($this->response, $this->offset, $index); $this->offset += $index; - $index = (int)hexdec($this->getLine()); + $index = hexdec($this->getLine()); } $this->data = implode("", $chunk); @@ -64,33 +55,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..b1f7db2 100644 --- a/src/Controller/Action.php +++ b/src/Controller/Action.php @@ -1,69 +1,63 @@ part = new Url(); } - public function setUp(): void { + public function setUp() { } - /** - * Загрузка файла настроек - * @param string $name - * @return array - */ public function loadConfig($name) { $basePath = $this->config->get('site', 'path'); @@ -77,40 +71,25 @@ class Action implements ActionInterface 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); } - /** - * Добавляет подсказки - * @param View $view - * @param string $name - */ - public function addSuggest(View $view, $name): void { + public function addSuggest(View $view, $name) { + $suggest = []; $file = Path::join($this->modulePath, 'help', $name . '.suggest'); if (file_exists($file)) { $view->suggestions = include($file); } } - /** - * Поиск иконки - * @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'); @@ -119,7 +98,7 @@ class Action implements ActionInterface /** * Создает представление * @param string $name - * @param class-string $viewClass + * @param string $viewClass * @return Composite */ public function getView($name, $viewClass = Composite::class) @@ -130,8 +109,7 @@ class Action implements ActionInterface $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($this->modulePath, 'templates', $this->viewPathPrefix) => Path::join($webPath, "modules", $this->name, 'templates', $this->viewPathPrefix), Path::join($basePath, "templates") => Path::join($webPath, "templates") ]; @@ -141,8 +119,7 @@ class Action implements ActionInterface if(file_exists($template)) { break; } } - /** @var \ctiso\View\Composite */ - $tpl = new $viewClass($template); + $tpl/*: Composite*/ = new $viewClass($template); $tpl->config = $this->config; $stylePath = Path::join($webPath, "assets", "css"); @@ -163,15 +140,12 @@ class Action implements ActionInterface '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) { @@ -186,7 +160,6 @@ class Action implements ActionInterface * 1. Можно переопределить действия * 2. Использовать наследование чтобы добавить к старому обработчику новое поведение * @param HttpRequest $request запроса - * @return View|string */ public function preProcess(HttpRequest $request) { @@ -202,63 +175,45 @@ class Action implements ActionInterface return $view; } - /** - * Выполнение действия - * @param HttpRequest $request - * @return View|string|false - */ public function execute(HttpRequest $request) { $result = $this->preProcess($request); - return $result; + 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([$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 { + public function addUrlPart($key, $value) { $this->part->addQueryParam($key, $value); } /** * Генерация ссылки c учетом прав пользователя на ссылки - * @param string $actionName Действие + * @param string $name Действие * @param array $param Дополнительные параметры * 'mode' означает что элемент до отправки обрабатывается javascript * @return Url|null */ - public function nUrl($actionName, array $param = []) + public function nUrl($name, array $param = []) { - $access = $this->access; + $access/*: ActionAccess*/ = $this->access; $url = new Url(); - if ($access == null || $access->checkAction($actionName)) { + if ($access == null || $access->checkAction($name)) { $moduleName = explode("\\", strtolower(get_class($this))); if (count($moduleName) > 2) { array_shift($moduleName); @@ -266,7 +221,7 @@ class Action implements ActionInterface array_shift($moduleName); } } - $param = array_merge(['module' => implode("\\", $moduleName), "action" => $actionName], $param); + $param = array_merge(['module' => implode("\\", $moduleName), "action" => $name], $param); $url->setParent($this->part); $url->setQuery($param); @@ -278,7 +233,7 @@ class Action implements ActionInterface /** * Генерация ссылки на действие контроллера * Ajax определяется автоматически mode = ajax используется для смены layout - * @param string $name + * @param $name * @param array $param * @return Url|null * @@ -290,13 +245,31 @@ class Action implements ActionInterface return $this->nUrl($name, array_merge(['mode' => 'ajax'], $param)); } + /** + * Добавление помошника контроллера + */ + 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([$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,21 +288,69 @@ 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 к отображению + */ + public function addChild($section, $node) + { + $this->childNodes[$section] = $node; + } + + public function setValue($name, $value) + { + $this->ctrlValues[$name] = $value; + } + + /** + * Добавление дочернего отображения к текущему отображению + */ + public function addView($section, $node) + { + $this->childViews[$section] = $node; + } + + /** + * Генерация содержания + * Путаница c execute и render + */ + public function render() + { + $view = $this->view; + if ($view instanceof View) { + $this->view->assignValues($this->ctrlValues); + + $node/*: Composite*/ = 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) { if ($request->get('__forced__')) { @@ -346,14 +362,16 @@ class Action implements ActionInterface return $result; } - /** - * @return State - */ function _getActionPath() { return new State('index'); } - function redirect(string $action): void { + // Тоже убрать в метод Controller_Model + function getActionPath(HttpRequest $request, $action = null) { + $this->_getActionPath()->getPath($this, ($action) ? $action : $request->getAction()); + } + + function redirect($action/*: string*/) { header('location: ' . $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..9ab1a00 100644 --- a/src/Controller/Component.php +++ b/src/Controller/Component.php @@ -1,90 +1,75 @@ _name = $name; + } + + function __set($key, $value) { + $this->_data[$key] = $value; + } + + function execute() { + return json_encode($this->_data); + } +} /** * Класс компонента */ class 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; - /** @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])); } - /** - * @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); + return preg_replace_callback('/<(\w+)(\s+[a-zA-Z\-]+=\"[^\"]*\")*\s+tal:replace="structure\s+component:([^\"]*)"[^>]*>/u', 'ctiso\\Controller\\Component::replaceContent', $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); @@ -96,47 +81,37 @@ class Component } $this->before(); - $actionMethod = [$this, $action]; - if (is_callable($actionMethod)) { - return call_user_func($actionMethod, $crequest); + if (method_exists($this, $action)) { + return call_user_func([$this, $action], $crequest); + } else { + return $this->actionIndex($crequest); } - - return $this->actionIndex($crequest); } - /** - * Получить имя шаблона - * @param Registry $_registry - * @return string - */ - public function getTemplateName($_registry) { + public function getTemplateName($_registry/*: \ctiso\Settings*/) { return (isset($_COOKIE['with_template']) && preg_match('/^[\w\d-]{3,20}$/', $_COOKIE['with_template'])) ? $_COOKIE['with_template'] : ($_registry ? $_registry->get('site', 'template') : 'modern'); } - /** - * Получить шаблон - * @param string $name - * @return PHPTAL|JsonView - */ public function getView($name) { - if ($this->output === 'json') { - return new JsonView($name); + if ($this->output == 'json') { + return new FakeTemplate($name); } - /** @var Registry $config */ - $config = $this->config; + $config/*: Registry*/ = $this->config; $default = $config->get('site', 'template'); $template = ($this->template) ? $this->template : $this->getTemplateName($config); + // Определение пути к шаблону $selected = null; $tpl = null; foreach ($this->viewPath as $index => $viewPath) { // Загружать шаблон по умолчанию если не найден текущий $dir = Path::join($this->viewPath[$index], 'templates', $template); - if (is_dir($dir)) { - $tpl = new PHPTAL(Path::join($this->viewPath[$index], 'templates', $template, $name)); + if(is_dir($dir)) { + $source = Path::join($this->viewPath[$index], 'templates', $template, $name); + $tpl = new PHPTAL($source); $tpl->setPhpCodeDestination(PHPTAL_PHP_CODE_DESTINATION); $selected = $index; break; @@ -146,13 +121,14 @@ class Component if ($selected === null) { // Последний вариант viewPath, путь к папке компонента $selected = count($this->viewPath) - 1; - $tpl = new PHPTAL(Path::join($this->viewPath[$selected], 'templates', 'modern', $name)); + $source = Path::join($this->viewPath[$selected], 'templates', 'modern', $name); + $tpl = new PHPTAL($source); $tpl->setPhpCodeDestination(PHPTAL_PHP_CODE_DESTINATION); $template = 'modern'; } $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')); @@ -163,6 +139,7 @@ class Component } $tpl->set('base', $this->config->get('site', 'web')); + $tpl->set('source__', $source); $tpl->set('component_base', $this->webPath[$selected]); $tpl->set('component', Path::join($this->webPath[$selected], 'templates', $template)); $tpl->set('component_id', $this->component_id); @@ -170,24 +147,15 @@ 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; // Брать настройки из куков если есть $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); } @@ -196,10 +164,6 @@ class Component return Path::join($this->viewPath[count($this->viewPath) - 1], 'templates', 'modern', $name); } - /** - * Возвращает путь к шаблонам - * @return string - */ public function getTemplateWebPath() { return Path::join($this->webPath[count($this->webPath) - 1], 'templates', 'modern'); @@ -207,26 +171,19 @@ class Component /** * Создает модель - * - * @template T - * @param class-string $modelName - * @return T + * @param string $name + * @return mixed */ - public function getModel($modelName) + public function getModel($name) { + $modelName = "App\\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) { + public function options($key, $val, $res/*: PDOStatement*/) { $result = []; while($res->next()) { $result[] = ['value' => $res->getString($key), 'name' => $res->getString($val)]; @@ -234,12 +191,7 @@ class Component return $result; } - /** - * @param array $list - * @param bool $selected - * @return array{value: string, name: string, selected: bool}[] - */ - public function optionsPair(array $list, $selected = false) { + public function optionsPair($list, $selected = false) { $result = []; foreach ($list as $key => $value) { $result [] = ['value' => $key, 'name' => $value, 'selected' => $key == $selected]; @@ -247,13 +199,7 @@ class Component return $result; } - /** - * Найти файл по пути - * @param string[] $pathList - * @param string $name - * @return string|null - */ - function findFile(array $pathList, string $name) { + function findFile($pathList, $name) { foreach($pathList as $item) { $filename = Path::join($item, $name); if (file_exists($filename)) { @@ -263,10 +209,6 @@ class Component return null; } - /** - * Получить информацию о параметрах - * @return array - */ function getInfo() { $filename = Path::join($this->viewPath[count($this->viewPath) - 1], 'install.json'); if (file_exists($filename)) { @@ -280,10 +222,8 @@ class Component /** * Генерация интерфейса для выбора галлереи фотографии - * @param Composite $view - * @param ?\ctiso\Form\OptionsFactory $options */ - public function setParameters(Composite $view, $options = null): void + public function setParameters(Composite $view, $options = null) { $form = new Form(); @@ -295,26 +235,9 @@ 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, $site/*: SiteInterface*/) { + $expression = htmlspecialchars_decode($expression); $offset = strpos($expression, '?'); $url = parse_url($expression); @@ -327,21 +250,16 @@ class Component parse_str($query, $arguments); } $name = $path; - $config = $site->getConfig(); - - // FIXME: Если имя для компонента не задано то возвращаем пустой компонент - // Нужно дополнительно проверить и файл или в autoloader просто не найдет файл копонента - if (!$name) { - return new Component(); - } + $config = $site->config; $filename = ucfirst($name); $path = Path::join ($config->get('site', 'components'), $name, $filename . '.php'); $className = implode("\\", ['Components', ucfirst($name), $filename]); - $component = null; + $component/*: Component*/ = null; + if (file_exists($path)) { - /** @var Component $component */ + // require_once ($path); $component = new $className(); $component->viewPath = [$config->get('site', 'components') . '/' . $name . '/']; @@ -349,9 +267,8 @@ class Component $component->COMPONENTS_WEB = $config->get('site', 'web') . '/components/'; } else { - /** @var Component $component */ $component = new $className(); - $template = $component->getTemplateName($site->getConfig()); + $template = $component->getTemplateName($site->config); $component->viewPath = [ // Сначало ищем локально @@ -376,11 +293,10 @@ class Component } } - // Вынести в отдельную функцию $db = $site->getDatabase(); $component->db = $db; - $component->config = $site->getConfig(); + $component->config = $site->config; $component->site = $site; $stmt = $db->prepareStatement("SELECT * FROM component WHERE code = ?"); @@ -416,29 +332,22 @@ class Component $editor = $component->getEditUrl(); if ($editor) { - $site->addComponentConfig($editor); + $site->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; + $parameter/*: Collection*/ = $this->parameter; foreach($parameter->export() as $key => $value) { $param[$key] = $value; } @@ -456,12 +365,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'); @@ -473,28 +377,10 @@ class Component return '?' . http_build_query($arr); } - /** - * @param string $name - * @param string $path - * @param array $shim - */ - function addRequireJsPath($name, $path, $shim = null): void { + function addRequireJsPath($name, $path, $shim = null) { $this->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..d1bc119 100644 --- a/src/Controller/Front.php +++ b/src/Controller/Front.php @@ -5,37 +5,25 @@ * @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; +use ctiso\Controller\Action, + ctiso\Registry, + ctiso\Database, + ctiso\Collection, + ctiso\Filter\ActionAccess, + ctiso\Filter\ActionLogger, + ctiso\Path, + ctiso\UserMessageException, + ctiso\HttpRequest, + ctiso\Role\User; class Front extends Action { - /** - * Параметр по которому выбирается модуль - * @var string - */ - protected $_param; - /** - * Значение параметра по умолчанию - * @var string - */ - protected $default; + protected $_param; // Параметр по которому выбирается модуль + protected $default; // Значение параметра по умолчанию - /** @var array */ - protected $modules = []; + protected $modules = array(); - /** - * @param string $default - */ public function __construct(Database $db, Registry $config, User $user, $default) { parent::__construct(); $this->config = $config; @@ -44,13 +32,7 @@ class Front extends Action $this->default = $default; } - /** - * Проверяет загружен ли модуль - * @param string $name Имя модуля - * @return bool - */ - public function isLoaded($name): bool - { + public function isLoaded($name) { return isset($this->modules[$name]); } @@ -81,7 +63,6 @@ class Front extends Action $ucpart = ucfirst($second); $moduleClass = "Modules\\$ucname\\$ucpart"; - /** @var Action $module */ $module = new $moduleClass(); // Инициализация модуля @@ -111,7 +92,7 @@ class Front extends Action public function execute(HttpRequest $request) { - $name = $request->getString('module', $this->default); + $name = $request->get('module', $this->default); try { return $this->loadModule($name, $request); } catch (UserMessageException $ex) { //Исключение с понятным пользователю сообщением diff --git a/src/Controller/Installer.php b/src/Controller/Installer.php index 79b08f2..e00b705 100644 --- a/src/Controller/Installer.php +++ b/src/Controller/Installer.php @@ -1,64 +1,38 @@ _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); @@ -72,14 +46,6 @@ 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 = []; @@ -94,28 +60,18 @@ 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->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 = []; $setup = $this->getSetupFile($name); @@ -130,7 +86,7 @@ class Installer $version_new = $settings->get('version'); if ($item) { - $version_old = $item['version']; + $version_old = $item['version']; } else { $version_old = "0.0"; $registry->writeKey([$name], []); @@ -140,15 +96,15 @@ class Installer if (is_array($sql)) { $res = $this->installSQL($sql, $version_new, $version_old, $name); if ($res) { - $result[] = $res; + $result[]=$res; } } - } + } // Обновление версии меню $registry->removeKey($name); $registry->set($name, [ - 'version' => $version_new, + 'version' => $version_new, 'time' => filemtime($setup) ]); // $registry->writeKey([$name], $settings->export()); @@ -158,13 +114,7 @@ class Installer return $result; } - /** - * Устанавливает базу данных - * @param string $dbinit_path - * @param string|null $dbfill_path - */ - function install($dbinit_path, $dbfill_path = null): void - { + function install($dbinit_path, $dbfill_path = null) { $json_installer = new 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..fb2d950 100644 --- a/src/Controller/Request.php +++ b/src/Controller/Request.php @@ -4,25 +4,14 @@ namespace ctiso\Controller; use ctiso\HttpRequest; class Request { - /** @var HttpRequest */ public $r; - /** @var string */ public $id; - /** - * @param HttpRequest $request - * @param string $id - */ - function __construct($request, $id) { + function __construct($request/*: HttpRequest*/, $id) { $this->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; diff --git a/src/Controller/Service.php b/src/Controller/Service.php index e4d7fb9..331475d 100644 --- a/src/Controller/Service.php +++ b/src/Controller/Service.php @@ -4,70 +4,56 @@ * Класс сервиса = Упрощенный компонент */ namespace ctiso\Controller; - -use ctiso\Path; -use ctiso\Model\BaseMapper; -use ctiso\File; -use ctiso\Registry; -use ctiso\Database\PDOStatement; -use ctiso\Database; +use ctiso\Path, + ctiso\Model\BaseMapper, + ctiso\File, + ctiso\Registry, + ctiso\Database\PDOStatement; class Service { - /** @var array */ public $viewPath = []; - /** @var array */ public $webPath = []; - /** @var Registry */ - public $config; - /** @var string */ + public $config/*: Registry*/; 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 string $name Имя модели + */ + private function getModelPath($name) + { + return Path::join ($this->config->get('system', 'path'), "model", $name . ".php"); + } + /** * Создает модель - * @param class-string $modelName + * @param string $name * @return BaseMapper */ - public function getModel($modelName) + public function getModel($name) { - /** @var BaseMapper */ - $model = new $modelName(); + 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) { + public function options($key, $val, $res/*: PDOStatement*/) { $result = []; while($res->next()) { $result[] = ['value' => $res->getInt($key), 'name' => $res->getString($val)]; @@ -75,11 +61,6 @@ class Service return $result; } - /** - * @param array $list - * @param bool $selected - * @return array - */ public function optionsPair($list, $selected = false) { $result = []; foreach ($list as $key => $value) { @@ -87,10 +68,7 @@ class Service } return $result; } - - /** - * @return array - */ + function getInfo() { $filename = Path::join($this->viewPath[0], 'install.json'); if (file_exists($filename)) { diff --git a/src/Controller/SiteInterface.php b/src/Controller/SiteInterface.php index 92c06a5..1125601 100644 --- a/src/Controller/SiteInterface.php +++ b/src/Controller/SiteInterface.php @@ -3,39 +3,10 @@ namespace ctiso\Controller; interface SiteInterface { - /** - * FIXME: Возвращает ресурс (но его тип опрделяется в App) - * @return mixed - */ function getResource(); - /** - * @return \ctiso\Database - */ + function loadComponent($expression); function getDatabase(); - /** - * @return \ctiso\Registry - */ function getConfig(); - /** - * @return \ctiso\Settings - */ - function getTheme(); - /** - * @param array $config - */ - function addComponentConfig($config): void; - function addRequireJsPath(string $name, string $path, ?array $shim = null): void; - function addStyleSheet(string $url): void; - - /** - * @param string $expression - * @return ?Component - */ - function loadComponent(string $expression); - /** - * @return array{string, string, string} - */ - function findTemplate(string $name); - function replaceImg(string $src, int $width, int $height): string; - function updatePageTime(int $time): void; + function setComponentConfig($config); + function addRequireJsPath($name, $path, $schim = null); } diff --git a/src/Database.php b/src/Database.php index ab2a233..e5e4d6a 100644 --- a/src/Database.php +++ b/src/Database.php @@ -1,280 +1,193 @@ 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, []]); + } + + function prepare(string $sql, array $options = []): PDOStatement|false { + $result/*: PDOStatement*/ = parent::prepare($sql, $options); + return $result; + } + + 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, []]); - } - - /** - * 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 (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); + /** @var Database|null */ + $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"'); } - $connection->dsn = $dsn; - return $connection; - } - - /** - * Выполняет запрос к базе данных - * @param string $query - запрос - * @param ?array $values - значения - */ - public function executeQuery($query, $values = null): PDOStatement - { - $stmt = $this->prepare($query); - - $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); - } - - /** - * Извлекает из базы все элементы по запросу (Для совместимости со старым представлением баз данных 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); - } - - /** - * Извлекает из базы первый элемент по запросу - * @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); - } - - /** - * Преобразует значения в подготовленные значения - * @param array $values - значения - * @return ?array - */ - private function prepareValues($values) - { - if (!$values) { - return null; + + if (isset($dsn['schema'])) { + $connection->query('SET search_path TO ' . $dsn['schema']); } - $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; + } 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; + } - /** - * Создает 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); + public function executeQuery($query, $values=null): PDOStatement|bool + { + $stmt = $this->prepare($query); - $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']; - } - } + $stmt->execute($values); + $stmt->cache = $stmt->fetchAll(PDO::FETCH_ASSOC); + return $stmt; + } + + public function prepareStatement($query) + { + return new Statement($query, $this); + } + + // Для совместимости со старым представлением баз данных CIS + /** + * Извлекает из базы все элементы по запросу + */ + public function fetchAllArray($query, $values = null) + { + $sth = $this->prepare($query); + $prep = $this->prepareValues($values); + $sth->execute($prep); + return $sth->fetchAll(PDO::FETCH_ASSOC); + } + + /** + * Извлекает из базы первый элемент по запросу + */ + public function fetchOneArray($query, $values = null) + { + $sth = $this->prepare($query); + $prep = $this->prepareValues($values); + $sth->execute($prep); + return $sth->fetch(PDO::FETCH_ASSOC); + } + + 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 = []; + 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 .= " 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 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..5ae4664 100644 --- a/src/Database/IdGenerator.php +++ b/src/Database/IdGenerator.php @@ -4,40 +4,26 @@ namespace ctiso\Database; use ctiso\Database; class IdGenerator { - /** @var Database */ private $db; function __construct(Database $db) { $this->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']; } } diff --git a/src/Database/JsonInstall.php b/src/Database/JsonInstall.php index f7842fb..eef8f8b 100644 --- a/src/Database/JsonInstall.php +++ b/src/Database/JsonInstall.php @@ -5,21 +5,13 @@ namespace ctiso\Database; use ctiso\Database\Manager; class JsonInstall { - /** @var Manager */ public $db_manager; - /** @var array */ public $serialColumns; public function __construct(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)) { @@ -38,16 +30,10 @@ class JsonInstall { $this->fillDataBase($dbfill_path); } $this->makeConstraints($initActions); - return 1; } - /** - * Получить список таблиц, которые не существуют в базе данных - * @param array $tables - * @return array - */ function missingTables($tables) { - $actual_tables = $this->db_manager->getAllTableNames(); + $actual_tables = $this->db_manager->GetAllTableNames(); $missingTables = []; foreach ($tables as $table) { if (!in_array($table, $actual_tables)) @@ -56,13 +42,8 @@ class JsonInstall { return $missingTables; } - /** - * Создать таблицы - * @param array $initActions - * @param string $dbinit_path - * @return void - */ - function initDataBase(array $initActions, $dbinit_path) { + //Создать таблицы + function initDataBase($initActions/*: array*/, $dbinit_path) { $pg = $this->db_manager->db->isPostgres(); if (!$pg) { $refs = []; @@ -92,7 +73,7 @@ class JsonInstall { } } if ($action["type"] != "alterReference") { - $this->db_manager->executeAction($action, $dbinit_path); + $this->db_manager->ExecuteAction($action, $dbinit_path); } } @@ -114,11 +95,7 @@ class JsonInstall { } } - /** - * Заполнить данными - * @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)) { @@ -141,7 +118,7 @@ class JsonInstall { //Выполнение действий foreach ($actions as $action) { - $this->db_manager->executeAction($action, $dbfill_file_path); + $this->db_manager->ExecuteAction($action, $dbfill_file_path); } } else { echo "Invalid dbfill.json"; @@ -151,22 +128,18 @@ class JsonInstall { } } - /** - * Обновить ключи serial и создать ограничения - * @param array $initActions - * @return void - */ + //Обновить ключи 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"]); + $this->db_manager->UpdateSerial($serialColumn["table"], $serialColumn["column"]); } foreach ($initActions as $action) { if ($action["type"] == "alterReference") { - $this->db_manager->executeAction($action); + $this->db_manager->ExecuteAction($action); } } } diff --git a/src/Database/Manager.php b/src/Database/Manager.php index ff8211e..1fbc101 100644 --- a/src/Database/Manager.php +++ b/src/Database/Manager.php @@ -7,113 +7,36 @@ use ctiso\Tools\SQLStatementExtractor; use ctiso\Path; use Exception; -/** - * @phpstan-type DropAction array{ - * type:"dropTable", - * table_name:string - * } - * - * @phpstan-type CreateAction array{ - * type:"createTable", - * table_name:string, - * constraints?:array{fields: array, 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 { - /** @var Database */ - public $db; + public $db/*: Database*/; public function __construct(Database $db) { $this->db = $db; } - /** - * Выполняет действие - * @param Action $action - * @param string $db_file - * @throws Exception - */ - public function executeAction(array $action, $db_file = ""): void + public function ExecuteAction($action/*: array*/, $db_file = "") { - switch ($action["type"]) { + switch($action["type"]) { case "dropTable": - $this->dropTableQuery($action["table_name"], true); + $this->DropTableQuery($action["table_name"], true); break; case "createTable": $constraints = $action["constraints"] ?? null; - $this->createTableQuery($action["table_name"], $action["fields"], $constraints); + $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"]); + $this->AlterReference($action["table"], $action["column"], $action["refTable"], $action["refColumn"]); break; case "renameColumn": - $this->renameColumn($action["table"], $action["old_name"], $action["new_name"]); + $this->RenameColumn($action["table"], $action["old_name"], $action["new_name"]); break; case "createView": $this->recreateView($action["view"], $action["select"]); @@ -132,100 +55,74 @@ class Manager break; default: - throw new Exception("unknown action " . $action["type"] . PHP_EOL); + throw new Exception("unknown action ". $action["type"] . PHP_EOL); } } - /** - * Дропает и создаёт SQL VIEW - * @param string $viewName - * @param string $selectStatement - */ - public function recreateView($viewName, $selectStatement): void + //Дропает и создаёт SQL VIEW + public function recreateView($viewName, $selectStatement) { - $this->db->query("DROP VIEW " . $viewName); - $this->db->query("CREATE VIEW " . $viewName . " AS " . $selectStatement); + $this->db->query("DROP VIEW ".$viewName); + $this->db->query("CREATE VIEW ".$viewName." AS ".$selectStatement); } - /** - * Дропает таблицу - * @param string $table - * @param bool $cascade - */ - public function dropTableQuery($table, $cascade = false): void + public function DropTableQuery($table, $cascade=false) { - $statement = "DROP TABLE IF EXISTS " . $table; - if ($this->db->isPostgres() && $cascade) { + $statement = "DROP TABLE IF EXISTS ".$table; + if ($this->db->isPostgres()&&$cascade) { $statement .= " CASCADE"; } $this->db->query($statement); } - /** - * Добавляет ссылку на другую таблицу - * @param string $table - * @param string $column - * @param string $refTable - * @param string $refColumn - */ - public function alterReference($table, $column, $refTable, $refColumn): void + public function AlterReference($table, $column, $refTable, $refColumn) { - $this->db->query("ALTER TABLE " . $table . " ADD CONSTRAINT " . $table . "_" . $column . "fk" . " FOREIGN KEY (" . $column . ") REFERENCES " . $refTable . " (" . $refColumn . ") ON DELETE CASCADE ON UPDATE CASCADE"); + $this->db->query("ALTER TABLE ".$table." ADD CONSTRAINT ".$table."_".$column."fk"." FOREIGN KEY (".$column.") REFERENCES ".$refTable." (".$refColumn.")"); } - /** - * Извлечение информации о полях таблицы - * @param string $table - * @return array{type:string,not_null:bool,constraint:?string}[]|null - */ - public function tableInfo($table) + //Извлечение информации о полях таблицы + 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 . ");"); + $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 + "type"=> $result["type"], + "not_null"=> boolval($result["notnull"]), + "constraint"=> ((bool) $result["pk"]) ? "PRIMARY KEY" : null ]; } return $fields; } } - /** - * Переименование столбца в таблице - * @param string $table - * @param string $old_name - * @param string $new_name - */ - public function renameColumn($table, $old_name, $new_name): void + 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); + $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); + $this->DropTableQuery($tmp_table); + $table_info = $this->TableInfo($table); 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 . ";"); + $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->CreateTableQuery($table, $table_info, null); foreach ($data as $row) { $values = $row['values']; @@ -233,66 +130,46 @@ class Manager unset($values[$old_name]); $this->db->insertQuery($table, $values); } - $this->dropTableQuery($tmp_table); + $this->DropTableQuery($tmp_table); } } - /** - * Обновление ключа serial после ручной вставки - * @param string $table - * @param string $column - */ - public function updateSerial($table, $column): void + //Обновление ключа 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); + $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) + public function Column_Definition($name, $data, $pg) { - $constraint = isset($data['constraint']) ? " " . $data['constraint'] : ""; + $constraint = isset($data['constraint']) ? " ".$data['constraint'] : ""; $references = ""; if (isset($data['references'])) { - $references = " REFERENCES " . $data['references']['refTable'] . '(' . $data['references']['refColumn'] . ')'; + $references = " REFERENCES " . $data['references']['refTable'] . '(' .$data['references']['refColumn'] . ')'; } if (isset($data["not_null"]) && $data["not_null"]) { - $constraint .= " NOT NULL"; + $constraint .=" NOT NULL"; } $type = $data['type']; if (!$pg) { - if (strtolower($type) == "serial") { + if (strtolower($type)=="serial") { $type = "integer"; } + //if (strtolower($type)=="boolean") + // $type = "integer"; } - return $name . " " . $type . $references . $constraint; + 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 + public function AddColumn($table_name, $column_name, $field) { $pg = $this->db->isPostgres(); - $q = "ALTER TABLE " . $table_name . " ADD COLUMN " . - $this->columnDefinition($column_name, $field, $pg); + $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) + public function getConstraintDef($c/*: array*/) { if ($c['type'] == 'unique') { return "UNIQUE(" . implode(", ", $c['fields']) . ")"; @@ -300,15 +177,8 @@ class Manager 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 + //CreateTableQuery('users',['id'=>['type'=>'integer','constraint'=>'PRIMARY KEY']]) + public function CreateTableQuery($table, $fields, $constraints) { $pg = $this->db->isPostgres(); if ($constraints) { @@ -321,30 +191,26 @@ class Manager $statement = "CREATE TABLE $table (" . implode( ",", array_map(function ($name, $data) use ($pg) { - return $this->columnDefinition($name, $data, $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) + public function DumpTable($table_name) { $pg = $this->db->isPostgres(); - $result = []; - $data = $this->db->fetchAllArray("SELECT * FROM " . $table_name . ";"); + $result/*: array*/ = []; + $data/*: array*/ = $this->db->fetchAllArray("SELECT * FROM ".$table_name.";"); if (!$pg) { - $table_fields = $this->tableInfo($table_name); + $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]); } @@ -354,19 +220,15 @@ class Manager } foreach ($data as $r) { $result[] = [ - "type" => "insert", - "table_name" => $table_name, - "values" => $r + "type" => "insert", + "table_name" => $table_name, + "values" => $r ]; } return $result; } - /** - * Возвращает все имена таблиц - * @return list - */ - public function getAllTableNames() + public function GetAllTableNames() { $result = []; if ($this->db->isPostgres()) { @@ -381,16 +243,12 @@ class Manager return $result; } - /** - * Возвращает дамп всех таблиц - * @return array - */ - public function dumpInserts() + public function DumpInserts() { - $table_names = $this->getAllTableNames(); + $table_names = $this->GetAllTableNames(); $result = []; foreach ($table_names as $table_name) { - $result = array_merge($result, $this->dumpTable($table_name)); + $result = array_merge($result, $this->DumpTable($table_name)); } return $result; } diff --git a/src/Database/PDOStatement.php b/src/Database/PDOStatement.php index 69a1c49..2a6a834 100644 --- a/src/Database/PDOStatement.php +++ b/src/Database/PDOStatement.php @@ -7,16 +7,10 @@ use ctiso\Database\StatementIterator, PDO; use TheSeer\Tokenizer\Exception; -/** - * @implements \IteratorAggregate - */ class PDOStatement extends \PDOStatement implements \IteratorAggregate { - /** @var int */ protected $cursorPos = 0; - /** @var array */ - public $cache = []; - /** @var ?array */ + public $cache = array(); public $fields; function getIterator(): \Iterator { @@ -26,15 +20,11 @@ class PDOStatement extends \PDOStatement implements \IteratorAggregate protected function __construct() { } - function rewind(): void { + function rewind() { $this->cursorPos = 0; } - /** - * @param int $rownum - * @return bool - */ - public function seek($rownum): bool { + public function seek($rownum) { if ($rownum < 0) { return false; } @@ -45,19 +35,17 @@ class PDOStatement extends \PDOStatement implements \IteratorAggregate return true; } - function valid(): bool { + function valid() { 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); @@ -72,86 +60,49 @@ 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'); } 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; } - /** - * @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 int - */ function getRecordCount() { return count($this->cache); } - /** - * @param array $args - * @return bool - */ function execute($args = null): bool { $result = parent::execute($args); return $result; diff --git a/src/Database/Statement.php b/src/Database/Statement.php index e270822..e4d5ff1 100644 --- a/src/Database/Statement.php +++ b/src/Database/Statement.php @@ -1,83 +1,51 @@ query = $query; $this->conn = $conn; } - - /** - * @param int|string $n - * @param int $value - */ - function setInt($n, $value): void { + + function setInt($n, $value) { $this->binds [] = [$n, $value, PDO::PARAM_INT]; } - /** - * @param int|string $n - * @param string $value - */ - function setString($n, $value): void { + function setString($n, $value) { $this->binds [] = [$n, $value, PDO::PARAM_STR]; } - /** - * @param int|string $n - * @param mixed $value - */ - function setBlob($n, $value): void { + function setBlob($n, $value) { $this->binds [] = [$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/*: 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..f767408 100644 --- a/src/Database/StatementIterator.php +++ b/src/Database/StatementIterator.php @@ -3,22 +3,14 @@ namespace ctiso\Database; use PDO; -/** - * @implements \Iterator - */ class StatementIterator implements \Iterator { - /** @var PDOStatement */ + private $result; - /** @var int */ private $pos = 0; - /** @var int */ private $row_count; - /** - * @param PDOStatement $rs - */ - public function __construct($rs) { + public function __construct($rs/*: PDOStatement*/) { $this->result = $rs; $this->row_count = $rs->getRecordCount(); } @@ -42,18 +34,15 @@ class StatementIterator implements \Iterator return $this->result->cache[$this->pos]; } - function next(): void { + function next(): void{ $this->pos++; } - /** - * @param int $index - */ - function seek($index): void { + function seek($index) { $this->pos = $index; } - function count(): int { + function count() { return $this->row_count; } } diff --git a/src/Excel/DataTime.php b/src/Excel/DataTime.php index 7a910df..877546d 100644 --- a/src/Excel/DataTime.php +++ b/src/Excel/DataTime.php @@ -4,19 +4,15 @@ namespace ctiso\Excel; class DateTime { - /** @var int */ public $value; - /** - * @param int $value - */ - function __construct($value) + function __construct($value) { $this->value = (int)$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..e149da2 100644 --- a/src/Excel/Document.php +++ b/src/Excel/Document.php @@ -8,40 +8,32 @@ use XMLWriter, Exception; class Document { - /** @var string */ 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] = []; + } $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 +43,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 +66,21 @@ class Document { /** * Преобразует переводы строки в спец символы - * @param string $s - * @return string */ function clean ($s) { + assert(is_string($s)); + return strtr($s, ["\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,7 +90,7 @@ class Document { $doc->writeAttribute('xmlns:ss', self::$ns); $this->createStyles($doc); - + foreach ($this->table as $table) { if ($table instanceof Table) { $table->createTable($doc); diff --git a/src/Excel/Number.php b/src/Excel/Number.php index 3df78bb..8ed12b4 100644 --- a/src/Excel/Number.php +++ b/src/Excel/Number.php @@ -4,20 +4,16 @@ namespace ctiso\Excel; class Number { - /** @var int */ public $value; - /** - * @param int|float $value - */ - function __construct($value) + function __construct($value) { $this->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..d5a539c 100644 --- a/src/Excel/Table.php +++ b/src/Excel/Table.php @@ -1,25 +1,19 @@ value = $value; @@ -27,53 +21,36 @@ 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 { - /** @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() @@ -82,31 +59,27 @@ class Table } /** - * Записать значение в клетку с заданными координатами - * @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 +90,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 = [""]) { - 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([$this, 'getRowCells'], $this->rows)); } - /** - * Кодирование строки - * @deprecated Можно заменить на значение - * @param string $s Строка - * @return string - */ function encode($s) { return $s; @@ -243,13 +206,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 +215,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 +228,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); @@ -306,26 +264,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,23 +292,23 @@ 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', (string)0); } else if($this->_splitHorizontal) { - $doc->writeElement('ActivePane', (string) 2); + $doc->writeElement('ActivePane', (string)2); } $doc->endElement(); } diff --git a/src/File.php b/src/File.php index 8ee2eae..c523cf6 100644 --- a/src/File.php +++ b/src/File.php @@ -4,11 +4,6 @@ namespace ctiso; use Exception; class File { - /** - * @param string $filename - * @return string - * @throws Exception - */ static function getContents($filename) { $buffer = @file_get_contents($filename); if ($buffer !== false) { diff --git a/src/Filter/ActionAccess.php b/src/Filter/ActionAccess.php index 6dd44c3..4fabc60 100644 --- a/src/Filter/ActionAccess.php +++ b/src/Filter/ActionAccess.php @@ -1,27 +1,20 @@ processor = $processor; $this->user = $user; } @@ -30,19 +23,12 @@ class ActionAccess * Проверка доступных действий для пользователя * !! Реализация класса проверки действий не должна быть внутри Контроллера!!! * Информация о доступе может быть в файле, базе данных и т.д. - * - * @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])); } - /** - * @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..b2b02ff 100644 --- a/src/Filter/ActionLogger.php +++ b/src/Filter/ActionLogger.php @@ -5,25 +5,15 @@ use ctiso\Role\UserInterface, ctiso\HttpRequest; /* Переделать формат Логов на список json */ -class ActionLogger implements FilterInterface -{ - /** @var array */ - public $before = []; - /** @var resource */ +class ActionLogger +{ + public $before = array(); public $file; - /** @var UserInterface */ public $user; - /** @var string */ public $action; - /** @var \ctiso\Controller\ActionInterface */ public $processor; - /** - * @param \ctiso\Controller\ActionInterface $processor - * @param string $logPath - * @param UserInterface $user - */ - function __construct($processor, $logPath, $user) { + function __construct($processor/*: Filter*/, $logPath, $user/*: UserInterface*/) { $this->processor = $processor; $this->user = $user; diff --git a/src/Filter/Authorization.php b/src/Filter/Authorization.php index 2421212..8510433 100644 --- a/src/Filter/Authorization.php +++ b/src/Filter/Authorization.php @@ -5,20 +5,13 @@ namespace ctiso\Filter; class Authorization { const SESSION_BROWSER_SIGN_SECRET = '@w3dsju45Msk#'; const SESSION_BROWSER_SIGN_KEYNAME = 'session.app.browser.sign'; - /** @var string */ public $group; - /** - * @param string $group - */ function __construct($group) { $this->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(); @@ -36,11 +29,7 @@ class Authorization { 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"); @@ -51,7 +40,7 @@ class Authorization { $_SESSION ["time"] = time(); } - static function getRawSign(): string + static function getRawSign() { $rawSign = self::SESSION_BROWSER_SIGN_SECRET; $signParts = ['HTTP_USER_AGENT']; @@ -59,16 +48,17 @@ class Authorization { foreach ($signParts as $signPart) { $rawSign .= '::' . ($_SERVER[$signPart] ?? 'none'); } - + return $rawSign; } - static function getBrowserSign(): string + static function getBrowserSign() { + return md5(self::getRawSign()); } - function logout(): void { + function logout() { session_destroy(); } } diff --git a/src/Filter/Filter.php b/src/Filter/Filter.php index 57d8e7c..156d4e0 100644 --- a/src/Filter/Filter.php +++ b/src/Filter/Filter.php @@ -5,44 +5,29 @@ */ namespace ctiso\Filter; -use ctiso\Database; -use ctiso\HttpRequest; -use ctiso\Controller\ActionInterface; +use ctiso\Controller\Action, + ctiso\HttpRequest; -class Filter implements ActionInterface +class Filter { - /** @var ActionInterface */ public $processor; - - /** - * @param ActionInterface $processor - */ - public function __construct($processor) + public function __construct($processor/*: 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 = 'ctiso\\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 @@ -getAction()) { // Авторизация по постоянному паролю case 'login': - $login = $request->getString('login', '') ; - $password = $request->getString('password'); + $login = $request->get('login'); + $password = $request->get('password'); $result = $this->role->getUserByLogin($login); // Поиск по логину if ($result) { @@ -63,9 +60,6 @@ class Login extends Filter $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 дней @@ -73,7 +67,7 @@ class Login extends Filter $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*/) { @@ -81,7 +75,7 @@ class Login extends Filter $request->set('timeout_error', true); break; } else { - $this->role->resetTries($request->getString('login')); + $this->role->resetTries($request->get('login')); } } // Извлечнеие пользователя из родительской CMS, для проверки пароля @@ -106,7 +100,7 @@ class Login extends Filter $result = $this->role->getUserByLogin($login); // Поиск по логину if ($result) { $temp = md5($result->getString('password') . $result->getString('login') . $result->getString('sid')); - if ($password == $temp) { + if ($password == $temp) { $this->enter($result); return true; } @@ -131,15 +125,11 @@ class Login extends Filter return false; } - /** - * Вход в систему - * @param PDOStatement $result - */ - private function enter($result): void + private function enter($result) { $this->user = $result; $random = rand(0, 1024 * 1024); - $this->role->setSID((string)$random, $result); + $this->role->setSID($random, $result); $_SESSION["group"] = $result->getInt('access'); $_SESSION["access"] = $result->getInt('id_user'); // id_user @@ -148,13 +138,10 @@ class Login extends Filter $_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') { + if ($request->get('action') == 'user_access') { if ($logged) { $result = []; $result['fullname'] = $this->user->getString('patronymic') . " " . $this->user->getString('firstname'); @@ -166,7 +153,7 @@ class Login extends Filter } } - if ($request->getString('action') == 'relogin') { + if ($request->get('action') == 'relogin') { if ($logged) { return json_encode(['result' => 'ok', 'message' => "Авторизация успешна"]); } else { @@ -177,7 +164,7 @@ class Login extends Filter if (!$logged) { // Параметры при неправильной авторизации // Действия по умолчанию !! Возможно переход на форму регистрации - if ($request->getString('mode') == 'ajax') { + if ($request->get('mode') == 'ajax') { if (!$this->requestIsWhite($request)) { return json_encode(['result' => 'fail', 'message' =>"NOT_AUTHORIZED"]); } @@ -187,11 +174,8 @@ class Login extends Filter } } 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') - { + 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,23 +184,19 @@ 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'); 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; } } diff --git a/src/Form/CheckBox.php b/src/Form/CheckBox.php index fd1fa2a..ea5f880 100644 --- a/src/Form/CheckBox.php +++ b/src/Form/CheckBox.php @@ -3,11 +3,10 @@ namespace ctiso\Form; use ctiso\Form\Field; -class CheckBox extends Field +class Checkbox extends Field { - /** @var bool */ public $checked = false; - function setValue($value): void + function setValue($value) { $this->value = $value; $this->checked = $value; diff --git a/src/Form/Field.php b/src/Form/Field.php index 098003e..d4e8a34 100644 --- a/src/Form/Field.php +++ b/src/Form/Field.php @@ -4,51 +4,27 @@ */ namespace ctiso\Form; -use ctiso\Form\OptionsFactory; - class Field { - /** @var bool */ public $hidden = false; - /** @var string */ public $name; - /** @var string */ public $label; // Метка поля - - /** @var mixed */ public $value; // Значение поля - /** @var string */ public $type = ""; // Каждому типу элемента соответствует макрос TAL - /** @var ?string */ - public $error_msg = null; - /** @var ?mixed */ - public $default = null; - /** @var bool */ - public $error = false; - /** @var bool */ + public $error_msg = null; + public $default = null; + public $error = false; public $require = false; - /** @var ?string */ public $hint = null; - /** @var ?int */ - public $maxlength = null; - /** @var ?string */ public $fieldset = null; // Блоки (Убрать в отдельный класс!!!) - /** @var array */ - public $_title = []; - /** @var string */ + public $_title = array(); public $description = ""; - /** @var array */ - public $alias = []; - - - /** - * @param array $input - * @param OptionsFactory|null $factory - * @phpstan-ignore-next-line - */ + public $alias = array(); + + /** @phpstan-ignore-next-line */ public function __construct ($input = [], $factory = null) - { + { $this->default = null; if (isset($input['validate'])) { $this->require = strpos($input['validate'], 'require') !== false; @@ -57,22 +33,19 @@ class Field $this->fieldset = $input['fieldset']; } // Инициализация свойст обьетка - foreach (['label', 'name', 'type', 'description', 'maxlength'] as $name) { + foreach (['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..7cc74f8 100644 --- a/src/Form/Form.php +++ b/src/Form/Form.php @@ -5,99 +5,83 @@ */ namespace ctiso\Form; - -use ctiso\Form\Field; -use ctiso\Form\Select; -use ctiso\Form\Input; -use ctiso\Validator\Validator; -use ctiso\HttpRequest; +use ctiso\Form\Field, + ctiso\Form\Select, + ctiso\Form\Input, + ctiso\View\View, + ctiso\Validator\Validator, + ctiso\HttpRequest; /** * Форма для ввода */ -class Form { - /** @var array */ - public $field = []; //Поля формы - /** @var array */ - public $fieldsets = []; //Группы полей (fieldset). Некоторые поля могут не принадлежать никаким группам +class Form extends 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' => 'ctiso\\Form\\Input', // input с проверкой на заполненность - 'inputreq' => Input::class, - 'date' => Date::class, - 'datereq' => Date::class, - 'datetime' => DateTime::class, + 'inputreq' => 'ctiso\\Form\\Input', - 'color' => Color::class, - 'textarea' => TextArea::class, - 'text' => TextArea::class, - 'multiselect' => SelectMany::class, - 'select1' => SelectOne::class, - 'select' => SelectOne::class, + 'date' => 'ctiso\\Form\\Date', + 'datereq' => 'ctiso\\Form\\Date', + 'datetime' => 'ctiso\\Form\\DateTime', - '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' => 'ctiso\\Form\\Color', + 'textarea' => 'ctiso\\Form\\TextArea', + 'text' => 'ctiso\\Form\\TextArea', + 'multiselect' => 'ctiso\\Form\\SelectMany', + 'select1' => 'ctiso\\Form\\SelectOne', + 'select' => 'ctiso\\Form\\SelectOne', + + 'questiontype'=> 'ctiso\\Form\\QuestionType', + 'secret' => 'ctiso\\Form\\Secret', + 'upload' => 'ctiso\\Form\\Upload', + 'image' => 'ctiso\\Form\\Upload', + 'checkbox' => 'ctiso\\Form\\CheckBox', + 'checkmany' => 'ctiso\\Form\\SelectMany', + 'hidden' => 'ctiso\\Form\\Hidden', + 'radio' => 'ctiso\\Form\\SelectOne', + 'filebrowser' => 'ctiso\\Form\\BrowserInput', + 'documents' => 'ctiso\\Form\\BrowserInput', + 'chooser' => 'ctiso\\Form\\Input', + 'select_chooser' => 'ctiso\\Form\\SelectOne', + 'html_text' => 'ctiso\\Form\\HtmlText' ]; } - 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,7 +95,7 @@ class Form { if(isset($init['hint'])) { $el->hint = $init['hint']; } - + $this->field[$init['name']] = $el; return $el; } @@ -119,7 +103,8 @@ class Form { /** * Добавление fieldset на форму */ - public function addFieldSet(array $fieldset): void + + public function addFieldSet(array $fieldset) { $this->fieldsets[$fieldset['name']] = $fieldset; } @@ -127,7 +112,8 @@ class Form { /** * Добавление массива fieldset на форму */ - public function addFieldSetList(array $list): void + + public function addFieldSetList(array $list) { foreach ($list as $fieldset) { $this->addFieldSet($fieldset); @@ -136,10 +122,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 +134,7 @@ class Form { /** * Устанавливает ошибки после проверки */ - function setError(Validator $validator): void + function setError(Validator $validator) { foreach ($validator->getErrorMsg() as $name => $error) { @@ -158,12 +143,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,8 +151,8 @@ class Form { /** * Устанавливает значения из масива - */ - function setValues(HttpRequest $request): void { + */ + function setValues(HttpRequest $request) { foreach ($this->field as $key => $_) { $value = $request->getRawData($this->method, $key); $this->field[$key]->setValue($value); @@ -180,32 +160,24 @@ class Form { } /** - * Заполняет форму данными из обьекта + * Заполняет форму данными из обьекта * @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(['ctiso\\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 index 6e3df61..535e21b 100644 --- a/src/Form/Hidden.php +++ b/src/Form/Hidden.php @@ -4,6 +4,5 @@ namespace ctiso\Form; use ctiso\Form\Input; class Hidden extends Input { - /** @var bool */ public $hidden = true; } 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; diff --git a/src/Form/Select.php b/src/Form/Select.php index 89ea70d..4b00b0a 100644 --- a/src/Form/Select.php +++ b/src/Form/Select.php @@ -3,18 +3,10 @@ namespace ctiso\Form; use ctiso\Form\Field; -/** - * @phpstan-type Option = array{value: string, name: string, selected?: bool, class?: string|false} - */ class Select extends Field { - /** @var Option[] */ - public $options = []; + public $options = array(); - /** - * @param array{ options?: Option[], 'options.pair'?: array } $input - * @param OptionsFactory $factory - */ public function __construct ($input, $factory) { parent::__construct($input); @@ -32,11 +24,6 @@ class Select extends Field } } - /** - * @param string[] $list - * @param bool $selected - * @return Option[] - */ public function optionsPair($list, $selected = false) { $result = []; foreach ($list as $key => $value) { diff --git a/src/Form/SelectMany.php b/src/Form/SelectMany.php index 9ca752d..86f4295 100644 --- a/src/Form/SelectMany.php +++ b/src/Form/SelectMany.php @@ -5,7 +5,7 @@ use ctiso\Form\Select; class SelectMany extends Select { - function setValue(mixed $value): void + function setValue($value) { // Установить selected у options if (!is_array($value)) { $value = [$value]; } diff --git a/src/Form/SelectOne.php b/src/Form/SelectOne.php index d631d81..d2dc842 100644 --- a/src/Form/SelectOne.php +++ b/src/Form/SelectOne.php @@ -8,7 +8,7 @@ use ctiso\Form\Select; class SelectOne extends 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..50ce417 100644 --- a/src/Form/TextArea.php +++ b/src/Form/TextArea.php @@ -1,13 +1,13 @@ value = $value; } diff --git a/src/Form/ViewState.php b/src/Form/ViewState.php index b315e6d..c9c6831 100644 --- a/src/Form/ViewState.php +++ b/src/Form/ViewState.php @@ -1,6 +1,6 @@ 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 +28,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..b547974 100644 --- a/src/Functions.php +++ b/src/Functions.php @@ -1,55 +1,42 @@ */ - protected $params; - /** @var callable */ - protected $fn; +namespace ctiso; - /** - * @param array $params - */ +class right { + protected $params; + protected $fn; + 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 */ + 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); } @@ -57,25 +44,16 @@ class left { define('__', '_ARGUMENT_PLACE_'); class partial { - /** @var array */ - protected $params; - /** @var callable */ + 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(); $result = []; $count = count($this->params); for($i = 0, $j = 0; $i < $count; $i++) { @@ -88,28 +66,19 @@ class partial { } return call_user_func_array ($this->fn, $result); } -} +} /** * Композиция функций */ class compose { - /** @var array */ 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++) { @@ -121,53 +90,48 @@ class compose { class Functions { - /** - * Частичное применение функции - * @param mixed ...$args - * @return mixed - */ - static function partial(...$args) { - $closure = new partial($args); + static function partial($_rest) { + $closure = new partial(func_get_args()); return [$closure, 'apply']; } /** * Композиция функций - * @param mixed ...$args - * @return mixed + * @param array $_rest + * @return mixed */ - static function compose(...$args) { - $closure = new compose($args); + static function compose($_rest) { + $closure = new compose(func_get_args()); return [$closure, 'apply']; } /** * Карирование справа - * @param mixed ...$args - * @return mixed + * + * @return mixed */ - static function rcurry(...$args) { - $closure = new right($args); + static function rcurry($_rest) { + $closure = new right(func_get_args ()); return [$closure, 'apply']; } /** * Карирование слева - * @param mixed ...$args - * @return mixed + * + * @return mixed */ - static function lcurry(...$args) { - $closure = new left($args); + static function lcurry($_rest) { + $closure = new left(func_get_args ()); return [$closure, 'apply']; } /** * Разделение массива на два по условию * @param mixed $pred Условие по которому разделяется массив - * @param array $lst + * @param array $lst * - * @return mixed + * @return mixed */ static function partition($pred, $lst) { $left = []; @@ -183,33 +147,25 @@ class Functions { } /** - * @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,75 +173,75 @@ 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([$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) { + static function key_values($key, $array/*: array|ArrayIterator*/) { $result = []; - + 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) { + + static function key_values_object($key, $array/*: array|ArrayIterator*/) { $result = []; - + 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 = []; foreach ($array as $item) { @@ -293,12 +249,7 @@ class Functions { } return $result; } - - /** - * @param string $key - * @param array>|\ArrayIterator $array - * @return array - */ + static function assoc_key($key, $array) { $result = []; foreach ($array as $item) { @@ -306,44 +257,24 @@ class Functions { } 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 +285,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,15 +303,10 @@ class Functions { } return false; } - - /** - * Разбивает массив на массивы определенной длины - * @template T - * @param int $length Длина массива - * @param T[] $array Массив - * @return T[][] - */ - static function span(int $length, array $array) { + + static function span($length, array $array) { + assert(is_int($length)); + $result = []; $count = count($array); for($i = 0; $i < $count; $i += $length) { @@ -385,70 +314,54 @@ class Functions { } 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 mixed $cb сравнение с элементом массива * @param array $hs массив в котором ищется значение - * @param bool $strict * * @return int|string|null ключ найденого элемента в массиве */ 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; - } + if (call_user_func_array($cb, [$value, $key, $strict])) return $key; } return null; - } - + } + /** * Выбирает все сроки из таблицы с уникальными значениями ключа - * @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 Массив с уникальными значениями ключа + * @example + * key_unique_values ('name', array (array ('name' => 1), array ('name' => 2), array ('name' => 1))) + => array (1, 2) + * @end example */ static function key_unique_values ($name, $table) { - // Ищем уникальные значения для заданного ключа + // Ищем уникальные значения для заданного ключа $keys = []; 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 Отсортированный массив */ static function sortOn($array, $key, $fn = '\\ctiso\\Functions::__cmp') { @@ -458,18 +371,16 @@ class Functions { } /** - * Преобразует ключи элементов для многомерного массива - * @param string $key_name Имя ключа - * @param array $array Многомерный массив + * Преобразует ключи элементов для многомерного массива * @return mixed */ - static function hash_key ($key_name, $array) { + static function hash_key ($key_name,$array/*: array */) { $result = []; 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..186ae12 100644 --- a/src/HttpRequest.php +++ b/src/HttpRequest.php @@ -1,22 +1,19 @@ $_REQUEST, - 'get' => $_GET, - 'post' => $_POST, + 'data' => $_REQUEST, + 'get' => $_GET, + 'post' => $_POST, 'cookie' => $_COOKIE ]; @@ -42,77 +39,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); } - /** - * @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 +79,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 +88,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 +96,28 @@ 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 { + static function getProtocol() { return (!empty($_SERVER['HTTPS']) && $_SERVER['HTTPS'] !== 'off' || $_SERVER['SERVER_PORT'] == 443) ? "https://" : "http://"; } } diff --git a/src/Layout/Blank.php b/src/Layout/Blank.php index 8a0d0ff..f731df3 100644 --- a/src/Layout/Blank.php +++ b/src/Layout/Blank.php @@ -9,9 +9,6 @@ use ctiso\Filter\Filter, class Blank extends 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..78a4686 100644 --- a/src/Layout/Manager.php +++ b/src/Layout/Manager.php @@ -5,44 +5,37 @@ * Выбор оформления страницы осуществляется если было совпадение с каким либо условием */ namespace ctiso\Layout; - -use ctiso\Filter\Filter; -use ctiso\HttpRequest; +use ctiso\Filter\Filter, + ctiso\Functions, + ctiso\HttpRequest; class Manager extends 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 $layout) { - $this->addCondition(fn(HttpRequest $request) => $this->checkGet($request, $get), $layout); + $this->addCondition(Functions::rcurry([$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 $layout) { - $this->addCondition(fn(HttpRequest $request) => $this->checkXHR($request, $get), $layout); + $this->addCondition(Functions::rcurry([$this, 'checkXHR'], $get), $layout); } - /** - * @param HttpRequest $request - * @param array|true $get - * @return bool - */ - public function checkGet($request, $get) + public function checkGet($request/*: HttpRequest*/, $get) { if (is_array($get)) { foreach ($get as $key => $value) { @@ -54,44 +47,37 @@ 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/*: HttpRequest*/, $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 - { + public function addCondition($get, Filter $layout) + { $this->condition [] = [$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(); + return $view->render(); } else { return $view; } } } - return ''; } } diff --git a/src/Mail.php b/src/Mail.php index 848c645..7f3930d 100644 --- a/src/Mail.php +++ b/src/Mail.php @@ -4,39 +4,26 @@ * Класс для работы с почтой * 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())); // Идентефикатор разделителя } @@ -44,35 +31,32 @@ class Mail /** * Установка отправителя */ - 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 +64,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) ? [$data, $name] : [$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 [] = [$data, $name]; } - /** - * @param string $var - * @param string $val - */ - function quote($var, $val): string + function quote($var, $val) { return ";" . PHP_EOL . "\t" . $var . "=\"" . $val . "\""; } @@ -151,40 +124,36 @@ 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 = []) { - 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([$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->uniqid . PHP_EOL; $message .= $this->mimeTag("Content-Type", $this->type, ['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) { @@ -202,7 +171,7 @@ class Mail /** * Заголовок сообщения */ - function getHeader(): string + function getHeader() { $head = $this->mimeTag("MIME-Version", "1.0"); $head .= $this->mimeTag("From", $this->_from); @@ -219,7 +188,7 @@ class Mail return $head; } - function getSubject(): string + function getSubject() { return $this->encodedWord($this->_subject); } @@ -227,28 +196,27 @@ 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 = []; } diff --git a/src/MailAlt.php b/src/MailAlt.php index c9cae8a..7a42a7a 100644 --- a/src/MailAlt.php +++ b/src/MailAlt.php @@ -5,11 +5,8 @@ use PHPMailer\PHPMailer\PHPMailer; class MailAlt { - /** @var PHPMailer */ public $mailer; - /** @var string */ public $_notify; - /** @var string */ public $encoding; function __construct() { @@ -20,65 +17,62 @@ class MailAlt /** * Установка отправителя */ - function from(string $name): void + function from($name) { $this->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 +80,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 index 37831a0..7e55e72 100644 --- a/src/Model/BaseMapper.php +++ b/src/Model/BaseMapper.php @@ -2,9 +2,6 @@ namespace ctiso\Model; -/** - * @property \ctiso\Database $db - */ abstract class BaseMapper { function getAllAsOptions(): array { return []; diff --git a/src/Model/Factory.php b/src/Model/Factory.php index 6f6e840..cf7f46e 100644 --- a/src/Model/Factory.php +++ b/src/Model/Factory.php @@ -1,35 +1,31 @@ db = $db; $this->config = $config; $this->user = $user; } - + /** * Создает модель - * @template T - * @param class-string $modelName - * @return T + * @param string $name + * @return BaseMapper */ - public function getModel($modelName) + public function getModel ($name) { + $modelName = "App\\Mapper\\" . $name; $model = new $modelName(); $model->db = $this->db; $model->factory = $this; diff --git a/src/Numbers.php b/src/Numbers.php index 5d92be2..2494706 100644 --- a/src/Numbers.php +++ b/src/Numbers.php @@ -4,27 +4,24 @@ namespace ctiso; class Numbers { - static function roman(float $i): float + static function roman($i) { return 0; } - static function decimal(float $i): float + static function decimal($i) { return $i; } - /** - * @param array $array - * @return array - */ - static function prefix(callable $prefix, array $array) + static function prefix($prefix, array $array, $key = false) { $result = []; $count = count($array); for ($i = 0; $i < $count; $i++) { - $result [] = call_user_func($prefix, $i + 1) . '. ' . $array[$i]; + $result [] = call_user_func($prefix, $i + 1) . '. ' . $array[$i]; } return $result; } } + diff --git a/src/Path.php b/src/Path.php index 55a0022..b36fe6b 100644 --- a/src/Path.php +++ b/src/Path.php @@ -8,25 +8,23 @@ namespace ctiso; -class Path +class Path { const SEPARATOR = "/"; - protected array $path = []; - protected array $url = []; - protected bool $absolute = false; + protected $path = array(); + protected $url = array(); + protected $absolute = false; - /** - * @param string $path Путь (Тип указан в doccomments т.к откудато приходит null) - */ public function __construct($path = '') { - $this->url = parse_url($path) ?: []; + //assert(is_string($path)); + $this->url = parse_url($path ?? ''); if (isset($this->url['path'])) { $path = $this->url['path']; // $path = preg_replace('/\/{2,}/', '/', $path); - $list = self::listFromString($path); + $list = $this->listFromString($path); if (isset($this->url['scheme']) && !isset($this->url['host'])) { $this->absolute = false; @@ -34,20 +32,20 @@ class Path $this->absolute = true; } - $this->path = self::optimize($list); + $this->path = $this->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 +53,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); } @@ -75,12 +73,6 @@ class Path 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 +84,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 +105,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 +121,48 @@ 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 = []; 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 ($this->path[$i] != $path->path[$i]) { - return false; + return false; } } return true; @@ -168,29 +170,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,11 +200,13 @@ 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); @@ -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); @@ -259,10 +257,10 @@ class Path $result = []; $count = count($list_path); for ($i = 0; $i < $count; $i++) { - if (($i >= count($self_path)) || $list_path[$i] != $self_path[$i]) { - break; + if (($i >= count($self_path)) || $list_path[$i] != $self_path[$i]) { + break; } - } + } $list_count = count($list_path); for($j = $i; $j < $list_count; $j++) { array_push($result, '..'); @@ -274,10 +272,6 @@ class Path return implode("/", $result); } - /** - * @param string $path - * @return string - */ public function append($path) { $base = $this->__toString(); @@ -287,10 +281,11 @@ class Path /** * Обьединяет строки в Path соединяя необходимым разделителем * fixme не обрабатывает параметры урла, решение Path::join(SITE_WWW_PATH) . '?param=pampam' - * @param string ...$args - * @return string + * @return string */ - static function fromJoin(...$args) { + static function fromJoin($_rest) { + $args = func_get_args(); + $result = []; $parts0 = new Path(array_shift($args)); $result [] = $parts0->getParts(); @@ -300,7 +295,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 +303,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) { + $args = func_get_args(); $path = call_user_func_array([self::class, "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 +337,7 @@ class Path return true; } - public function isAbsolute(): bool + public function isAbsolute() { return $this->absolute; } @@ -352,6 +346,7 @@ class Path * Подбирает новое временное имя для файла * * @param string $dst Предпологаемое имя файла + * * @return string Новое имя файла */ static function resolveFile($dst) @@ -368,15 +363,15 @@ 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 = []) { $ignore = array_merge([".", ".."], $ignore); return self::fileList($this->__toString(), $allow, $ignore); @@ -384,13 +379,13 @@ class Path /** * Обьединяет строки в путь соединяя необходимым разделителем + * + * @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 = []) { $result = []; $ignore = array_merge([".", ".."], $ignore); @@ -398,16 +393,8 @@ class Path 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 = []; @@ -419,7 +406,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 +418,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 +439,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 +453,29 @@ class Path /** * Обновить относительную ссылку при переносе файла - * + * * @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 */ - 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..283d7e1 100644 --- a/src/Primitive.php +++ b/src/Primitive.php @@ -3,74 +3,51 @@ /** * Преобразование типов !!! Пересмотреть использование классов!! * Класс преобразования типа значения поля класса в тип поля таблицы + * @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); - + if (count($tmp) != 3) { return $result; } @@ -81,39 +58,29 @@ class Primitive { if ($month != 0 && $day != 0 && $year != 0) { if (checkdate($month, $day, $year)) { - return mktime(0, 0, 0, $month, $day, $year) ?: 0; + 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 = []; 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; + $result = mktime((int)$tmp[4], (int)$tmp[5], 0, (int)$tmp[2], (int)$tmp[3], (int)$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 +88,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 +97,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 : []; } - /** - * @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 index ce1c177..a1728f5 100644 --- a/src/Process.php +++ b/src/Process.php @@ -2,46 +2,28 @@ namespace ctiso; -/** - * str_getcsv - * @param string $input - * @param string $delimiter - * @param string $enclosure - * @param string $escape - * @return array|false - */ -function str_getcsv($input, $delimiter = ",", $enclosure = '"', $escape = "\\") -{ - $fiveMBs = 1024; - $fp = fopen("php://temp/maxmemory:$fiveMBs", 'r+'); - $data = []; - if (is_resource($fp)) { - fputs($fp, $input); - rewind($fp); - $data = fgetcsv($fp, 1000, $delimiter, $enclosure); - fclose($fp); - } - return $data; +if (!function_exists('str_getcsv')) { + function str_getcsv($input, $delimiter = ",", $enclosure = '"', $escape = "\\") { + $fiveMBs = 1024; + $fp = fopen("php://temp/maxmemory:$fiveMBs", 'r+'); + $data = ''; + if (is_resource($fp)) { + fputs($fp, $input); + rewind($fp); + $data = fgetcsv($fp, 1000, $delimiter, $enclosure); + fclose($fp); + } + return $data; + } } - -/** - * process_exists - * @param int $pid - * @return bool - */ -function process_exists($pid) -{ +function process_exists($pid) { if (PHP_OS == 'WINNT') { - $content = shell_exec("tasklist.exe /NH /FO CSV"); - if (!$content) { - return false; - } - $processes = explode("\n", $content); - foreach ($processes as $process) { + $processes = explode("\n", shell_exec("tasklist.exe /NH /FO CSV")); + foreach($processes as $process) { if ($process != "") { $csv = str_getcsv($process); - if ($csv && $pid == $csv[1]) return true; + if ($pid == $csv[1]) return true; } } return false; @@ -50,19 +32,13 @@ function process_exists($pid) } } -/** - * create_single_proces - * @param string $fpid - * @param callable $fn - * @return int - */ -function create_single_process($fpid, $fn) -{ +function create_single_proces($fpid, $fn) { if (file_exists($fpid)) { - if (process_exists((int)file_get_contents($fpid))) { - return 1; + print_r(realpath($fpid)); + if (process_exists(file_get_contents($fpid))) { + return 1; } - } + } call_user_func($fn); return 0; } diff --git a/src/Registry.php b/src/Registry.php index 5eda214..21e08eb 100644 --- a/src/Registry.php +++ b/src/Registry.php @@ -5,58 +5,47 @@ use ctiso\File, Exception; class Registry { - /** @var array */ - private array $namespace = []; + public $namespace = []; + public $data; - function importFile(string $namespace, ?string $filePath = null): void { + function importFile($namespace, $filePath = null) { $data = json_decode(File::getContents($filePath), true); $data['_file'] = $filePath; $this->namespace[$namespace] = [ 'path' => $filePath, 'data' => $data - ]; + ]; } - function importArray(string $namespace, array $data = []): void { + function importArray($namespace, $data = []) { if (isset($this->namespace[$namespace])) { $data = array_merge($this->namespace[$namespace]['data'], $data); - } + } $this->namespace[$namespace] = [ 'path' => null, 'data' => $data - ]; + ]; } - /** - * @param string $ns - * @param string $key - * @return mixed - * @throws Exception - */ - public function get(string $ns, string $key) { + public function get($ns, $key) { if (isset($this->namespace[$ns]['data'][$key])) { return $this->namespace[$ns]['data'][$key]; } throw new Exception('Unknown key ' . $ns . '::' . $key); } - /** - * @param string $ns - * @param string $key - * @return mixed|null - */ - public function getOpt(string $ns, string $key) { + public function getOpt($ns, $key) { if (isset($this->namespace[$ns]['data'][$key])) { return $this->namespace[$ns]['data'][$key]; } return null; } - public function has(string $ns, string $key): bool { + public function has($ns, $key) { return isset($this->namespace[$ns]['data'][$key]); } - function set(string $ns, string $key, mixed $value): void { + function set($ns, $key, $value) { $this->namespace[$ns]['data'][$key] = $value; } } diff --git a/src/Role/User.php b/src/Role/User.php index 78f2923..3f5728e 100644 --- a/src/Role/User.php +++ b/src/Role/User.php @@ -1,47 +1,41 @@ db = $db; $this->groups = $groups; } - public function setDB(Database $db): void { + public function setDB(Database $db) { $this->db = $db; } - public function getName(): string { + public function getName() { return $this->name; } - /** - * @return bool - */ function isLogged() { return \ctiso\Filter\Authorization::isLogged(); } - public function getUserByQuery(Statement $stmt): ?PDOStatement + + public function getUserByQuery(Statement $stmt) { $result = $stmt->executeQuery(); if ($result->next()) { @@ -50,38 +44,32 @@ class User implements UserInterface $this->id = $result->getInt('id_user'); $this->password = $result->getString('password'); $this->fullname = implode(' ', [ - $result->getString('surname'), - $result->getString('firstname'), + $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 + public function getUserByLogin($login) { $stmt = $this->db->prepareStatement("SELECT * FROM users WHERE login = ?"); $stmt->setString(1, $login); $result = $this->getUserByQuery($stmt); - if ($result) { + if ($result) { $time = time(); $id = $this->id; - $this->db->executeQuery( - "UPDATE users SET lasttime = :time WHERE id_user = :id", - ['time' => $time, 'id' => $id]); // Время входа + $this->db->executeQuery("UPDATE users SET lasttime = $time WHERE id_user = $id"); // Время входа } return $result; } - public function getUserById(int $id): ?PDOStatement + public function getUserById($id) { $stmt = $this->db->prepareStatement("SELECT * FROM users WHERE id_user = ?"); $stmt->setInt(1, $_SESSION ['access']); @@ -89,37 +77,25 @@ class User implements UserInterface if ($result) { $lasttime = $result->getInt('lasttime'); $time = time(); - if ($time - $lasttime > self::LIFE_TIME) return null; // Вышло время сессии + 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 setSID($random, $result) { + return $this->db->executeQuery("UPDATE users SET sid = '$random', trie_count = 0 WHERE id_user = " . $result->getInt('id_user')); } - function resetTries(string $login): void { + function resetTries($login) { $this->db->executeQuery( "UPDATE users SET trie_count = :count WHERE login = :login", ['count' => 0, 'login' => $login] ); } - function updateTries(string $login): void { + function updateTries($login) { $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 index a69d9b7..295e4ca 100644 --- a/src/Role/UserInterface.php +++ b/src/Role/UserInterface.php @@ -2,18 +2,11 @@ namespace ctiso\Role; use ctiso\Database\Statement; -use ctiso\Database\PDOStatement; interface UserInterface { - function getUserByQuery(Statement $stmt): ?PDOStatement; - function getUserByLogin(string $login): ?PDOStatement; - function getUserById(int $id): ?PDOStatement; - function getName(): string; - - /** - * @param string $random - * @param PDOStatement $result - * @return PDOStatement|bool - */ - function setSID(string $random, $result); + function getUserByQuery(Statement $stmt); + function getUserByLogin($login); + function getUserById($id); + function getName(); + function setSID($random, $result); } \ No newline at end of file diff --git a/src/Security.php b/src/Security.php index fa9bea0..ea25461 100644 --- a/src/Security.php +++ b/src/Security.php @@ -3,7 +3,7 @@ namespace ctiso; class Security { - static function generatePassword(int $length = 9, int $strength = 0): string { + static function generatePassword($length = 9, $strength = 0) { $vowels = 'aeuy'; $consonants = 'bdghjmnpqrstvz'; if ($strength & 1) { @@ -18,7 +18,7 @@ class Security { if ($strength & 8) { $consonants .= '@#$%'; } - + $password = ''; $alt = time() % 2; for ($i = 0; $i < $length; $i++) { diff --git a/src/Session.php b/src/Session.php index ff2bba6..6eab118 100644 --- a/src/Session.php +++ b/src/Session.php @@ -2,9 +2,9 @@ namespace ctiso; -class Session +class Session { - function get(string $key): mixed + function get($key) { if (isset($_SESSION[$key])) { return $_SESSION[$key]; @@ -12,27 +12,26 @@ class Session return null; } - function set(string|array $key, mixed $value): void + function set($key, $value) { if (is_array($key)) { - $className = get_class($key[0]); - $_SESSION[strtolower($className ?: '')][$key[1]] = $value; + $_SESSION[strtolower(get_class($key[0]))][$key[1]] = $value; } else { $_SESSION[$key] = $value; } } - function clean(string $key): void + function clean($key) { unset($_SESSION[$key]); } - function start(): void + function start() { @session_start(); } - function stop(): void + function stop() { session_destroy(); } diff --git a/src/Settings.php b/src/Settings.php index d6958c3..1f38299 100644 --- a/src/Settings.php +++ b/src/Settings.php @@ -5,30 +5,21 @@ use ctiso\File, Exception; /** - * Класс реестра + * Класс реестра * Реестр организован как ассоциативный многомерный массив * array( 'name1' => parameters1, 'name2' => parameters1, ... ) * - * name1, name2 ... - Имена модулей + * name1, name2 ... - Имена модулей * parameters1, parameters1 - Массивы с параметрами модуля * Имя необходимо чтобы потом легко было удалить ненужные ветки дерева */ class Settings { - /** @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']; @@ -42,7 +33,7 @@ class Settings * Чтение настроек из файла * @return Boolean */ - public function read(): bool + public function read() { if (!file_exists ($this->file)) { $this->is_read = true; @@ -67,19 +58,18 @@ class 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])) { @@ -93,10 +83,8 @@ 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)) { @@ -109,23 +97,17 @@ class Settings } /** - * Чтение ключа из реестра + * Чтение ключа из реестра * @param array $key Путь к значению ключа - * @return mixed */ 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 +115,9 @@ class Settings } else { return null; } - } - + } + +// assert(count($key) == 1); $name = array_shift($key); if (isset($data[$name])) { return $data[$name]; @@ -146,10 +129,9 @@ class Settings /** * Чтение ключа из реестра (Собирает все ключи с определенным значением во всех модулях) * @param mixed $key Путь к значению ключа внутри модуля - * @return array */ public function readKeyList(...$key) - { + { $result = []; foreach ($this->data as $name => $value) { $output = $this->readKeyData($key, $value); @@ -160,17 +142,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) { @@ -180,11 +158,11 @@ class Settings $name = array_shift($key); unset($data[$name]); } - + /** * Запись настроек в файл (Может переименовать в store) * - * @param string $file + * @param File $file * @return void */ public function write($file = null) @@ -199,49 +177,28 @@ class Settings $result = var_export($this->data, true); $result = ""; } - file_put_contents(($file) ? $file : $this->file, $result); + file_put_contents (($file) ? $file : $this->file, $result); } - /** - * Установка значения ключа - * @param string $key Ключ - * @param mixed $value Значение - */ - public function set($key, $value): void { + public function set($key, $value) { $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() { @@ -250,8 +207,6 @@ class Settings /** * Проверка наличия ключа - * @param string $name Ключ - * @return bool */ public function hasKey($name) { diff --git a/src/Setup.php b/src/Setup.php index e3538be..1aef431 100644 --- a/src/Setup.php +++ b/src/Setup.php @@ -6,65 +6,40 @@ * $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 { + function open($path) { $this->base = $path; } - /** - * Возвращает содержимое файла - * @param string $file - * @return string - */ function getFromName($file) { - return File::getContents(Path::join($this->base, $file)); + return file_get_contents(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 = ''; @@ -81,29 +56,22 @@ class Setup } /** - * Регистрация новых действия для установки - * @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 +84,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); 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 +100,6 @@ class Setup /** * Заменяет переменные на их значения в строке - * @param array $match массив совпадения - * @return string */ function replaceVariable(array $match) { @@ -145,55 +111,50 @@ class Setup /** * Для всех аттрибутов заменяет переменные на их значения - * @param SimpleXMLElement $attributes аттрибуты - * @return array */ - function resolve(SimpleXMLElement $attributes): array - { + function resolve($attributes) + { $result = []; foreach ($attributes as $key => $value) { - $result[$key] = preg_replace_callback("/\\\${(\w+)}/", $this->replaceVariable(...), $value); + $result [$key] = preg_replace_callback("/\\\${(\w+)}/", [$this, 'replaceVariable'], $value); } return $result; } - + /** * Выполняет список действий если для действия не указан аттрибут when то оно выполняется всегда - * + * * @param string $action специальное действие - * @return void */ 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)]); array_pop($this->stack); } - } - + } + /** - * Копирования файла + * Копирования файла * preserve - Не переписывать файл если он существует * template Файл является шаблоном подставить параметры до копирования * src Исходный файл * dst Новый файл - * + * * @param array{preserve?: string, template: string, src: string, dst: string} $attributes - * @return void */ public function copyFile(array $attributes) - { + { $path = $this->targetPath($attributes['dst']); if (!(file_exists($path) && isset($attributes['preserve']))) { @@ -203,9 +164,9 @@ class Setup /** * Создает символическую ссылку на папку/файл - * @param array{target: string, link: string} $attributes + * @param array{target: string, link: string} $attributes */ - public function makeLink(array $attributes): void + public function makeLink(array $attributes) { if (function_exists('symlink')) { symlink($attributes['target'], $attributes['link']); @@ -213,37 +174,37 @@ class Setup } /** - * Подключение файла установки + * Подключение файла установки * @param array{file: string} $attributes Имя подключаемого файла */ - 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 + * dst Имя папки + * + * @param array{dst:string} $attributes */ - 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,11 +212,9 @@ 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)); foreach ($stmtList as $stmt) { @@ -263,12 +222,7 @@ class Setup } } - /** - * Выполнение Списка SQL команд - * @param Database $conn - * @param string $file - */ - static function batchSQL($conn, $file): void + static function batchSQL($conn/*: Database*/, $file) { $stmtList = SQLStatementExtractor::extractFile($file); foreach ($stmtList as $stmt) { diff --git a/src/SortRecord.php b/src/SortRecord.php index 84604ea..3c4fe48 100644 --- a/src/SortRecord.php +++ b/src/SortRecord.php @@ -2,23 +2,20 @@ namespace ctiso; -class SortRecord +class SortRecord { - public string $key; - public int $order; + public $key; + public $mode; + public $order; - function __construct(string $key, bool $order) - { + function __construct($key, $mode, $order) + { $this->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 +23,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,17 +31,17 @@ 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']); } - function sortKeys(array &$list): bool + function sortKeys(&$list) { return usort($list, [$this, 'compareKeys']); } - function group(array &$list, string $key, array $types): void + function group(&$list, $key, $types) { $groups = []; foreach ($types as $name) { @@ -62,6 +59,6 @@ class SortRecord foreach ($groups as $value) { $result = array_merge($result, $value); } - $list = $result; + $list = $result; } } diff --git a/src/TableTree.php b/src/TableTree.php index d09eac3..ba0ec60 100644 --- a/src/TableTree.php +++ b/src/TableTree.php @@ -4,29 +4,26 @@ * Преобразование дерева из модели Plain в массив массивов (Adjacency List) */ +/** + * Обходит таблицу как дерево + * $fn ($name, $index, $rows, $cc) + * $name Ключ уровня + * $index Значение ключа уровня + * $rows Все столбцы текущго уровня + * $cc Столбцы более низкого уровня + * + * @param Array $level Уровни вложенности + * @param array $table Таблица + * @param Function $fn Функция которая применяется к каждой ветке дерева + */ namespace ctiso; use ctiso\Functions; class TableTree { - /** - * Обходит таблицу как дерево - * $fn ($name, $index, $rows, $cc) - * $name Ключ уровня - * $index Значение ключа уровня - * $rows Все столбцы текущго уровня - * $cc Столбцы более низкого уровня - * - * @param array $level Уровни вложенности - * @param array $table Таблица - * @param callable $fn Функция которая применяется к каждой ветке дерева - * @return array - */ static function walk($level, $table, $fn) { - if (empty ($level)) { - return $table; - } + if (empty ($level)) return $table; $name = array_shift ($level); - + $keys = Functions::key_unique_values($name, $table); $data = []; foreach ($keys as $index) { diff --git a/src/Tales.php b/src/Tales.php index 2e3529f..26437e4 100644 --- a/src/Tales.php +++ b/src/Tales.php @@ -4,87 +4,101 @@ * Расширения для PHPTAL для отображения времени и даты */ namespace ctiso; +use PHPTAL_Php_TalesInternal, + ctiso\Controller\SiteInterface, + ctiso\Controller\Component, + ctiso\HttpRequest, + PHPTAL_Tales, + PHPTAL_TalesRegistry; -use PHPTAL_Php_TalesInternal; -use ctiso\Controller\SiteInterface; -use ctiso\Controller\Component; -use ctiso\HttpRequest; -use PHPTAL_Tales; -use PHPTAL_TalesRegistry; - -class Tales_DateTime implements PHPTAL_Tales +class Tales_Inline implements PHPTAL_Tales { - static public function date(string $expression, bool $nothrow = false): string - { + static public function date($expression, $nothrow = false) { return "ctiso\\Tales::phptal_date(".PHPTAL_Php_TalesInternal::path($expression).")"; } - static public function time(string $expression, bool $nothrow = false): string - { + static public function time($expression, $nothrow = false) { return "ctiso\\Tales::phptal_time(".PHPTAL_Php_TalesInternal::path($expression).")"; } -} -class Tales_Component implements PHPTAL_Tales -{ - static public function component(string $expression, bool $nothrow = false): string + static public function component($expression, $nothrow = false) { $s = PHPTAL_Php_TalesInternal::string($expression); return "ctiso\\Tales::phptal_component(" . $s . ")"; } -} - -class Tales_Assets implements PHPTAL_Tales -{ - static public function assets(string $expression, bool $nothrow = false): string + + static public function assets($expression, $nothrow = false) { $s = PHPTAL_Php_TalesInternal::string($expression); return "ctiso\\Tales::phptal_asset(" . $s . ")"; } + + static public function module($expression, $nothrow = false) + { + $s = PHPTAL_Php_TalesInternal::string($expression); + return "ctiso\\Tales::phptal_module(" . $s . ", \$ctx)"; + } } class Tales { - /** @var ?SiteInterface */ - static $site; + static $site/*: SiteInterface*/; - static function phptal_date (int $e): string { + static function phptal_date ($e) { return date("d.m.Y", $e); } - static function phptal_time (int $e): string { + static function phptal_time ($e) { return date("H:i", $e); } - static function phptal_asset(string $s): string { + static function phptal_asset($s) { self::$site->addStyleSheet($s); return ""; } + static function phptal_module($s, $ctx) { + $dir = dirname($ctx->source__); + $web = $ctx->component; + $file = \realpath($dir . '/' . $s); + error_log($web); + // Для модулей использовать только локальный путь + // Преобразовать в url + self::$site->addStyleSheet(Path::join($web, $s)); + // Получить карту с ассоциациями для модуля + // file_get_contents($file); + // Присвоить значения + // + $data = file_get_contents(strtr($file, ['.css' => '.json'])); + error_log($data); + + return json_decode($data, true); + } + /** * Функция подключения компонента - * @param string $expression - * @return string */ - static function phptal_component($expression): string { + static function phptal_component($expression) { $begin = floatval(microtime(true)); - /** @var Component */ + $component/*: Component*/ = null; + $component = self::$site->loadComponent($expression); - $req = new HttpRequest(); + $req = new HttpRequest(); $result = $component->execute($req); - + echo ""; return $result; } - static function register(?SiteInterface $site): void { + static function register($site) { 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']); + $tales->registerPrefix('component', ['ctiso\\Tales_Inline', 'component']); + $tales->registerPrefix('date', ['ctiso\\Tales_Inline', 'date']); + $tales->registerPrefix('time', ['ctiso\\Tales_Inline', 'time']); + $tales->registerPrefix('assets', ['ctiso\\Tales_Inline', 'assets']); + $tales->registerPrefix('module', ['ctiso\\Tales_Inline', 'module']); } } diff --git a/src/Tools/Drawing.php b/src/Tools/Drawing.php index 8a7568e..306d914 100644 --- a/src/Tools/Drawing.php +++ b/src/Tools/Drawing.php @@ -2,8 +2,6 @@ namespace ctiso\Tools; -use GdImage; - class Drawing { const ALIGN_LEFT = "left"; @@ -12,61 +10,26 @@ class Drawing const ALIGN_CENTER = "center"; const ALIGN_RIGHT = "right"; - /** - * @param GdImage $image - * @param int $left - * @param int $top - * @param int $width - * @param int $height - * @param list> $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 */ - 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 = []; @@ -84,9 +47,6 @@ class Drawing for ($i = 0; $i < $count; $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]; @@ -142,15 +102,20 @@ class Drawing 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 + + function imagettftextSp($image, $size, $angle, $x, $y, $color, $font, $text, $spacing = 0) { - if ($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..a59642f 100644 --- a/src/Tools/Image.php +++ b/src/Tools/Image.php @@ -2,15 +2,9 @@ namespace ctiso\Tools; -use GdImage; - class Image -{ - /** - * @param string $uri - * @return GdImage|false - */ - static function load($uri): GdImage|false +{ + static function load($uri) { $e = strtolower(pathinfo($uri, PATHINFO_EXTENSION)); switch ($e) { @@ -18,32 +12,24 @@ class Image case 'jpeg': case 'jpg': return imagecreatefromjpeg($uri); case 'gif': return imagecreatefromgif($uri); } - return false; } - static function fit(GdImage $image, int $prewidth, int $preheight, bool $force = true): GdImage|false + static function fit($image, $prewidth, $preheight, $force = true) { $width = imagesx($image); $height = imagesy($image); - $percent = min($prewidth / $width, $preheight / $height); - if ($percent > 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 +37,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..771b52b 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,142 @@ * @version $Revision: 1.5 $ * @package creole.util.sql */ - namespace ctiso\Tools; - use Exception; -class SQLStatementExtractor -{ - - /** @var string */ +class 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 * @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 array */ - protected static function extractStatements($lines) - { - + protected static function extractStatements($lines) { + $statements = []; $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 @@ -27,7 +21,7 @@ class StringUtil $in_subarr--; } } elseif ($tok[0] === '{') { // we're inside a new sub-array - if ('}' !== substr($tok, -1, 1)) { + if ('}' !== substr($tok, -1, 1)) { $in_subarr++; // if sub-array has more than one element $subarr[$in_subarr] = []; @@ -38,131 +32,81 @@ class StringUtil } else { // not sub-array $val = trim($tok, '"'); // remove " (surrounding strings) // perform type castng here? - $res[] = $val; + $res[] = $val; } } return $res; } - /** - * Нормализация строк на русском - * @param string $str - * @return string - */ - static function normalizeRussian(string $str): string - { - $result = preg_replace('/\s+/', ' ', $str); + //Нормализация строк на русском + static function normalizeRussian($str) { + $result = preg_replace('/\s+/',' ', $str); if (is_string($result)) { $result = trim($result); //Замена длинных пробелов на одинарные, пробелы по краям $result = mb_strtolower($result); - $result = preg_replace('/ё/', 'е', $str); //е на ё + $result = preg_replace('/ё/','е', $str); //е на ё } return $result; } - /** - * Проверка равенства двух строк на русском языке. - * @param string $str1 - * @param string $str2 - * @return bool - */ - static function equalRussianCheck($str1, $str2): bool - { + //Проверка равенства двух строк на русском языке. + 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 - * - * @param string $str - * @param string $variants - * @return bool - */ - static function compare_string_to_variants($str, string $variants) - { +*/ + 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); + $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) ?: []; + static function mb_str_split($str) { + 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) - { + 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"); + static function encodestring($st) { + $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" - ]); + " " => '_', + "." => '_', + "," => '_', + "?" => '_', + "\"" => '_', + "'" => '_', + "/" => '_', + "\\" => '_', + "%" => '_', + "#" => '_', + "*" => '_', + "ж"=>"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 - { + 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/TemplateImage.php b/src/Tools/TemplateImage.php index cb0ad0d..ad9d8f0 100644 --- a/src/Tools/TemplateImage.php +++ b/src/Tools/TemplateImage.php @@ -3,18 +3,13 @@ /** * Формат для композиции изображений */ - namespace ctiso\Tools; - use ctiso\Tools\Drawing; -use GdImage; class 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,28 +24,26 @@ 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 $context = array(); + protected $data = array(); + protected $base = "c:\\windows\\fonts\\"; + protected $image; protected $_prepare = true; - /** @var bool */ public $debug = false; - public string $resource; - public string $filename; + public $resource; + public $filename; - function __construct(?array $template = null) + function __construct ($template = null) { +// assert(is_string($src)); if ($template) { $this->data = $template; } @@ -59,165 +52,131 @@ 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]) { + if ($value->align[0]) { $align = Drawing::ALIGN_LEFT; - } elseif ($value->align[2]) { + } elseif ($value->align[2]) { $align = Drawing::ALIGN_RIGHT; } else { $align = Drawing::ALIGN_CENTER; } - if ($value->valign[0]) { + if ($value->valign[0]) { $valign = Drawing::ALIGN_TOP; - } elseif ($value->valign[1]) { + } elseif ($value->valign[1]) { $valign = Drawing::ALIGN_CENTER; } else { $valign = Drawing::ALIGN_BOTTOM; } - Drawing::imagettftextbox( - $this->image, - $size, - 0, - $value->left, - $value->top, - $color, - $fontfile, - $text, - $value->width, - $value->height, - $align, - $valign - ); + 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)); + $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) { + function prepare() { + if($this->_prepare) { $this->_prepare = false; foreach ($this->data as $value) { $this->imageText($value->text, $value); // break; @@ -228,8 +187,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..5eb93a0 100644 --- a/src/UTF8.php +++ b/src/UTF8.php @@ -2,20 +2,13 @@ namespace ctiso; -class UTF8 -{ - /** - * @param string $str - * @param int $split_length - * @return list - */ - static function str_split(string $str, int $split_length = 1): array - { - $split_length = (int) $split_length; - +class UTF8 { + static function str_split($str, $split_length = 1) { + $split_length = (int) $split_length; + $matches = []; - preg_match_all('/.{' . $split_length . '}|[^\x00]{1,' . $split_length . '}$/us', $str, $matches); - - return $matches[0]; + 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 index 83ce86b..f4393b0 100644 --- a/src/Url.php +++ b/src/Url.php @@ -3,29 +3,25 @@ namespace ctiso; class Url { - /** @var array */ - public array $parts = []; - public ?Url $parent; + public $parts = []; + public $parent/*: Url*/; - /** - * @param Url|null $parent - */ - function setParent($parent): void { + function __construct() { + } + + function setParent($parent) { $this->parent = $parent; } - /** - * @param string[] $parts - */ - function setQuery(array $parts): void { + function setQuery($parts) { $this->parts = $parts; } - function addQueryParam(string $key, ?string $value): void { + function addQueryParam($key, $value) { $this->parts[$key] = $value; } - function toString(): string { + function toString() { 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..226eb75 100644 --- a/src/UserMessageException.php +++ b/src/UserMessageException.php @@ -6,11 +6,7 @@ namespace ctiso; class UserMessageException extends \Exception { - /** @var string */ public $userMessage; - /** - * @param string $message - */ public function __construct($message) { parent::__construct($message); $this->userMessage = $message; diff --git a/src/Validator/Rule/AbstractRule.php b/src/Validator/Rule/AbstractRule.php index 706d8b6..4ab8307 100644 --- a/src/Validator/Rule/AbstractRule.php +++ b/src/Validator/Rule/AbstractRule.php @@ -1,57 +1,47 @@ field = $field; $this->errorMsg = $errorMsg; } - - public function setName(string $field): self + + public function setName($field) { $this->field = $field; return $this; } - public function setErrorMsg(?string $errorMsg): self + public function setErrorMsg($errorMsg) { $this->errorMsg = $errorMsg; return $this; } - public function getErrorMsg(): string - { + public function getErrorMsg() + { return $this->errorMsg; } - /** - * @param Collection $container - * @param bool|null $status - * @return bool - */ - public function isValid(Collection $container, $status = null): bool + public function isValid(Collection $container, $status = null) { return true; } - function skipEmpty(): bool { + function skipEmpty() { return true; } - /** - * @param RuleContext $ctx - */ - public function setContext($ctx): void + public function setContext($ctx) { $this->ctx = $ctx; } diff --git a/src/Validator/Rule/Alpha.php b/src/Validator/Rule/Alpha.php index 2f13230..06793fd 100644 --- a/src/Validator/Rule/Alpha.php +++ b/src/Validator/Rule/Alpha.php @@ -4,18 +4,17 @@ * Проверка на число */ namespace ctiso\Validator\Rule; - -use ctiso\Validator\Rule\AbstractRule; -use ctiso\Collection; +use ctiso\Validator\Rule\AbstractRule, + ctiso\Collection; class Alpha extends AbstractRule { - 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..4ae1b48 100644 --- a/src/Validator/Rule/Code.php +++ b/src/Validator/Rule/Code.php @@ -9,11 +9,12 @@ use ctiso\Validator\Rule\AbstractRule, class Code extends AbstractRule { - 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,7 +23,7 @@ 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; @@ -31,27 +32,27 @@ class Code extends AbstractRule $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] + $_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 { + } 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'], + $_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'] ]; diff --git a/src/Validator/Rule/Count.php b/src/Validator/Rule/Count.php index fa650a8..c346892 100644 --- a/src/Validator/Rule/Count.php +++ b/src/Validator/Rule/Count.php @@ -9,30 +9,26 @@ use ctiso\Validator\Rule\AbstractRule, class Count extends AbstractRule { - public int $size = 1; - public ?int $max = null; + public $size = 1; + public $max = null; - 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))), [$this, 'not_empty'])); return $count >= $this->size && $count <= ((int)$this->max); } diff --git a/src/Validator/Rule/Date.php b/src/Validator/Rule/Date.php index a53975d..fdfff71 100644 --- a/src/Validator/Rule/Date.php +++ b/src/Validator/Rule/Date.php @@ -9,16 +9,16 @@ use ctiso\Validator\Rule\AbstractRule, class Date extends AbstractRule { - public function getErrorMsg(): string - { + 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) + return (preg_match($pattern, $container->get($this->field), $matches) && checkdate((int)$matches[2], (int)$matches[1], (int)$matches[3])); } } diff --git a/src/Validator/Rule/Email.php b/src/Validator/Rule/Email.php index ebbdc17..49ad808 100644 --- a/src/Validator/Rule/Email.php +++ b/src/Validator/Rule/Email.php @@ -9,15 +9,21 @@ use ctiso\Validator\Rule\AbstractRule, class Email extends AbstractRule { - 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..2132d0b 100644 --- a/src/Validator/Rule/EmailList.php +++ b/src/Validator/Rule/EmailList.php @@ -9,14 +9,20 @@ use ctiso\Validator\Rule\AbstractRule, class EmailList extends AbstractRule { - 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..d45d1f8 100644 --- a/src/Validator/Rule/FileName.php +++ b/src/Validator/Rule/FileName.php @@ -7,12 +7,12 @@ use ctiso\Validator\Rule\AbstractRule, class FileName extends AbstractRule { - public function getErrorMsg(): string + public function getErrorMsg() { return 'Название файла может содержать только символы латиницы в нижнем регистре и цифры'; } - public function isValid(Collection $container, $status = null): bool + public function isValid(Collection $container, $status = null) { return Path::isName($container->get($this->field)); } diff --git a/src/Validator/Rule/IsFile.php b/src/Validator/Rule/IsFile.php index 37115f8..5304718 100644 --- a/src/Validator/Rule/IsFile.php +++ b/src/Validator/Rule/IsFile.php @@ -9,42 +9,42 @@ use ctiso\Validator\Rule\AbstractRule, class IsFile extends AbstractRule { - 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/MatchRule.php index b0db64b..d54f448 100644 --- a/src/Validator/Rule/MatchRule.php +++ b/src/Validator/Rule/MatchRule.php @@ -9,16 +9,14 @@ use ctiso\Validator\Rule\AbstractRule, class MatchRule extends AbstractRule { - /** @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..d9130da 100644 --- a/src/Validator/Rule/Notnull.php +++ b/src/Validator/Rule/Notnull.php @@ -6,16 +6,16 @@ use ctiso\Validator\Rule\AbstractRule, class Notnull extends AbstractRule { - function skipEmpty(): bool { + function skipEmpty() { return false; } - public function getErrorMsg(): string - { + public function getErrorMsg() + { return "Поле не должно быть пустым"; } - public function isValid(Collection $container, $status = null): bool + public function isValid(Collection $container, $status = null) { $data = $container->get($this->field); if (is_array($data)) { diff --git a/src/Validator/Rule/Numeric.php b/src/Validator/Rule/Numeric.php index 1fe5b0d..a3c6a5a 100644 --- a/src/Validator/Rule/Numeric.php +++ b/src/Validator/Rule/Numeric.php @@ -9,12 +9,12 @@ use ctiso\Validator\Rule\AbstractRule, class Numeric extends AbstractRule { - 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 index 71e4252..3d400bb 100644 --- a/src/Validator/Rule/PregMatch.php +++ b/src/Validator/Rule/PregMatch.php @@ -1,20 +1,21 @@ pattern, $container->get($this->field)) !== false; - } + public function isValid(Collection $container, $status = null) + { + return preg_match($this->pattern,$container->get($this->field)); + } } 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 */ + /** @var array[string]|null */ $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 ((int)$tmp[0], (int)$tmp[1])) { + return true; + } } - return false; } } diff --git a/src/Validator/Rule/Unique.php b/src/Validator/Rule/Unique.php index 37dfccf..81489c3 100644 --- a/src/Validator/Rule/Unique.php +++ b/src/Validator/Rule/Unique.php @@ -3,20 +3,19 @@ /** */ namespace ctiso\Validator\Rule; - -use ctiso\Validator\Rule\AbstractRule; -use ctiso\Collection; +use ctiso\Validator\Rule\AbstractRule, + ctiso\Collection; class Unique extends AbstractRule { - 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..465c679 100644 --- a/src/Validator/Validator.php +++ b/src/Validator/Validator.php @@ -1,70 +1,51 @@ + /** * Проверка коллекции */ namespace ctiso\Validator; -use Exception; -use ctiso\Validator\Rule\AbstractRule; -use ctiso\Validator\Rule\RuleContext; -use ctiso\Collection; +use Exception, + ctiso\Validator\Rule\AbstractRule, + ctiso\Collection; -/** - * @phpstan-type Rule array{ - * validate?:string, // Описание правила см. формат правила ниже - * name:string, // Имя переменой для проверки - * context?:RuleContext - * } - */ class Validator { - /** @var AbstractRule[] */ - protected array $chain = []; // Массив правил - /** @var array */ - protected array $errorMsg = []; // Массив ошибок + protected $chain = array(); // Массив правил + protected $errorMsg = array(); // Массив ошибок + protected $type = array( + 'date' => 'ctiso\\Validator\\Rule\\Date', + 'email' => 'ctiso\\Validator\\Rule\\Email', + 'emaillist'=> 'ctiso\\Validator\\Rule\\EmailList', + 'match' => 'ctiso\\Validator\\Rule\\MatchRule', + 'time' => 'ctiso\\Validator\\Rule\\Time', + 'alpha' => 'ctiso\\Validator\\Rule\\Alpha', + 'require' => 'ctiso\\Validator\\Rule\\Notnull', + 'numeric' => 'ctiso\\Validator\\Rule\\Numeric', + 'unique' => 'ctiso\\Validator\\Rule\\Unique', + 'filename' => 'ctiso\\Validator\\Rule\\FileName', + 'count' => 'ctiso\\Validator\\Rule\\Count', + 'isfile' => 'ctiso\\Validator\\Rule\\IsFile', + 'code' => 'ctiso\\Validator\\Rule\\Code', + 'reg' => 'ctiso\\Validator\\Rule\\PregMatch', + ); - /** - * Поля по умолчанию - * @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 = []) { $this->addRuleList($rules); } - /** - * Добавление правила в список - * @param string $name - * @param class-string $className - */ - function addRuleType(string $name, string $className): void { + function addRuleType($name, $className) { $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) { // Разбор правила проверки // Формат правила 'rule1|rule2,param1=value1|rule3,param1=value1,param2=value2' @@ -97,7 +78,7 @@ class Validator } } - public function addRule(array|AbstractRule $rule): void { + public function addRule($rule/*:z any*/) { if (is_array($rule)) { $this->chain = array_merge($this->chain, $rule); } else { @@ -105,10 +86,7 @@ class Validator } } - /** - * @param AbstractRule $rule - */ - public function skip($rule, Collection $container): bool + public function skip($rule/*z: AbstractRule*/, $container/*: Collection*/) // -> Rule_Abstract { if ($rule->skipEmpty()) { $data = $container->get($rule->field); @@ -120,23 +98,13 @@ class Validator 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; + if ($rule) { + $this->chain = $rule; } - + $this->errorMsg = []; foreach ($this->chain as $rule) { //echo $key; if (!in_array($rule->field, $fields) && !$this->skip($rule, $container) && !$rule->isValid($container, $status)) { @@ -148,25 +116,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..aa2890a 100644 --- a/src/View/Composite.php +++ b/src/View/Composite.php @@ -1,46 +1,50 @@ tal = new PHPTAL($file); $this->tal->setPhpCodeDestination(PHPTAL_PHP_CODE_DESTINATION); - $this->tal->setEncoding(PHPTAL_DEFAULT_ENCODING); + $this->tal->setEncoding(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(); 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/ListView.php b/src/View/ListView.php new file mode 100644 index 0000000..3acd298 --- /dev/null +++ b/src/View/ListView.php @@ -0,0 +1,16 @@ +_section as $key => $value) { + $result [] = $value->execute(); + } + return $result; + } +} diff --git a/src/View/Pages.php b/src/View/Pages.php index a64873d..e5e93c7 100644 --- a/src/View/Pages.php +++ b/src/View/Pages.php @@ -1,21 +1,13 @@ ($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)) , + '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 [ 'count' => $onpage, @@ -59,13 +51,9 @@ class Pages ]; } - /** - * @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..5ffb102 100644 --- a/src/View/Plain.php +++ b/src/View/Plain.php @@ -1,76 +1,50 @@ 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..37b3339 100644 --- a/src/View/Top.php +++ b/src/View/Top.php @@ -8,32 +8,16 @@ class Top extends Composite { /** * Общая строка заголовка - * @var int */ public $mid = 0; - /** @var array */ - public $require = []; - /** @var array */ - public $deps = []; - /** @var \ctiso\Registry */ - public $config; + public $require = array(); + public $deps = array(); - /** - * Заголовок страницы - * - * @return string - */ public function getTitle() { return implode(" - ", array_filter($this->doTree('_title', false), [$this, 'isNotNull'])); } - /** - * Идентификатор - * - * @param string $pref - * @return string - */ function getId($pref) { $this->mid++; @@ -45,8 +29,7 @@ class Top extends Composite * * @return string */ - #[\Override] - public function execute(): string + public function render() { $this->doTree('alias'); @@ -85,12 +68,11 @@ class Top extends Composite } $init = []; - /** @var View $item */ - foreach ($s->_section as $key => $item) { - if ($item->codeGenerator !== null) { + $ss /*: View*/= $item; + if ($ss->codeGenerator !== null) { // функцию которая вычисляет а не результат - $part = call_user_func($item->codeGenerator, $this, $key, $value); + $part = call_user_func($ss->codeGenerator, $this, $key, $value); $init[] = $part; } } @@ -107,14 +89,14 @@ class Top extends Composite $this->set('title', $this->getTitle()); $this->set('jspath', $this->config->get('system', 'web')); - // - return parent::execute(); // execute+phptal ?? + // + return $this->execute(); // execute+phptal ?? } /** * Массив имен файлов скриптов * - * @return array + * return array */ public function getScripts() { @@ -131,11 +113,6 @@ class Top extends Composite return implode("\n", $this->doTree('_scriptstring')); } - /** - * Строка со скриптом - * - * @return string - */ public function getScriptStartup() { return implode("\n", $this->doTree('_startup')); @@ -144,10 +121,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..141e541 100644 --- a/src/View/View.php +++ b/src/View/View.php @@ -5,35 +5,24 @@ use Exception; class View extends \stdClass { - /** @var array Вложенные шаблоны */ - protected array $_section = []; + protected $_section = array(); // Вложенные шаблоны + // Блоки + protected $_stylesheet = array(); // Массив стилей текущего шаблона + protected $_script = array(); // Массив скриптов текущего шаблона + public $_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; + public $prefix; - 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() { @@ -45,29 +34,31 @@ class View extends \stdClass * @param string $section переменная шаблона * @param View|string $view вложенный шаблон */ - public function setView($section, $view): void + public function setView($section, $view/*: View|string*/) { - $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 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)); $this->_script [] = $output; @@ -76,39 +67,39 @@ class View extends \stdClass /** * Добавляет код скипта к текущему шаблону * - * @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 { + public function setPrefix($name, $val) { $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)); - $this->_stylesheet [] = $output; + $output = $this->resolveName($this->alias, $name . '?' . http_build_query($this->prefix)); + $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]; foreach ($this->_section as $value) { @@ -123,22 +114,14 @@ 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) { } - + /** * Обработка всех вложенных шаблонов */ - public function processChild(): void + public function execute() { foreach ($this->_section as $key => $value) { $this->set($key, (is_object($value)) ? $value->execute() : $value); // ? @@ -147,35 +130,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,20 +162,16 @@ class View extends \stdClass } } throw new Exception("file not found: $file"); - } + } - - /** - * FIXME: Префикс, конфликтует с протоколом - * @param string[]|string[][] $alias - */ - function resolveName($alias, string $file): string { + // FIXME: Префикс, конфликтует с протоколом + 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); + $output = $this->find_file($alias[$type], $filename); } else { $output = $alias[$type] . '/' . $filename; } @@ -205,23 +180,31 @@ class View extends \stdClass return $file; } - /** - * @param string[][] $alias - * @param string[] $list - * @return string[] - */ - public function resolveAllNames($alias, array $list): array { + function loadImports($importFile) + { + $types = [ + 'js' => [$this, 'addScript'], + 'css' => [$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 = []; foreach($list as $item) { $result [] = $this->resolveName($alias, $item); } return $result; } - - /** - * Шаблон всегда возвращает строку - */ - function execute(): string { - return ''; - } } diff --git a/src/ZipFile.php b/src/ZipFile.php index b6ecdf6..e858432 100644 --- a/src/ZipFile.php +++ b/src/ZipFile.php @@ -8,38 +8,36 @@ use ZipArchive; class ZipFile extends ZipArchive { - /** - * @var list - */ - 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([$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); }