diff --git a/composer.json b/composer.json index de9a023..4c325c2 100644 --- a/composer.json +++ b/composer.json @@ -8,8 +8,8 @@ } ], "autoload": { - "psr-0": { - "": "src/" + "psr-4": { + "ctiso\\": "src/" } } } diff --git a/src/Adapter.php b/src/Adapter.php index 42bd4ab..2ba68f9 100644 --- a/src/Adapter.php +++ b/src/Adapter.php @@ -1,5 +1,8 @@ get($key, $default)); + return (string)$this->get($key, $default); } public function getNat($key, $default = 1) diff --git a/src/ComponentRequest.php b/src/ComponentRequest.php new file mode 100644 index 0000000..6bc7dbc --- /dev/null +++ b/src/ComponentRequest.php @@ -0,0 +1,36 @@ +component_id = $c; + $this->r = $r; + } + + function get($key, $default = null) { + if ($key == 'active_page') { + return $this->r->get($key); + } + $arr = $this->r->get($key); + if (!is_null($arr)) { + if (is_array($arr)) { + return Arr::get($arr, $this->component_id, $default); + } else { + return $arr; + } + } + return $default; + } + + function getAction() { + return $this->r->getAction(); + } +} diff --git a/src/Connection/HttpRequest.php b/src/Connection/HttpRequest.php index ce2f13b..006cc63 100644 --- a/src/Connection/HttpRequest.php +++ b/src/Connection/HttpRequest.php @@ -1,6 +1,9 @@ param['Transfer-Encoding']) && $this->param['Transfer-Encoding'] == 'chunked') { //$this->data = substr($this->response, $this->offset); - $nline = hexdec($this->getLine()); + $index = hexdec($this->getLine()); $chunk = array(); - while ($nline > 0) { - $chunk [] = substr($this->response, $this->offset, $nline); - $this->offset += $nline; - $nline = hexdec($this->getLine()); + while ($index > 0) { + $chunk [] = substr($this->response, $this->offset, $index); + $this->offset += $index; + $index = hexdec($this->getLine()); } $this->data = implode("", $chunk); diff --git a/src/Controller/Action.php b/src/Controller/Action.php index df0de65..b73b685 100644 --- a/src/Controller/Action.php +++ b/src/Controller/Action.php @@ -1,49 +1,52 @@ part = new Url(); } public function setUp() { } public function loadConfig($name) { - $filename = Shortcut::getUrl('config', $name); + $basePath = $this->config->get('site', 'path'); + + $filename = Path::join($basePath, 'modules', $name); $settings = []; if (file_exists($filename)) { - include($filename); + $settings = include($filename); } else { throw new Exception('Невозможно загрузить файл настроек ' . $name); } @@ -75,37 +81,39 @@ class Controller_Action public function installPath($name) { - return Path::join(CMS_PATH, "modules", $name); + $basePath = $this->config->get('system', 'path'); + return Path::join($basePath, "modules", $name); } - public function addSuggest(View_View $view, $name) - { + public function addSuggest(View $view, $name) { $suggest = array(); - $file = Path::join($this->viewPath, 'help', $name . '.suggest'); + $file = Path::join($this->modulePath, 'help', $name . '.suggest'); if (file_exists($file)) { - include($file); - $view->suggestions = $suggest; + $view->suggestions = include($file); } } - function findIcon($icon, $size) - { - return Path::join($this->iconPath, $size . 'x' . $size, $icon . '.png'); + function findIcon($icon, $size) { + $webPath = $this->config->get('site', 'web'); + return Path::join($webPath, 'icons', $size . 'x' . $size, $icon . '.png'); } /** * Создает представление - * @param $name String - * @param $viewClass String - * @return View_Composite + * @param string + * @param string $viewClass + * @return Composite */ - public function getView($name, $viewClass = 'View_Composite') + public function getView($name, $viewClass = 'ctiso\\View\\Composite') { $file = $name . self::TEMPLATE_EXTENSION; + $basePath = $this->config->get('system', 'path'); + $webPath = $this->config->get('system', 'web'); + $list = array( - Path::join($this->viewPath, TEMPLATES, $this->viewPathPrefix) => Path::join(WWW_PATH, "modules", $this->name, TEMPLATES, $this->viewPathPrefix), - Path::join(CMS_PATH, "templates") => Path::join(WWW_PATH, "templates") + Path::join($this->modulePath, 'templates', $this->viewPathPrefix) => Path::join($webPath, "modules", $this->name, 'templates', $this->viewPathPrefix), + Path::join($basePath, "templates") => Path::join($webPath, "templates") ); // Поиск файла для шаблона @@ -114,19 +122,22 @@ class Controller_Action if(file_exists($template)) { break; } } - $tpl/*: View_Composite*/ = new $viewClass($template); + $tpl/*: Composite*/ = new $viewClass($template); + $tpl->config = $this->config; - $assets = Path::join(enableHttps(WWW_PATH), "assets", "css"); - $tpl->set('icons', $this->iconPath); // Путь к файлам текущей темы - $tpl->set('media', $this->themePath); // Путь к файлам текущей темы - $tpl->set('assets', $assets); - $tpl->set('script', $this->jsPath); // Путь к файлам скриптов + $stylePath = Path::join($webPath, "assets", "css"); + $iconsPath = Path::join($webPath, 'icons'); + $scriptPath = Path::join($webPath, 'assets'); + + $tpl->set('icons', $iconsPath); // Путь к файлам текущей темы + $tpl->set('assets', $stylePath); + $tpl->set('script', $scriptPath); // Путь к файлам скриптов $tpl->set('template', $path); // Путь к файлам текущего шаблона $tpl->setAlias(array( - 'assets' => $assets, - 'icons' => $this->iconPath, - 'script' => $this->jsPath, + 'assets' => $stylePath, + 'icons' => $iconsPath, + 'script' => $scriptPath, // Для media и template поиск происходит как для файлов шаблонов 'media' => $list, 'template' => $list @@ -141,7 +152,7 @@ class Controller_Action public function getModel($name) { if (!$this->factory) { - $this->factory = new Model_Factory($this->db, $this->_registry); + $this->factory = new Factory($this->db, $this->config, $this->user); } return $this->factory->getModel($name); } @@ -151,25 +162,25 @@ class Controller_Action * Т.к действия являются методами класса то * 1. Можно переопределить действия * 2. Использовать наследование чтобы добавить к старому обработчику новое поведение - * @param $request Обьект запроса + * @param HttpRequest $request запроса */ - public function preprocess(HttpRequest $request) + public function preProcess(HttpRequest $request) { $action = self::ACTION_PREFIX . ucfirst($request->getAction()); if (!method_exists($this, $action)) { $action = "actionIndex"; } $view = $this->forward($action, $request); - if ($view instanceof View_View) { - $view->active_module = get_class($this); - $view->module_action = $action; - } - return $view; + if ($view instanceof View) { + $view->active_module = get_class($this); + $view->module_action = $action; + } + return $view; } - + public function execute(HttpRequest $request) { - $result = $this->preprocess($request); + $result = $this->preProcess($request); if (!empty($result)) { $this->view = $result; } @@ -189,13 +200,8 @@ class Controller_Action return ""; } - public function postUrl($name, $param) - { - $uri = array_merge(array('module' => - strtr($this->modulePrefix . strtolower(get_class($this)), array('module_' => '')), "action" => $name), - $this->param, $param); - - return "?" . http_build_query($uri); + public function addUrlPart($key, $value) { + $this->part->addQueryParam($key, $value); } /** @@ -203,31 +209,28 @@ class Controller_Action * @param string $name Действие * @param array $param Дополнительные параметры * 'mode' означает что элемент до отправки обрабатывается javascript - * @return array|null + * @return Url|null */ public function nUrl($name, array $param = array()) { - $access/*: Filter_ActionAccess*/ = $this->access; + $access/*: ActionAccess*/ = $this->access; + $url = new Url(); if ($access == null || $access->checkAction($name)) { - return Functions::lcurry(array($this, 'postUrl'), $name, $param); - } - return null; - } + $moduleName = explode("\\", strtolower(get_class($this))); + if (count($moduleName) > 2) { + array_shift($moduleName); + if ($moduleName[0] == $moduleName[1]) { + array_shift($moduleName); + } + } + $param = array_merge(array('module' => implode("\\", $moduleName), "action" => $name), $param); - public function fUrl($name, array $param = array()) - { - return forceUrl($this->nUrl($name, $param)); - } - - /** - * Добавляет параметр для всех ссылок создаваемых функцией nUrl, aUrl - */ - public function addParameter($name, $value) - { - if ($value) { - $this->param [$name] = $value; + $url->setParent($this->part); + $url->setQuery($param); } + + return $url; } /** @@ -235,14 +238,14 @@ class Controller_Action * Ajax определяется автоматически mode = ajax используется для смены layout * @param $name * @param array $param - * @return array|null + * @return Url|null * * @example ?action=$name&mode=ajax * {$param[i].key = $param[i].value} */ public function aUrl($name, array $param = array()) { - return $this->nUrl($name, array_merge(array('mode' => 'ajax'), $param)); // FIXME + return $this->nUrl($name, array_merge(array('mode' => 'ajax'), $param)); } /** @@ -295,29 +298,29 @@ class Controller_Action /** * Установка заголовка для отображения - */ + */ public function setTitle($title) { $this->view->setTitle($title); } /** - * Добавление widget к отображению + * Добавление widget к отображению */ - public function addChild(/*Widget*/ $section, $node) + public function addChild($section, $node) { $this->childNodes[$section] = $node; } - public function setValue(/*Widget*/ $name, $value) + public function setValue($name, $value) { $this->ctrlValues[$name] = $value; } /** - * Добавление дочернего отображения к текущему отображению + * Добавление дочернего отображения к текущему отображению */ - public function addView(/*CompositeView*/ $section, $node) + public function addView($section, $node) { $this->childViews[$section] = $node; } @@ -326,12 +329,13 @@ class Controller_Action * Генерация содержания * Путаница c execute и render */ - public function render() + public function render() { - if ($this->view instanceof View_View) { - $this->view->assignValues($this->ctrlValues); + $view = $this->view; + if ($view instanceof View) { + $this->view->assignValues($this->ctrlValues); - $node/*: Widgets_Widget*/ = null; + $node/*: Composite*/ = null; foreach ($this->childNodes as $name => $node) { $node->make($this); $this->view->setView($name, $node->view); @@ -340,18 +344,17 @@ class Controller_Action foreach ($this->childViews as $name => $node) { $this->view->setView($name, $node); } - } + } return $this->view; } - function getPageId(HttpRequest $request) - { - $pageId = time(); + function getPageId(HttpRequest $request) { + $pageId = time(); $request->session()->set('page', $pageId); return $pageId; } - function checkPageId(HttpRequest $request, $page) + function checkPageId(HttpRequest $request, $page) { if ($request->get('__forced__')) { return true; @@ -362,19 +365,17 @@ class Controller_Action return $result; } - function _getActionPath() - { - return new Controller_State('index'); + function _getActionPath() { + return new State('index'); } // Тоже убрать в метод Controller_Model - function getActionPath(HttpRequest $request, $action = null) - { + function getActionPath(HttpRequest $request, $action = null) { $this->_getActionPath()->getPath($this, ($action) ? $action : $request->getAction()); } - function redirect($action) { - header('location: ' . $this->fUrl($action)); + function redirect($action/*: string*/) { + header('location: ' . $action); exit(); } } diff --git a/src/Controller/Component.php b/src/Controller/Component.php index 209d765..4e6f459 100644 --- a/src/Controller/Component.php +++ b/src/Controller/Component.php @@ -1,48 +1,42 @@ ]*>/u', 'replaceContent', $text); -} - -class ComponentRequest { - public $component_id; - public $component_title; - public $r; - - function __construct($c, HttpRequest $r) { - $this->component_id = $c; - $this->r = $r; +class FakeTemplate { + public $_data = []; + public $_name = ''; + + function __construct($name) { + $this->_name = $name; } - function get($key, $default = null) { - if ($key == 'active_page') { - return $this->r->get($key); - } - $arr = $this->r->get($key); - if ($arr !== NULL) { - if (is_array($arr)) { - return Arr::get($arr, $this->component_id, $default); - } else { - return $arr; - } - } - return $default; - } + function __set($key, $value) { + $this->_data[$key] = $value; + } - function getAction() { - return $this->r->getAction(); + function execute() { + return json_encode($this->_data); } } /** * Класс компонента */ -class Controller_Component +class Component { public $viewPath = array(); public $webPath = array(); @@ -52,19 +46,28 @@ class Controller_Component public $component_id; public $component_title; + public $COMPONENTS_WEB; - public $registry/*: Settings*/; + public $config/*: Registry*/; public $db/*: Database*/; public $parameter/*: Collection*/; + public $output = 'html'; + public $module; public $item_module; + public $site; function before() { } - function get($request, $key, $default) { + static function replaceContent($match) { + return \ctiso\Tales::phptal_component(htmlspecialchars_decode($match[3])); + } + + static function applyComponents($text) { + return preg_replace_callback('/<(\w+)(\s+[a-zA-Z\-]+=\"[^\"]*\")*\s+tal:replace="structure\s+component:([^\"]*)"[^>]*>/u', 'ctiso\\Controller\\Component::replaceContent', $text); } function execute(HttpRequest $request, $has_id = true) { @@ -85,16 +88,20 @@ class Controller_Component } } - public function getTemplateName($_registry/*: Settings*/) { + 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->readKey(array('system', 'template')) : 'modern'); + ? $_COOKIE['with_template'] : ($_registry ? $_registry->get('site', 'template') : 'modern'); } public function getView($name) { - // - $registry/*: Settings*/ = $this->registry; - $template = ($this->template) ? $this->template : $this->getTemplateName($registry); + if ($this->output == 'json') { + return new FakeTemplate($name); + } + + $config/*: Registry*/ = $this->config; + $default = $config->get('site', 'template'); + $template = ($this->template) ? $this->template : $this->getTemplateName($config); $selected = null; foreach ($this->viewPath as $index => $viewPath) { @@ -119,13 +126,14 @@ class Controller_Component $tpl->stripComments(true); $tpl->addPreFilter(new PHPTAL_PreFilter_Normalize()); - $tpl->set('common', Path::join(WWW_PATH, '../', 'common')); - $tpl->set('script', Path::join(WWW_PATH, 'js')); - $tpl->set('media', Path::join(TEMPLATE_WEB, $template)); - if ($registry) { - $tpl->set('site_template', SITE_WWW_PATH . '/templates/' . $registry->readKey(array('system', 'template'))); + $tpl->set('common', Path::join($this->config->get('system', 'web'), '../', 'common')); + $tpl->set('script', Path::join($this->config->get('system', 'web'), 'js')); + $tpl->set('media', Path::join($this->config->get('system', 'templates.web'), $template)); + + if ($default) { + $tpl->set('site_template', Path::join($this->config->get('site', 'templates.web'), $default)); } - $tpl->set('base', SITE_WWW_PATH); + $tpl->set('base', $this->config->get('site', 'web')); $tpl->set('component_base', $this->webPath[$selected]); $tpl->set('component', Path::join($this->webPath[$selected], 'templates', $template)); @@ -139,7 +147,7 @@ class Controller_Component } public function getTemplatePath($name) { - $registry/*: Settings*/ = $this->registry; + $registry/*: \ctiso\Settings*/ = $this->config; // Брать настройки из куков если есть $template = ($this->template) ? $this->template : $this->getTemplateName($registry); foreach ($this->viewPath as $index => $viewPath) { @@ -163,13 +171,14 @@ class Controller_Component */ public function getModel($name) { - $modelName = "Mapper_" . $name; + $modelName = "App\\Mapper\\" . $name; $model = new $modelName(); + $model->config = $this->config; $model->db = $this->db; return $model; } - public function options($key, $val, $res/*: Database_PDOStatement*/) { + public function options($key, $val, $res/*: PDOStatement*/) { $result = array(); while($res->next()) { $result[] = array('value' => $res->getString($key), 'name' => $res->getString($val)); @@ -185,22 +194,33 @@ class Controller_Component return $result; } + function findFile($pathList, $name) { + foreach($pathList as $item) { + $filename = Path::join($item, $name); + if (file_exists($filename)) { + return $filename; + } + } + return null; + } + function getInfo() { $filename = Path::join($this->viewPath[count($this->viewPath) - 1], 'install.json'); if (file_exists($filename)) { $settings = json_decode(File::getContents($filename), true); - return $settings; + if ($settings) { + return $settings; + } } - return array(); + return array('parameter' => []); } /** * Генерация интерфейса для выбора галлереи фотографии */ - public function setParameters($view/*: View_Composite*/) + public function setParameters($view/*: Composite*/, $options = null) { - $form = new Form_Form(); - $options = new Form_OptionFactory($this->db, $this->registry); + $form = new Form(); $settings = $this->getInfo(); $form->addFieldList($settings['parameter'], $options); @@ -210,7 +230,7 @@ class Controller_Component $view->component_title = $settings['title']; } - static function loadComponent($expression, Database $db, $registry/*: Registry*/) + static function loadComponent($expression, $site/*: SiteInterface*/) { $expression = htmlspecialchars_decode($expression); @@ -226,55 +246,54 @@ class Controller_Component parse_str($query, $arguments); } $name = $path; + $config = $site->config; - $path = Path::join (BASE_PATH, 'components', $name, $name . '.php'); - $className = 'Component_' . $name; + $filename = ucfirst($name); + $path = Path::join ($config->get('site', 'components'), $name, $filename . '.php'); + $className = implode("\\", ['Components', ucfirst($name), $filename]); - $component/*: Controller_Component*/ = null; + $component/*: Component*/ = null; if (file_exists($path)) { - require_once ($path); - + // require_once ($path); $component = new $className(); - $component->db = $db; - $component->registry = $registry; - $component->viewPath = array(BASE_PATH . '/components/' . $name . '/'); - $component->webPath = array(SITE_WWW_PATH . '/components/' . $name); - - $component->COMPONENTS_WEB = SITE_WWW_PATH . '/components/'; + $component->viewPath = array($config->get('site', 'components') . '/' . $name . '/'); + $component->webPath = array($config->get('site', 'components.web') . '/' . $name); + $component->COMPONENTS_WEB = $config->get('site', 'web') . '/components/'; } else { - $path = Path::join (COMPONENTS, $name, $name . '.php'); - require_once ($path); $component = new $className(); - $component->db = $db; - $component->registry = $registry; - - $template = $component->getTemplateName($registry); + $template = $component->getTemplateName($site->config); $component->viewPath = array( // Сначало ищем локально - BASE_PATH . '/templates/' . $template . '/_components/' . $name . '/', - BASE_PATH . '/components/' . $name . '/', + $config->get('site', 'templates') . '/'. $template . '/_components/' . $name . '/', + $config->get('site', 'components') . '/' . $name . '/', // Потом в общем хранилище - CMS_PATH . '/../templates/' . $template . '/_components/' . $name . '/', - COMPONENTS . '/' . $name . '/', + $config->get('system', 'templates'). '/' . $template . '/_components/' . $name . '/', + $config->get('system', 'components') . '/' . $name . '/', ); if (defined('COMPONENTS_WEB')) { $component->webPath = array( // Сначало локально - SITE_WWW_PATH . '/templates/' . $template . '/_components/' . $name, - SITE_WWW_PATH . '/components/' . $name, + $config->get('site', 'templates.web') . '/' . $template . '/_components/' . $name, + $config->get('site', 'components.web') . '/' . $name, // Потом в общем хранилище - TEMPLATE_WEB . '/' . $template . '/_components/' . $name, - COMPONENTS_WEB . '/' . $name, + $config->get('system', 'templates.web') . '/' . $template . '/_components/' . $name, + $config->get('system', 'components.web') . '/' . $name, ); - $component->COMPONENTS_WEB = COMPONENTS_WEB; + $component->COMPONENTS_WEB = $config->get('system', 'components.web'); } else { - $component->webPath = array('', SITE_WWW_PATH . '/components/' . $name, ''); + $component->webPath = array('', $config->get('site', 'components.web') . '/' . $name, ''); } - } + } + + $db = $site->getDatabase(); + + $component->db = $db; + $component->config = $site->config; + $component->site = $site; $stmt = $db->prepareStatement("SELECT * FROM component WHERE code = ?"); $stmt->setString(1, $expression); @@ -302,18 +321,13 @@ class Controller_Component $params = new Collection(); $params->import(array_merge($_GET, $arguments)); + $component->parameter = $params; $component->template = $params->get('template', false); $editor = $component->getEditUrl(); if ($editor) { - if(class_exists("Controller_Site")){ //Если мы в CMS2 - $instance = Controller_Site::getInstance(); - $instance->componentsConfig[] = $editor; - } else { - global $componentsConfig; - $componentsConfig[] = $editor; - } + $site->componentsConfig[] = $editor; } return $component; @@ -358,15 +372,10 @@ class Controller_Component return '?' . http_build_query($arr); } - /** - * @deprecated В CMS2 перенесено в контроллер сайта! - */ - function addRequireJsPath($name, $path, $shim = null) { - Controller_Site::addRequireJsPath($name, $path, $shim); + $this->site->addRequireJsPath($name, $path, $shim); } function actionIndex($request/*: ComponentRequest*/) { } } - diff --git a/src/Controller/Front.php b/src/Controller/Front.php index ed5aee2..ed9148a 100644 --- a/src/Controller/Front.php +++ b/src/Controller/Front.php @@ -4,76 +4,85 @@ * Первичный контроллер контроллер страниц * @package system.controller */ -class Controller_Front extends Controller_Action +namespace ctiso\Controller; +use ctiso\Controller\Action, + ctiso\Settings, + ctiso\Database, + ctiso\Collection, + ctiso\Filter\ActionAccess, + ctiso\Filter\ActionLogger, + ctiso\Path, + ctiso\UserMessageException, + ctiso\HttpRequest; + +class Front extends Action { - /** @var Shortcut */ - protected $shortcut; // Ярлык к модулю protected $_param; // Параметр по которому выбирается модуль protected $default; // Значение параметра по умолчанию protected $modules = array(); /** - * @param Settings $_registry - * @param Shortcut $_shortcut + * @param Settings $settings */ - public function __construct(Settings $_registry, $_shortcut) // $db, $installer, $shortcut - { + public function __construct($db, $config, $user, $default) { parent::__construct(); - $registry = $_registry; - $this->_registry = $_registry; - $this->_shortcut = $_shortcut; // $cc->newShortcut(); - - $dsn = $registry->readKey(array('system', 'dsn')); - $this->db = Database::getConnection($dsn); // $cc->newConnection(); + $this->config = $config; + $this->db = $db; + $this->user = $user; + $this->default = $default; } - public function isLoaded($name) - { + public function isLoaded($name) { return isset($this->modules[$name]); } /** * Создает экземпляр модуля и выполняет действия для него * @param string $name Имя модуля - * @param request $request Имя модуля + * @param Request $request Имя модуля * @return string */ - public function loadModule($name, Collection $request, $controller = false) + public function loadModule($name, Collection $request) { if ($this->isLoaded($name)) { $module = $this->modules[$name]; return $module->access->execute($request); } - $suffix = ($controller) ? $controller : $name; - $moduleFile = Shortcut::getUrl($this->shortcut, $name, $suffix); // ModuleLoader (2) + $parts = explode('\\', $name); + + $config = $this->config; + + $moulesPath = Path::join($config->get('system', 'path'), 'modules'); + $logPath = Path::join($config->get('site', 'path'), $config->get('system', 'access.log')); - $module = $this->loadClass($moduleFile, null, 'Module_'); + $first = $parts[0]; + $second = (count($parts) >= 2) ? $parts[1] : $parts[0]; + + $ucname = ucfirst($first); + $ucpart = ucfirst($second); + + $moduleClass = "Modules\\$ucname\\$ucpart"; + $module = new $moduleClass(); if ($module) { // Инициализация модуля - $module->front = $this; - $module->viewPath = Shortcut::getUrl('modulepath', $name); + $modPath = Path::join($moulesPath, $first); + $module->modulePath = $modPath; $module->name = $name; - - $module->param = $this->param; // - $module->_registry = $this->_registry; - $module->_shortcut = $this->_shortcut; - - $module->iconPath = $this->iconPath; // -> Registry - $module->themePath = $this->themePath; // -> Registry - $module->jsPath = $this->jsPath; // -> Registry + $module->config = $this->config; $module->db = $this->db; - // Не для всех приложений нужно вести лог действий + $module->user = $this->user; + $module->front = $this; // Ведение лога - $logger = $this->loadClass(__DIR__ . '/../Filter/ActionLogger.php', $module, 'Filter_'); - $logger->before = $this->loadSettings(Shortcut::getUrl('logger', $name)); + $logger = new ActionLogger($module, $logPath, $this->user); + $filename = Path::join($modPath, 'filters', 'logger.json'); + $logger->before = $this->loadSettings($filename); // Управление доступом - $module->access = $this->loadClass(__DIR__ . '/../Filter/ActionAccess.php', $logger, 'Filter_'); - $module->access->name = $suffix; - $module->access->access = $this->loadSettings(Shortcut::getUrl('access', $name)); + $module->access = new ActionAccess($logger, $this->user); + $module->access->access = $this->loadSettings(Path::join($modPath, 'filters', 'access.json')); $module->setUp(); @@ -84,27 +93,15 @@ class Controller_Front extends Controller_Action return null; // throw new FileNotFoundException(); } - public function setParameter($shortcut, $param, $name) - { - $this->shortcut = $shortcut; - // Параметр - $this->_param = $param; - $this->default = $name; - } public function execute(HttpRequest $request) { - $name = explode("_", $request->get($this->_param, $this->default)); - if (count($name) >= 2) { - $controller = $name[1]; - } else { - $controller = false; - } - try{ - return $this->loadModule($name[0], $request, $controller); + $name = $request->get('module', $this->default); + try { + return $this->loadModule($name, $request); } catch (UserMessageException $ex) { //Исключение с понятным пользователю сообщением $mode = $request->get('mode'); - if($mode == 'ajax' || $mode == 'json'){ + if ($mode == 'ajax' || $mode == 'json') { return json_encode(['result'=>'fail', 'message'=> $ex->userMessage]); } else { return $ex->userMessage; diff --git a/src/Controller/Installer.php b/src/Controller/Installer.php index d20a93d..2adff19 100644 --- a/src/Controller/Installer.php +++ b/src/Controller/Installer.php @@ -1,6 +1,11 @@ _registry->readKey(array($name)); + $item = $this->_registry->get('system', $name); if ($item) { $setup = $this->getSetupFile($name); if (file_exists($setup) && (filemtime($setup) > $item['time'])) { @@ -44,7 +49,7 @@ class Controller_Installer function installSQL(array $sql, $version_new, $version_old, $name) { $result = []; - $json_installer = new Database_JsonInstall($this->db_manager); + $json_installer = new JsonInstall($this->db_manager); foreach ($sql as $version => $install) { if (version_compare($version, $version_new, "<=") && version_compare($version, $version_old, ">")) { $file = Path::join(call_user_func($this->installPath, $name), "sql", $install); @@ -58,7 +63,7 @@ class Controller_Installer function uninstall($name){ $uninstall = $this->getUninstallFile($name); if (file_exists($uninstall)) { - $json_installer = new Database_JsonInstall($this->db_manager); + $json_installer = new JsonInstall($this->db_manager); $json_installer->install($uninstall,null); } $this->_registry->removeKey($name); @@ -76,7 +81,7 @@ class Controller_Installer $settings = new Settings($setup); $settings->read(); - $item = $registry->readKey(array($name)); + $item = $registry->get('system', $name); $version_new = $settings->get('version'); if ($item) { @@ -89,26 +94,27 @@ class Controller_Installer $sql = $settings->get('sql'); if (is_array($sql)) { $res = $this->installSQL($sql, $version_new, $version_old, $name); - if($res){ + if ($res) { $result[]=$res; } } - - // Обновление версии меню - $registry->removeKey($name); - $registry->writeKey(array($name), $settings->get('settings')); - $registry->writeKey(array($name), - array('version' => $version_new, - 'time' => filemtime($setup))); } + // Обновление версии меню + $registry->removeKey($name); + $registry->set($name, [ + 'version' => $version_new, + 'time' => filemtime($setup) + ]); + $registry->writeKey([$name], $settings->get('settings')); + $registry->write(); } return $result; } function install($dbinit_path, $dbfill_path = null) { - $json_installer = new Database_JsonInstall($this->db_manager); + $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 6567ad7..81fbc46 100644 --- a/src/Controller/Request.php +++ b/src/Controller/Request.php @@ -1,10 +1,13 @@ r = $request; $this->id = $id; } diff --git a/src/Controller/Service.php b/src/Controller/Service.php index a1f7185..cccecdf 100644 --- a/src/Controller/Service.php +++ b/src/Controller/Service.php @@ -3,11 +3,17 @@ /** * Класс сервиса = Упрощенный компонент */ -class Controller_Service +namespace ctiso\Controller; +use ctiso\Path, + ctiso\File, + ctiso\Registry, + ctiso\Database\PDOStatement; + +class Service { public $viewPath = []; public $webPath = []; - public $registry; // Registry->getInstance + public $config/*: Registry*/; public $template; public $templatePath; public $COMPONENTS_WEB; @@ -25,17 +31,17 @@ class Controller_Service } /** - * @param $name Имя модели + * @param string $name Имя модели */ private function getModelPath($name) { - return Path::join (CMS_PATH, "model", $name . ".php"); + return Path::join ($this->config->get('system', 'path'), "model", $name . ".php"); } /** * Создает модель * @param string $name - * @return model + * @return Model */ public function getModel($name) { @@ -46,7 +52,7 @@ class Controller_Service return $model; } - public function options($key, $val, $res) { + public function options($key, $val, $res/*: PDOStatement*/) { $result = array(); while($res->next()) { $result[] = array('value' => $res->getInt($key), 'name' => $res->getString($val)); diff --git a/src/Controller/SiteInterface.php b/src/Controller/SiteInterface.php new file mode 100644 index 0000000..1125601 --- /dev/null +++ b/src/Controller/SiteInterface.php @@ -0,0 +1,12 @@ +states [$state->getAction()] = $state; return $this; @@ -49,7 +53,7 @@ class Controller_State return false; } - function makeTitle(Controller_Action $module) + function makeTitle(Action $module) { foreach ($this->titles as $item) { $module->path->addMenuItem($module->nUrl($this->action, $item[1]), $item[0]); diff --git a/src/Database.php b/src/Database.php index acd8c59..ad989d7 100644 --- a/src/Database.php +++ b/src/Database.php @@ -1,6 +1,19 @@ -require_once "Database/PDOStatement.php"; + +namespace { + if(!function_exists('sqliteLower')){ + function sqliteLower($str) { + return mb_strtolower($str, 'UTF-8'); + } + } +} + +namespace ctiso { +use PDO, + ctiso\Database\Statement, + ctiso\Database\PDOStatement, + ctiso\Database\IdGenerator; /** * Класс оболочка для PDO для замены Creole @@ -14,11 +27,11 @@ class Database/**/ extends PDO parent::__construct($dsn, $username, $password); $this->setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION); $this->setAttribute(PDO::ATTR_DEFAULT_FETCH_MODE, PDO::FETCH_ASSOC); - $this->setAttribute(PDO::ATTR_STATEMENT_CLASS, array('Database_PDOStatement', array())); + $this->setAttribute(PDO::ATTR_STATEMENT_CLASS, array('ctiso\\Database\\PDOStatement', array())); } - function prepare($sql, $args = []) { - $result = parent::prepare($sql, $args); + function prepare($sql, $args = []) { + $result/*: PDOStatement*/ = parent::prepare($sql, $args); return $result; } @@ -35,8 +48,8 @@ class Database/**/ extends PDO static function getConnection(array $dsn) { - if ($dsn['phptype'] == 'pgsql' || $dsn['phptype'] == 'mysql') { - $port = (isset($dsn['port'])) ? "port={$dsn['port']};" : ""; + if ($dsn['phptype'] == 'pgsql' || $dsn['phptype'] == 'mysql') { + $port = (isset($dsn['port'])) ? "port={$dsn['port']};" : ""; $connection/*: Database*/ = new static("{$dsn['phptype']}:host={$dsn['hostspec']}; $port dbname={$dsn['database']}", $dsn['username'], $dsn['password']); if ($dsn['phptype'] == 'pgsql') { $connection->query('SET client_encoding="UTF-8"'); @@ -51,13 +64,7 @@ class Database/**/ extends PDO $connection->setAttribute(PDO::ATTR_TIMEOUT, 5); $mode = defined('SQLITE_JOURNAL_MODE') ? SQLITE_JOURNAL_MODE : 'WAL'; $connection->query("PRAGMA journal_mode=$mode"); - - if(!function_exists('sqliteLower')){ - function sqliteLower($str) { - return mb_strtolower($str, 'UTF-8'); - } - $connection->sqliteCreateFunction('LOWER', 'sqliteLower', 1); - } + $connection->sqliteCreateFunction('LOWER', 'sqliteLower', 1); } $connection->dsn = $dsn; return $connection; @@ -65,7 +72,7 @@ class Database/**/ extends PDO public function executeQuery($query, $values=null) { - $stmt/*: Database_PDOStatement*/ = $this->prepare($query); + $stmt/*: PDOStatement*/ = $this->prepare($query); $stmt->execute($values); $stmt->cache = $stmt->fetchAll(PDO::FETCH_ASSOC); @@ -74,7 +81,7 @@ class Database/**/ extends PDO public function prepareStatement($query) { - return new Database_Statement($query, $this); + return new Statement($query, $this); } // Для совместимости со старым представлением баз данных CIS @@ -83,7 +90,7 @@ class Database/**/ extends PDO */ public function fetchAllArray($query, $values = null) { - $sth/*: Database_PDOStatement*/ = $this->prepare($query); + $sth/*: PDOStatement*/ = $this->prepare($query); $prep = $this->prepareValues($values); $sth->execute($prep); return $sth->fetchAll(PDO::FETCH_ASSOC); @@ -94,7 +101,7 @@ class Database/**/ extends PDO */ public function fetchOneArray($query, $values = null) { - $sth/*: Database_PDOStatement*/ = $this->prepare($query); + $sth/*: PDOStatement*/ = $this->prepare($query); $prep = $this->prepareValues($values); $sth->execute($prep); return $sth->fetch(PDO::FETCH_ASSOC); @@ -170,7 +177,7 @@ class Database/**/ extends PDO } function getIdGenerator() { - return new Database_IdGenerator($this); + return new IdGenerator($this); } /** @@ -183,8 +190,7 @@ class Database/**/ extends PDO return $result['nextval']; } - function close() - { + function close() { return null; } -} +}} diff --git a/src/Database/IdGenerator.php b/src/Database/IdGenerator.php index 045ec86..5ae4664 100644 --- a/src/Database/IdGenerator.php +++ b/src/Database/IdGenerator.php @@ -1,6 +1,9 @@ db->fetchOneArray("SELECT last_insert_rowid() AS nextval"); } - return intval($result['nextval']); + return (int)$result['nextval']; } } diff --git a/src/Database/JsonInstall.php b/src/Database/JsonInstall.php index 078113b..9fc0c2f 100644 --- a/src/Database/JsonInstall.php +++ b/src/Database/JsonInstall.php @@ -1,143 +1,146 @@ db_manager = $db_manager; - } + public function __construct(Manager $db_manager) { + $this->db_manager = $db_manager; + } - function install($dbinit_path, $dbfill_path = null) { - $dbinit_file = file_get_contents($dbinit_path); - if (is_string($dbinit_file)) { - $initActions = json_decode($dbinit_file, true); - if (!$initActions) { - echo "Invalid ".$dbinit_path; - return 0; - } - } else { - echo "No ".$dbinit_path; - return 0; - } + function install($dbinit_path, $dbfill_path = null) { + $dbinit_file = file_get_contents($dbinit_path); + if (is_string($dbinit_file)) { + $initActions = json_decode($dbinit_file, true); + if (!$initActions) { + echo "Invalid ".$dbinit_path; + return 0; + } + } else { + echo "No ".$dbinit_path; + return 0; + } - $this->initDataBase($initActions, $dbinit_path); - if ($dbfill_path) { - $this->fillDataBase($dbfill_path); - } - $this->makeConstraints($initActions); - } + $this->initDataBase($initActions, $dbinit_path); + if ($dbfill_path) { + $this->fillDataBase($dbfill_path); + } + $this->makeConstraints($initActions); + } - function missingTables($tables) { - $actual_tables = $this->db_manager->GetAllTableNames(); - $missingTables = []; - foreach ($tables as $table) { - if (!in_array($table, $actual_tables)) - $missingTables[] = $table; - } - return $missingTables; - } + function missingTables($tables) { + $actual_tables = $this->db_manager->GetAllTableNames(); + $missingTables = []; + foreach ($tables as $table) { + if (!in_array($table, $actual_tables)) + $missingTables[] = $table; + } + return $missingTables; + } - //Создать таблицы - function initDataBase($initActions/*: array*/, $dbinit_path) { - $pg = $this->db_manager->db->isPostgres(); - if (!$pg) { - $refs = []; - //В sqlite нет alter reference. Референсы надо создавать при создании таблицы. - foreach ($initActions as $action) { - if ($action["type"] == "alterReference") { - if (!isset($refs[$action["table"]])) - $refs[$action["table"]] = []; - $refs[$action["table"]][]=$action;//добавить к списку референсов для таблицы - } - } - } + //Создать таблицы + function initDataBase($initActions/*: array*/, $dbinit_path) { + $pg = $this->db_manager->db->isPostgres(); + if (!$pg) { + $refs = []; + //В sqlite нет alter reference. Референсы надо создавать при создании таблицы. + foreach ($initActions as $action) { + if ($action["type"] == "alterReference") { + if (!isset($refs[$action["table"]])) + $refs[$action["table"]] = []; + $refs[$action["table"]][]=$action;//добавить к списку референсов для таблицы + } + } + } - foreach ($initActions as $action) { - if (!$pg) { - if ($action["type"] == "createTable") { - $table_name = $action["table_name"]; - if (isset($refs[$table_name])) { - foreach ($refs[$table_name] as $value) { - $action['fields'][$value['column']]['references'] = - $value['refTable']."(".$value['refColumn'].")"; - } - } + foreach ($initActions as $action) { + if (!$pg) { + if ($action["type"] == "createTable") { + $table_name = $action["table_name"]; + if (isset($refs[$table_name])) { + foreach ($refs[$table_name] as $value) { + $action['fields'][$value['column']]['references'] = + $value['refTable']."(".$value['refColumn'].")"; + } + } - } - } - if ($action["type"] != "alterReference") { - $this->db_manager->ExecuteAction($action, $dbinit_path); - } - } + } + } + if ($action["type"] != "alterReference") { + $this->db_manager->ExecuteAction($action, $dbinit_path); + } + } - //Запомнить все колонки serial - $this->serialColumns = []; - if ($pg) { - foreach ($initActions as $action) { - if ($action["type"] == "createTable") { - foreach ($action["fields"] as $name => $field) { - if ($field["type"]=="serial") { - $this->serialColumns[] = [ + //Запомнить все колонки serial + $this->serialColumns = []; + if ($pg) { + foreach ($initActions as $action) { + if ($action["type"] == "createTable") { + foreach ($action["fields"] as $name => $field) { + if ($field["type"]=="serial") { + $this->serialColumns[] = [ "table"=>$action["table_name"], - "column"=>$name + "column"=>$name ]; - } - } - } - } - } - } + } + } + } + } + } + } - //Заполнить данными - function fillDataBase($dbfill_file_path) { - $dbfill_file = file_get_contents($dbfill_file_path); - if (is_string($dbfill_file)) { - $actions = json_decode($dbfill_file,true); - if ($actions) { - - //Проверка что упоминаемые в списке действий таблицы уже есть в базе - $affected_tables = []; - foreach ($actions as $action) { - if ($action["table_name"]) { - $affected_tables[$action["table_name"]] = 1; + //Заполнить данными + function fillDataBase($dbfill_file_path) { + $dbfill_file = file_get_contents($dbfill_file_path); + if (is_string($dbfill_file)) { + $actions = json_decode($dbfill_file,true); + if ($actions) { + + //Проверка что упоминаемые в списке действий таблицы уже есть в базе + $affected_tables = []; + foreach ($actions as $action) { + if ($action["table_name"]) { + $affected_tables[$action["table_name"]] = 1; } } - $missing = $this->missingTables(array_keys($affected_tables)); - if (!empty($missing)) { - echo "dbfill error. Missing tables: ".implode(" ", $missing); - return; - } - - //Выполнение действий - foreach ($actions as $action) { - $this->db_manager->ExecuteAction($action, $dbfill_file_path); - } - } else { - echo "Invalid dbfill.json"; - } - } else { - echo "No dbfill.json"; - } - } - - //Обновить ключи serial и создать ограничения - function makeConstraints($initActions) { - $pg = $this->db_manager->db->isPostgres(); - if ($pg) { - foreach ($this->serialColumns as $serialColumn) { - $this->db_manager->UpdateSerial($serialColumn["table"], $serialColumn["column"]); - } - - - foreach ($initActions as $action) { - if ($action["type"] == "alterReference") { - $this->db_manager->ExecuteAction($action); + $missing = $this->missingTables(array_keys($affected_tables)); + if (!empty($missing)) { + echo "dbfill error. Missing tables: ".implode(" ", $missing); + return; } - } - } - } + + //Выполнение действий + foreach ($actions as $action) { + $this->db_manager->ExecuteAction($action, $dbfill_file_path); + } + } else { + echo "Invalid dbfill.json"; + } + } else { + echo "No dbfill.json"; + } + } + + //Обновить ключи serial и создать ограничения + function makeConstraints($initActions) { + $pg = $this->db_manager->db->isPostgres(); + if ($pg) { + foreach ($this->serialColumns as $serialColumn) { + $this->db_manager->UpdateSerial($serialColumn["table"], $serialColumn["column"]); + } + + + foreach ($initActions as $action) { + if ($action["type"] == "alterReference") { + $this->db_manager->ExecuteAction($action); + } + } + } + } } \ No newline at end of file diff --git a/src/Database/Manager.php b/src/Database/Manager.php index f5bdaf0..669b570 100644 --- a/src/Database/Manager.php +++ b/src/Database/Manager.php @@ -1,221 +1,255 @@ -db = $db; - } + public function __construct(Database $db) + { + $this->db = $db; + } - public function ExecuteAction($action/*: array*/, $db_file = "") { - switch($action["type"]) { - case "dropTable": - $this->DropTableQuery($action["table_name"], true); - break; - case "createTable": - $constraints = isset($action["constraints"]) ? $action["constraints"] : NULL; - $this->CreateTableQuery($action["table_name"], $action["fields"], $constraints); - break; - case "addColumn": - $this->AddColumn($action["table_name"], $action["column_name"], $action["field"]); - break; - case "insert": - $this->db->insertQuery($action["table_name"], $action["values"]); - break; - case "alterReference": - $this->AlterReference($action["table"], $action["column"], $action["refTable"], $action["refColumn"]); - break; - case "renameColumn": - $this->RenameColumn($action["table"], $action["old_name"], $action["new_name"]); + public function ExecuteAction($action/*: array*/, $db_file = "") + { + switch($action["type"]) { + case "dropTable": + $this->DropTableQuery($action["table_name"], true); break; - case "executeFile": + case "createTable": + $constraints = isset($action["constraints"]) ? $action["constraints"] : null; + $this->CreateTableQuery($action["table_name"], $action["fields"], $constraints); + break; + case "addColumn": + $this->AddColumn($action["table_name"], $action["column_name"], $action["field"]); + break; + case "insert": + $this->db->insertQuery($action["table_name"], $action["values"]); + break; + case "alterReference": + $this->AlterReference($action["table"], $action["column"], $action["refTable"], $action["refColumn"]); + break; + case "renameColumn": + $this->RenameColumn($action["table"], $action["old_name"], $action["new_name"]); + break; + case "createView": + $this->recreateView($action["view"], $action["select"]); + break; + case "executeFile": if ($this->db->isPostgres() && isset($action["pgsql"])) { - $file = $action["pgsql"]; + $file = $action["pgsql"]; } else { - $file = $action["source"]; + $file = $action["source"]; } - $stmtList = Tools_SQLStatementExtractor::extractFile(Path::join(dirname($db_file), $file)); - foreach($stmtList as $stmt) { + $stmtList = SQLStatementExtractor::extractFile(Path::join(dirname($db_file), $file)); + foreach ($stmtList as $stmt) { $this->db->executeQuery($stmt); } break; - default: - throw new Exception("unknown action ". $action["type"] . PHP_EOL); - } - } + default: + throw new Exception("unknown action ". $action["type"] . PHP_EOL); + } + } - public function DropTableQuery($table, $cascade=false) { - $statement = "DROP TABLE IF EXISTS ".$table; - if ($this->db->isPostgres()&&$cascade) { - $statement = $statement." CASCADE"; - } - $this->db->query($statement); - } + //Дропает и создаёт SQL VIEW + public function recreateView($viewName, $selectStatement) + { + $this->db->query("DROP VIEW ".$viewName); + $this->db->query("CREATE VIEW ".$viewName." AS ".$selectStatement); + } - public function AlterReference($table,$column,$refTable,$refColumn) { - $this->db->query("ALTER TABLE ".$table." ADD CONSTRAINT ".$table."_".$column."fk"." FOREIGN KEY (".$column.") REFERENCES ".$refTable." (".$refColumn.")"); - } + public function DropTableQuery($table, $cascade=false) + { + $statement = "DROP TABLE IF EXISTS ".$table; + if ($this->db->isPostgres()&&$cascade) { + $statement = $statement." CASCADE"; + } + $this->db->query($statement); + } - //Извлечение информации о полях таблицы - public function TableInfo($table) { - $pg = $this->db->isPostgres(); - if ($pg) { - throw new Exception("Not implemented for postgres"); - } else { - $results = $this->db->fetchAllArray("PRAGMA table_info(".$table.");"); - if (empty($results)) { - return null; + public function AlterReference($table, $column, $refTable, $refColumn) + { + $this->db->query("ALTER TABLE ".$table." ADD CONSTRAINT ".$table."_".$column."fk"." FOREIGN KEY (".$column.") REFERENCES ".$refTable." (".$refColumn.")"); + } + + //Извлечение информации о полях таблицы + public function TableInfo($table) + { + $pg = $this->db->isPostgres(); + if ($pg) { + throw new Exception("Not implemented for postgres"); + } else { + $results = $this->db->fetchAllArray("PRAGMA table_info(".$table.");"); + if (empty($results)) { + return null; } - $fields = []; - foreach ($results as $result) { - $fields[$result["name"]] = [ - "type"=> $result["type"], - "not_null"=> boolval($result["notnull"]), - "constraint"=> ((boolean) $result["pk"]) ? "PRIMARY KEY" : null + $fields = []; + foreach ($results as $result) { + $fields[$result["name"]] = [ + "type"=> $result["type"], + "not_null"=> boolval($result["notnull"]), + "constraint"=> ((bool) $result["pk"]) ? "PRIMARY KEY" : null ]; - } - return $fields; - } - } + } + return $fields; + } + } - public function RenameColumn($table, $old_name, $new_name) { - $pg = $this->db->isPostgres(); - if ($pg) { - $this->db->query("ALTER TABLE ".$table." RENAME COLUMN ".$old_name." TO ".$new_name); - } else { - $tmp_table = "tmp_" . $table; - $this->DropTableQuery($tmp_table); - $table_info = $this->TableInfo($table); + public function RenameColumn($table, $old_name, $new_name) + { + $pg = $this->db->isPostgres(); + if ($pg) { + $this->db->query("ALTER TABLE ".$table." RENAME COLUMN ".$old_name." TO ".$new_name); + } else { + $tmp_table = "tmp_" . $table; + $this->DropTableQuery($tmp_table); + $table_info = $this->TableInfo($table); - if (isset($table_info[$new_name])) { - return; + if (isset($table_info[$new_name])) { + return; } - $data/*: array*/ = $this->DumpTable($table); + $data/*: array*/ = $this->DumpTable($table); - $this->db->query("ALTER TABLE ".$table." RENAME TO ".$tmp_table.";"); - $table_info[$new_name] = $table_info[$old_name]; - unset($table_info[$old_name]); - $this->CreateTableQuery($table,$table_info,null); + $this->db->query("ALTER TABLE ".$table." RENAME TO ".$tmp_table.";"); + $table_info[$new_name] = $table_info[$old_name]; + unset($table_info[$old_name]); + $this->CreateTableQuery($table, $table_info, null); - foreach ($data as $row) { - $values = $row['values']; - $values[$new_name] = $values[$old_name]; - unset($values[$old_name]); - $this->db->insertQuery($table, $values); - } - $this->DropTableQuery($tmp_table); - } - } + foreach ($data as $row) { + $values = $row['values']; + $values[$new_name] = $values[$old_name]; + unset($values[$old_name]); + $this->db->insertQuery($table, $values); + } + $this->DropTableQuery($tmp_table); + } + } - //Обновление ключа serial после ручной вставки - public function UpdateSerial($table,$column) { - $this->db->query("SELECT setval(pg_get_serial_sequence('".$table."', '".$column."'), coalesce(max(".$column."),0) + 1, false) FROM ".$table); - } + //Обновление ключа serial после ручной вставки + public function UpdateSerial($table, $column) + { + $this->db->query("SELECT setval(pg_get_serial_sequence('".$table."', '".$column."'), coalesce(max(".$column."),0) + 1, false) FROM ".$table); + } - public function Column_Definition($name,$data,$pg){ - $constraint = isset($data['constraint'])?" ".$data['constraint']:""; - $references = ""; - if (isset($data['references'])) { - $references = " REFERENCES ".$data['references']; - } - if (isset($data["not_null"]) && $data["not_null"]) - $constraint .=" NOT NULL"; - $type = $data['type']; - if (!$pg) { - if (strtolower($type)=="serial") - $type = "integer"; - //if (strtolower($type)=="boolean") - // $type = "integer"; - } - return $name." ".$type.$references.$constraint; - } + public function Column_Definition($name, $data, $pg) + { + $constraint = isset($data['constraint']) ? " ".$data['constraint'] : ""; + $references = ""; + if (isset($data['references'])) { + $references = " REFERENCES ".$data['references']; + } + if (isset($data["not_null"]) && $data["not_null"]) { + $constraint .=" NOT NULL"; + } + $type = $data['type']; + if (!$pg) { + if (strtolower($type)=="serial") { + $type = "integer"; + } + //if (strtolower($type)=="boolean") + // $type = "integer"; + } + return $name." ".$type.$references.$constraint; + } - public function AddColumn($table_name,$column_name,$field){ - $pg = $this->db->isPostgres(); - $q = "ALTER TABLE ".$table_name." ADD COLUMN ". - $this->Column_Definition($column_name, $field, $pg); - $this->db->query($q); - } + public function AddColumn($table_name, $column_name, $field) + { + $pg = $this->db->isPostgres(); + $q = "ALTER TABLE ".$table_name." ADD COLUMN ". + $this->Column_Definition($column_name, $field, $pg); + $this->db->query($q); + } - function getConstraintDef($c/*: array*/) { + public function getConstraintDef($c/*: array*/) + { if ($c['type'] == 'unique') { return "UNIQUE(" . implode(", ", $c['fields']) . ")"; } return ""; } - //CreateTableQuery('users',['id'=>['type'=>'integer','constraint'=>'PRIMARY KEY']]) - public function CreateTableQuery($table, $fields, $constraints) { - $pg = $this->db->isPostgres(); - if ($constraints) { + //CreateTableQuery('users',['id'=>['type'=>'integer','constraint'=>'PRIMARY KEY']]) + public function CreateTableQuery($table, $fields, $constraints) + { + $pg = $this->db->isPostgres(); + if ($constraints) { if (is_array($constraints)) { $constraints = $this->getConstraintDef($constraints); } - $constraints = ", " . $constraints; + $constraints = ", " . $constraints; } - $statement = "CREATE TABLE $table (" . implode(",", - array_map(function($name,$data) use ($pg) { - return $this->Column_Definition($name,$data,$pg); - }, array_keys($fields), array_values($fields)) - ) . " " . $constraints . ")"; - $this->db->query($statement); - } + $statement = "CREATE TABLE $table (" . implode( + ",", + array_map(function ($name, $data) use ($pg) { + return $this->Column_Definition($name, $data, $pg); + }, array_keys($fields), array_values($fields)) + ) . " " . $constraints . ")"; + $this->db->query($statement); + } - public function DumpTable($table_name) { - $pg = $this->db->isPostgres(); + public function DumpTable($table_name) + { + $pg = $this->db->isPostgres(); - $result/*: array*/ = array(); - $data/*: array*/ = $this->db->fetchAllArray("SELECT * FROM ".$table_name.";"); + $result/*: array*/ = array(); + $data/*: array*/ = $this->db->fetchAllArray("SELECT * FROM ".$table_name.";"); - if (!$pg) { - $table_fields = $this->TableInfo($table_name); - foreach ($table_fields as $name => $value) { - $type = strtolower($value['type']); - if ($type == "boolean") { - foreach ($data as &$row) { + if (!$pg) { + $table_fields = $this->TableInfo($table_name); + foreach ($table_fields as $name => $value) { + $type = strtolower($value['type']); + if ($type == "boolean") { + foreach ($data as &$row) { $row/*: array*/ = $row; - if (isset($row[$name])) { - $row[$name] = boolval($row[$name]); - } - } - } - } - } - foreach ($data as $r) { - $result[] = array( - "type" => "insert", - "table_name" => $table_name, - "values" => $r + if (isset($row[$name])) { + $row[$name] = boolval($row[$name]); + } + } + } + } + } + foreach ($data as $r) { + $result[] = array( + "type" => "insert", + "table_name" => $table_name, + "values" => $r ); - } - return $result; - } - - public function GetAllTableNames() { - $result = []; - if ($this->db->isPostgres()) { - $query = "SELECT table_name as name FROM information_schema.tables WHERE table_schema='public'"; - } else { - $query = "SELECT * FROM sqlite_master WHERE type='table'"; } - $tables = $this->db->fetchAllArray($query); - foreach ($tables as $table) { - $result[] = $table['name']; - } - return $result; - } + return $result; + } - public function DumpInserts() { - $table_names = $this->GetAllTableNames(); - $result = array(); - foreach ($table_names as $table_name) { - $result = array_merge($result, $this->DumpTable($table_name)); - } - return $result; - } -} \ No newline at end of file + public function GetAllTableNames() + { + $result = []; + if ($this->db->isPostgres()) { + $query = "SELECT table_name as name FROM information_schema.tables WHERE table_schema='public'"; + } else { + $query = "SELECT * FROM sqlite_master WHERE type='table'"; + } + $tables = $this->db->fetchAllArray($query); + foreach ($tables as $table) { + $result[] = $table['name']; + } + return $result; + } + + public function DumpInserts() + { + $table_names = $this->GetAllTableNames(); + $result = array(); + foreach ($table_names as $table_name) { + $result = array_merge($result, $this->DumpTable($table_name)); + } + return $result; + } +} diff --git a/src/Database/PDOStatement.php b/src/Database/PDOStatement.php index 11ccdd9..1ae56df 100644 --- a/src/Database/PDOStatement.php +++ b/src/Database/PDOStatement.php @@ -1,35 +1,42 @@ cursorPos = 0; } - public function seek($rownum) { - if ($rownum < 0) { - return false; - } - - // PostgreSQL rows start w/ 0, but this works, because we are - // looking to move the position _before_ the next desired position - $this->cursorPos = $rownum; - return true; - } + public function seek($rownum) { + if ($rownum < 0) { + return false; + } + + // PostgreSQL rows start w/ 0, but this works, because we are + // looking to move the position _before_ the next desired position + $this->cursorPos = $rownum; + return true; + } function valid() { - return true; + return true; } @@ -42,7 +49,7 @@ class Database_PDOStatement extends PDOStatement implements IteratorAggregate if ($this->getRecordCount() > $this->cursorPos) { if (!isset($this->cache[$this->cursorPos])) { $this->cache[$this->cursorPos] = $this->fetch(PDO::FETCH_ASSOC); - } + } $this->fields = $this->cache[$this->cursorPos]; $this->cursorPos++; @@ -67,7 +74,7 @@ class Database_PDOStatement extends PDOStatement implements IteratorAggregate function getInt($name) { if (!$this->fields) { - throw new Error('no fields'); + throw new \Exception('no fields'); } return (int)$this->fields[$name]; } @@ -89,13 +96,13 @@ class Database_PDOStatement extends PDOStatement implements IteratorAggregate } function getArray($name) { - return Tools_String::strToArray($this->fields[$name]); + return StringUtil::strToArray($this->fields[$name]); } function getRecordCount() { return count($this->cache); } - + function execute($args = null) { $result = parent::execute($args); return $result; diff --git a/src/Database/Statement.php b/src/Database/Statement.php index ae42fc7..38652e5 100644 --- a/src/Database/Statement.php +++ b/src/Database/Statement.php @@ -3,7 +3,11 @@ /** * Класс оболочка для PDOStatement для замены Creole */ -class Database_Statement +namespace ctiso\Database; +use PDO, + ctiso\Database; + +class Statement { protected $limit = null; protected $offset = null; @@ -41,7 +45,7 @@ class Database_Statement if ($this->limit) { $this->query .= " LIMIT {$this->limit} OFFSET {$this->offset}"; } - $stmt/*: Database_PDOStatement*/ = $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 8e6c970..eebd752 100644 --- a/src/Database/StatementIterator.php +++ b/src/Database/StatementIterator.php @@ -1,46 +1,49 @@ result = $rs; - $this->row_count = $rs->getRecordCount(); + $this->row_count = $rs->getRecordCount(); } - - function rewind() { + + function rewind() { $this->pos = 0; } - + function valid() { - return ($this->pos < $this->row_count); + return ($this->pos < $this->row_count); } - + function key() { return $this->pos; } - + function current() { if (!isset($this->result->cache[$this->pos])) { $this->result->cache[$this->pos] = $this->result->fetch(PDO::FETCH_ASSOC); - } + } return $this->result->cache[$this->pos]; } - + function next() { $this->pos++; } function seek($index) { - $this->pos = $index; + $this->pos = $index; } function count() { - return $this->row_count; + return $this->row_count; } } diff --git a/src/Excel/DataTime.php b/src/Excel/DataTime.php index 0536cbd..877546d 100644 --- a/src/Excel/DataTime.php +++ b/src/Excel/DataTime.php @@ -1,12 +1,14 @@ value = intval($value); + $this->value = (int)$value; } function getString() diff --git a/src/Excel/Document.php b/src/Excel/Document.php index 4600fad..dff1c3b 100644 --- a/src/Excel/Document.php +++ b/src/Excel/Document.php @@ -3,7 +3,11 @@ /** * Документ */ -class Excel_Document { +namespace ctiso\Excel; +use XMLWriter, + Exception; + +class Document { static $ns = "urn:schemas-microsoft-com:office:spreadsheet"; private $table = array (); protected $styles = array(); @@ -88,7 +92,7 @@ class Excel_Document { $this->createStyles($doc); foreach ($this->table as $table) { - if ($table instanceof Excel_Table) { + if ($table instanceof Table) { $table->createTable($doc); } else { $table_data = call_user_func($table); diff --git a/src/Excel/Number.php b/src/Excel/Number.php index dfc220a..8ed12b4 100644 --- a/src/Excel/Number.php +++ b/src/Excel/Number.php @@ -1,6 +1,8 @@ name = "Page " . intval(self::$index ++); + $this->name = "Page " . ((int)self::$index ++); } /** @@ -230,7 +235,7 @@ class Excel_Table } else { $doc->writeAttribute('ss:Type', "Number"); } - $doc->writeCData($this->encode($value)); + $doc->writeCdata($this->encode($value)); } $doc->endElement(); $doc->endElement(); @@ -308,4 +313,3 @@ class Excel_Table $doc->endElement(); } } - diff --git a/src/File.php b/src/File.php index 27ca254..c523cf6 100644 --- a/src/File.php +++ b/src/File.php @@ -1,8 +1,11 @@ processor = $processor; + $this->user = $user; } /** @@ -20,8 +26,7 @@ class Filter_ActionAccess */ function checkAction($action) { // Импликация !! http://ru.wikipedia.org/wiki/Импликация - $name = $this->name; - return (!isset($this->access[$name][$action]) || in_array(Filter_UserAccess::$access, $this->access[$name][$action])); + return (!isset($this->access[$action]) || in_array($this->user->access, $this->access[$action])); } function execute(HttpRequest $request) { diff --git a/src/Filter/ActionLogger.php b/src/Filter/ActionLogger.php index 5a2cbab..b2b02ff 100644 --- a/src/Filter/ActionLogger.php +++ b/src/Filter/ActionLogger.php @@ -1,21 +1,34 @@ processor = $processor; - $this->file = fopen(Shortcut::getUrl('access.log'), "a"); + $this->user = $user; + + $file = fopen($logPath, "a"); + if (is_resource($file)) { + $this->file = $file; + } else { + throw new \Exception('Ошибка открытия файла ' . $logPath); + } } function execute(HttpRequest $request) { $action = $request->getAction(); if(in_array($action, $this->before)) { - $line = ['time' => time(), 'user' => Filter_UserAccess::$name, 'sid' => session_id(), 'query' => array_merge($_POST, $_GET)]; + $line = ['time' => time(), 'user' => $this->user->getName(), 'sid' => session_id(), 'query' => array_merge($_POST, $_GET)]; fwrite($this->file, json_encode($line) . "\n"); } return $this->processor->execute($request); diff --git a/src/Filter/Authorization.php b/src/Filter/Authorization.php index 5afd556..0df3e6f 100644 --- a/src/Filter/Authorization.php +++ b/src/Filter/Authorization.php @@ -1,8 +1,15 @@ group = $group; + } static function isLogged($group = 'access') { // echo session_status(); @@ -16,25 +23,23 @@ class Filter_Authorization { // UserAccess::getUserById($_SESSION ['access']); // Поиск по идентификатору return true; } else { - return false; + return false; } } return false; } - static function enter($id, $group = 'access') - { + static function enter($id, $group = 'access') { // $db->executeQuery("UPDATE visitor SET sid = '' WHERE id_visitor = " . $result->getInt('id_user')); // session_register("access"); // session_register("time"); -// $_SESSION ["group"] = $result->getInt('access'); - $_SESSION [$group] = $id; // id_user + $_SESSION [$group] = $id; $_SESSION [self::SESSION_BROWSER_SIGN_KEYNAME] = self::getBrowserSign(); - $_SESSION ["time"] = time(); + $_SESSION ["time"] = time(); } - private static function getBrowserSign() + static function getBrowserSign() { $rawSign = self::SESSION_BROWSER_SIGN_SECRET; // $signParts = array('HTTP_USER_AGENT', 'HTTP_ACCEPT_ENCODING'); @@ -46,7 +51,7 @@ class Filter_Authorization { return md5($rawSign); } - static function logout() { + function logout() { session_destroy(); } } diff --git a/src/Filter/Filter.php b/src/Filter/Filter.php index 645f624..156d4e0 100644 --- a/src/Filter/Filter.php +++ b/src/Filter/Filter.php @@ -3,10 +3,15 @@ /** * Попытка реализовать фильтр для запросов */ -class Filter_Filter +namespace ctiso\Filter; + +use ctiso\Controller\Action, + ctiso\HttpRequest; + +class Filter { public $processor; - public function __construct($processor/*: Controller_Action*/) + public function __construct($processor/*: Action*/) { $this->processor = $processor; } @@ -16,7 +21,7 @@ class Filter_Filter return $this->processor->execute($request); } - public function getView($name, $class = 'View_Top') + public function getView($name, $class = 'ctiso\\View\\Top') { return $this->processor->getView($name, $class); } diff --git a/src/Filter/Login.php b/src/Filter/Login.php index 6d724bc..a6591bd 100644 --- a/src/Filter/Login.php +++ b/src/Filter/Login.php @@ -8,7 +8,17 @@ */ // В класс авторизации передавать обьект для управления пользователем // Вынести в отдельный файл -class Filter_Login extends Filter_Filter +namespace ctiso\Filter; +use ctiso\Filter\Filter, + ctiso\HttpRequest, + ctiso\Settings, + ctiso\Registry, + ctiso\Database, + ctiso\Role\User, + ctiso\Collection, + ctiso\Path; + +class Login extends Filter { const SESSION_BROWSER_SIGN_SECRET = '@w3dsju45Msk#'; const SESSION_BROWSER_SIGN_KEYNAME = 'session.app.browser.sign'; @@ -16,28 +26,34 @@ class Filter_Login extends Filter_Filter const AUTH_LAST_ATTEMPT_TIMER = 600; public $mode = 'ajax'; public $user; + public $role; + public $config; + + function __construct($processor, User $role, Registry $config) { + parent::__construct($processor); + $this->role = $role; + $this->config = $config; + } /** * Проверка авторизации + * @param HttpRequest $request * @return Boolean Авторизовани пользователь или нет */ public function isLoggin(HttpRequest $request) { // Авторизация session_start(); - $db = $this->getConnection(); - Filter_UserAccess::setUp($db); // Соединение - switch ($request->getAction()) { // Авторизация по постоянному паролю case 'login': $login = $request->get('login'); $password = $request->get('password'); - $result = Filter_UserAccess::getUserByLogin($login); // Поиск по логину + $result = $this->role->getUserByLogin($login); // Поиск по логину if ($result) { - $userPassword = $result->getString('password'); - if (Filter_UserAccess::$access == 'site_root' && defined('PARENT_PATH')) { + $userPassword = $this->role->getUserPassword($result); + if ($this->role->access == 'site_root' && defined('PARENT_PATH')) { $s = new Settings(PARENT_PATH . '/settings.json'); $s->read(); $dsn = $s->readKey(array('system', 'dsn')); @@ -51,31 +67,24 @@ class Filter_Login extends Filter_Filter $request->set('lastupdate', true); return false; }*/ - // Проверка на количества попыток авторизации - $lastAttempt = $db->fetchOneArray( - "SELECT trie_count, trie_time FROM users WHERE login = :login", ['login' => $request->get('login')]); - if ($lastAttempt['trie_count'] >= self::AUTH_MAX_ATTEMPT /*&& time() - $lastAttempt['trie_time'] < self::AUTH_LAST_ATTEMPT_TIMER*/) { - if (time() - $lastAttempt['trie_time'] < self::AUTH_LAST_ATTEMPT_TIMER) { + // Проверка на количества попыток авторизации + $lastAttempt = $result; + + if ($lastAttempt->get('trie_count') >= self::AUTH_MAX_ATTEMPT /*&& time() - $lastAttempt['trie_time'] < self::AUTH_LAST_ATTEMPT_TIMER*/) { + if (time() - $lastAttempt->get('trie_time') < self::AUTH_LAST_ATTEMPT_TIMER) { $request->set('timeout_error', true); break; } else { - $db->executeQuery( - "UPDATE users SET trie_count = :count WHERE login = :login", - ['count' => 0, 'login' => $request->get('login')] - ); + $this->role->resetTries($request->get('login')); } } // Извлечнеие пользователя из родительской CMS, для проверки пароля if (md5($password) == $userPassword) { // password - $this->enter($db, $result); + $this->enter($result); return true; } else { // Обновление количества неудачных попыток входа - $user = $db->fetchOneArray("SELECT id_user, trie_count FROM users WHERE login = :login", ['login' => $login]); - $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']] - ); + $this->role->updateTries($login); } } $request->set('error', true); @@ -88,11 +97,11 @@ class Filter_Login extends Filter_Filter case 'enter': $login = $request->get('login'); $password = $request->get('sid'); - $result = Filter_UserAccess::getUserByLogin($login); // Поиск по логину + $result = $this->role->getUserByLogin($login); // Поиск по логину if ($result) { $temp = md5($result->getString('password') . $result->getString('login') . $result->getString('sid')); - if ($password == $temp) { - $this->enter($db, $result); + if ($password == $temp) { + $this->enter($result); return true; } } @@ -103,7 +112,7 @@ class Filter_Login extends Filter_Filter // Если $hash не совпадает $_SESSION['hash'] то удаляем сессию if (isset($_SESSION ['access']) && isset($_SESSION[self::SESSION_BROWSER_SIGN_KEYNAME])) { if ($hash == $_SESSION[self::SESSION_BROWSER_SIGN_KEYNAME]) { - $this->user = $user = Filter_UserAccess::getUserById($_SESSION['access']); // Поиск по идентификатору + $this->user = $user = $this->role->getUserById($_SESSION['access']); // Поиск по идентификатору if ($user && isset($_SESSION['random']) && ($user->get('sid') == $_SESSION['random'])) { return true; } @@ -116,8 +125,7 @@ class Filter_Login extends Filter_Filter return false; } - private function getBrowserSign() - { + private function getBrowserSign() { $rawSign = self::SESSION_BROWSER_SIGN_SECRET; //$signParts = array('HTTP_USER_AGENT', 'HTTP_ACCEPT_ENCODING'); $signParts = array(); @@ -128,11 +136,11 @@ class Filter_Login extends Filter_Filter return md5($rawSign); } - private function enter($db, $result) + private function enter($result) { $this->user = $result; $random = rand(0, 1024 * 1024); - $db->executeQuery("UPDATE users SET sid = '$random', trie_count = 0 WHERE id_user = " . $result->getInt('id_user')); + $this->role->setSID($random, $result); $_SESSION["group"] = $result->getInt('access'); $_SESSION["access"] = $result->getInt('id_user'); // id_user @@ -149,7 +157,6 @@ class Filter_Login extends Filter_Filter $result = array(); $result['fullname'] = $this->user->getString('patronymic') . " " . $this->user->getString('firstname'); $result['email'] = $this->user->getString('email'); - $result['site'] = 187; $result['hash'] = sha1(self::SESSION_BROWSER_SIGN_SECRET . $this->user->getString('email')); return json_encode($result); } else { @@ -191,13 +198,12 @@ class Filter_Login extends Filter_Filter /* --------------------- * Проверка на попадание реквеста в белый список */ - public function requestIsWhite(Collection $request) { $module = $request->get('module'); $action = $request->get('action'); - $moduleDir = explode('_',$module)[0]; - $file = Path::join(CMS_PATH, 'modules', $moduleDir, 'filters', 'white.json'); + $moduleDir = explode('\\',$module)[0]; + $file = Path::join($this->config->get('system', 'path'), 'modules', $moduleDir, 'filters', 'white.json'); if (file_exists($file)) { $whiteList = json_decode(file_get_contents($file), true); diff --git a/src/Filter/UserAccess.php b/src/Filter/UserAccess.php deleted file mode 100644 index fbf97b4..0000000 --- a/src/Filter/UserAccess.php +++ /dev/null @@ -1,69 +0,0 @@ -executeQuery(); - if ($result->next()) { - self::$access = $GROUPS[$result->getString('access')]; - self::$name = $result->getString('login'); - self::$id = $result->getInt('id_user'); - self::$password = $result->getString('password'); - self::$fullname = implode(' ', array( - $result->getString('surname'), - $result->getString('firstname'), - $result->getString('patronymic'))); - return $result; - } - return null; - } - - public static function getUserByLogin($login) - { - $stmt = self::$db->prepareStatement("SELECT * FROM users WHERE login = ?"); - $stmt->setString(1, $login); - $result = self::getUserByQuery($stmt); - if ($result) { - $time = time(); - $id = self::$id; - self::$db->executeQuery("UPDATE users SET lasttime = $time WHERE id_user = $id"); // Время входа - } - return $result; - } - - public static function getUserById($id) - { - $stmt = self::$db->prepareStatement("SELECT * FROM users WHERE id_user = ?"); - $stmt->setInt(1, $_SESSION ['access']); - $result = self::getUserByQuery($stmt); - if ($result) { - $lasttime = $result->getInt('lasttime'); - $time = time(); - if ($time - $lasttime > self::LIFE_TIME) return null; // Вышло время сессии - $id = self::$id; - // self::$db->executeQuery("UPDATE users SET lasttime = $time WHERE id_user = $id"); // Время последнего обращения входа - } - return $result; - } -} diff --git a/src/Form/BrowserInput.php b/src/Form/BrowserInput.php new file mode 100644 index 0000000..f6e1e69 --- /dev/null +++ b/src/Form/BrowserInput.php @@ -0,0 +1,6 @@ +value = $value; + $this->checked = $value; + } +} diff --git a/src/Form/Color.php b/src/Form/Color.php index c7c0d2d..17a9caf 100644 --- a/src/Form/Color.php +++ b/src/Form/Color.php @@ -3,6 +3,9 @@ /** * Поле с цветом */ -class Form_Color extends Form_Field +namespace ctiso\Form; +use ctiso\Form\Field; + +class Color extends Field { } \ No newline at end of file diff --git a/src/Form/Date.php b/src/Form/Date.php index 42f8b00..3b1c526 100644 --- a/src/Form/Date.php +++ b/src/Form/Date.php @@ -2,5 +2,8 @@ /** * Поле с датой */ -class Form_Date extends Form_Field { +namespace ctiso\Form; +use ctiso\Form\Field; + +class Date extends Field { } \ No newline at end of file diff --git a/src/Form/DateTime.php b/src/Form/DateTime.php new file mode 100644 index 0000000..4f995fb --- /dev/null +++ b/src/Form/DateTime.php @@ -0,0 +1,7 @@ +value = $value; - $this->checked = $value; - } -} +namespace ctiso\Form; +use ctiso\Form\Field, + ctiso\Form\Select, + ctiso\Form\Input, + ctiso\View\View, + ctiso\Validator\Validator, + ctiso\HttpRequest; -class TQuestionType extends Form_Select -{ - function setValue($value) - { - // Установить selected у options - $this->value = $value; - foreach ($this->options as &$option) { - $option['selected'] = ($option['value'] == $value); - } - } -} - -class TDateTime extends Form_Input { -} - -/** - * Поле для ввода пароля - */ -class TSecret extends Form_Field { -} - -class TUpload extends Form_Field { -} - -class THidden extends Form_Input { - public $hidden = true; -} - -class TComponentBrowserInput extends Form_Input { -} - -// вставка простого html -class Html_Text extends Form_Field { -} /** * Форма для ввода */ -class Form_Form extends View_View { +class Form extends View { public $field = array(); //Поля формы public $fieldsets = array(); //Группы полей (fieldset). Некоторые поля могут не принадлежать никаким группам @@ -72,33 +36,34 @@ class Form_Form extends View_View { public function __construct() { $this->constructor = array( - 'input' => 'Form_Input', - 'inputreq' => 'Form_Input', // input с проверкой на заполненность + 'input' => 'ctiso\\Form\\Input', + // input с проверкой на заполненность + 'inputreq' => 'ctiso\\Form\\Input', - 'date' => 'Form_Date', - 'datereq' => 'Form_Date', - 'datetime' => 'TDateTime', + 'date' => 'ctiso\\Form\\Date', + 'datereq' => 'ctiso\\Form\\Date', + 'datetime' => 'ctiso\\Form\\DateTime', - 'color' => 'Form_Color', - 'textarea' => 'Form_TextArea', - 'text' => 'Form_TextArea', - 'multiselect' => 'Form_SelectMany', -// 'selectmany' => 'TSelectMany', - 'select1' => 'Form_SelectOne', - 'select' => 'Form_SelectOne', - 'questiontype'=> 'TQuestionType', - 'secret' => 'TSecret', - 'upload' => 'TUpload', - 'image' => 'TUpload', - 'checkbox' => 'TCheckbox', - 'checkmany' => 'Form_SelectMany', - 'hidden' => 'THidden', - 'radio' => 'Form_SelectOne', - 'filebrowser' => 'TComponentBrowserInput', - 'documents' => 'TComponentBrowserInput', - 'chooser' => 'Form_Input', - 'select_chooser' => 'Form_SelectOne', - 'html_text' => 'Html_Text' + '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' ); } @@ -131,7 +96,7 @@ class Form_Form extends View_View { $el->hint = $init['hint']; } - $this->field [$init['name']] = $el; + $this->field[$init['name']] = $el; return $el; } @@ -169,7 +134,7 @@ class Form_Form extends View_View { /** * Устанавливает ошибки после проверки */ - function setError(Validator_Validator $validator) + function setError(Validator $validator) { foreach ($validator->getErrorMsg() as $name => $error) { @@ -203,7 +168,7 @@ class Form_Form extends View_View { { foreach ($schema as $key => $conv) { list($value, $type) = $conv; - $this->field [$key]->setValue(call_user_func(array('Primitive', 'from_' . $type), $data->$value)); + $this->field [$key]->setValue(call_user_func(array('ctiso\\Primitive', 'from_' . $type), $data->$value)); } } diff --git a/src/Form/Hidden.php b/src/Form/Hidden.php new file mode 100644 index 0000000..535e21b --- /dev/null +++ b/src/Form/Hidden.php @@ -0,0 +1,8 @@ +db = $db; - $this->registry = $registry; - } - - function create(Form_Select $field, $input) { - if (isset($input['options.resid'])) { - $type = $input['options.resid']; - - $res = new Model_Resources($this->db); - $field->options = $this->optionsArray('id_section', 'title', $res->getSubsections('', $type)); - - } else if (isset($input['options.res'])) { - $type = $input['options.res']; - - $res = new Model_Resources($this->db); - $field->options = $this->optionsArray('path', 'title', $res->getSubsections('', $type)); - - } else if (isset($input['options.all_res'])) { - $type = $input['options.all_res']; - - $res = new Model_Resources($this->db); - $field->options = $this->optionsArray('id_resource', 'subtitle', $res->getAllResource($type)); - - } else if (isset($input['options.db'])) { - list($table, $keyvalue) = explode(":", $input['options.db']); - list($key, $value) = explode(",", $keyvalue); - try { - $query_result = $this->db->executeQuery("SELECT * FROM $table"); - $field->options = $this->optionsDB($key, $value, $query_result); - } catch(Exception $ex) { - $field->options = []; - } - } elseif (isset($input['options.pair'])) { - $field->options = $this->optionsPair($input['options.pair']); - } elseif (isset($input['options.model'])) { - $factory = new Model_Factory($this->db, $this->registry); - $model = $factory->getModel($input['options.model']); - $field->options = $model->getAllAsOptions(); - } else { - $field->options = $input['options']; - } - if (isset($input['default'])) { - array_unshift($field->options, ['value' => 0, 'name' => $input['default']]); - } - - // Ставим корневой каталог в начало списка (скорее всего он будет в конце массива) - if ($field->options) - { - $root_elem = array_pop($field->options); - if ($root_elem['value'] == '/') - array_unshift($field->options, $root_elem); - else - array_push($field->options, $root_elem); - } - } - - public function optionsDB($key, $val, $res) { - $result = array(); - while($res->next()) { - $result[] = array('value' => $res->getInt($key), 'name' => $res->getString($val)); - } - return $result; - } - - public function optionsArray($key, $val, $res) { - $result = array(); - foreach($res as $item) { - $result[] = array('value' => $item->{$key}, 'name' => $item->{$val}); - } - return $result; - } - - public function optionsPair($list, $selected = false) { - $result = array(); - foreach ($list as $key => $value) { - $result [] = array('value' => $key, 'name' => $value, 'selected' => $key == $selected); - } - return $result; - } -} diff --git a/src/Form/QuestionType.php b/src/Form/QuestionType.php new file mode 100644 index 0000000..a2e7ae0 --- /dev/null +++ b/src/Form/QuestionType.php @@ -0,0 +1,16 @@ +value = $value; + foreach ($this->options as &$option) { + $option['selected'] = ($option['value'] == $value); + } + } +} diff --git a/src/Form/Secret.php b/src/Form/Secret.php new file mode 100644 index 0000000..ce0175a --- /dev/null +++ b/src/Form/Secret.php @@ -0,0 +1,10 @@ +value = $value; diff --git a/src/Form/Upload.php b/src/Form/Upload.php new file mode 100644 index 0000000..7cd38b8 --- /dev/null +++ b/src/Form/Upload.php @@ -0,0 +1,7 @@ +params); $i++) { + $count = count($this->params); + for($i = 0, $j = 0; $i < $count; $i++) { if ($this->params[$i] == __) { $result [] = $params[$j]; $j++; @@ -68,7 +71,7 @@ class __partial { /** * Композиция функций */ -class __compose { +class compose { protected $fns; function __construct($list) { $this->fns = array_reverse($list); @@ -77,7 +80,8 @@ class __compose { function apply () { $params = func_get_args (); $result = call_user_func_array($this->fns[0], $params); - for ($i = 1; $i < count($this->fns); $i++) { + $count = count($this->fns); + for ($i = 1; $i < $count; $i++) { $result = call_user_func($this->fns[$i], $result); } return $result; @@ -86,8 +90,8 @@ class __compose { class Functions { - static function partial() { - $closure = new __partial(func_get_args()); + static function partial($_rest) { + $closure = new partial(func_get_args()); return array($closure, 'apply'); } @@ -97,30 +101,30 @@ class Functions { * @param mixed $a * @param mixed $b * - * @return array[int]mixed + * @return mixed */ - static function compose() { - $closure = new __compose(func_get_args()); + static function compose($_rest) { + $closure = new compose(func_get_args()); return array($closure, 'apply'); } /** * Карирование справа * - * @return array[int]mixed + * @return mixed */ static function rcurry($_rest) { - $closure = new __right(func_get_args ()); + $closure = new right(func_get_args ()); return array($closure, 'apply'); } /** * Карирование слева * - * @return array[int]mixed + * @return mixed */ static function lcurry($_rest) { - $closure = new __left(func_get_args ()); + $closure = new left(func_get_args ()); return array($closure, 'apply'); } @@ -129,7 +133,7 @@ class Functions { * @param mixed $pred Условие по которому разделяется массив * @param array $lst * - * @return array[int]mixed + * @return mixed */ static function partition($pred, $lst) { $left = array (); @@ -222,7 +226,7 @@ class Functions { * * @return mixed */ - static function key_values($key, /*array|ArrayIterator*/ $array) { + static function key_values($key, $array/*: array|ArrayIterator*/) { $result = array(); foreach($array as $item) { @@ -231,7 +235,7 @@ class Functions { return $result; } - static function key_values_object($key, /*array|ArrayIterator*/ $array) { + static function key_values_object($key, $array/*: array|ArrayIterator*/) { $result = array(); foreach($array as $item) { @@ -306,7 +310,8 @@ class Functions { assert(is_int($length)); $result = array(); - for($i = 0; $i < count($array); $i += $length) { + $count = count($array); + for($i = 0; $i < $count; $i += $length) { $result [] = array_slice($array, $i, $length); } return $result; @@ -324,19 +329,20 @@ class Functions { /** * Поиск элемента в массиве - * @param function $cb сравнение с элементом массива - * @param array $hs массив в котором ищется значение + * @param mixed $cb сравнение с элементом массива + * @param Array $hs массив в котором ищется значение * * @return int|string ключ найденого элемента в массиве */ static function array_usearch($cb, array $hs, $strict = false) { foreach($hs as $key => $value) if (call_user_func_array($cb, array($value, $key, $strict))) return $key; + return null; } /** * Выбирает все сроки из таблицы с уникальными значениями ключа - * @param $name Имя ключа - * @param $table Двухмерный массив + * @param string $name Имя ключа + * @param Array $table Двухмерный массив * @example * key_unique_values ('name', array (array ('name' => 1), array ('name' => 2), array ('name' => 1))) => array (1, 2) @@ -354,11 +360,11 @@ class Functions { /** * Сортировка двумерного массива по заданному ключу - * @param $array Массив - * @param $key Имя ключа по значению которого будет идти сравнение - * @return Отсортированный массив + * @param Array $array Массив + * @param string $key Имя ключа по значению которого будет идти сравнение + * @return Array Отсортированный массив */ - static function sortOn($array, $key, $fn = 'Functions::__cmp') { + static function sortOn($array, $key, $fn = '\\ctiso\\Functions::__cmp') { usort ($array, Functions::rcurry($fn, $key)); //usort ($array, create_function ('$x,$y', 'return __cmp ($x, $y, "'.$key.'");')); return $array; @@ -368,7 +374,7 @@ class Functions { * Преобразует ключи элементов для многомерного массива * @return mixed */ - static function hash_key ($key_name,$array/*: array*/) { + static function hash_key ($key_name,$array/*: array */) { $result = array(); foreach($array as $value) { diff --git a/src/HttpRequest.php b/src/HttpRequest.php index 25890a5..0a65a4c 100644 --- a/src/HttpRequest.php +++ b/src/HttpRequest.php @@ -3,9 +3,11 @@ /** * Неверный запрос */ -class WrongRequestException extends Exception -{ -} +namespace ctiso; +use Exception, + ArrayAccess, + ctiso\Collection, + ctiso\Session; // HTTPRequest = ArrayAccess class HttpRequest extends Collection implements ArrayAccess @@ -127,4 +129,8 @@ class HttpRequest extends Collection implements ArrayAccess public function offsetGet($key) { } + + static function getProtocol() { + return (!empty($_SERVER['HTTPS']) && $_SERVER['HTTPS'] !== 'off' || $_SERVER['SERVER_PORT'] == 443) ? "https://" : "http://"; + } } diff --git a/src/Layout/Empty.php b/src/Layout/Blank.php similarity index 65% rename from src/Layout/Empty.php rename to src/Layout/Blank.php index a7f99b8..f731df3 100644 --- a/src/Layout/Empty.php +++ b/src/Layout/Blank.php @@ -3,7 +3,11 @@ /** * Самый простой макет */ -class Layout_Empty extends Filter_Filter +namespace ctiso\Layout; +use ctiso\Filter\Filter, + ctiso\HttpRequest; + +class Blank extends Filter { function execute(HttpRequest $request) { diff --git a/src/Layout/Manager.php b/src/Layout/Manager.php index 942a8fd..d687113 100644 --- a/src/Layout/Manager.php +++ b/src/Layout/Manager.php @@ -4,7 +4,12 @@ * Выбор макета страницы. * Выбор оформления страницы осуществляется если было совпадение с каким либо условием */ -class Layout_Manager extends Filter_Filter +namespace ctiso\Layout; +use ctiso\Filter\Filter, + ctiso\Functions, + ctiso\HttpRequest; + +class Manager extends Filter { // Массив условий с их макетами protected $condition = array(); @@ -17,7 +22,7 @@ class Layout_Manager extends Filter_Filter * addConditionGet(array('module' => 'personal'), 'personal') * addConditionGet(array('module' => 'login'), 'login') */ - public function addConditionGet($get, Filter_Filter $layout) + public function addConditionGet($get, Filter $layout) { $this->addCondition(Functions::rcurry(array($this, 'checkGet'), $get), $layout); } @@ -25,12 +30,12 @@ class Layout_Manager extends Filter_Filter /** * Условие для аякс запросов. Тоже самое что и addConditionGet но еще проверяется является ли запрос ajax */ - public function addConditionXHR($get, Filter_Filter $layout) + public function addConditionXHR($get, Filter $layout) { $this->addCondition(Functions::rcurry(array($this, 'checkXHR'), $get), $layout); } - public function checkGet($request, $get) + public function checkGet($request/*: HttpRequest*/, $get) { if (is_array($get)) { foreach ($get as $key => $value) { @@ -42,7 +47,7 @@ class Layout_Manager extends Filter_Filter return true; } - public function checkXHR($request, $get) + public function checkXHR($request/*: HttpRequest*/, $get) { return $request->isAjax() && $this->checkGet($request, $get); } @@ -52,7 +57,7 @@ class Layout_Manager extends Filter_Filter * @parma $get function(HttpRequest) Функция * @parma $layout Layout Макет */ - public function addCondition($get, Filter_Filter $layout) + public function addCondition($get, Filter $layout) { $this->condition [] = array($get, $layout); } @@ -67,11 +72,10 @@ class Layout_Manager extends Filter_Filter $layout = $condition[1]; $view = $layout->execute($request); if (is_object($view)) { - echo $view->render(); + return $view->render(); } else { - echo $view; + return $view; } - return null; } } } diff --git a/src/Mail.php b/src/Mail.php index 1f4eda4..20cdb7c 100644 --- a/src/Mail.php +++ b/src/Mail.php @@ -4,6 +4,10 @@ * Класс для работы с почтой * http://en.wikipedia.org/wiki/MIME */ +namespace ctiso; +use ctiso\Path, + Exception; + class Mail { public $_from; diff --git a/src/MailAlt.php b/src/MailAlt.php index 098d921..753dedf 100644 --- a/src/MailAlt.php +++ b/src/MailAlt.php @@ -1,5 +1,8 @@ db = $db; - $this->_registry = $_registry; + $this->config = $config; + $this->user = $user; } /** * Создает модель * @param string $name - * @return model + * @return BaseMapper */ public function getModel ($name) { - $modelName = "Mapper_" . $name; + $modelName = "App\\Mapper\\" . $name; $model = new $modelName(); $model->db = $this->db; $model->factory = $this; - $model->_registry = $this->_registry; + $model->config = $this->config; + $model->user = $this->user; $model->setUp(); // return $model; diff --git a/src/Numbers.php b/src/Numbers.php index c0a39c7..5fc73e4 100644 --- a/src/Numbers.php +++ b/src/Numbers.php @@ -1,5 +1,7 @@ path) == count($path->path)) { - for ($i = 0; $i < count($this->path); $i++) { + $count = count($this->path); + if ($count == count($path->path)) { + for ($i = 0; $i < $count; $i++) { if ($this->path[$i] != $path->path[$i]) { return false; } @@ -210,8 +213,9 @@ class Path if (isset($this->url['host']) && isset($path->url['host']) && ($this->url['host'] != $path->url['host'])) return false; - if (count($path->path) > count($this->path)) { - for ($i = 0; $i < count($this->path); $i++) { + $count = count($this->path); + if (count($path->path) > $count) { + for ($i = 0; $i < $count; $i++) { if ($path->path[$i] != $this->path[$i]) { return false; } @@ -255,15 +259,18 @@ class Path $list_path = $list->getParts(); $result = array(); - for ($i = 0; $i < count($list_path); $i++) { + $count = count($list_path); + for ($i = 0; $i < $count; $i++) { if (($i >= count($self_path)) || $list_path[$i] != $self_path[$i]) { break; } } - for($j = $i; $j < count($list_path); $j++) { + $list_count = count($list_path); + for($j = $i; $j < $list_count; $j++) { array_push($result, '..'); } - for($j = $i; $j < count($self_path); $j++) { + $self_count = count($self_path); + for($j = $i; $j < $self_count; $j++) { array_push($result, $self_path[$j]); } return implode("/", $result); @@ -369,7 +376,7 @@ class Path */ public function getContent($allow = null, $ignore = array()) { - $ignore = array_merge(array(".", ".."), $ignore); + $ignore = array_merge(array(".", ".."), $ignore); return self::fileList($this->__toString(), $allow, $ignore); } diff --git a/src/Primitive.php b/src/Primitive.php index aec45fd..be695a9 100644 --- a/src/Primitive.php +++ b/src/Primitive.php @@ -6,6 +6,8 @@ * @package system */ +namespace ctiso; + class Primitive { // varchar public static function to_varchar($value) @@ -48,9 +50,9 @@ class Primitive { if (!empty($tmp)) { if (count($tmp) != 3) return $result; - $year = intval($tmp[2]); - $month = intval($tmp[1]); - $day = intval($tmp[0]); + $year = (int)$tmp[2]; + $month = (int)$tmp[1]; + $day = (int)$tmp[0]; if ($month != 0 && $day != 0 && $year != 0) { if (checkdate($month, $day, $year)) { diff --git a/src/process.php b/src/Process.php similarity index 98% rename from src/process.php rename to src/Process.php index c32c284..18f813d 100644 --- a/src/process.php +++ b/src/Process.php @@ -1,5 +1,7 @@ +namespace ctiso; +use ctiso\File, + Exception; -/** - * http://www.patternsforphp.com/wiki/Registry - * http://www.patternsforphp.com/wiki/Singleton - * http://www.phppatterns.com/docs/design/the_registry?s=registry - */ +class Registry { + public $namespace = []; + public $data; -class Registry extends Settings -{ - static $instance = null; - - /** - */ - static public function getInstance() - { - if (self::$instance == null) { - self::$instance = new Registry(); + function importFile($namespace, $filePath = null) { + $data = json_decode(File::getContents($filePath), true); + $data['_file'] = $filePath; + $this->namespace[$namespace] = [ + 'path' => $filePath, + 'data' => $data + ]; + } + + function importArray($namespace, $data = []) { + if (isset($this->namespace[$namespace])) { + $data = array_merge($this->namespace[$namespace]['data'], $data); + } + $this->namespace[$namespace] = [ + 'path' => null, + 'data' => $data + ]; + } + + public function get($ns, $key) { + if (isset($this->namespace[$ns]['data'][$key])) { + return $this->namespace[$ns]['data'][$key]; } - return self::$instance; + throw new Exception('Unknown key ' . $ns . '::' . $key); } - /** - * Список модулей - */ - public function getModules() - { - return array_keys($this->data); + public function getOpt($ns, $key) { + if (isset($this->namespace[$ns]['data'][$key])) { + return $this->namespace[$ns]['data'][$key]; + } + return null; } - /** - * Проверка наличия модуля - */ - public function hasModule($name) - { - return isset($this->data[$name]); + public function has($ns, $key) { + return isset($this->namespace[$ns]['data'][$key]); + } + + function set($ns, $key, $value) { + $this->namespace[$ns]['data'][$key] = $value; } } diff --git a/src/Role/User.php b/src/Role/User.php new file mode 100644 index 0000000..a22cb13 --- /dev/null +++ b/src/Role/User.php @@ -0,0 +1,104 @@ +db = $db; + $this->groups = $groups; + } + + public function setDB(Database $db) { + $this->db = $db; + } + + public function getName() { + return $this->name; + } + + function isLogged() { + return \ctiso\Filter\Authorization::isLogged(); + } + + + public function getUserByQuery(Statement $stmt) + { + $result = $stmt->executeQuery(); + if ($result->next()) { + $this->access = $this->groups[$result->getString('access')]; + $this->name = $result->getString('login'); + $this->id = $result->getInt('id_user'); + $this->password = $result->getString('password'); + $this->fullname = implode(' ', array( + $result->getString('surname'), + $result->getString('firstname'), + $result->getString('patronymic'))); + return $result; + } + return null; + } + + function getUserPassword($result) { + return $result->get('password'); + } + + public function getUserByLogin($login) + { + $stmt = $this->db->prepareStatement("SELECT * FROM users WHERE login = ?"); + $stmt->setString(1, $login); + $result = $this->getUserByQuery($stmt); + if ($result) { + $time = time(); + $id = $this->id; + $this->db->executeQuery("UPDATE users SET lasttime = $time WHERE id_user = $id"); // Время входа + } + return $result; + } + + public function getUserById($id) + { + $stmt = $this->db->prepareStatement("SELECT * FROM users WHERE id_user = ?"); + $stmt->setInt(1, $_SESSION ['access']); + $result = $this->getUserByQuery($stmt); + if ($result) { + $lasttime = $result->getInt('lasttime'); + $time = time(); + if ($time - $lasttime > self::LIFE_TIME) return null; // Вышло время сессии + $id = $this->id; + } + return $result; + } + + 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($login) { + $this->db->executeQuery( + "UPDATE users SET trie_count = :count WHERE login = :login", + ['count' => 0, 'login' => $login] + ); + } + + function updateTries($login) { + $user = $this->db->fetchOneArray("SELECT id_user, trie_count FROM users WHERE login = :login", ['login' => $login]); + $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 new file mode 100644 index 0000000..295e4ca --- /dev/null +++ b/src/Role/UserInterface.php @@ -0,0 +1,12 @@ +file)) { + $this->is_read = true; return false; } // Не include_once т.к читать настройки можно несколько раз @@ -37,13 +44,16 @@ class Settings extends Collection if ($this->format == 'json') { $settings = json_decode(File::getContents($this->file), true); } else { - include ($this->file); + $settings = include ($this->file); } if (!is_array($settings)) { - throw new Exception($this->file); + throw new Exception('no data in ' . $this->file); } - return $this->import($settings); + + $this->is_read = true; + $this->data = $settings; + return true; } /** @@ -88,7 +98,7 @@ class Settings extends Collection /** * Чтение ключа из реестра - * @param $args Путь к значению ключа + * @param mixed $args Путь к значению ключа */ public function readKey(array $key) { @@ -118,7 +128,7 @@ class Settings extends Collection /** * Чтение ключа из реестра (Собирает все ключи с определенным значением во всех модулях) - * @param $key Путь к значению ключа внутри модуля + * @param mixed $key Путь к значению ключа внутри модуля */ public function readKeyList($_rest) { @@ -149,27 +159,58 @@ class Settings extends Collection $name = array_shift($key); unset($data[$name]); } - - public function getOwner() - { - return array_keys($this->data); - } /** * Запись настроек в файл (Может переименовать в store) * * @param File $file - * * @return void */ public function write($file = null) { + if (!$this->is_read) { + throw new Exception('read settings before write'); + } + if ($this->format == 'json') { $result = json_encode($this->data, JSON_PRETTY_PRINT | JSON_UNESCAPED_UNICODE); } else { $result = var_export($this->data, true); - $result = ""; + $result = ""; } file_put_contents (($file) ? $file : $this->file, $result); } + + public function set($key, $value) { + $this->data[$key] = $value; + } + + public function get($key, $default = null) + { + return isset($this->data[$key]) && $this->data[$key] != '' ? $this->data[$key] : $default; + } + + function export() { + return $this->data; + } + + function import($data) { + $this->data = $data; + } + + /** + * Список модулей/ключей + */ + public function getKeys() + { + return array_keys($this->data); + } + + /** + * Проверка наличия ключа + */ + public function hasKey($name) + { + return isset($this->data[$name]); + } } diff --git a/src/Setup.php b/src/Setup.php index 6e5dfa9..cfad705 100644 --- a/src/Setup.php +++ b/src/Setup.php @@ -7,6 +7,10 @@ * $setup->executeActions('install'); * */ +namespace ctiso; +use ZipArchive, + ctiso\Tools\SQLStatementExtractor; + class Setup { protected $actions = array(); @@ -119,7 +123,7 @@ class Setup return; } - $item/*: SimpleXMLElement*/ = $this->stack[count($this->stack) - 1]; + $item/*: \SimpleXMLElement*/ = $this->stack[count($this->stack) - 1]; $root = $item->children(); foreach ($root as $node) { @@ -198,7 +202,7 @@ class Setup */ function batchSQLZip($conn/*: Database*/, $file) { - $stmtList = Tools_SQLStatementExtractor::extract($this->zip->getFromName($file)); + $stmtList = SQLStatementExtractor::extract($this->zip->getFromName($file)); foreach ($stmtList as $stmt) { $conn->executeQuery ($stmt); } @@ -206,7 +210,7 @@ class Setup static function batchSQL($conn/*: Database*/, $file) { - $stmtList = Tools_SQLStatementExtractor::extractFile($file); + $stmtList = SQLStatementExtractor::extractFile($file); foreach ($stmtList as $stmt) { $conn->executeQuery ($stmt); } diff --git a/src/Shortcut.php b/src/Shortcut.php deleted file mode 100644 index 4e24046..0000000 --- a/src/Shortcut.php +++ /dev/null @@ -1,66 +0,0 @@ -list[$prefix] = $path; - } - - /** - * - */ - public function addVar($name, $value) - { - $this->variables['$' . $name] = $value; - } - - /** - * Возвращает путь по имени ярлыка - */ - static function getUrl($prefix, $name = null, $name1 = null) - { - $shortcut = self::getInstance(); - - $names = $shortcut->variables; - if ($name) { - $names['$name'] = $name; - } - if ($name1) { - $names['$name1'] = $name1; - } - - if (isset($shortcut->list[$prefix])) { - return strtr($shortcut->list[$prefix], $names); - } - return null; - } - - static function expand($path) - { - $shortcut = self::getInstance(); - $names = $shortcut->variables; - return strtr($path, $names); - } - -} diff --git a/src/SortRecord.php b/src/SortRecord.php index 24c054b..030bb52 100644 --- a/src/SortRecord.php +++ b/src/SortRecord.php @@ -1,5 +1,7 @@ addStyleSheet($s); + return ""; + } + + /** + * Функция подключения компонента + */ + static function phptal_component ($expression) { + $begin = floatval(microtime(true)); + $component/*: Component*/ = null; + + $component = self::$site->loadComponent($expression); + $req = new HttpRequest(); + $result = $component->execute($req); + + echo ""; + return $result; + } + + + static function register($site) { + self::$site = $site; + + /* Регистрация нового префикса для подключения компонента */ + $tales = PHPTAL_TalesRegistry::getInstance(); + $tales->registerPrefix('component', array('ctiso\\Tales_Component', 'component')); + $tales->registerPrefix('date', array('ctiso\\Tales_DateTime', 'date')); + $tales->registerPrefix('time', array('ctiso\\Tales_DateTime', 'time')); + $tales->registerPrefix('assets', array('ctiso\\Tales_Assets', 'assets')); + } +} diff --git a/src/Tools/Drawing.php b/src/Tools/Drawing.php index e13a323..ab4d43d 100644 --- a/src/Tools/Drawing.php +++ b/src/Tools/Drawing.php @@ -1,6 +1,8 @@ 'jpeg', 'gif' => 'gif', 'png' => 'png', 'bmp' => 'wbmp'); static $listfonts = array( @@ -33,15 +36,18 @@ class Tools_TemplateImage protected $data = array(); protected $base = "c:\\windows\\fonts\\"; protected $image; - protected $prepare = true; + protected $_prepare = true; public $debug = false; public $filename; public $resource; - function __construct ($template = false) + public $resource; + public $filename; + + function __construct ($template = null) { // assert(is_string($src)); - if($template) { + if ($template) { $this->data = $template; } } @@ -118,7 +124,7 @@ class Tools_TemplateImage return ""; } - function imageText($text, $value/*: stdClass*/) + function imageText($text, $value/*: \stdClass*/) { assert(is_string($text)); @@ -127,23 +133,23 @@ class Tools_TemplateImage $fontfile = $this->getFontFile($value->fontFamily . $this->fontSuffix($value->fontStyle)); $color = intval(substr($value->color, 1), 16); - if ($value->align[0]) { - $align = Tools_Drawing::ALIGN_LEFT; - } elseif ($value->align[2]) { - $align = Tools_Drawing::ALIGN_RIGHT; + if ($value->align[0]) { + $align = Drawing::ALIGN_LEFT; + } elseif ($value->align[2]) { + $align = Drawing::ALIGN_RIGHT; } else { - $align = Tools_Drawing::ALIGN_CENTER; + $align = Drawing::ALIGN_CENTER; } - if ($value->valign[0]) { - $valign = Tools_Drawing::ALIGN_TOP; - } elseif ($value->valign[1]) { - $valign = Tools_Drawing::ALIGN_CENTER; + if ($value->valign[0]) { + $valign = Drawing::ALIGN_TOP; + } elseif ($value->valign[1]) { + $valign = Drawing::ALIGN_CENTER; } else { - $valign = Tools_Drawing::ALIGN_BOTTOM; + $valign = Drawing::ALIGN_BOTTOM; } - Tools_Drawing::imagettftextbox($this->image, $size, 0, $value->left, $value->top, $color, $fontfile, $text, + Drawing::imagettftextbox($this->image, $size, 0, $value->left, $value->top, $color, $fontfile, $text, $value->width, $value->height, $align, $valign); } @@ -161,7 +167,7 @@ class Tools_TemplateImage { $width = imagesx($this->image); $height = imagesy($this->image); - if($new_height == false) { + if ($new_height == null) { $new_height = ceil($height * $new_width / $width); } @@ -173,8 +179,8 @@ class Tools_TemplateImage } function prepare() { - if($this->prepare) { - $this->prepare = false; + if($this->_prepare) { + $this->_prepare = false; foreach ($this->data as $value) { $this->imageText($value->text, $value); // break; } diff --git a/src/UTF8.php b/src/UTF8.php index 3cc68b8..fe97742 100644 --- a/src/UTF8.php +++ b/src/UTF8.php @@ -1,5 +1,7 @@ parent = $parent; + } + + function setQuery($parts) { + $this->parts = $parts; + } + + function addQueryParam($key, $value) { + $this->parts[$key] = $value; + } + + 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 88286de..226eb75 100644 --- a/src/UserMessageException.php +++ b/src/UserMessageException.php @@ -1,14 +1,11 @@ field; if (is_array($_POST[$name . '_code_genre'])) { - for($n = 0; $n < count($_POST[$name . '_code_genre']); $n++) { + $count = count($_POST[$name . '_code_genre']); + for($n = 0; $n < $count; $n++) { $code = array( $_POST[$name . '_code_genre'][$n], $_POST[$name . '_code_f'][$n], diff --git a/src/Validator/Rule/Count.php b/src/Validator/Rule/Count.php index 2afd612..ff030a4 100644 --- a/src/Validator/Rule/Count.php +++ b/src/Validator/Rule/Count.php @@ -3,10 +3,14 @@ /** * Проверка формата даты */ -class Validator_Rule_Count extends Validator_Rule_Abstract +namespace ctiso\Validator\Rule; +use ctiso\Validator\Rule\AbstractRule, + ctiso\Collection; + +class Count extends AbstractRule { public $size = 1; - public $max = false; + public $max = null; public function getErrorMsg() { @@ -26,7 +30,7 @@ class Validator_Rule_Count extends Validator_Rule_Abstract $count = count(array_filter(array_map('trim', explode(";", $container->get($this->field))), array($this, 'not_empty'))); - return $count >= $this->size && $count <= $this->max; + return $count >= $this->size && $count <= ((int)$this->max); } } diff --git a/src/Validator/Rule/Date.php b/src/Validator/Rule/Date.php index 166907a..1b416b0 100644 --- a/src/Validator/Rule/Date.php +++ b/src/Validator/Rule/Date.php @@ -3,7 +3,11 @@ /** * Проверка формата даты */ -class Validator_Rule_Date extends Validator_Rule_Abstract +namespace ctiso\Validator\Rule; +use ctiso\Validator\Rule\AbstractRule, + ctiso\Collection; + +class Date extends AbstractRule { private $split = "\\/"; diff --git a/src/Validator/Rule/Email.php b/src/Validator/Rule/Email.php index dd2b0e0..49ad808 100644 --- a/src/Validator/Rule/Email.php +++ b/src/Validator/Rule/Email.php @@ -3,7 +3,11 @@ /** * Проверка формата электронной почты */ -class Validator_Rule_Email extends Validator_Rule_Abstract +namespace ctiso\Validator\Rule; +use ctiso\Validator\Rule\AbstractRule, + ctiso\Collection; + +class Email extends AbstractRule { public function getErrorMsg() { diff --git a/src/Validator/Rule/EmailList.php b/src/Validator/Rule/EmailList.php index 98ac122..2132d0b 100644 --- a/src/Validator/Rule/EmailList.php +++ b/src/Validator/Rule/EmailList.php @@ -3,7 +3,11 @@ /** * Проверка формата электронной почты */ -class Validator_Rule_EmailList extends Validator_Rule_Abstract +namespace ctiso\Validator\Rule; +use ctiso\Validator\Rule\AbstractRule, + ctiso\Collection; + +class EmailList extends AbstractRule { public function getErrorMsg() { diff --git a/src/Validator/Rule/FileName.php b/src/Validator/Rule/FileName.php index 87732b3..d45d1f8 100644 --- a/src/Validator/Rule/FileName.php +++ b/src/Validator/Rule/FileName.php @@ -1,6 +1,11 @@ split, $container->get($this->field), 2); if ($tmp) { - if (self::checktime ($tmp[0], $tmp[1])) { + if (self::checktime ((int)$tmp[0], (int)$tmp[1])) { return true; } } diff --git a/src/Validator/Rule/Unique.php b/src/Validator/Rule/Unique.php index e458b8d..81489c3 100644 --- a/src/Validator/Rule/Unique.php +++ b/src/Validator/Rule/Unique.php @@ -2,7 +2,11 @@ /** */ -class Validator_Rule_Unique extends Validator_Rule_Abstract +namespace ctiso\Validator\Rule; +use ctiso\Validator\Rule\AbstractRule, + ctiso\Collection; + +class Unique extends AbstractRule { public function getErrorMsg() { diff --git a/src/Validator/Validator.php b/src/Validator/Validator.php index d01c001..c8303ad 100644 --- a/src/Validator/Validator.php +++ b/src/Validator/Validator.php @@ -3,41 +3,49 @@ /// /** - * Проверка коллекции + * Проверка коллекции */ -class Validator_Validator +namespace ctiso\Validator; +use Exception, + ctiso\Validator\Rule\AbstractRule, + ctiso\Collection; + +class Validator { 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' + ); function __construct($rules = array()) { $this->addRuleList($rules); } + function addRuleType($name, $className) { + $this->type[$name] = $className; + } + /** * Добавление списка правил в специальном формате * array(array('name' => fieldname, 'validate' => ruletext), ...) - * fieldname - Имя переменой для проверки + * fieldname - Имя переменой для проверки * ruletext - Описание правила см. формат правила ниже */ public function addRuleList(array $input) { - $type = array( - 'date' => 'Validator_Rule_Date', - 'email' => 'Validator_Rule_Email', - 'emaillist'=> 'Validator_Rule_EmailList', - 'match' => 'Validator_Rule_Match', - 'time' => 'Validator_Rule_Time', - 'alpha' => 'Validator_Rule_Alpha', - 'require' => 'Validator_Rule_Notnull', - 'numeric' => 'Validator_Rule_Numeric', - 'unique' => 'Validator_Rule_Unique', - 'filename' => 'Validator_Rule_FileName', - 'count' => 'Validator_Rule_Count', - 'isfile' => 'Validator_Rule_IsFile', - 'code' => 'Validator_Rule_Code' - ); - // Разбор правила проверки // Формат правила 'rule1|rule2,param1=value1|rule3,param1=value1,param2=value2' foreach ($input as $value) { @@ -50,8 +58,8 @@ class Validator_Validator $rule_param = explode(",", $rule); $name = array_shift($rule_param); - if (isset($type[$name])) { - $constructor = $type[$name]; + if (isset($this->type[$name])) { + $constructor = $this->type[$name]; $ruleObj = new $constructor($value['name'], false); // Нужны шаблонные сообщения для правил if (isset($value['context'])) { $ruleObj->setContext($value['context']); @@ -76,8 +84,8 @@ class Validator_Validator $this->chain[] = $rule; } } - - public function skip($rule/*: Validator_Rule_Abstract*/, $container/*: Collection*/) // -> Rule_Abstract + + public function skip($rule/*: AbstractRule*/, $container/*: Collection*/) // -> Rule_Abstract { if ($rule->skipEmpty()) { $data = $container->get($rule->field); @@ -85,10 +93,10 @@ class Validator_Validator $value = trim($data); return $value == ''; } - } + } return false; } - + public function validate(Collection $container, $rule = null, $status = null) { $fields = array(); diff --git a/src/View/Composite.php b/src/View/Composite.php index 812ee48..ff659ef 100644 --- a/src/View/Composite.php +++ b/src/View/Composite.php @@ -4,9 +4,14 @@ */ // View_Base + PHPTAL = View_Template (View_Composite) -class View_Composite extends View_View +namespace ctiso\View; +use ctiso\View\View, + PHPTAL; + +class Composite extends View { private $tal; + public $config; function __construct($file) { @@ -14,7 +19,7 @@ class View_Composite extends View_View $this->tal = new PHPTAL($file); $this->tal->setPhpCodeDestination(PHPTAL_PHP_CODE_DESTINATION); - $this->tal->setEncoding(PHPTAL_DEFAULT_ENCODING); // PHPTAL_DEFAULT_ENCODING !! + $this->tal->setEncoding(PHPTAL_DEFAULT_ENCODING); $this->tal->setTemplateRepository(PHPTAL_TEMPLATE_REPOSITORY); $this->tal->setOutputMode(PHPTAL::HTML5); $this->tal->stripComments(true); @@ -35,7 +40,6 @@ class View_Composite extends View_View function execute() { parent::execute(); - // postProcess return $this->tal->execute(); } diff --git a/src/View/List.php b/src/View/ListView.php similarity index 74% rename from src/View/List.php rename to src/View/ListView.php index 8522b32..16945ff 100644 --- a/src/View/List.php +++ b/src/View/ListView.php @@ -1,6 +1,9 @@ $group) { - if(in_array($file, $group)) { + foreach ($groups as $key => $group) { + if (in_array($file, $group)) { return $key; } } @@ -25,8 +30,8 @@ class View_Top extends View_Composite { private function groupFiles(array $list, $debugMode = true) { - $debug = ($debugMode) ? 'debug=1' : ''; - $path = parse_url(WWW_PATH, PHP_URL_PATH); + $debug = ($debugMode) ? 'debug=1' : ''; + $path = parse_url($this->config->get('system', 'web'), PHP_URL_PATH); $groups = array(); $use = array(); @@ -34,7 +39,7 @@ class View_Top extends View_Composite { $result = array(); foreach ($list as $file) { $name = $this->findGroup($groups, $file); - if($name) { + if ($name) { $use[$name] = 1; } else { $result[] = $file; @@ -49,17 +54,18 @@ class View_Top extends View_Composite { } - function getId($pref) { - $this->mid++; - return $pref.$this->mid; - } + function getId($pref) + { + $this->mid++; + return $pref . $this->mid; + } /** * Обработка шаблона * * @return string */ - public function render() + public function render() { $alias = $this->doTree('alias'); @@ -69,55 +75,56 @@ class View_Top extends View_Composite { $this->set('scripts', array_unique($this->groupFiles($this->getScripts(), false))); $this->set('stylesheet', array_unique($this->groupFiles($this->getStyleSheet(), false))); - $this->require = array('admin' => 'ma'); - $this->deps = array(); + $this->require = array('admin' => 'ma'); + $this->deps = array(); - $startup = array(); - foreach($this->_section as $s) { + $startup = array(); + foreach ($this->_section as $s) { if (is_string($s)) { continue; } - $moduleName = explode('_', $s->active_module, 2); + $moduleName = explode('_', $s->active_module, 2); if (count($moduleName) < 2) { continue; } $module = $moduleName[1]; - $name = mb_strtolower($module); - $fname = $name . '/' . $name; + $name = mb_strtolower($module); + $fname = $name . '/' . $name; - $current = $this->getId('m'); - $this->require[$fname] = $current; + $current = $this->getId('m'); + $this->require[$fname] = $current; - $value = $this->getId('v'); + $value = $this->getId('v'); - $script = "var " . $value . " = new " . $current . '.' . $module . "();\n"; - foreach($s->_values as $key => $v) { - $script .= $value . "." . $key . " = " . json_encode($v/*, JSON_PRETTY_PRINT*/) . ";\n"; - } + $script = "var " . $value . " = new " . $current . '.' . $module . "();\n"; + foreach ($s->_values as $key => $v) { + $script .= $value . "." . $key . " = " . json_encode($v /*, JSON_PRETTY_PRINT*/) . ";\n"; + } - $init = array(); - foreach($s->_section as $key => $item) { - $ss/*: View_View*/ = $item; + $init = array(); + foreach ($s->_section as $key => $item) { + $ss /*: View*/= $item; if ($ss->codeGenerator !== null) { - // функцию которая вычисляет а не результат - $part = call_user_func($ss->codeGenerator, $this, $key, $value); - $init [] = $part; - } - } + // функцию которая вычисляет а не результат + $part = call_user_func($ss->codeGenerator, $this, $key, $value); + $init[] = $part; + } + } - $script .= $value . ".execute('" . $s->module_action . "', " . json_encode($init) .");\n"; - $startup[] = $script; - } + $script .= $value . ".execute('" . $s->module_action . "', " . json_encode($init) . ");\n"; + $startup[] = $script; + } $this->set('startup', implode("", $startup) . $this->getScriptStartup()); - $this->set('require', implode(",", array_map(function ($x) { return "'$x'";}, array_keys($this->require)))); + $this->set('require', implode(",", array_map(function ($x) { + return "'$x'"; }, array_keys($this->require)))); $this->set('deps', implode(",", array_values($this->require))); $this->set('title', $this->getTitle()); - $this->set('jspath', enableHttps(WWW_PATH)); + $this->set('jspath', $this->config->get('system', 'web')); // return $this->execute(); // execute+phptal ?? } @@ -157,4 +164,4 @@ class View_Top extends View_Composite { return $this->doTree('_stylesheet'); } -} +} \ No newline at end of file diff --git a/src/View/View.php b/src/View/View.php index b54079e..088cd43 100644 --- a/src/View/View.php +++ b/src/View/View.php @@ -1,6 +1,9 @@ _section [$section] = $view; if (is_object($view)) { @@ -44,11 +47,6 @@ class View_View $this->_values["suggestions"] = $this->suggestions; } - public function jGrowl($message, $args) - { - $this->addScriptRaw('$.jGrowl("' . $message . '", ' . json_encode($args) . ");\n", true); - } - public function setGlobal($name, $args) { $this->addScriptRaw("var " . $name . " = " . json_encode($args) . ";\n", false); @@ -202,4 +200,4 @@ class View_View } return $result; } -} \ No newline at end of file +} diff --git a/src/WrongRequestException.php b/src/WrongRequestException.php new file mode 100644 index 0000000..34863be --- /dev/null +++ b/src/WrongRequestException.php @@ -0,0 +1,7 @@ +execute($req); - - echo ""; - return $result; -} - - -/* Регистрация нового префикса для подключения компонента */ -$tales = PHPTAL_TalesRegistry::getInstance(); -$tales->registerPrefix('component', array('Component_Tales', 'component')); -$tales->registerPrefix('date', array('DateTime_Tales', 'date')); -$tales->registerPrefix('time', array('DateTime_Tales', 'time')); -$tales->registerPrefix('assets', array('Assets_Tales', 'assets')); -