From 75bb35d5bfe89599aabe98af164e75ae3c27f780 Mon Sep 17 00:00:00 2001 From: origami11 Date: Fri, 17 Feb 2017 17:31:17 +0300 Subject: [PATCH] =?UTF-8?q?=D0=92=D0=B5=D1=80=D1=81=D0=B8=D1=8F=20=D0=BF?= =?UTF-8?q?=D0=BE=D0=BB=D0=BD=D0=BE=D1=81=D1=82=D1=8C=D1=8E=20=D1=81=D0=BE?= =?UTF-8?q?=D0=B2=D0=BC=D0=B5=D1=81=D1=82=D0=B8=D0=BC=D0=B0=D1=8F=20c=20CM?= =?UTF-8?q?S?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/Controller/Action.php | 227 ++++++++++++------- src/Controller/Component.php | 366 +++++++++++++++++++++---------- src/Controller/Front.php | 58 +++-- src/Controller/Installer.php | 46 +++- src/Controller/Model.php | 354 +++++++++++++++++++----------- src/Database/PDOStatement.php | 4 +- src/Filter/Login.php | 112 ++++++++-- src/Form/Form.php | 300 +++++++++++++++++++++---- src/Primitive.php | 160 ++++++++------ src/Tools/String.php | 154 ++++++++----- src/Validator/Rule/Alpha.php | 2 +- src/Validator/Rule/Date.php | 2 +- src/Validator/Rule/Email.php | 2 +- src/Validator/Rule/EmailList.php | 2 +- src/Validator/Rule/Match.php | 10 +- src/Validator/Rule/Numeric.php | 2 +- src/Validator/Rule/Time.php | 2 +- src/Validator/Rule/Unique.php | 5 +- src/Validator/Validator.php | 25 ++- src/View/Composite.php | 25 ++- src/View/Top.php | 329 +++++++++++---------------- 21 files changed, 1404 insertions(+), 783 deletions(-) diff --git a/src/Controller/Action.php b/src/Controller/Action.php index 6e51caa..4ddeb58 100644 --- a/src/Controller/Action.php +++ b/src/Controller/Action.php @@ -13,7 +13,7 @@ function forceUrl($name) /** * Контроллер страниц - */ + */ class Controller_Action { @@ -24,9 +24,16 @@ class Controller_Action public $themePath; // Глобальный путь к текущей теме // Параметры устанавливаются при создании контроллера - public $name; // Имя модуля - public $viewPath = null; // Путь к шаблонам контроллера - public /*.Database.*/$db; // Соединение с базой данных + public $name = ''; // Имя модуля + public $viewPath = null; // Путь к шаблонам контроллера + public $viewPathPrefix = null; // Путь к шаблонам контроллера + + public $moduleTitle = ""; + + /** + * Соединение с базой данных + */ + public $db; // Фильтры public $access = null; // Обьект хранит параметры доступа @@ -42,14 +49,11 @@ class Controller_Action public $iconPath = ''; public $path; - public function __construct () - { - // + public function __construct () { + $this->path = new Widgets_PathMenu(); } - public function setUp () - { - // override this + public function setUp() { } public function loadConfig($name) { @@ -69,15 +73,16 @@ class Controller_Action public function installPath($name) { - return Path::join(CMS_PATH, "modules", $name, "install"); + return Path::join(CMS_PATH, "modules", $name); } - public function addSuggest($view, $name) + public function addSuggest(View_View $view, $name) { $suggest = array(); $file = Path::join($this->viewPath, 'help', $name . '.suggest'); - if (file_exists($file) && include($file)) { - $view->addScriptRaw("add_suggest(".json_encode($suggest).");\n"); + if (file_exists($file)) { + include($file); + $view->suggestions = $suggest; } } @@ -85,39 +90,43 @@ class Controller_Action { return Path::join($this->iconPath, $size . 'x' . $size, $icon . '.png'); } - + /** * Создает представление - * @param string $file - * @return template + * @param $name String + * @param $viewClass String + * @return View_Composite */ - public function getView($name) + public function getView($name, $viewClass = 'View_Composite') { - $file = $name . self::TEMPLATE_EXTENSION; - // Список возможных директорий для поиска файла шаблона - $theme = $this->_registry->readKey(array('system', 'theme')); - $icon_theme = $this->_registry->readKey(array('system', 'icon_theme')); - $list = array( - Path::join($this->viewPath, TEMPLATES) => Path::join(WWW_PATH, "modules", $this->name, TEMPLATES), - PHPTAL_TEMPLATE_REPOSITORY => ""); + $file = $name . self::TEMPLATE_EXTENSION; + $list = array( + Path::join($this->viewPath, TEMPLATES, $this->viewPathPrefix) => Path::join(WWW_PATH, "modules", $this->name, TEMPLATES, $this->viewPathPrefix), + Path::join(CMS_PATH, "templates") => Path::join(WWW_PATH, "templates") + ); // Поиск файла для шаблона foreach($list as $ospath => $path) { - $template = Path::join($ospath, $file); + $template = Path::join($ospath, $file); if(file_exists($template)) { break; } } - $tpl = new View_Composite($template); - $tpl->icons = $this->iconPath; // Путь к файлам текущей темы - $tpl->media = $this->themePath; // Путь к файлам текущей темы - $tpl->script = $this->jsPath; // Путь к файлам скриптов - $tpl->template = $path; // Путь к файлам текущего шаблона + /*.View_Composite.*/$tpl = new $viewClass($template); + + $tpl->set('icons', $this->iconPath); // Путь к файлам текущей темы + $tpl->set('media', $this->themePath); // Путь к файлам текущей темы + $tpl->set('assets', Path::join(WWW_PATH, "assets", "css")); + $tpl->set('script', $this->jsPath); // Путь к файлам скриптов + $tpl->set('template', $path); // Путь к файлам текущего шаблона + $tpl->setAlias(array( - '${icons}' => $this->iconPath, - '${media}' => $this->themePath, - '${script}' => $this->jsPath, - '${template}' => $path)); + 'icons' => $this->iconPath, + 'script' => $this->jsPath, + // Для media и template поиск происходит как для файлов шаблонов + 'media' => $list, + 'template' => $list + )); $tpl->loadImports(Path::skipExtension($template) . ".import"); @@ -128,7 +137,7 @@ class Controller_Action public function getModel($name) { if (!$this->factory) { - $this->factory = new ModelFactory($this->db, $this->_registry, $this->_shortcut); + $this->factory = new Model_Factory($this->db, $this->_registry); } return $this->factory->getModel($name); } @@ -143,57 +152,59 @@ class Controller_Action public function execute1(HttpRequest $request) { $action = self::ACTION_PREFIX . ucfirst($request->getAction()); - if (method_exists($this, $action)) { - return $this->forward($action, $request); - } else { - return $this->forward("actionIndex", $request); + 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; } public function execute(HttpRequest $request) { $result = $this->execute1($request); - if ($result) { + if (!empty($result)) { $this->view = $result; } - return $this->render(); + $text = $this->render(); + return $text; } - public function forward($action, HttpRequest $args) - { - // Действия до вызова основного обработчика - /*foreach($this->_aspect as $aspect) { - if (isset($aspect->before[$action])) { - call_user_func ($aspect->before[$action], $action, $args); - } - }*/ - return call_user_func(array($this, $action), $args); + public function forward($action, HttpRequest $args) { + $value = call_user_func(array($this, $action), $args); + return $value; } /** * Страница по умолчанию */ - public function actionIndex(HttpRequest $request) - { + public function actionIndex(HttpRequest $request) { return ""; } public function postUrl($name, $param) { - return "?" . http_build_query( - array_merge(array('module' => strtolower(get_class($this)), "action" => $name), - $this->param, $param)); + $uri = array_merge(array('module' => + strtr($this->modulePrefix . strtolower(get_class($this)), array('module_' => '')), "action" => $name), + $this->param, $param); + + return "?" . http_build_query($uri); } /** * Генерация ссылки c учетом прав пользователя на ссылки - * - * @parma string $name Действие - * @parma string $param Дополнительные параметры + * @param string $name Действие + * @param array $param Дополнительные параметры + * 'mode' означает что элемент до отправки обрабатывается javascript + * @return array|null */ public function nUrl($name, array $param = array()) { - if (!$this->access || $this->access->checkAction($name)) { + /*.Filter_ActionAccess.*/$access = $this->access; + if ($access != null || $access->checkAction($name)) { return lcurry(array($this, 'postUrl'), $name, $param); } return null; @@ -217,6 +228,12 @@ class Controller_Action /** * Генерация ссылки на действие контроллера * Ajax определяется автоматически mode = ajax используется для смены layout + * @param $name + * @param array $param + * @return array|null + * + * @example ?action=$name&mode=ajax + * {$param[i].key = $param[i].value} */ public function aUrl($name, array $param = array()) { @@ -249,14 +266,14 @@ class Controller_Action /** * Загрузка файла класса */ - public function loadClass($path, $setup = null) + public function loadClass($path, $setup = null, $prefix = '') { if (file_exists($path)) { require_once ($path); - $class = pathinfo($path, PATHINFO_FILENAME); + $class = $prefix . pathinfo($path, PATHINFO_FILENAME); return new $class($setup); } - return null; + throw new Exception("NO CLASS $path"); } public function loadSettings($path) @@ -269,6 +286,7 @@ class Controller_Action // Для Widgets public $view = null; public $childNodes = array(); + public $ctrlValues = array(); public $childViews = array(); public function setView($name) @@ -292,6 +310,11 @@ class Controller_Action $this->childNodes[$section] = $node; } + public function setValue(/*Widget*/ $name, $value) + { + $this->ctrlValues[$name] = $value; + } + /** * Добавление дочернего отображения к текущему отображению */ @@ -306,34 +329,86 @@ class Controller_Action */ public function render() { - foreach ($this->childNodes as $name => $node) { - $node->make($this); - $this->view->setView($name, $node->view); - } - foreach ($this->childViews as $name => $node) { - $this->view->setView($name, $node); - } + if ($this->view instanceof View_View) { + $this->view->assignValues($this->ctrlValues); + + foreach ($this->childNodes as $name => $node) { + $node->make($this); + $this->view->setView($name, $node->view); + } + foreach ($this->childViews as $name => $node) { + $this->view->setView($name, $node); + } + } return $this->view; } - function getPageId($request) + function getPageId(HttpRequest $request) { $pageId = time(); $request->session()->set('page', $pageId); return $pageId; } - function checkPageId($request, $page) + function checkPageId(HttpRequest $request, $page) { + if ($request->get('__forced__')) { + return true; + } $_page = $request->session()->get('page'); $result = ($_page && $_page == $page); $request->session()->clean('page'); return $result; } - function redirect($action) { - header('location: ' . $this->fUrl($action)); - exit(); + function _getActionPath() + { + return new Controller_State('index'); } -} + // Тоже убрать в метод Controller_Model + function getActionPath(HttpRequest $request, $action = null) + { + $this->_getActionPath()->getPath($this, ($action) ? $action : $request->getAction()); + } + + function addFilePathToPath($filePath, $type) + { + $pathToItem = $this->directoryPath($filePath, $type, 'default'); + $this->path->addMenuItems($pathToItem['path']); + } + + function directoryPath($path, $type, $action) + { + $path = empty($path) ? '/' : $path; + + $base = new Path($path); + $parts = $base->getParts(); + + $_path = '/' . implode('/', $parts); + + $rs = new Model_Resources($this->db); + $section_path = $rs->getSectionByPath($_path, $type); + + $pathMenu = new Widgets_PathMenu(); + $pathMenu->addTitle('title'); + $modules = ['image' => 'images','page' => 'pages','document' => 'documents','media' => 'videos']; + + while ($section_path->id_parent) { + $_path = '/' . implode('/', $parts); + $pathMenu->addMenuItem( + forceUrl($this->nUrl('', array('module'=>$modules[$type],'action' => $action, 'mode' => 'ajax', 'path' => $_path))), + $section_path->title + ); + $section_path = $rs->getSectionById($section_path->id_parent); + array_pop($parts); + } + + $pathMenu->addMenuItem( + forceUrl($this->nUrl('', array('module'=>$modules[$type],'action' => $action, 'mode' => 'ajax', 'path' => '/'))), + $this->moduleTitle + ); + return $pathMenu->getItemsReverse(); + } + +} diff --git a/src/Controller/Component.php b/src/Controller/Component.php index ae4c131..0a8220c 100644 --- a/src/Controller/Component.php +++ b/src/Controller/Component.php @@ -1,7 +1,40 @@ ]*>/u', 'replaceContent', $text); +} + +class ComponentRequest { + public $component_id; + public $r; + + function __construct($c, HttpRequest $r) { + $this->component_id = $c; + $this->r = $r; + } + + function get($key, $default = null) { + if ($key == 'active_page') { + return $this->r->get($key); + } + if ($arr = $this->r->get($key)) { + if (is_array($arr)) { + return Arr::get($arr, $this->component_id, $default); + } else { + return $arr; + } + } + return $default; + } + + function getAction() { + return $this->r->getAction(); + } } /** @@ -9,51 +42,87 @@ class FileNotFountException extends Exception */ class Controller_Component { - static $_uid = 1; - public $uid; // UID компонента создается при создании страницы, вставки компонента, или это статическое свойство - public $viewPath; - public $registry; // Registry->getInstance - public $template; + public $viewPath = array(); + public $webPath = array(); - function __construct() - { - self::$_uid ++; - $this->uid = self::$_uid; + public $template = null; + public $templatePath; + + public $component_id; + public $COMPONENTS_WEB; + + public /*.Settings.*/$registry; + public /*.Database.*/$db; + public /*.Collection.*/$parameter; + + public $module; + public $item_module; + + function before() { } - function getUID() - { - return 'component:'. $this->uid; + function get($request, $key, $default) { + } + + function execute(HttpRequest $request, $has_id = true) { + $crequest = new ComponentRequest($this->component_id, $request); + $action = 'action' . ucfirst($request->get('action', 'index')); + + $this->before(); + if (method_exists($this, $action)) { + return call_user_func(array($this, $action), $crequest); + } else { + return $this->actionIndex($crequest); + } } public function getView($name) { - require_once "core/view/compositeview.php"; // - $template = ($this->template) ? $this->template : $this->_registry->readKey(array('system', 'template')); - // Загружать шаблон по умолчанию если не найден текущий - if (is_dir(Path::join($this->viewPath, 'templates', $template))) { - $template_file = Path::join($this->viewPath, 'templates', $template, $name); - } else { - $template_file = Path::join($this->viewPath, 'templates', 'modern', $name); + /*.Settings.*/$registry = $this->registry; + $template = ($this->template) ? $this->template : $registry->readKey(array('system', 'template')); + + $selected = null; + foreach ($this->viewPath as $index => $viewPath) { + // Загружать шаблон по умолчанию если не найден текущий + if(is_dir(Path::join($this->viewPath[$index], 'templates', $template))) { + $tpl = new PHPTAL(Path::join($this->viewPath[$index], 'templates', $template, $name)); + $tpl->setPhpCodeDestination(PHPTAL_PHP_CODE_DESTINATION); + $selected = $index; + break; + } } - $tpl = new View_Composite($template_file); - $tpl->script = $_script = Path::join(WWW_PATH, 'js'); - $tpl->media = $_media = Path::join(TEMPLATE_WEB, $template); - $tpl->component = $_template = Path::join(COMPONENTS_WEB, strtolower(get_class($this)), 'templates', 'modern'); - $tpl->setAlias(array( - '${media}' => $_media, - '${script}' => $_script, - '${template}' => $_template)); + if ($selected === null) { + $tpl = new PHPTAL(Path::join($this->viewPath[0], 'templates', 'modern', $name)); + $tpl->setPhpCodeDestination(PHPTAL_PHP_CODE_DESTINATION); + $template = 'modern'; + $selected = 0; + } - $tpl->loadImports(Path::skipExtension($template_file) . ".import"); + $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)); + $tpl->set('site_template', SITE_WWW_PATH . '/templates' . $registry->readKey(array('system', 'template'))); + $tpl->set('base', SITE_WWW_PATH); + + $tpl->set('component_base', $this->webPath[$selected]); + $tpl->set('component', Path::join($this->webPath[$selected], 'templates', $template)); + $tpl->set('component_id', $this->component_id); return $tpl; } - public function setParameters($view) + public function getTemplatePath($name) { + return Path::join($this->viewPath[0], 'templates', 'modern', $name); + } + + public function getTemplateWebPath() { + return Path::join($this->webPath[0], 'templates', 'modern'); } /** @@ -71,8 +140,6 @@ class Controller_Component */ public function getModel($name) { - require_once 'core/mapper/mapper.php'; - require_once ($this->getModelPath ($name)); $modelName = $name . "Mapper"; $model = new $modelName (); @@ -80,104 +147,179 @@ class Controller_Component return $model; } - public function options($key, $val, $res) { + public function options($key, $val, /*.Database_PDOStatement.*/$res) { $result = array(); while($res->next()) { - $result[] = array('value' => $res->getInt($key), 'name' => $res->getString($val)); + $result[] = array('value' => $res->getString($key), 'name' => $res->getString($val)); } return $result; } - public function optionsPair($list) { + public function optionsPair($list, $selected = false) { $result = array(); foreach ($list as $key => $value) { - $result [] = array('value' => $key, 'name' => $value); + $result [] = array('value' => $key, 'name' => $value, 'selected' => $key == $selected); } return $result; } - /* В дальнейшем нужно зменить на методы - + Методы могут быть и javascript - */ - protected $editUrl; - - function setEditUrl($url) - { - $this->editUrl = $url; + function getInfo() { + $filename = Path::join($this->viewPath[0], 'install.json'); + if (file_exists($filename)) { + $settings = json_decode(file_get_contents($filename), true); + return $settings; + } + return array(); } - function getEditUrl() + /** + * Генерация интерфейса для выбора галлереи фотографии + */ + public function setParameters(/*.View_Composite.*/$view) { - return $this->editUrl; - } -} + $form = new Form_Form(); + $options = new OptionFactory($this->db); -/** - * TALES для подключения компонентов - * component:name?param1=value1¶m2=value2 - */ -class Component_Tales implements PHPTAL_Tales -{ - static public function component($expression, $nothrow = false) + $settings = $this->getInfo(); + $form->addFieldList($settings['parameter'], $options); + + $view->form = $form; + $view->component = $settings['component']; + $view->component_title = $settings['title']; + } + + static function loadComponent($expression, Database $db, Settings $registry) { - return "phptal_component('" . $expression . "')"; - } -} + + $expression = htmlspecialchars_decode($expression); + $offset = strpos($expression, '?'); + $url = parse_url($expression); + + $arguments = array(); + if ($offset === false) { + $path = $expression; + } else if (is_int($offset)) { + $path = substr($expression, 0, $offset); + $query = substr($expression, $offset + 1); + parse_str($query, $arguments); + } + $name = $path; + + $path = Path::join (BASE_PATH, 'components', $name, $name . '.php'); + $className = 'Component_' . $name; + + if (file_exists($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/'; + + } else { + $path = Path::join (COMPONENTS, $name, $name . '.php'); + require_once ($path); + $component = new $className(); + $component->db = $db; + $component->registry = $registry; + + $component->viewPath = array(COMPONENTS . '/' . $name . '/', BASE_PATH . '/components/' . $name . '/'); + if (defined('COMPONENTS_WEB')) { + $component->webPath = array(COMPONENTS_WEB . '/' . $name, SITE_WWW_PATH . '/components/' . $name); + $component->COMPONENTS_WEB = COMPONENTS_WEB; + } + } + + $stmt = $db->prepareStatement("SELECT * FROM component WHERE code = ?"); + $stmt->setString(1, $expression); + $cid = $stmt->executeQuery(); + if ($cid->next()) { + $component->component_id = $cid->getInt('id_component'); + } else { + $last = $db->getIdGenerator(); + if ($last->isBeforeInsert()) { + $result = $last->getId('component_id_component_seq'); + + $stmt = $db->prepareStatement("INSERT INTO component (id_component, code) VALUES ($result, ?)"); + $stmt->setString(1, $expression); + $stmt->executeQuery(); + } + if ($last->isAfterInsert()) { + $stmt = $db->prepareStatement("INSERT INTO component (code) VALUES (?)"); + $stmt->setString(1, $expression); + $stmt->executeQuery(); + + $result = $last->getId('component_id_component_seq'); + } + $component->component_id = $result; + } + + $params = new Collection(); + $params->import(array_merge($_GET, $arguments)); + $component->parameter = $params; + $component->template = $params->get('template', false); + + global $componentsConfig; + $editor = $component->getEditUrl(); + if ($editor) { + $componentsConfig[] = $editor; + } -function loadComponent($name, $db, $registry) -{ - $path = Path::join(COMPONENTS, $name, $name . ".php"); -// echo COMPONENTS, '
'; -// echo $path; - if (file_exists($path)) { - require_once ($path); - $component = new $name(); - $component->db = $db; - $component->_registry = $registry; - $component->viewPath = COMPONENTS."/".$name."/"; return $component; } - throw new FileNotFountException(); + + function getEditUrl() { + return null; + } + + function raw_query(/*.ComponentRequest.*/ $request) + { + $arr = $request->r->export('get'); + + $param = array(); + /*.Collection.*/$parameter = $this->parameter; + foreach($parameter->export() as $key => $value) { + $param[$key] = $value; + } + + $data = array(); + foreach($arr as $key => $value) { + if (is_array($value)) { + $data[$key] = Arr::get($value, $this->component_id); + } else { + $data[$key] = $value; + } + } + $data['param'] = $param; + return $data; + } + + + function query(/*.ComponentRequest.*/ $request, $list) + { + $arr = $request->r->export('get'); + + foreach($list as $key => $val) { + $arr[$key] [$this->component_id] = $val; + } + + unset($arr['active_page']); + return '?' . http_build_query($arr); + } + + function addRequireJsPath($name, $path, $shim = null) { + global $requireJsConfig; + $requireJsConfig['paths'][$name] = $path; + if ($shim) { + $requireJsConfig['shim'][$name] = $shim; + } + } + + function actionIndex(/*.ComponentRequest.*/ $request) { + } } -/** - * Функция подключения компонента - */ -global $componentList; -$componentList = array(); - -function phptal_component ($real_expression, $offset = 0) { - global $db, $registry, $componentList; // Нужно както передавать параметры - - $expression = htmlspecialchars_decode($real_expression); - $url = parse_url($expression); - parse_str($url['query'], $arguments); - $name = $url['path']; - - $component = loadComponent($name, $db, $registry); - $req = new HttpRequest(); - $params = new Collection(); - $params->import(array_merge($_GET, $arguments)); - $component->params = $params; - - $componentList [] = array( - 'uid' => $component->getUID(), 'params' => $expression, 'name' => $name, 'offset' => $offset, - 'size' => strlen($real_expression), - /* Вместо ссылки на редактирование нужно передавать список методов для работы с компонентом - edit (редактирование содержание), new (новое содержание), шаблон коменнента ... вместе с иконками этих методов - ! Компоненты могут содержать другие компоненты - */ - 'editurl' => $component->getEditUrl(), - 'newurl' => '' - ); - - unset($req['active_page']); - $component->template = $params->get('template', false); - - return $component->execute($params, $req); -} - -/* Регистрация нового префикса для подключения компонента */ -$registry = PHPTAL_TalesRegistry::getInstance(); -$registry->registerPrefix('component', array('Component_Tales', 'component')); - diff --git a/src/Controller/Front.php b/src/Controller/Front.php index badcf43..38b1a40 100644 --- a/src/Controller/Front.php +++ b/src/Controller/Front.php @@ -2,25 +2,37 @@ /** * Первичный контроллер контроллер страниц - * @package core + * @package system.controller */ class Controller_Front extends Controller_Action { - + + /** @var Shortcut */ protected $shortcut; // Ярлык к модулю protected $_param; // Параметр по которому выбирается модуль protected $default; // Значение параметра по умолчанию - public function __construct(Settings $_registry, $_shortcut) + protected $modules = array(); + + /** + * @param Settings $_registry + * @param Shortcut $_shortcut + */ + public function __construct(Settings $_registry, $_shortcut) // $db, $installer, $shortcut { parent::__construct(); $registry = $_registry; $this->_registry = $_registry; - $this->_shortcut = $_shortcut; + $this->_shortcut = $_shortcut; // $cc->newShortcut(); - $this->db = Database::getConnection($registry->readKey(array('system', 'dsn'))); + $dsn = $registry->readKey(array('system', 'dsn')); + $this->db = Database::getConnection($dsn); // $cc->newConnection(); } + public function isLoaded($name) + { + return isset($this->modules[$name]); + } /** * Создает экземпляр модуля и выполняет действия для него @@ -28,15 +40,22 @@ class Controller_Front extends Controller_Action * @param request $request Имя модуля * @return string */ - public function loadModule($name, Collection $request) + public function loadModule($name, Collection $request, $controller = false) { + if ($this->isLoaded($name)) { + $module = $this->modules[$name]; + return $module->access->execute($request); + } - $moduleFile = Shortcut::getUrl($this->shortcut, $name); // ModuleLoader (2) - $module = $this->loadClass($moduleFile); + if ($controller) { + $moduleFile = Shortcut::getUrl($this->shortcut, $name, $controller); // ModuleLoader (2) + } else { + $moduleFile = Shortcut::getUrl($this->shortcut, $name, $name); // ModuleLoader (2) + } + $module = $this->loadClass($moduleFile, null, 'Module_'); if ($module) { // Инициализация модуля -// $module->viewPath = dirname($moduleFile); $module->viewPath = Shortcut::getUrl('modulepath', $name); $module->name = $name; @@ -51,15 +70,17 @@ class Controller_Front extends Controller_Action $module->db = $this->db; // Не для всех приложений нужно вести лог действий // Ведение лога - $logger = $this->loadClass(FRAMEWORK_PATH . '/src/filter/actionlogger.php', $module); + $logger = $this->loadClass(FRAMEWORK_PATH . '/filter/actionlogger.php', $module, 'Filter_'); $logger->before = $this->loadSettings(Shortcut::getUrl('logger', $name)); // Управление доступом - $module->access = $this->loadClass(FRAMEWORK_PATH . '/src/filter/actionaccess.php', $logger); + $module->access = $this->loadClass(FRAMEWORK_PATH . '/filter/actionaccess.php', $logger, 'Filter_'); $module->access->access = $this->loadSettings(Shortcut::getUrl('access', $name)); $module->setUp(); - return $module->access->execute($request); + $this->modules[$name] = $module; + $result = $module->access->execute($request); + return $result; } return null; // throw new FileNotFoundException(); } @@ -72,13 +93,14 @@ class Controller_Front extends Controller_Action $this->default = $name; } - private function getParameter(Collection $list) - { - return ($list->get($this->_param)) ? $list->get($this->_param): $this->default; - } - public function execute(HTTPRequest $request) { - return $this->loadModule($this->getParameter($request), $request); + $name = explode("_", $request->get($this->_param, $this->default)); + if (count($name) >= 2) { + $controller = $name[1]; + } else { + $controller = false; + } + return $this->loadModule($name[0], $request, $controller); } } diff --git a/src/Controller/Installer.php b/src/Controller/Installer.php index 1bbbe3a..dcc4562 100644 --- a/src/Controller/Installer.php +++ b/src/Controller/Installer.php @@ -2,7 +2,7 @@ class Controller_Installer { - protected $db; + protected $db_manager; protected $installPath; public $_registry; @@ -11,15 +11,20 @@ class Controller_Installer $this->_registry = $_registry; } - public function setUp($db, $installPath) + public function setUp($db_manager, $installPath) { - $this->db = $db; + $this->db_manager = $db_manager; $this->installPath = $installPath; } function getSetupFile($name) { - return Path::join(call_user_func($this->installPath, $name), "setup.php"); + $setup = Path::join(call_user_func($this->installPath, $name), "install.json"); + return $setup; + } + + function getUninstallFile($name){ + return Path::join(call_user_func($this->installPath, $name), "sql", "uninstall.json"); } // Проверка версии обновления @@ -38,22 +43,33 @@ class Controller_Installer function installSQL(array $sql, $version_new, $version_old, $name) { - require_once "core/setup.php"; + $result = []; + $json_installer = new Database_JsonInstall($this->db_manager); foreach ($sql as $version => $install) { if (version_compare($version, $version_new, "<=") && version_compare($version, $version_old, ">")) { - // this->installPath this->db $file = Path::join(call_user_func($this->installPath, $name), "sql", $install); - Setup::batchSQL($this->db, $file); + $json_installer->install($file,null); + $result[] = $version; } } + return $result; } + function uninstall($name){ + $uninstall = $this->getUninstallFile($name); + if (file_exists($uninstall)) { + $json_installer = new Database_JsonInstall($this->db_manager); + $json_installer->install($uninstall,null); + } + $this->_registry->removeKey($name); + $this->_registry->write(); + } // Устанавливает обновления если есть function doUpdates($name, $force = false) // Установка модуля { + $result = array(); $setup = $this->getSetupFile($name); if (file_exists($setup) && ($this->isChanged($name) || $force)) { - $registry = $this->_registry; $settings = new Settings($setup); $settings->read(); @@ -67,21 +83,29 @@ class Controller_Installer $version_old = "0.0"; $registry->writeKey(array($name), array()); } - if (version_compare($version_old, $settings->get('version'), "!=")) { $sql = $settings->get('sql'); if (is_array($sql)) { - $this->installSQL($sql, $version_new, $version_old, $name); + $res = $this->installSQL($sql, $version_new, $version_old, $name); + 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->write(); } + return $result; + } + + function install($dbinit_path,$dbfill_path=null){ + $json_installer = new Database_JsonInstall($this->db_manager); + $json_installer->install($dbinit_path,$dbfill_path); } } - diff --git a/src/Controller/Model.php b/src/Controller/Model.php index 9c4dab7..4c1cbf9 100644 --- a/src/Controller/Model.php +++ b/src/Controller/Model.php @@ -28,38 +28,53 @@ class Controller_Model extends Controller_Action public function __construct() { - $this->path = new PathMenu(); - $this->menu = new PageMenu(); - $this->table = new ListTable(); + parent::__construct(); + $this->menu = new Widgets_PageMenu(); + $this->table = new Widgets_ReactListTable(); } /** */ - function setUp() - { - $this->table->addMenuItem($this->aUrl('delete'), 'удалить', false, 'all', 'warning'); - //$this->table->addMenuItem($this->nUrl('form'), 'редактировать', 'edit-24.png'); + function setUp() { + parent::setUp(); + $this->table->addMenuItem($this->aUrl('delete'), 'удалить', false, 'all', 'btn-danger', 'remove'); } - function saveParameters($args, $list) - { + function saveParameters(HttpRequest $args, $list) { foreach ($list as $item) { $args->session()->set(array($this, $item), $args->get($item)); } } - protected function getJSONList(/*Mapper*/ $model, Collection $request) - { + protected function getJSONList(/*.Model_Mapper.*/ $model, HttpRequest $request) { $result = array(); $this->saveParameters($request, array('size','page','desc', 'key')); $result['list'] = $model->findAll($request, $request->get('ref')); $result['size'] = $model->getCount($request, $request->get('ref')); - return json::encode($result); + return json_encode($result); } + protected function getCSV(Model_Mapper $model, HttpRequest $request, $title) { + $ref = $request->get('ref'); + + $list = $model->findAll($request, $request->get('ref')); + + header('Content-Type: text/csv; charset=utf-8'); + header('Content-Disposition: attachment; filename='.$title.'.csv'); + + echo "\xEF\xBB\xBF"; //UTF-8 BOM. + + $output = fopen('php://output', 'w'); + if (is_resource($output)) { + foreach ($list as $row) { + fputcsv($output, (array)$row,';'); + } + } + } + /** - * Удаление сторк из таблицы + * Удаление строк из таблицы */ public function actionDelete(HttpRequest $request) { @@ -68,7 +83,8 @@ class Controller_Model extends Controller_Action $list = ($request->get('table_item')) ? $request->get('table_item'): $request->get('id'); $model->deleteList($list); - return $this->getJSONList($model, $request); +// return $this->getJSONList($model, $request); + return json_encode(array('result' => 'ok')); } /** @@ -88,16 +104,29 @@ class Controller_Model extends Controller_Action public function actionList(HttpRequest $request) { $model = $this->getModel($this->useModel); + + if ($request->get('filter')) { + $data = new Collection(); + $data->import($request->get('filter')); + $model->addFilter($model->requestToSQL($data, $this->formSchema)); + } return $this->getJSONList($model, $request); } + public function actionCSV(HttpRequest $request) + { + $model = $this->getModel($this->useModel); + $title = $request->get("title"); + if(!$title){ + $title = "noname"; + } + return $this->getCSV($model, $request, $title); + } private function setFormSchema() { - require_once 'core/mapper/uimapper.php'; - $model = $this->getModel($this->useModel); - $ui = new UIMapper($model); + $ui = new Model_UIMapper($model); $this->formSchema = $ui->getFormSchema(); } @@ -105,29 +134,29 @@ class Controller_Model extends Controller_Action /** * Сохранение формы */ - function beforeSave(/*Model*/ $item, Collection $request) + function beforeSave(/*Model*/ $item, HttpRequest $request) { if (empty($this->formSchema)) { $this->setFormSchema(); } - // Сделать отображение Формы в обьект и обратно <-- Убрать в beforeSave + // Сделать отображение Формы в обьект и обратно foreach ($this->formSchema as $key => $conv) { list($value, $type) = $conv; - $item->$value = call_user_func(array('Cast', 'to_' . $type), $request->get($key)); // Здесть нужно преобразовывать тип значения + $item->$value = call_user_func(array('Primitive', 'to_' . $type), $request->get($key)); // Здесь нужно преобразовывать тип значения } } /** * Обновление формы */ - function formUpdate(TForm $form, Collection $request) - { + function formUpdate(Form_Form $form, HttpRequest $request) { + $form->setValues($request); } /** * Загрузка формы */ - function beforeLoad(/*Model*/ $item, TForm $form) + function beforeLoad(/*.Model_Model.*/$item, Form_Form $form) { if (empty($this->formSchema)) { $this->setFormSchema(); @@ -137,8 +166,13 @@ class Controller_Model extends Controller_Action $form->fill($item, $this->formSchema); } + function beforeFirstLoad(Form_Form $form) + { + + } + // Проверка ввода - protected function validate($validator, $request) + protected function validate(Validator_Validator $validator, Collection $request) { } @@ -147,8 +181,7 @@ class Controller_Model extends Controller_Action */ public function actionValidate($request) { - require_once "core/validator/validator.php"; - $validator = new Validator(); + $validator = new Validator_Validator(); $validator->addRuleList($this->schema); // Действия до проверки формы @@ -156,19 +189,19 @@ class Controller_Model extends Controller_Action $validator->validate($request); // --| // Проверка формы if (!$validator->isValid()) { - return json::encode($validator->getErrorMsg()); + return json_encode($validator->getErrorMsg()); } - return json::encode(true); + return json_encode(true); } /** * Инициализация формы */ - protected function formSetup($form, $id = null, $ref = null) + protected function formSetup(Form_Form $form, $id = null, $ref = null) { if (empty($this->schema)) { $model = $this->getModel($this->useModel); - $ui = new UIMapper($model); + $ui = new Model_UIMapper($model); $schema = $ui->getEditSchema(); $form->addFieldList($schema); @@ -178,71 +211,57 @@ class Controller_Model extends Controller_Action } /** - * Добавление пользователя + * Добавление */ public function actionAdd(HttpRequest $request) { - require_once "core/validator/validator.php"; // {{{ тоже может быть один ref или несколько $ref = $request->get('ref'); $this->addParameter('ref', $ref); // Добавляет параметр в url /// }}} - if ($this->checkPageId($request, $request->get('page'))) { - // Проверка - $validator = new Validator(); - $validator->addRuleList($this->schema); - - // Действия до проверки формы - $this->validate($validator, $request); // <--| - $validator->validate($request); // --| - // Проверка формы - if (!$validator->isValid()) { - $request->setAction('form'); - $this->getActionPath($request); + // Проверка + $validator = new Validator_Validator(); + $validator->addRuleList($this->schema); - $form = new TForm(); - $this->formSetup($form, $request->get('id'), $request->get('ref')); // Инициализация формы + // Действия до проверки формы + $this->validate($validator, $request); // <--| + $validator->validate($request); // --| + // Проверка формы + if (!$validator->isValid()) { + return json_encode(array('result'=>'fail','errors'=>$validator->getErrorMsg())); + } + // Нужен тест для формы + $model = $this->getModel($this->useModel); + $className = $model->className; + $item = new $className(); - $form->setValues($request); // <-- Убрать в formUpdate - $this->formUpdate($form, $request); + // Сохраняем значение в базе данных + $item->id = $request->get('id'); + // Если таблица связана с другой таблицей + if ($request->get('ref') && $model->reference[1]) { + $ref_id = $model->reference[1]; + $item->$ref_id = $request->get('ref'); + } - $form->setError($validator); // Установка ошибок для формы + // Подготовка к сохранению + $this->beforeSave($item, $request); // Сюдаже и истрия переходов + // nextId ??? или выход или новая форма для создания новости + + $id = $model->saveDB($item, $request); - $tpl = $this->formPage($form, $request); - $id = $request->get('id'); - if ($id) { // Редактирование - $tpl->action = forceUrl($this->nUrl('add', array('id' => $id, 'page' => $this->getPageId($request)))); // action Совйство формы - } - return $tpl /*->execute()*/; - } - - // Нужен тест для формы - $model = $this->getModel($this->useModel); - $className = $model->className; - $item = new $className(); - - // Сохраняем значение в базе данных - $item->id = $request->get('id'); - // Если таблица связана с другой таблицей - if ($request->get('ref') && $model->reference[1]) { - $ref_id = $model->reference[1]; - $item->$ref_id = $request->get('ref'); - } - - // Подготовка к сохранению - $this->beforeSave($item, $request); // Сюдаже и истрия переходов - // nextId ??? или выход или новая форма для создания новости - $model->saveDB($item, $request); - } - - // Для страницы со списком id -> идентефикатор родительской таблицы !!?? + // Для страницы со списком id -> идентификатор родительской таблицы !!?? // $request->set('id', $request->get('ref')); if ($request->get('apply')) { $request->setAction('form'); - return $this->forward('actionForm', $request); + return (string) $this->forward('actionForm', $request); } - return $this->forward('actionIndex', $request); + //$request->setAction('index'); + $result = array('result'=>'ok'); + if($id){ + $result['action'] = forceUrl($this->nUrl('add', array('id' => $id, 'ref' => $request->get('ref')))); + } + return json_encode($result); } /** @@ -275,38 +294,40 @@ class Controller_Model extends Controller_Action $this->setTitlePath($ref); $model = $this->getModel($this->useModel); - $form = new TForm(); // Показываем форму + $form = new Form_Form(); // Показываем форму $form->header = 'Редактирование записи'; $this->formSetup($form, $request->get('id'), $request->get('ref')); // Инициализация формы $list = $request->get('table_item'); $id = ($list[0]) ? $list[0] : $request->get('id'); - - $tpl = $this->formPage ($form, $request); + // + $tpl = $this->formPage($form, $request); if ($id) { // Редактирование $form->action = forceUrl($this->nUrl('add', array('id' => $id, 'page' => $this->getPageId($request)))); // action Свойство формы $item = $model->findById($id); // Загрузка формы $this->beforeLoad($item, $form); - /// + }else{//Создание нового элемента + $this->beforeFirstLoad($form); } - return $tpl; + return json_encode($tpl); } /** */ - function tableSetup($table, $id = null, $ref = null) + function tableSetup(Widgets_ListTable $table, $id = null, $ref = null) { // FIXME: После замены везде $tableSchema -> table->setHeader удалить! if ($this->tableSchema) { $table->setHeader($this->tableSchema); } else { // Настройка таблицы отображения по схеме данных - require_once 'core/mapper/uimapper.php'; $model = $this->getModel($this->useModel); - $ui = new UIMapper($model); - $schema = $ui->getTableSchema(); - $schema[0]['action'] = $table->getFirstItem(); + $ui = new Model_UIMapper($model); + $ui->hidden = $table->hidden; + + $schema = $ui->getTableSchema(); + $schema[0]['action'] = forceUrl($table->getFirstItem()); $table->setHeader($schema); } @@ -314,7 +335,7 @@ class Controller_Model extends Controller_Action /** */ - public function actionIndex(HttpRequest $request) + public function actionDefault(HttpRequest $request) { $this->getActionPath($request, 'index'); // Такое мета действие наверное можно вынести в отдельный класс @@ -335,14 +356,14 @@ class Controller_Model extends Controller_Action $ref = $request->session()->get('ref'); } - $request->session->set('ref', $ref); + $request->session()->set('ref', $ref); $this->addParameter('ref', $ref); // }}} $this->setTitlePath($ref); - $tpl = $this->getView('list'); + $tpl = new stdClass(); - // Помошники действий + // Помощники действий $this->callHelpers($request); // Таблица if ($request->session()->get(strtolower(get_class($this)))) { @@ -355,7 +376,7 @@ class Controller_Model extends Controller_Action 'size' => $session['size'], 'desc' => $session['desc'])); - $this->table->setData('sorter', $session['key']); + //$this->table->setData('sorter', $session['key']); if (isset($session['desc'])) { $this->table->setData('desc', $session['desc']); } @@ -363,64 +384,137 @@ class Controller_Model extends Controller_Action call_user_func($setup, $this->table, $request->get('id'), $ref);// --> Эквивалент formSetup $this->table->setAction($list); - // + if (!$this->table->getData('module')) { + $this->table->setData('module', strtolower($this->useModel)); + } $tpl->menu_path = $this->path->getItems(); - // Поиск - $search = new SearchDialog(); - $search->setTitle('Поиск'); - $search->setAction($this->aUrl('search')); - $search->setFriend($this->table); - $search->addFields($this->schemaSearch); + $this->table->makeData(); + $tpl->table = array('data' => $this->table->data); + $tpl->menu = $this->menu->menu->getItems(); + $tpl->path = $this->path->getItems(); - // Настройки - $setup = new SetupDialog(); - $setup->setTitle('Настройки'); - $setup->setAction($this->nUrl('setup')); - $setup->setFriend($this->table); - - // Меню - $this->menu->addMenuItem('?menu=toggle&id=' . $search->getName(), 'поиск', 'actions/system-search'); // Стандартный размер для иконок 22-24px - $this->menu->addMenuItem('?menu=toggle&id=' . $setup->getName(), 'настройки', 'categories/applications-system'); - // Добавление компонентов - $this->addChild('menu', $this->menu); - $this->addChild('search', $search); - $this->addChild('setup', $setup); - $this->addChild('table', $this->table); - // - return $tpl; + return json_encode($tpl); } /** */ - public function actionSetup($request) - { + public function actionSetup(HttpRequest $request) { $left = explode(",", $request->get('left')); $right = explode(",", $request->get('right')); - $$request->session()->set(strtolower(get_class($this)), - array('view' => array('left' => $left, 'right' => $right))); + $request->session()->set(strtolower(get_class($this)), + array('view' => array('left' => $left, 'right' => $right), 'page' => 1, 'size' => 0, 'desc' => 'asc', 'key' => false)); return $this->forward('actionIndex', $request); } /** */ - private function formPage($form, $request) - { - $view = $this->getView('form'); - $view->setView('form', $form); - $view->action = forceUrl($this->nUrl('add', array('page' => $this->getPageId($request)))); // Действие для формы + protected function formPage($form, $request, $template = 'form') { + $view = new stdClass();//$this->getView($template); + $view->form = $form; + $form->action = forceUrl($this->nUrl('add', array('page' => $this->getPageId($request)))); // Действие для формы - $view->menu_path = $this->path->getItems(); + $view->path = $this->path->getItems(); $view->back = $this->path->getPrev(); return $view; } + function _getActionPath() { + return new Controller_State('index'); + } + // Тоже убрать в метод Controller_Model - function getActionPath(HttpRequest $request/*, $action = false*/) - { - require_once 'state.php'; + function getActionPath(HttpRequest $request, $action = null) { $this->_getActionPath()->getPath($this, ($action) ? $action : $request->getAction()); } + + + function parse_params($expression) { + $expression = htmlspecialchars_decode($expression); + $offset = strpos($expression, '?'); + $url = parse_url($expression); + + $arguments = array(); + if ($offset === false) { + $path = $expression; + } else if (is_int($offset)) { + $path = substr($expression, 0, $offset); + $query = substr($expression, $offset+1); + parse_str($query, $arguments); + } + return $arguments; + } + + public function actionFormPage(HttpRequest $request) { + //$tpl = $this->getView('formpage', 'View_Top'); + + $view = $this->getView('formpage', 'View_Top'); + + $params = $this->parse_params($request->get('params')); + + +// $model = $this->getModel($this->useModel); + $form = new Form_Form(); // Показываем форму + $form->header = 'Редактирование записи'; + $this->formSetup($form, $request->get('id'), $request->get('ref')); // Инициализация формы + /* + $ui = new Model_UIMapper($model); + $schema = $ui->getEditSchema(); + $form->addFieldList($schema); + */ + + $list = $request->get('table_item'); + $id = ($list[0]) ? $list[0] : $request->get('id'); + +// $tpl = $this->formPage($form, $request); + + $view->setView('form', $form); + $view->action = forceUrl($this->nUrl('addpage', array('ref' => $params['id']))); // Действие для формы + +// $view->menu_path = $this->path->getItems(); + $view->back = ''; + return $view; + +// return $tpl; + } + + /* Для поддержки редактрования на сайте */ + public function actionAddPage(HttpRequest $request) + { + // {{{ тоже может быть один ref или несколько + $ref = $request->get('ref'); + $this->addParameter('ref', $ref); // Добавляет параметр в url + /// }}} + $validator = new Validator_Validator(); + $validator->addRuleList($this->schema); + + // Действия до проверки формы + $this->validate($validator, $request); // <--| + $validator->validate($request); // --| + // Проверка формы + if (!$validator->isValid()) { + return $validator; + } + + // Нужен тест для формы + $model = $this->getModel($this->useModel); + $className = $model->className; + $item = new $className(); + + // Сохраняем значение в базе данных + $item->id = $request->get('id'); + // Если таблица связана с другой таблицей + if ($request->get('ref') && $model->reference[1]) { + $ref_id = $model->reference[1]; + $item->$ref_id = $request->get('ref'); + } + + // Подготовка к сохранению + $this->beforeSave($item, $request); // Сюдаже и истрия переходов + $model->saveDB($item, $request); + + return null; + } } diff --git a/src/Database/PDOStatement.php b/src/Database/PDOStatement.php index 4561611..4df5db7 100644 --- a/src/Database/PDOStatement.php +++ b/src/Database/PDOStatement.php @@ -1,5 +1,7 @@ fields[$name]); + return strToArray($this->fields[$name]); } function getRecordCount() { diff --git a/src/Filter/Login.php b/src/Filter/Login.php index 7b0c8ea..4ce7302 100644 --- a/src/Filter/Login.php +++ b/src/Filter/Login.php @@ -13,6 +13,9 @@ class Filter_Login extends Filter_Filter const SESSION_BROWSER_SIGN_SECRET = '@w3dsju45Msk#'; const SESSION_BROWSER_SIGN_KEYNAME = 'session.app.browser.sign'; public $mode = 'ajax'; + + //AJAX-Реквесты для которых не требуется авторизация, потребовалось для сбора статистики + public $whiteRequestList = array(array('module' => "requiredcontent", "action" => "getcount")); /** * Проверка авторизации * @return Boolean Авторизовани пользователь или нет @@ -20,7 +23,7 @@ class Filter_Login extends Filter_Filter public function isLoggin(HttpRequest $request) { // Авторизация - // session_start(); + session_start(); $db = $this->getConnection(); Filter_UserAccess::setUp($db); // Соединение switch ($request->getAction()) { @@ -31,7 +34,18 @@ class Filter_Login extends Filter_Filter $result = Filter_UserAccess::getUserByLogin($login); // Поиск по логину if ($result) { - if (md5($password) == $result->getString('password')) { // password + $userPassword = $result->getString('password'); + if (Filter_UserAccess::$access == 'site_root' && defined('PARENT_PATH')) { + $s = new Settings(PARENT_PATH . '/settings.json'); + $s->read(); + $dsn = $s->readKey(array('system', 'dsn')); + + $db = Database::getConnection($dsn); + $user = $db->fetchOneArray("SELECT * FROM users WHERE login = :login", ['login' => $login]); + $userPassword = $user['password']; + } + // Извлечнеие пользователя из родительской CMS, для проверки пароля + if (md5($password) == $userPassword) { // password $this->enter($db, $result); return true; } @@ -45,7 +59,7 @@ class Filter_Login extends Filter_Filter case 'enter': $login = $request->get('login'); $password = $request->get('sid'); - $result = UserAccess::getUserByLogin($login); // Поиск по логину + $result = Filter_UserAccess::getUserByLogin($login); // Поиск по логину if ($result) { $temp = md5($result->getString('password') . $result->getString('login') . $result->getString('sid')); if ($password == $temp) { @@ -57,12 +71,15 @@ class Filter_Login extends Filter_Filter default: $hash = $this->getBrowserSign(); // Если $hash не совпадает $_SESSION['hash'] то удаляем сессию - if (isset($_SESSION ['access']) && isset($_SESSION[self::SESSION_BROWSER_SIGN_SECRET])) { - if ($hash == $_SESSION[self::SESSION_BROWSER_SIGN_SECRET]) { - UserAccess::getUserById($_SESSION ['access']); // Поиск по идентификатору + 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']); // Поиск по идентификатору + if ($user && isset($_SESSION['random']) && ($user->get('sid') == $_SESSION['random'])) { + return true; + } return true; } else { - session_destroy(); + session_destroy(); } } } @@ -72,9 +89,9 @@ class Filter_Login extends Filter_Filter private function getBrowserSign() { $rawSign = self::SESSION_BROWSER_SIGN_SECRET; - $signParts = array('HTTP_USER_AGENT', 'HTTP_ACCEPT_ENCODING'); + //$signParts = array('HTTP_USER_AGENT', 'HTTP_ACCEPT_ENCODING'); + $signParts = array(); - $rawSign = ''; foreach ($signParts as $signPart) { $rawSign .= '::' . (isset($_SERVER[$signPart]) ? $_SERVER[$signPart] : 'none'); } @@ -83,23 +100,78 @@ class Filter_Login extends Filter_Filter private function enter($db, $result) { - $db->executeQuery("UPDATE users SET sid = '' WHERE id_user = " . $result->getInt('id_user')); + $this->user = $result; + $random = rand(0, 1024 * 1024); + $db->executeQuery("UPDATE users SET sid = '$random' WHERE id_user = " . $result->getInt('id_user')); - $_SESSION ["group"] = $result->getInt('access'); - $_SESSION ["access"] = $result->getInt('id_user'); // id_user - $_SESSION [self::SESSION_BROWSER_SIGN_SECRET] = $this->getBrowserSign(); - $_SESSION ["time"] = time(); + $_SESSION["group"] = $result->getInt('access'); + $_SESSION["access"] = $result->getInt('id_user'); // id_user + $_SESSION["random"] = $random; // id_user + $_SESSION[self::SESSION_BROWSER_SIGN_KEYNAME] = $this->getBrowserSign(); + $_SESSION["time"] = time(); } public function execute(HttpRequest $request) { - if (!$this->isLoggin($request)) { - // Параметры при неправильной авторизации - // Действия по умолчанию !! Возможно переход на форму регистрации - $request->set('module', 'login'); - $request->set('mode', $this->mode); + $logged = $this->isLoggin($request); + if ($request->get('action') == 'user_access') { + if ($logged) { + $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 { + return json_encode("NOT AUTHORIZED"); + } } - return $this->processor->execute($request); + + if ($request->get('action') == 'relogin') { + if ($logged) { + return json_encode(array('result' => 'ok', 'message' => "Авторизация успешна")); + } else { + return json_encode(array('result' => 'fail', 'message' => "Неправильное имя пользователя или пароль")); + } + } + + if (!$logged) { + // Параметры при неправильной авторизации + // Действия по умолчанию !! Возможно переход на форму регистрации + if ($request->get('mode') == 'ajax') { + if (!$this->requestIsWhite($request, $this->whiteRequestList)) { + return json_encode(array('result' => 'fail', 'message' =>"NOT_AUTHORIZED")); + } + } else { + $request->set('module', 'login'); + $request->set('mode', $this->mode); + } + } else if (isset($_SERVER['HTTP_REFERER'])) { + $arr = array(); + parse_str(parse_url($_SERVER['HTTP_REFERER'], PHP_URL_QUERY), $arr); + if (isset($arr['back_page']) && $request->get('mode') != 'ajax') { + $request->redirect($arr['back_page']); + } + } + + $text = $this->processor->execute($request); + return $text; + } + + /* --------------------- + * Проверка на попадание реквеста в белый список + */ + + public function requestIsWhite(Collection $request, $whiteRequestList){ + $module = $request->get('module'); + $action = $request->get('action'); + foreach ($whiteRequestList as $whiteRequest) { + if ($module == $whiteRequest['module'] && $action == $whiteRequest['action']) { + return true; + } + } + + return false; } } diff --git a/src/Form/Form.php b/src/Form/Form.php index 7d38691..aa68acc 100644 --- a/src/Form/Form.php +++ b/src/Form/Form.php @@ -20,68 +20,147 @@ class TField public $description = ""; public $alias = array(); - public function __construct ($input) + public function __construct ($input = array(), $factory = null) { - $this->deafult = null; + + $this->default = null; if (isset($input['validate'])) { - $this->require = strpos($input['validate'], 'require') !== false; + $this->require = strpos($input['validate'], 'require') !== false; } // Инициализация свойст обьетка - foreach (array('label', 'name', 'type') as $name) { - $this->$name = $input[$name]; + foreach (array('label', 'name', 'type', 'description') as $name) { + if (isset($input[$name])) { + $this->$name = $input[$name]; + } } } - function setValue($value) + function setValue(/*.any.*/$value) { $this->value = $value; } + + function getId() + { + return $this->name . '_label'; + } } /** * Поле ввода Input - * @package core */ class TInput extends TField { } +class TCheckbox extends TField +{ + public $checked = false; + function setValue($value) + { + $this->value = $value; + $this->checked = $value; + } +} + + +class TSelect extends TField +{ + public $options = array(); + + public function __construct ($input, $factory) { + parent::__construct($input, $factory); + + if ($factory != null) { + $factory->create($this, $input); + } else if (isset($input['options.pair'])) { + $this->options = $this->optionsPair($input['options.pair']); + } else if (isset($input['options'])) { + $this->options = $input['options']; + } + + foreach ($this->options as &$option) { + $option['selected'] = false; + $option['class'] = (isset($option['class'])) ? $option['class'] : false; + } + } + + public function optionsPair($list, $selected = false) { + $result = array(); + foreach ($list as $key => $value) { + $result [] = array('value' => $key, 'name' => $value, 'selected' => $key == $selected); + } + return $result; + } +} + /** * Выбор из одного элемента */ -class TSelect1 extends TField +class TSelectOne extends TSelect { - public $options = array (); - public function __construct ($input) { - parent::__construct($input); - $this->options = $input['options']; - } - function setValue($value) { // Установить selected у options $this->value = $value; + foreach ($this->options as &$option) { + $option['selected'] = ($option['value'] == $value); + } + } +} + +class TSelectMany extends TSelect +{ + function setValue($value) + { + // Установить selected у options + if (!is_array($value)) { $value = array($value); } + $this->value = $value; + foreach ($this->options as &$option) { + $option['selected'] = (in_array($option['value'], $value)); + } + } +} + +class TQuestionType extends TSelect +{ + function setValue($value) + { + // Установить selected у options + $this->value = $value; + foreach ($this->options as &$option) { + $option['selected'] = ($option['value'] == $value); + } } } /** * Поле с датой - * @package core */ class TDate extends TField { } -/* * +/** + * Поле с цветом + */ +class TColor extends TField +{ +} + + +/** * Текстовое поле - * @package core */ class TTextArea extends TField { + function setValue($value) + { + $this->value = $value; + } } /** * Поле для ввода пароля - * @package core */ class TSecret extends TField { @@ -91,62 +170,181 @@ class TUpload extends TField { } +class THidden extends TInput { + public $hidden = true; +} + +class TComponentBrowserInput extends TInput +{ +} + +/** + * При рендеринге каждому классу соответствует шаблон (см. themes/maxim/templates/macros.html) + */ +class TDateTime extends TInput { +} + +class OptionFactory { + public $db; + + function __construct($db) { + $this->db = $db; + } + + function create(TSelect $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); + + $field->options = $this->optionsDB($key, $value, $this->db->executeQuery("SELECT * FROM $table")); + } elseif (isset($input['options.pair'])) { + $field->options = $this->optionsPair($input['options.pair']); + } else { + $field->options = $input['options']; + } + } + + 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; + } +} + /** * Форма для ввода - * @package core */ -class Form_Form -{ - public $field = array (); +class Form_Form extends View_View { + public $field = array(); public $action = ""; public $method = 'post'; + public $header; + protected $replace; protected $before; + + public $_title = array(); + public $alias = array(); + public $constructor = array(); - public function __construct () + /** + * Строим форму по ее структуре. Каждому типу соответствует определенный класс. + */ + public function __construct() { - $this->constructor = array ( - 'input' => 'TInput', - 'date' => 'TDate', - 'textarea' => 'TTextArea', - 'select' => 'TSelect', - 'select1' => 'TSelect1', - 'secret' => 'TSecret', - 'upload' => 'TUpload' + $this->constructor = array( + 'input' => 'TInput', + 'inputreq' => 'TInput', // input с проверкой на заполненность + + 'date' => 'TDate', + 'datereq' => 'TDate', + 'datetime' => 'TDateTime', + + 'color' => 'TColor', + 'textarea' => 'TTextArea', + 'text' => 'TTextArea', + 'multiselect' => 'TSelectMany', +// 'selectmany' => 'TSelectMany', + 'select1' => 'TSelectOne', + 'select' => 'TSelectOne', + 'questiontype'=> 'TQuestionType', + 'secret' => 'TSecret', + 'upload' => 'TUpload', + 'image' => 'TUpload', + 'checkbox' => 'TCheckbox', + 'checkmany' => 'TSelectMany', + 'hidden' => 'THidden', + 'radio' => 'TSelectOne', + 'filebrowser' => 'TComponentBrowserInput', ); + } + + function getId() + { + return '_form_edit'; + } + + public function addFieldClass($name, $class) + { + $this->constructor [$name] = $class; + } /** * Добавляет одно поле ввода на форму */ - public function addField (array $init) + public function addField(array $init, $factory = null) { - assert (isset($init['type'])); - assert (isset($init['name'])); + assert(isset($init['type'])); + assert(isset($init['name'])); + +// print_r($init); $constructor = $this->constructor[$init['type']]; - $el = new $constructor ($init); - $el->type = $init['type']; + $el = new $constructor($init, $factory); + if (!$el->type) { + $el->type = $init['type']; + } + if(isset($init['hint'])) { + $el->hint = $init['hint']; + } + $this->field [$init['name']] = $el; return $el; } /** - * Добавляет спсок полей для формы + * Добавляет список полей для формы * @param array $list */ - public function addFieldList (array $list) + public function addFieldList(array $list, $factory = null) { foreach ($list as $init) { - $this->addField ($init); + $this->addField($init, $factory); } } /** * Устанавливает ошибки после проверки */ - function setError (Validator $validator) + function setError(Validator_Validator $validator) { foreach ($validator->getErrorMsg() as $name => $error) { @@ -155,12 +353,18 @@ class Form_Form } } + function setFieldError($name, $message) + { + $this->field[$name]->error = true; + $this->field[$name]->error_msg = $message; + } + /** * Устанавливает значения из масива */ - function setValues (Collection $request) { + function setValues(HttpRequest $request) { foreach ($this->field as $key => $el) { - $value = $request->getRawData ($this->method, $key); + $value = $request->getRawData($this->method, $key); $this->field[$key]->setValue($value); } } @@ -170,10 +374,11 @@ class Form_Form * @param object $data * @param array $schema Связь между элементами формы и свойствами обьекта */ - public function fill ($data, array $schema) + public function fill($data, array $schema) { - foreach ($schema as $key => $value) { - $this->field [$value]->setValue($data->$value->getString ()); + foreach ($schema as $key => $conv) { + list($value, $type) = $conv; + $this->field [$key]->setValue(call_user_func(array('Primitive', 'from_' . $type), $data->$value)); } } @@ -181,4 +386,9 @@ class Form_Form { $this->field[$name]->setValue($value); } + + function execute() + { + return $this; + } } diff --git a/src/Primitive.php b/src/Primitive.php index e9dab1a..aec45fd 100644 --- a/src/Primitive.php +++ b/src/Primitive.php @@ -1,103 +1,119 @@ name = $name; + return ((string) $value); } - // Преобразование из внешнего вормата - public function setString ($value) + public static function from_varchar($value) { - $this->value = $value; + return $value; } - // Преобразование из формата базы данных - public function setRes ($res, $key) + // int + public static function to_bool($value) { - $this->value = $res->getString ($key); + return filter_var($value, FILTER_VALIDATE_BOOLEAN);//(int)((bool) $value); } - public function __toString () + public static function from_bool($value) { - return ((string) $this->value); + return ((bool) $value); } - // Преобразование во внешний формат - public function getString () + // int + public static function to_int($value) { - return $this->__toString (); - } -} - -/** - * Отображение поля таблицы в целое число - * @package core - */ -class Int4 extends Primitive { - public function setRes ($res, $key) { - $this->value = $res->getInt ($key); + return ((int) $value); } - public function setString ($value) { - $this->value = ((int) $value); - } -} - -/* Foreign key */ -class FKey extends Int4 {} - -/** - * Отображение поля таблицы в дату - время - */ -class Date extends Primitive -{ - public function setRes ($res, $key) + public static function from_int($value) { - $this->value = $res->getInt ($key); + return ((string) $value); } - - public function setString ($value) + + // date + public static function to_date($value) { - $this->value = 0; - if ($tmp = explode("/",$value,3)) { - if ($tmp[1] && $tmp[0] && $tmp[2]) { - if (checkdate($tmp[1], $tmp[0], $tmp[2])) { - $this->value = mktime(0, 0, 0, $tmp[1], $tmp[0], $tmp[2]); + $result = 0; + $tmp = explode("/", $value, 3); + if (!empty($tmp)) { + if (count($tmp) != 3) return $result; + + $year = intval($tmp[2]); + $month = intval($tmp[1]); + $day = intval($tmp[0]); + + if ($month != 0 && $day != 0 && $year != 0) { + if (checkdate($month, $day, $year)) { + return mktime(0, 0, 0, $month, $day, $year); + } else { + return 0; } } } + return $result; } - public function getString () + public static function to_datetime($value) { - return date ("d/m/Y", $this->value); + $result = 0; + + $tmp = array(); + if (preg_match('/(\d+)-(\d+)-(\d+)T(\d+):(\d+)Z/', $value, $tmp)) { + if (checkdate($tmp[2], $tmp[3], $tmp[1])) { + $result = mktime($tmp[4], $tmp[5], 0, $tmp[2], $tmp[3], $tmp[1]); + } + } + return $result; + } + + public static function from_date($value) + { + if ($value > 0) { + return date("d/m/Y", $value); + } + return ''; + } + + public static function from_datetime($value) + { + if ($value > 0) { + return date("Y-m-d\TH:i\Z", $value); + } + return ''; + } + + + // secure + public static function to_secure($value) + { + // Значение приабразуется во время сохранения в базе данных + return $value; + } + + public static function from_secure($value) + { + return $value; + } + + // array + public static function to_array($value) + { + return (is_array($value)) ? $value : array(); + } + + public static function from_array($value) + { + return $value; } } -/** - * - */ -class Password extends Primitive -{ - public function setRes ($res, $key) - { - $this->value = $res->getString($key); - } - - public function setString ($value) - { - $this->value = md5($value); - } - - public function getString () - { - return $this->value; - } -} diff --git a/src/Tools/String.php b/src/Tools/String.php index 1745b25..32aeb3b 100644 --- a/src/Tools/String.php +++ b/src/Tools/String.php @@ -1,53 +1,107 @@ 0) { // already in sub-array? - $subarr[$in_subarr][] = $tok; - if ('}' === substr($tok, -1, 1)) { // check to see if we just added last component - $res[] = $this->strToArray(implode(',', $subarr[$in_subarr])); - $in_subarr--; - } - } elseif ($tok{0} === '{') { // we're inside a new sub-array - if ('}' !== substr($tok, -1, 1)) { - $in_subarr++; - // if sub-array has more than one element - $subarr[$in_subarr] = array(); - $subarr[$in_subarr][] = $tok; - } else { - $res[] = $this->strToArray($tok); - } - } else { // not sub-array - $val = trim($tok, '"'); // remove " (surrounding strings) - // perform type castng here? - $res[] = $val; - } - } - - return $res; - } - - - static function translit($st) { - $st = strtr($st,"абвгдеёзийклмнопрстуфхъыэ !№", "abvgdeeziyklmnoprstufh_ie__#"); - $st = strtr($st,"АБВГДЕЁЗИЙКЛМНОПРСТУФХЪЫЭ", "ABVGDEEZIYKLMNOPRSTUFH_IE"); - $st = strtr($st, array( - "ж"=>"zh", "ц"=>"ts", "ч"=>"ch", "ш"=>"sh", - "щ"=>"shch","ь"=>"", "ю"=>"yu", "я"=>"ya", - "Ж"=>"ZH", "Ц"=>"TS", "Ч"=>"CH", "Ш"=>"SH", - "Щ"=>"SHCH","Ь"=>"", "Ю"=>"YU", "Я"=>"YA", - "ї"=>"i", "Ї"=>"Yi", "є"=>"ie", "Є"=>"Ye" - )); - return $st; - } +// from creole +function strToArray($str) { + $str = substr($str, 1, -1); // remove { } + $res = array(); + + $subarr = array(); + $in_subarr = 0; + + $toks = explode(',', $str); + foreach($toks as $tok) { + if ($in_subarr > 0) { // already in sub-array? + $subarr[$in_subarr][] = $tok; + if ('}' === substr($tok, -1, 1)) { // check to see if we just added last component + $res[] = strToArray(implode(',', $subarr[$in_subarr])); + $in_subarr--; + } + } elseif ($tok{0} === '{') { // we're inside a new sub-array + if ('}' !== substr($tok, -1, 1)) { + $in_subarr++; + // if sub-array has more than one element + $subarr[$in_subarr] = array(); + $subarr[$in_subarr][] = $tok; + } else { + $res[] = strToArray($tok); + } + } else { // not sub-array + $val = trim($tok, '"'); // remove " (surrounding strings) + // perform type castng here? + $res[] = $val; + } + } + + return $res; +} + +//Нормализация строк на русском +function normalizeRussian($str) { + $result = preg_replace('/\s+/',' ', $str); + if (is_string($result)) { + $result = trim($result); //Замена длинных пробелов на одинарные, пробелы по краям + $result = mb_strtolower($result); + $result = preg_replace('/ё/','е', $str); //е на ё + } + return $result; +} + +//Проверка равенства двух строк на русском языке. +function equalRussianCheck($str1,$str2) { + return normalizeRussian($str1) == normalizeRussian($str2); +} + + +/** + * Попадает ли строка в список вариантов + * input: $str="foo1" $variants="foo1|foo2|foo3" + * output: true + * input: $str="foo" $variants="foo1|foo2|foo3" + * output: false +*/ +function compare_string_to_variants($str, $variants){ + $variants_array = explode('|', $variants); + $founded = false; + foreach ($variants_array as $variant) { + $founded = $founded || equalRussianCheck($variant, $str); + } + return $founded; +} + +function mb_str_split($str) { + return preg_split('~~u', $str, null, PREG_SPLIT_NO_EMPTY); +} + +function mb_strtr($str, $from, $to) { + return str_replace(mb_str_split($from), mb_str_split($to), $str); +} + +function encodestring($st) { + $st = mb_strtr($st,"абвгдеёзийклмнопрстуфхъыэ !+-()", "abvgdeeziyklmnoprstufh_ie______"); + $st = mb_strtr($st,"АБВГДЕЁЗИЙКЛМНОПРСТУФХЪЫЭ", "ABVGDEEZIYKLMNOPRSTUFH_IE"); + $st = strtr($st, array( + " " => '_', + "." => '_', + "," => '_', + "?" => '_', + "\"" => '_', + "'" => '_', + "/" => '_', + "\\" => '_', + "%" => '_', + "#" => '_', + "*" => '_', + "ж"=>"zh", "ц"=>"ts", "ч"=>"ch", "ш"=>"sh", + "щ"=>"shch","ь"=>"", "ю"=>"yu", "я"=>"ya", + "Ж"=>"ZH", "Ц"=>"TS", "Ч"=>"CH", "Ш"=>"SH", + "Щ"=>"SHCH","Ь"=>"", "Ю"=>"YU", "Я"=>"YA", + "Й"=>"i", "й"=>"ie", "ё"=>"Ye", + "№"=>"N" + )); + return strtolower($st); +} + +function validate_encoded_string($st) { + $enc_st = encodestring($st); + return preg_match('/^[\w_-]+(\.[\w_-]+)?$/', $enc_st); } diff --git a/src/Validator/Rule/Alpha.php b/src/Validator/Rule/Alpha.php index 02b422e..2443da1 100644 --- a/src/Validator/Rule/Alpha.php +++ b/src/Validator/Rule/Alpha.php @@ -3,7 +3,7 @@ /** * Проверка на число */ -class Validator_Rule_Alpha extends Rule_Abstract +class Validator_Rule_Alpha extends Validator_Rule_Abstract { public function getErrorMsg() { diff --git a/src/Validator/Rule/Date.php b/src/Validator/Rule/Date.php index 8b40b4d..be8e17e 100644 --- a/src/Validator/Rule/Date.php +++ b/src/Validator/Rule/Date.php @@ -3,7 +3,7 @@ /** * Проверка формата даты */ -class Validator_Rule_Date extends Rule_Abstract +class Validator_Rule_Date extends Validator_Rule_Abstract { private $split = "\\/"; diff --git a/src/Validator/Rule/Email.php b/src/Validator/Rule/Email.php index e40486a..dd2b0e0 100644 --- a/src/Validator/Rule/Email.php +++ b/src/Validator/Rule/Email.php @@ -3,7 +3,7 @@ /** * Проверка формата электронной почты */ -class Validator_Rule_Email extends Rule_Abstract +class Validator_Rule_Email extends Validator_Rule_Abstract { public function getErrorMsg() { diff --git a/src/Validator/Rule/EmailList.php b/src/Validator/Rule/EmailList.php index 16bdd50..98ac122 100644 --- a/src/Validator/Rule/EmailList.php +++ b/src/Validator/Rule/EmailList.php @@ -3,7 +3,7 @@ /** * Проверка формата электронной почты */ -class Validator_Rule_EmailList extends Rule_Abstract +class Validator_Rule_EmailList extends Validator_Rule_Abstract { public function getErrorMsg() { diff --git a/src/Validator/Rule/Match.php b/src/Validator/Rule/Match.php index c3fdcdf..eb37a82 100644 --- a/src/Validator/Rule/Match.php +++ b/src/Validator/Rule/Match.php @@ -3,7 +3,7 @@ /** * Проверка на равентство двух полей */ -class Validator_Rule_Match extends Rule_Abstract +class Validator_Rule_Match extends Validator_Rule_Abstract { public $same; @@ -12,14 +12,6 @@ class Validator_Rule_Match extends Rule_Abstract return "Поля не совпадают"; } -/* public function __construct($field, $refField, $errorMsg) - { - $this->field = $field; - $this->refField = $refField; - $this->errorMsg = $errorMsg; - } -*/ - public function isValid(Collection $container, $status = null) { return (strcmp($container->get($this->field), $container->get($this->same)) == 0); } diff --git a/src/Validator/Rule/Numeric.php b/src/Validator/Rule/Numeric.php index 86b2bc2..2d080e7 100644 --- a/src/Validator/Rule/Numeric.php +++ b/src/Validator/Rule/Numeric.php @@ -3,7 +3,7 @@ /** * Проверка на число */ -class Validator_Rule_Numeric extends Rule_Abstract +class Validator_Rule_Numeric extends Validator_Rule_Abstract { public function getErrorMsg() { diff --git a/src/Validator/Rule/Time.php b/src/Validator/Rule/Time.php index b343a84..05a7a46 100644 --- a/src/Validator/Rule/Time.php +++ b/src/Validator/Rule/Time.php @@ -3,7 +3,7 @@ /** * Проверка формата времени */ -class Validator_Rule_Time extends Rule_Abstract +class Validator_Rule_Time extends Validator_Rule_Abstract { private $split = ":"; diff --git a/src/Validator/Rule/Unique.php b/src/Validator/Rule/Unique.php index fe97a07..e458b8d 100644 --- a/src/Validator/Rule/Unique.php +++ b/src/Validator/Rule/Unique.php @@ -1,9 +1,8 @@ ctx->isUnique($container->get($this->field), $status); + return $this->ctx->isUnique($container->get($this->field), $status, $container); } } diff --git a/src/Validator/Validator.php b/src/Validator/Validator.php index 4f053a4..fe3ea2e 100644 --- a/src/Validator/Validator.php +++ b/src/Validator/Validator.php @@ -32,7 +32,8 @@ class Validator_Validator 'require' => 'Validator_Rule_Notnull', 'numeric' => 'Validator_Rule_Numeric', 'unique' => 'Validator_Rule_Unique', - 'count' => 'Validator_Rule_Count', + 'filename' => 'Validator_Rule_FileName', + 'count' => 'Validator_Rule_Count', 'isfile' => 'Validator_Rule_IsFile', 'code' => 'Validator_Rule_Code' ); @@ -41,8 +42,7 @@ class Validator_Validator // Формат правила 'rule1|rule2,param1=value1|rule3,param1=value1,param2=value2' foreach ($input as $value) { // Список правил - if (!isset($value['validate']) || $value['validate'] == '') continue; - + if (! isset($value['validate'])) continue; $rules = explode("|", $value['validate']); foreach ($rules as $rule) { // Список параметров правила @@ -50,17 +50,17 @@ class Validator_Validator $name = array_shift($rule_param); if (isset($type[$name])) { - $constructor = $type[$name]; // "Rule_" . ucfirst($name) - $rule = new $constructor($value['name'], false); // Нужны шаблонные сообщения для правил + $constructor = $type[$name]; + $ruleObj = new $constructor($value['name'], false); // Нужны шаблонные сообщения для правил if (isset($value['context'])) { - $rule->setContext($value['context']); + $ruleObj->setContext($value['context']); } foreach ($rule_param as $param) { // Имя и значение параметра - list($name, $value) = explode("=", $param); - $rule->$name = $value; + list($p_name, $p_value) = explode("=", $param); + $ruleObj->$p_name = $p_value; } - $this->addRule($rule); + $this->addRule($ruleObj); } else { throw new Exception('Unknown validation rule "' . $rule . "'"); } @@ -90,14 +90,17 @@ class Validator_Validator public function validate(Collection $container, $rule = null, $status = null) { + $fields = array(); if ($rule) { $this->chain = $rule; } $this->errorMsg = array(); - foreach ($this->chain as $key => $rule) { - if (!$this->skip($rule, $container) && !$rule->isValid($container, $status)) { + foreach ($this->chain as $rule) { + //echo $key; + if (!in_array($rule->field, $fields) && !$this->skip($rule, $container) && !$rule->isValid($container, $status)) { $name = $rule->field; $this->errorMsg[$name] = $rule->getErrorMsg(); + $fields [] = $name; } } return $this->isValid(); diff --git a/src/View/Composite.php b/src/View/Composite.php index e9427a6..0a21508 100644 --- a/src/View/Composite.php +++ b/src/View/Composite.php @@ -1,36 +1,37 @@ tal = new PHPTAL($file); + $this->tal->setPhpCodeDestination(PHPTAL_PHP_CODE_DESTINATION); + $this->tal->setEncoding(PHPTAL_DEFAULT_ENCODING); // PHPTAL_DEFAULT_ENCODING !! + $this->tal->setTemplateRepository(PHPTAL_TEMPLATE_REPOSITORY); + $this->tal->setOutputMode(PHPTAL::HTML5); $this->tal->stripComments(true); +// $this->tal->addPreFilter(new PHPTAL_PreFilter_Normalize()); } - function set($key, $val) - { + function set($key, $val) { if ($key == 'title') { $this->setTitle($val); } $this->tal->set($key, $val); } - function __set($key, $val) - { + function __set($key, $val) { $this->tal->set($key, $val); } - function setTranslator($tr) - { - $this->tal->setTranslator($tr); - } - function execute() { parent::execute(); diff --git a/src/View/Top.php b/src/View/Top.php index 776d6d4..95bbff5 100644 --- a/src/View/Top.php +++ b/src/View/Top.php @@ -1,88 +1,139 @@ _section [$section] = $view; + return implode(" - ", array_filter($this->doTree('_title', false), array($this, 'isNotNull'))); } - public function jGrowl($message, $args) + private function findGroup($groups, $file) { - $this->addScriptRaw('$.jGrowl("' . $message . '", ' . json_encode($args) . ");\n", true); - } - - public function setGlobal($name, $args) - { - $this->addScriptRaw("var " . $name . " = " . json_encode($args) . ";\n", false); - } - - /** - * Добавляет скипт к текущему шаблону - * - * @param string $name путь к скрипту - */ - public function addScript($name) - { - $this->_script [] = $name; - } - - /** - * Добавляет код скипта к текущему шаблону - * - * @param string $name строка javascript кода - */ - public function addScriptRaw($name, $startup = false) - { - if ($startup) { - $this->_startup [] = $name; - } else { - $this->_scriptstring [] = $name; + foreach($groups as $key => $group) { + if(in_array($file, $group)) { + return $key; + } } + return false; } + private function groupFiles(array $list, $debug = true) + { + $debug = ($debug) ? 'debug=1' : ''; + $path = parse_url(WWW_PATH, PHP_URL_PATH); + // Группы определять в import через , + $groups = array( ); + $use = array(); + + $result = array(); + foreach ($list as $file) { + $name = $this->findGroup($groups, $file); + if($name) { + $use [$name] = 1; + } else { + if (strpos($file, 'ckeditor')) { + $result [] = $file; + } else { +// $result [] = WWW_PATH . "/min/?$debug&f=" . parse_url($file, PHP_URL_PATH); + $result [] = $file; + } + } + } + $list = array(); + foreach ($use as $name => $value) { +// $list [] = WWW_PATH . "/min/?$debug&f=" . implode(",", $groups[$name]); + $list [] = $groups[$name]; + } + + return array_merge($list, $result); + } + + + function getId($pref) { + $this->mid++; + return $pref.$this->mid; + } + /** - * Добавляет стили к текущему шаблону - * - * @param string $name путь к стилю - */ - public function addStyleSheet($name) - { - $this->_stylesheet [] = $name; - } - - /** - * Рекурсивно извлекает из значение свойства обьекта + * Обработка шаблона * - * @param string $list Имя свойства - * @param boolean $flatten + * @return string */ - private function doTree($list, $flatten = true) { - $result = ($flatten == true) ? $this->$list : array($this->$list); - foreach ($this->_section as $key => $value) { - if (is_object($value)) $result = array_merge($value->doTree($list, $flatten), $result); - } - return $result; + public function render() + { + + $alias = $this->doTree('alias'); + +// require_once 'minify.php'; + // Скрипты и стили + $this->set('scriptstring', $this->getScriptRaw()); + $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(); + + $startup = array(); + foreach($this->_section as $s) { + $module = explode('_', $s->active_module, 2); + if (count($module) < 2) { + continue; + } + + $module = $module[1]; + + $name = mb_strtolower($module); + $fname = $name . '/' . $name; + + $current = $this->getId('m'); + $this->require[$fname] = $current; + + $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"; + } + + $init = array(); + foreach($s->_section as $key => $item) { + /*.View_View.*/$ss = $item; + if ($ss->codeGenerator !== null) { + // функцию которая вычисляет а не результат + $part = call_user_func($ss->codeGenerator, $this, $key, $value); + $init [] = $part; + } + } + + $script .= $value . ".execute('" . $s->module_action . "', " . json_encode($init) .");\n"; + $startup[] = $script; + + } + + +/* echo "
";
+		print_r($this->require);
+		print_r(implode("", $startup));
+		echo "
";*/ + + //$this->set('scriptstring', ''); + $this->set('startup', implode("", $startup) . $this->getScriptStartup()); + + + $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', WWW_PATH); + // + return $this->execute(); // execute+phptal ?? } /** @@ -95,15 +146,6 @@ class View_Top // AbstractCompositeView return $this->doTree('_script'); } - function resolveAlias($alias, $list) - { - $result = array(); - foreach($list as $item) { - $result [] = strtr($item, $alias); - } - return $result; - } - /** * Строка со скриптом * @@ -119,10 +161,6 @@ class View_Top // AbstractCompositeView return implode("\n", $this->doTree('_startup')); } - /*abstract*/ public function set($key, $value) - { - } - /** * Массив имен файлов стилей * @@ -132,128 +170,5 @@ class View_Top // AbstractCompositeView { return $this->doTree('_stylesheet'); } - - /** - * Обработка всех вложенных шаблонов - * - * @return string - */ - public function execute() - { - foreach ($this->_section as $key => $value) { - $this->set($key, (is_object($value)) ? $value->execute() : $value); // ? - } - } - /** - * Установка заголовка шаблона - * - * @param string $title - */ - public function setTitle($title) - { - $this->_title = $title; - } - - private function isNotNull($title) - { - return $title !== null; - } - - /** - * Общая строка заголовка - */ - public function getTitle() - { - return implode(" - ", array_filter($this->doTree('_title', false), array($this, 'isNotNull'))); - } - - private function findGroup($groups, $file) - { - foreach($groups as $key => $group) { - if(in_array($file, $group)) { - return $key; - } - } - return false; - } - - private function groupFiles(array $list, $debug) - { - $debug = ($debug) ? 'debug=1' : ''; - $path = parse_url(WWW_PATH, PHP_URL_PATH); - $list = array_reverse($list); - // Группы нужно передвавать как параметр !!! - $groups = array( - 'table' => array($path . '/js/table.js', $path . '/js/listtable.js', - $path . '/js/page.js', $path . '/js/pagemenu.js'), - 'base' => array($path . '/js/admin.js', $path . '/js/cookie.js'), - ); - $use = array(); - - $result = array(); - foreach ($list as $file) { - $name = $this->findGroup($groups, $file); - if($name) { - $use [$name] = 1; - } else { - $result [] = $file; - } - } - $list = array(); - foreach ($use as $name => $value) { - $list [] = WWW_PATH . "/min/?$debug&f=" . implode(",", $groups[$name]); - } - return array_merge($list, $result); - } - - /** - * Обработка шаблона - * - * @return string - */ - public function render() - { - - $alias = $this->doTree('alias'); - -// require_once 'minify.php'; - // Скрипты и стили - $this->set('scripts', array_unique($this->groupFiles($this->resolveAlias($alias, $this->getScripts()), false))); - $this->set('stylesheet', array_unique($this->groupFiles($this->resolveAlias($alias, $this->getStyleSheet()), false))); - - $this->set('scriptstring', $this->getScriptRaw()); - $this->set('startup', $this->getScriptStartup()); - $this->set('title', $this->getTitle()); - // - return $this->execute(); // execute+phptal ?? - } - - function setAlias($alias) - { - $this->alias = $alias; - } - - function addAlias($name, $path) - { - $this->alias['${' . $name . '}'] = $path; - $this->set($name, $path); - } - - function loadImports($importFile) - { - // Подключение стилей и скриптов - if (file_exists($importFile)) { - $import = file_get_contents($importFile); - $files = explode("\n", $import); - foreach ($files as $file) { - if (strpos($file, ".js") !== false) { - $this->addScript(strtr(trim($file), $this->alias)); - } else if(strpos($file, ".css") !== false) { - $this->addStyleSheet(strtr(trim($file), $this->alias)); - } - } - } - } } -