Версия полностью совместимая c CMS

This commit is contained in:
origami11 2017-02-17 17:31:17 +03:00
parent 7ce493414e
commit 75bb35d5bf
21 changed files with 1404 additions and 783 deletions

View file

@ -13,7 +13,7 @@ function forceUrl($name)
/** /**
* Контроллер страниц * Контроллер страниц
*/ */
class Controller_Action class Controller_Action
{ {
@ -24,9 +24,16 @@ class Controller_Action
public $themePath; // Глобальный путь к текущей теме public $themePath; // Глобальный путь к текущей теме
// Параметры устанавливаются при создании контроллера // Параметры устанавливаются при создании контроллера
public $name; // Имя модуля public $name = ''; // Имя модуля
public $viewPath = null; // Путь к шаблонам контроллера public $viewPath = null; // Путь к шаблонам контроллера
public /*.Database.*/$db; // Соединение с базой данных public $viewPathPrefix = null; // Путь к шаблонам контроллера
public $moduleTitle = "";
/**
* Соединение с базой данных
*/
public $db;
// Фильтры // Фильтры
public $access = null; // Обьект хранит параметры доступа public $access = null; // Обьект хранит параметры доступа
@ -42,14 +49,11 @@ class Controller_Action
public $iconPath = ''; public $iconPath = '';
public $path; public $path;
public function __construct () public function __construct () {
{ $this->path = new Widgets_PathMenu();
//
} }
public function setUp () public function setUp() {
{
// override this
} }
public function loadConfig($name) { public function loadConfig($name) {
@ -69,15 +73,16 @@ class Controller_Action
public function installPath($name) 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(); $suggest = array();
$file = Path::join($this->viewPath, 'help', $name . '.suggest'); $file = Path::join($this->viewPath, 'help', $name . '.suggest');
if (file_exists($file) && include($file)) { if (file_exists($file)) {
$view->addScriptRaw("add_suggest(".json_encode($suggest).");\n"); include($file);
$view->suggestions = $suggest;
} }
} }
@ -88,19 +93,18 @@ class Controller_Action
/** /**
* Создает представление * Создает представление
* @param string $file * @param $name String
* @return template * @param $viewClass String
* @return View_Composite
*/ */
public function getView($name) public function getView($name, $viewClass = 'View_Composite')
{ {
$file = $name . self::TEMPLATE_EXTENSION; $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 => "");
$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) { foreach($list as $ospath => $path) {
@ -108,16 +112,21 @@ class Controller_Action
if(file_exists($template)) { break; } if(file_exists($template)) { break; }
} }
$tpl = new View_Composite($template); /*.View_Composite.*/$tpl = new $viewClass($template);
$tpl->icons = $this->iconPath; // Путь к файлам текущей темы
$tpl->media = $this->themePath; // Путь к файлам текущей темы $tpl->set('icons', $this->iconPath); // Путь к файлам текущей темы
$tpl->script = $this->jsPath; // Путь к файлам скриптов $tpl->set('media', $this->themePath); // Путь к файлам текущей темы
$tpl->template = $path; // Путь к файлам текущего шаблона $tpl->set('assets', Path::join(WWW_PATH, "assets", "css"));
$tpl->set('script', $this->jsPath); // Путь к файлам скриптов
$tpl->set('template', $path); // Путь к файлам текущего шаблона
$tpl->setAlias(array( $tpl->setAlias(array(
'${icons}' => $this->iconPath, 'icons' => $this->iconPath,
'${media}' => $this->themePath, 'script' => $this->jsPath,
'${script}' => $this->jsPath, // Для media и template поиск происходит как для файлов шаблонов
'${template}' => $path)); 'media' => $list,
'template' => $list
));
$tpl->loadImports(Path::skipExtension($template) . ".import"); $tpl->loadImports(Path::skipExtension($template) . ".import");
@ -128,7 +137,7 @@ class Controller_Action
public function getModel($name) public function getModel($name)
{ {
if (!$this->factory) { 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); return $this->factory->getModel($name);
} }
@ -143,57 +152,59 @@ class Controller_Action
public function execute1(HttpRequest $request) public function execute1(HttpRequest $request)
{ {
$action = self::ACTION_PREFIX . ucfirst($request->getAction()); $action = self::ACTION_PREFIX . ucfirst($request->getAction());
if (method_exists($this, $action)) { if (!method_exists($this, $action)) {
return $this->forward($action, $request); $action = "actionIndex";
} else {
return $this->forward("actionIndex", $request);
} }
$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) public function execute(HttpRequest $request)
{ {
$result = $this->execute1($request); $result = $this->execute1($request);
if ($result) { if (!empty($result)) {
$this->view = $result; $this->view = $result;
} }
return $this->render(); $text = $this->render();
return $text;
} }
public function forward($action, HttpRequest $args) public function forward($action, HttpRequest $args) {
{ $value = call_user_func(array($this, $action), $args);
// Действия до вызова основного обработчика return $value;
/*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 actionIndex(HttpRequest $request) public function actionIndex(HttpRequest $request) {
{
return ""; return "";
} }
public function postUrl($name, $param) public function postUrl($name, $param)
{ {
return "?" . http_build_query( $uri = array_merge(array('module' =>
array_merge(array('module' => strtolower(get_class($this)), "action" => $name), strtr($this->modulePrefix . strtolower(get_class($this)), array('module_' => '')), "action" => $name),
$this->param, $param)); $this->param, $param);
return "?" . http_build_query($uri);
} }
/** /**
* Генерация ссылки c учетом прав пользователя на ссылки * Генерация ссылки c учетом прав пользователя на ссылки
* * @param string $name Действие
* @parma string $name Действие * @param array $param Дополнительные параметры
* @parma string $param Дополнительные параметры * 'mode' означает что элемент до отправки обрабатывается javascript
* @return array|null
*/ */
public function nUrl($name, array $param = array()) 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 lcurry(array($this, 'postUrl'), $name, $param);
} }
return null; return null;
@ -217,6 +228,12 @@ class Controller_Action
/** /**
* Генерация ссылки на действие контроллера * Генерация ссылки на действие контроллера
* Ajax определяется автоматически mode = ajax используется для смены layout * 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()) 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)) { if (file_exists($path)) {
require_once ($path); require_once ($path);
$class = pathinfo($path, PATHINFO_FILENAME); $class = $prefix . pathinfo($path, PATHINFO_FILENAME);
return new $class($setup); return new $class($setup);
} }
return null; throw new Exception("NO CLASS $path");
} }
public function loadSettings($path) public function loadSettings($path)
@ -269,6 +286,7 @@ class Controller_Action
// Для Widgets // Для Widgets
public $view = null; public $view = null;
public $childNodes = array(); public $childNodes = array();
public $ctrlValues = array();
public $childViews = array(); public $childViews = array();
public function setView($name) public function setView($name)
@ -292,6 +310,11 @@ class Controller_Action
$this->childNodes[$section] = $node; $this->childNodes[$section] = $node;
} }
public function setValue(/*Widget*/ $name, $value)
{
$this->ctrlValues[$name] = $value;
}
/** /**
* Добавление дочернего отображения к текущему отображению * Добавление дочернего отображения к текущему отображению
*/ */
@ -306,34 +329,86 @@ class Controller_Action
*/ */
public function render() public function render()
{ {
foreach ($this->childNodes as $name => $node) { if ($this->view instanceof View_View) {
$node->make($this); $this->view->assignValues($this->ctrlValues);
$this->view->setView($name, $node->view);
} foreach ($this->childNodes as $name => $node) {
foreach ($this->childViews as $name => $node) { $node->make($this);
$this->view->setView($name, $node); $this->view->setView($name, $node->view);
} }
foreach ($this->childViews as $name => $node) {
$this->view->setView($name, $node);
}
}
return $this->view; return $this->view;
} }
function getPageId($request) function getPageId(HttpRequest $request)
{ {
$pageId = time(); $pageId = time();
$request->session()->set('page', $pageId); $request->session()->set('page', $pageId);
return $pageId; return $pageId;
} }
function checkPageId($request, $page) function checkPageId(HttpRequest $request, $page)
{ {
if ($request->get('__forced__')) {
return true;
}
$_page = $request->session()->get('page'); $_page = $request->session()->get('page');
$result = ($_page && $_page == $page); $result = ($_page && $_page == $page);
$request->session()->clean('page'); $request->session()->clean('page');
return $result; return $result;
} }
function redirect($action) { function _getActionPath()
header('location: ' . $this->fUrl($action)); {
exit(); 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();
}
}

View file

@ -1,7 +1,40 @@
<?php <?php
class FileNotFountException extends Exception function replaceContent($match) {
{ $result = phptal_component(htmlspecialchars_decode($match[3]));
return $result;
}
function applyComponents($text) {
return preg_replace_callback('/<(\w+)(\s+[a-zA-Z\-]+=\"[^\"]*\")*\s+tal:replace="structure\s+component:([^\"]*)"[^>]*>/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 class Controller_Component
{ {
static $_uid = 1; public $viewPath = array();
public $uid; // UID компонента создается при создании страницы, вставки компонента, или это статическое свойство public $webPath = array();
public $viewPath;
public $registry; // Registry->getInstance
public $template;
function __construct() public $template = null;
{ public $templatePath;
self::$_uid ++;
$this->uid = self::$_uid; public $component_id;
public $COMPONENTS_WEB;
public /*.Settings.*/$registry;
public /*.Database.*/$db;
public /*.Collection.*/$parameter;
public $module;
public $item_module;
function before() {
} }
function getUID() function get($request, $key, $default) {
{ }
return 'component:'. $this->uid;
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) public function getView($name)
{ {
require_once "core/view/compositeview.php";
// //
$template = ($this->template) ? $this->template : $this->_registry->readKey(array('system', 'template')); /*.Settings.*/$registry = $this->registry;
// Загружать шаблон по умолчанию если не найден текущий $template = ($this->template) ? $this->template : $registry->readKey(array('system', 'template'));
if (is_dir(Path::join($this->viewPath, 'templates', $template))) {
$template_file = Path::join($this->viewPath, 'templates', $template, $name); $selected = null;
} else { foreach ($this->viewPath as $index => $viewPath) {
$template_file = Path::join($this->viewPath, 'templates', 'modern', $name); // Загружать шаблон по умолчанию если не найден текущий
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'); if ($selected === null) {
$tpl->media = $_media = Path::join(TEMPLATE_WEB, $template); $tpl = new PHPTAL(Path::join($this->viewPath[0], 'templates', 'modern', $name));
$tpl->component = $_template = Path::join(COMPONENTS_WEB, strtolower(get_class($this)), 'templates', 'modern'); $tpl->setPhpCodeDestination(PHPTAL_PHP_CODE_DESTINATION);
$tpl->setAlias(array( $template = 'modern';
'${media}' => $_media, $selected = 0;
'${script}' => $_script, }
'${template}' => $_template));
$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; 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) public function getModel($name)
{ {
require_once 'core/mapper/mapper.php';
require_once ($this->getModelPath ($name)); require_once ($this->getModelPath ($name));
$modelName = $name . "Mapper"; $modelName = $name . "Mapper";
$model = new $modelName (); $model = new $modelName ();
@ -80,104 +147,179 @@ class Controller_Component
return $model; return $model;
} }
public function options($key, $val, $res) { public function options($key, $val, /*.Database_PDOStatement.*/$res) {
$result = array(); $result = array();
while($res->next()) { 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; return $result;
} }
public function optionsPair($list) { public function optionsPair($list, $selected = false) {
$result = array(); $result = array();
foreach ($list as $key => $value) { foreach ($list as $key => $value) {
$result [] = array('value' => $key, 'name' => $value); $result [] = array('value' => $key, 'name' => $value, 'selected' => $key == $selected);
} }
return $result; return $result;
} }
/* В дальнейшем нужно зменить на методы function getInfo() {
+ Методы могут быть и javascript $filename = Path::join($this->viewPath[0], 'install.json');
*/ if (file_exists($filename)) {
protected $editUrl; $settings = json_decode(file_get_contents($filename), true);
return $settings;
function setEditUrl($url) }
{ return array();
$this->editUrl = $url;
} }
function getEditUrl() /**
* Генерация интерфейса для выбора галлереи фотографии
*/
public function setParameters(/*.View_Composite.*/$view)
{ {
return $this->editUrl; $form = new Form_Form();
} $options = new OptionFactory($this->db);
}
/** $settings = $this->getInfo();
* TALES для подключения компонентов $form->addFieldList($settings['parameter'], $options);
* component:name?param1=value1&param2=value2
*/ $view->form = $form;
class Component_Tales implements PHPTAL_Tales $view->component = $settings['component'];
{ $view->component_title = $settings['title'];
static public function component($expression, $nothrow = false) }
static function loadComponent($expression, Database $db, Settings $registry)
{ {
return "phptal_component('" . $expression . "')";
}
}
function loadComponent($name, $db, $registry) $expression = htmlspecialchars_decode($expression);
{ $offset = strpos($expression, '?');
$path = Path::join(COMPONENTS, $name, $name . ".php"); $url = parse_url($expression);
// echo COMPONENTS, '<br />';
// echo $path; $arguments = array();
if (file_exists($path)) { if ($offset === false) {
require_once ($path); $path = $expression;
$component = new $name(); } else if (is_int($offset)) {
$component->db = $db; $path = substr($expression, 0, $offset);
$component->_registry = $registry; $query = substr($expression, $offset + 1);
$component->viewPath = COMPONENTS."/".$name."/"; 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;
}
return $component; 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'));

View file

@ -2,25 +2,37 @@
/** /**
* Первичный контроллер контроллер страниц * Первичный контроллер контроллер страниц
* @package core * @package system.controller
*/ */
class Controller_Front extends Controller_Action class Controller_Front extends Controller_Action
{ {
/** @var Shortcut */
protected $shortcut; // Ярлык к модулю protected $shortcut; // Ярлык к модулю
protected $_param; // Параметр по которому выбирается модуль protected $_param; // Параметр по которому выбирается модуль
protected $default; // Значение параметра по умолчанию 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(); parent::__construct();
$registry = $_registry; $registry = $_registry;
$this->_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 Имя модуля * @param request $request Имя модуля
* @return string * @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) if ($controller) {
$module = $this->loadClass($moduleFile); $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) { if ($module) {
// Инициализация модуля // Инициализация модуля
// $module->viewPath = dirname($moduleFile);
$module->viewPath = Shortcut::getUrl('modulepath', $name); $module->viewPath = Shortcut::getUrl('modulepath', $name);
$module->name = $name; $module->name = $name;
@ -51,15 +70,17 @@ class Controller_Front extends Controller_Action
$module->db = $this->db; $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)); $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->access->access = $this->loadSettings(Shortcut::getUrl('access', $name));
$module->setUp(); $module->setUp();
return $module->access->execute($request); $this->modules[$name] = $module;
$result = $module->access->execute($request);
return $result;
} }
return null; // throw new FileNotFoundException(); return null; // throw new FileNotFoundException();
} }
@ -72,13 +93,14 @@ class Controller_Front extends Controller_Action
$this->default = $name; $this->default = $name;
} }
private function getParameter(Collection $list)
{
return ($list->get($this->_param)) ? $list->get($this->_param): $this->default;
}
public function execute(HTTPRequest $request) 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);
} }
} }

View file

@ -2,7 +2,7 @@
class Controller_Installer class Controller_Installer
{ {
protected $db; protected $db_manager;
protected $installPath; protected $installPath;
public $_registry; public $_registry;
@ -11,15 +11,20 @@ class Controller_Installer
$this->_registry = $_registry; $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; $this->installPath = $installPath;
} }
function getSetupFile($name) 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) 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) { foreach ($sql as $version => $install) {
if (version_compare($version, $version_new, "<=") && version_compare($version, $version_old, ">")) { 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); $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) // Установка модуля function doUpdates($name, $force = false) // Установка модуля
{ {
$result = array();
$setup = $this->getSetupFile($name); $setup = $this->getSetupFile($name);
if (file_exists($setup) && ($this->isChanged($name) || $force)) { if (file_exists($setup) && ($this->isChanged($name) || $force)) {
$registry = $this->_registry; $registry = $this->_registry;
$settings = new Settings($setup); $settings = new Settings($setup);
$settings->read(); $settings->read();
@ -67,21 +83,29 @@ class Controller_Installer
$version_old = "0.0"; $version_old = "0.0";
$registry->writeKey(array($name), array()); $registry->writeKey(array($name), array());
} }
if (version_compare($version_old, $settings->get('version'), "!=")) { if (version_compare($version_old, $settings->get('version'), "!=")) {
$sql = $settings->get('sql'); $sql = $settings->get('sql');
if (is_array($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), $settings->get('settings'));
$registry->writeKey(array($name), $registry->writeKey(array($name),
array('version' => $version_new, array('version' => $version_new,
'time' => filemtime($setup))); 'time' => filemtime($setup)));
$registry->write(); $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);
} }
} }

View file

@ -28,38 +28,53 @@ class Controller_Model extends Controller_Action
public function __construct() public function __construct()
{ {
$this->path = new PathMenu(); parent::__construct();
$this->menu = new PageMenu(); $this->menu = new Widgets_PageMenu();
$this->table = new ListTable(); $this->table = new Widgets_ReactListTable();
} }
/** /**
*/ */
function setUp() function setUp() {
{ parent::setUp();
$this->table->addMenuItem($this->aUrl('delete'), 'удалить', false, 'all', 'warning'); $this->table->addMenuItem($this->aUrl('delete'), 'удалить', false, 'all', 'btn-danger', 'remove');
//$this->table->addMenuItem($this->nUrl('form'), 'редактировать', 'edit-24.png');
} }
function saveParameters($args, $list) function saveParameters(HttpRequest $args, $list) {
{
foreach ($list as $item) { foreach ($list as $item) {
$args->session()->set(array($this, $item), $args->get($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(); $result = array();
$this->saveParameters($request, array('size','page','desc', 'key')); $this->saveParameters($request, array('size','page','desc', 'key'));
$result['list'] = $model->findAll($request, $request->get('ref')); $result['list'] = $model->findAll($request, $request->get('ref'));
$result['size'] = $model->getCount($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) 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'); $list = ($request->get('table_item')) ? $request->get('table_item'): $request->get('id');
$model->deleteList($list); $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) public function actionList(HttpRequest $request)
{ {
$model = $this->getModel($this->useModel); $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); 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() private function setFormSchema()
{ {
require_once 'core/mapper/uimapper.php';
$model = $this->getModel($this->useModel); $model = $this->getModel($this->useModel);
$ui = new UIMapper($model); $ui = new Model_UIMapper($model);
$this->formSchema = $ui->getFormSchema(); $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)) { if (empty($this->formSchema)) {
$this->setFormSchema(); $this->setFormSchema();
} }
// Сделать отображение Формы в обьект и обратно <-- Убрать в beforeSave // Сделать отображение Формы в обьект и обратно
foreach ($this->formSchema as $key => $conv) { foreach ($this->formSchema as $key => $conv) {
list($value, $type) = $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)) { if (empty($this->formSchema)) {
$this->setFormSchema(); $this->setFormSchema();
@ -137,8 +166,13 @@ class Controller_Model extends Controller_Action
$form->fill($item, $this->formSchema); $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) public function actionValidate($request)
{ {
require_once "core/validator/validator.php"; $validator = new Validator_Validator();
$validator = new Validator();
$validator->addRuleList($this->schema); $validator->addRuleList($this->schema);
// Действия до проверки формы // Действия до проверки формы
@ -156,19 +189,19 @@ class Controller_Model extends Controller_Action
$validator->validate($request); // --| $validator->validate($request); // --|
// Проверка формы // Проверка формы
if (!$validator->isValid()) { 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)) { if (empty($this->schema)) {
$model = $this->getModel($this->useModel); $model = $this->getModel($this->useModel);
$ui = new UIMapper($model); $ui = new Model_UIMapper($model);
$schema = $ui->getEditSchema(); $schema = $ui->getEditSchema();
$form->addFieldList($schema); $form->addFieldList($schema);
@ -178,71 +211,57 @@ class Controller_Model extends Controller_Action
} }
/** /**
* Добавление пользователя * Добавление
*/ */
public function actionAdd(HttpRequest $request) public function actionAdd(HttpRequest $request)
{ {
require_once "core/validator/validator.php";
// {{{ тоже может быть один ref или несколько // {{{ тоже может быть один ref или несколько
$ref = $request->get('ref'); $ref = $request->get('ref');
$this->addParameter('ref', $ref); // Добавляет параметр в url $this->addParameter('ref', $ref); // Добавляет параметр в url
/// }}} /// }}}
if ($this->checkPageId($request, $request->get('page'))) { // Проверка
// Проверка $validator = new Validator_Validator();
$validator = new Validator(); $validator->addRuleList($this->schema);
$validator->addRuleList($this->schema);
// Действия до проверки формы // Действия до проверки формы
$this->validate($validator, $request); // <--| $this->validate($validator, $request); // <--|
$validator->validate($request); // --| $validator->validate($request); // --|
// Проверка формы // Проверка формы
if (!$validator->isValid()) { if (!$validator->isValid()) {
$request->setAction('form'); return json_encode(array('result'=>'fail','errors'=>$validator->getErrorMsg()));
$this->getActionPath($request); }
// Нужен тест для формы
$model = $this->getModel($this->useModel);
$className = $model->className;
$item = new $className();
$form = new TForm(); // Сохраняем значение в базе данных
$this->formSetup($form, $request->get('id'), $request->get('ref')); // Инициализация формы $item->id = $request->get('id');
// Если таблица связана с другой таблицей
$form->setValues($request); // <-- Убрать в formUpdate if ($request->get('ref') && $model->reference[1]) {
$this->formUpdate($form, $request); $ref_id = $model->reference[1];
$item->$ref_id = $request->get('ref');
$form->setError($validator); // Установка ошибок для формы
$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 -> идентефикатор родительской таблицы !!?? // Подготовка к сохранению
$this->beforeSave($item, $request); // Сюдаже и истрия переходов
// nextId ??? или выход или новая форма для создания новости
$id = $model->saveDB($item, $request);
// Для страницы со списком id -> идентификатор родительской таблицы !!??
// $request->set('id', $request->get('ref')); // $request->set('id', $request->get('ref'));
if ($request->get('apply')) { if ($request->get('apply')) {
$request->setAction('form'); $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); $this->setTitlePath($ref);
$model = $this->getModel($this->useModel); $model = $this->getModel($this->useModel);
$form = new TForm(); // Показываем форму $form = new Form_Form(); // Показываем форму
$form->header = 'Редактирование записи'; $form->header = 'Редактирование записи';
$this->formSetup($form, $request->get('id'), $request->get('ref')); // Инициализация формы $this->formSetup($form, $request->get('id'), $request->get('ref')); // Инициализация формы
$list = $request->get('table_item'); $list = $request->get('table_item');
$id = ($list[0]) ? $list[0] : $request->get('id'); $id = ($list[0]) ? $list[0] : $request->get('id');
//
$tpl = $this->formPage ($form, $request); $tpl = $this->formPage($form, $request);
if ($id) { // Редактирование if ($id) { // Редактирование
$form->action = forceUrl($this->nUrl('add', array('id' => $id, 'page' => $this->getPageId($request)))); // action Свойство формы $form->action = forceUrl($this->nUrl('add', array('id' => $id, 'page' => $this->getPageId($request)))); // action Свойство формы
$item = $model->findById($id); $item = $model->findById($id);
// Загрузка формы // Загрузка формы
$this->beforeLoad($item, $form); $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 удалить! // FIXME: После замены везде $tableSchema -> table->setHeader удалить!
if ($this->tableSchema) { if ($this->tableSchema) {
$table->setHeader($this->tableSchema); $table->setHeader($this->tableSchema);
} else { } else {
// Настройка таблицы отображения по схеме данных // Настройка таблицы отображения по схеме данных
require_once 'core/mapper/uimapper.php';
$model = $this->getModel($this->useModel); $model = $this->getModel($this->useModel);
$ui = new UIMapper($model); $ui = new Model_UIMapper($model);
$ui->hidden = $table->hidden;
$schema = $ui->getTableSchema(); $schema = $ui->getTableSchema();
$schema[0]['action'] = $table->getFirstItem(); $schema[0]['action'] = forceUrl($table->getFirstItem());
$table->setHeader($schema); $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'); $this->getActionPath($request, 'index');
// Такое мета действие наверное можно вынести в отдельный класс // Такое мета действие наверное можно вынести в отдельный класс
@ -335,14 +356,14 @@ class Controller_Model extends Controller_Action
$ref = $request->session()->get('ref'); $ref = $request->session()->get('ref');
} }
$request->session->set('ref', $ref); $request->session()->set('ref', $ref);
$this->addParameter('ref', $ref); $this->addParameter('ref', $ref);
// }}} // }}}
$this->setTitlePath($ref); $this->setTitlePath($ref);
$tpl = $this->getView('list'); $tpl = new stdClass();
// Помошники действий // Помощники действий
$this->callHelpers($request); $this->callHelpers($request);
// Таблица // Таблица
if ($request->session()->get(strtolower(get_class($this)))) { if ($request->session()->get(strtolower(get_class($this)))) {
@ -355,7 +376,7 @@ class Controller_Model extends Controller_Action
'size' => $session['size'], 'size' => $session['size'],
'desc' => $session['desc'])); 'desc' => $session['desc']));
$this->table->setData('sorter', $session['key']); //$this->table->setData('sorter', $session['key']);
if (isset($session['desc'])) { if (isset($session['desc'])) {
$this->table->setData('desc', $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 call_user_func($setup, $this->table, $request->get('id'), $ref);// --> Эквивалент formSetup
$this->table->setAction($list); $this->table->setAction($list);
// if (!$this->table->getData('module')) {
$this->table->setData('module', strtolower($this->useModel));
}
$tpl->menu_path = $this->path->getItems(); $tpl->menu_path = $this->path->getItems();
// Поиск $this->table->makeData();
$search = new SearchDialog(); $tpl->table = array('data' => $this->table->data);
$search->setTitle('Поиск'); $tpl->menu = $this->menu->menu->getItems();
$search->setAction($this->aUrl('search')); $tpl->path = $this->path->getItems();
$search->setFriend($this->table);
$search->addFields($this->schemaSearch);
// Настройки return json_encode($tpl);
$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;
} }
/** /**
*/ */
public function actionSetup($request) public function actionSetup(HttpRequest $request) {
{
$left = explode(",", $request->get('left')); $left = explode(",", $request->get('left'));
$right = explode(",", $request->get('right')); $right = explode(",", $request->get('right'));
$$request->session()->set(strtolower(get_class($this)), $request->session()->set(strtolower(get_class($this)),
array('view' => array('left' => $left, 'right' => $right))); array('view' => array('left' => $left, 'right' => $right), 'page' => 1, 'size' => 0, 'desc' => 'asc', 'key' => false));
return $this->forward('actionIndex', $request); return $this->forward('actionIndex', $request);
} }
/** /**
*/ */
private function formPage($form, $request) protected function formPage($form, $request, $template = 'form') {
{ $view = new stdClass();//$this->getView($template);
$view = $this->getView('form'); $view->form = $form;
$view->setView('form', $form); $form->action = forceUrl($this->nUrl('add', array('page' => $this->getPageId($request)))); // Действие для формы
$view->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(); $view->back = $this->path->getPrev();
return $view; return $view;
} }
function _getActionPath() {
return new Controller_State('index');
}
// Тоже убрать в метод Controller_Model // Тоже убрать в метод Controller_Model
function getActionPath(HttpRequest $request/*, $action = false*/) function getActionPath(HttpRequest $request, $action = null) {
{
require_once 'state.php';
$this->_getActionPath()->getPath($this, ($action) ? $action : $request->getAction()); $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;
}
} }

View file

@ -1,5 +1,7 @@
<?php <?php
require_once __DIR__ .'/../tools/string.php';
class Database_PDOStatement extends PDOStatement implements IteratorAggregate class Database_PDOStatement extends PDOStatement implements IteratorAggregate
{ {
protected $cursorPos = 0; protected $cursorPos = 0;
@ -86,7 +88,7 @@ class Database_PDOStatement extends PDOStatement implements IteratorAggregate
} }
function getArray($name) { function getArray($name) {
return Tools_String::strToArray($this->fields[$name]); return strToArray($this->fields[$name]);
} }
function getRecordCount() { function getRecordCount() {

View file

@ -13,6 +13,9 @@ class Filter_Login extends Filter_Filter
const SESSION_BROWSER_SIGN_SECRET = '@w3dsju45Msk#'; const SESSION_BROWSER_SIGN_SECRET = '@w3dsju45Msk#';
const SESSION_BROWSER_SIGN_KEYNAME = 'session.app.browser.sign'; const SESSION_BROWSER_SIGN_KEYNAME = 'session.app.browser.sign';
public $mode = 'ajax'; public $mode = 'ajax';
//AJAX-Реквесты для которых не требуется авторизация, потребовалось для сбора статистики
public $whiteRequestList = array(array('module' => "requiredcontent", "action" => "getcount"));
/** /**
* Проверка авторизации * Проверка авторизации
* @return Boolean Авторизовани пользователь или нет * @return Boolean Авторизовани пользователь или нет
@ -20,7 +23,7 @@ class Filter_Login extends Filter_Filter
public function isLoggin(HttpRequest $request) public function isLoggin(HttpRequest $request)
{ {
// Авторизация // Авторизация
// session_start(); session_start();
$db = $this->getConnection(); $db = $this->getConnection();
Filter_UserAccess::setUp($db); // Соединение Filter_UserAccess::setUp($db); // Соединение
switch ($request->getAction()) { switch ($request->getAction()) {
@ -31,7 +34,18 @@ class Filter_Login extends Filter_Filter
$result = Filter_UserAccess::getUserByLogin($login); // Поиск по логину $result = Filter_UserAccess::getUserByLogin($login); // Поиск по логину
if ($result) { 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); $this->enter($db, $result);
return true; return true;
} }
@ -45,7 +59,7 @@ class Filter_Login extends Filter_Filter
case 'enter': case 'enter':
$login = $request->get('login'); $login = $request->get('login');
$password = $request->get('sid'); $password = $request->get('sid');
$result = UserAccess::getUserByLogin($login); // Поиск по логину $result = Filter_UserAccess::getUserByLogin($login); // Поиск по логину
if ($result) { if ($result) {
$temp = md5($result->getString('password') . $result->getString('login') . $result->getString('sid')); $temp = md5($result->getString('password') . $result->getString('login') . $result->getString('sid'));
if ($password == $temp) { if ($password == $temp) {
@ -57,9 +71,12 @@ class Filter_Login extends Filter_Filter
default: default:
$hash = $this->getBrowserSign(); $hash = $this->getBrowserSign();
// Если $hash не совпадает $_SESSION['hash'] то удаляем сессию // Если $hash не совпадает $_SESSION['hash'] то удаляем сессию
if (isset($_SESSION ['access']) && isset($_SESSION[self::SESSION_BROWSER_SIGN_SECRET])) { if (isset($_SESSION ['access']) && isset($_SESSION[self::SESSION_BROWSER_SIGN_KEYNAME])) {
if ($hash == $_SESSION[self::SESSION_BROWSER_SIGN_SECRET]) { if ($hash == $_SESSION[self::SESSION_BROWSER_SIGN_KEYNAME]) {
UserAccess::getUserById($_SESSION ['access']); // Поиск по идентификатору $this->user = $user = Filter_UserAccess::getUserById($_SESSION['access']); // Поиск по идентификатору
if ($user && isset($_SESSION['random']) && ($user->get('sid') == $_SESSION['random'])) {
return true;
}
return true; return true;
} else { } else {
session_destroy(); session_destroy();
@ -72,9 +89,9 @@ class Filter_Login extends Filter_Filter
private function getBrowserSign() private function getBrowserSign()
{ {
$rawSign = self::SESSION_BROWSER_SIGN_SECRET; $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) { foreach ($signParts as $signPart) {
$rawSign .= '::' . (isset($_SERVER[$signPart]) ? $_SERVER[$signPart] : 'none'); $rawSign .= '::' . (isset($_SERVER[$signPart]) ? $_SERVER[$signPart] : 'none');
} }
@ -83,23 +100,78 @@ class Filter_Login extends Filter_Filter
private function enter($db, $result) 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["group"] = $result->getInt('access');
$_SESSION ["access"] = $result->getInt('id_user'); // id_user $_SESSION["access"] = $result->getInt('id_user'); // id_user
$_SESSION [self::SESSION_BROWSER_SIGN_SECRET] = $this->getBrowserSign(); $_SESSION["random"] = $random; // id_user
$_SESSION ["time"] = time(); $_SESSION[self::SESSION_BROWSER_SIGN_KEYNAME] = $this->getBrowserSign();
$_SESSION["time"] = time();
} }
public function execute(HttpRequest $request) public function execute(HttpRequest $request)
{ {
if (!$this->isLoggin($request)) { $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");
}
}
if ($request->get('action') == 'relogin') {
if ($logged) {
return json_encode(array('result' => 'ok', 'message' => "Авторизация успешна"));
} else {
return json_encode(array('result' => 'fail', 'message' => "Неправильное имя пользователя или пароль"));
}
}
if (!$logged) {
// Параметры при неправильной авторизации // Параметры при неправильной авторизации
// Действия по умолчанию !! Возможно переход на форму регистрации // Действия по умолчанию !! Возможно переход на форму регистрации
$request->set('module', 'login'); if ($request->get('mode') == 'ajax') {
$request->set('mode', $this->mode); 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']);
}
} }
return $this->processor->execute($request);
$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;
} }
} }

View file

@ -20,68 +20,147 @@ class TField
public $description = ""; public $description = "";
public $alias = array(); public $alias = array();
public function __construct ($input) public function __construct ($input = array(), $factory = null)
{ {
$this->deafult = null;
$this->default = null;
if (isset($input['validate'])) { 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) { foreach (array('label', 'name', 'type', 'description') as $name) {
$this->$name = $input[$name]; if (isset($input[$name])) {
$this->$name = $input[$name];
}
} }
} }
function setValue($value) function setValue(/*.any.*/$value)
{ {
$this->value = $value; $this->value = $value;
} }
function getId()
{
return $this->name . '_label';
}
} }
/** /**
* Поле ввода Input * Поле ввода Input
* @package core
*/ */
class TInput extends TField { 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) function setValue($value)
{ {
// Установить selected у options // Установить selected у options
$this->value = $value; $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 TDate extends TField
{ {
} }
/* * /**
* Поле с цветом
*/
class TColor extends TField
{
}
/**
* Текстовое поле * Текстовое поле
* @package core
*/ */
class TTextArea extends TField class TTextArea extends TField
{ {
function setValue($value)
{
$this->value = $value;
}
} }
/** /**
* Поле для ввода пароля * Поле для ввода пароля
* @package core
*/ */
class TSecret extends TField 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 class Form_Form extends View_View {
{ public $field = array();
public $field = array ();
public $action = ""; public $action = "";
public $method = 'post'; public $method = 'post';
public $header;
protected $replace; protected $replace;
protected $before; protected $before;
public function __construct () public $_title = array();
public $alias = array();
public $constructor = array();
/**
* Строим форму по ее структуре. Каждому типу соответствует определенный класс.
*/
public function __construct()
{ {
$this->constructor = array ( $this->constructor = array(
'input' => 'TInput', 'input' => 'TInput',
'date' => 'TDate', 'inputreq' => 'TInput', // input с проверкой на заполненность
'textarea' => 'TTextArea',
'select' => 'TSelect', 'date' => 'TDate',
'select1' => 'TSelect1', 'datereq' => 'TDate',
'secret' => 'TSecret', 'datetime' => 'TDateTime',
'upload' => 'TUpload'
'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['type']));
assert (isset($init['name'])); assert(isset($init['name']));
// print_r($init);
$constructor = $this->constructor[$init['type']]; $constructor = $this->constructor[$init['type']];
$el = new $constructor ($init); $el = new $constructor($init, $factory);
$el->type = $init['type']; if (!$el->type) {
$el->type = $init['type'];
}
if(isset($init['hint'])) {
$el->hint = $init['hint'];
}
$this->field [$init['name']] = $el; $this->field [$init['name']] = $el;
return $el; return $el;
} }
/** /**
* Добавляет спсок полей для формы * Добавляет список полей для формы
* @param array $list * @param array $list
*/ */
public function addFieldList (array $list) public function addFieldList(array $list, $factory = null)
{ {
foreach ($list as $init) { 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) 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) { foreach ($this->field as $key => $el) {
$value = $request->getRawData ($this->method, $key); $value = $request->getRawData($this->method, $key);
$this->field[$key]->setValue($value); $this->field[$key]->setValue($value);
} }
} }
@ -170,10 +374,11 @@ class Form_Form
* @param object $data * @param object $data
* @param array $schema Связь между элементами формы и свойствами обьекта * @param array $schema Связь между элементами формы и свойствами обьекта
*/ */
public function fill ($data, array $schema) public function fill($data, array $schema)
{ {
foreach ($schema as $key => $value) { foreach ($schema as $key => $conv) {
$this->field [$value]->setValue($data->$value->getString ()); 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); $this->field[$name]->setValue($value);
} }
function execute()
{
return $this;
}
} }

View file

@ -1,103 +1,119 @@
<?php <?php
/** /**
* Преобразование типов !!! Пересмотреть использование классов!!
* Класс преобразования типа значения поля класса в тип поля таблицы * Класс преобразования типа значения поля класса в тип поля таблицы
* @package core * @package system
*/ */
class Primitive
{ class Primitive {
public $value; // varchar
public $name; public static function to_varchar($value)
public function __construct ($name = "")
{ {
$this->name = $name; return ((string) $value);
} }
// Преобразование из внешнего вормата public static function from_varchar($value)
public function setString ($value)
{ {
$this->value = $value; return $value;
} }
// Преобразование из формата базы данных // int
public function setRes ($res, $key) 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);
} }
// Преобразование во внешний формат // int
public function getString () public static function to_int($value)
{ {
return $this->__toString (); return ((int) $value);
}
}
/**
* Отображение поля таблицы в целое число
* @package core
*/
class Int4 extends Primitive {
public function setRes ($res, $key) {
$this->value = $res->getInt ($key);
} }
public function setString ($value) { public static function from_int($value)
$this->value = ((int) $value);
}
}
/* Foreign key */
class FKey extends Int4 {}
/**
* Отображение поля таблицы в дату - время
*/
class Date extends Primitive
{
public function setRes ($res, $key)
{ {
$this->value = $res->getInt ($key); return ((string) $value);
} }
public function setString ($value) // date
public static function to_date($value)
{ {
$this->value = 0; $result = 0;
if ($tmp = explode("/",$value,3)) { $tmp = explode("/", $value, 3);
if ($tmp[1] && $tmp[0] && $tmp[2]) { if (!empty($tmp)) {
if (checkdate($tmp[1], $tmp[0], $tmp[2])) { if (count($tmp) != 3) return $result;
$this->value = mktime(0, 0, 0, $tmp[1], $tmp[0], $tmp[2]);
$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;
}
}

View file

@ -1,53 +1,107 @@
<?php <?php
class Tools_String { // from creole
// from creole function strToArray($str) {
static function strToArray($str) $str = substr($str, 1, -1); // remove { }
{ $res = array();
$str = substr($str, 1, -1); // remove { }
$res = array();
$subarr = array(); $subarr = array();
$in_subarr = 0; $in_subarr = 0;
$toks = explode(',', $str); $toks = explode(',', $str);
foreach($toks as $tok) { foreach($toks as $tok) {
if ($in_subarr > 0) { // already in sub-array? if ($in_subarr > 0) { // already in sub-array?
$subarr[$in_subarr][] = $tok; $subarr[$in_subarr][] = $tok;
if ('}' === substr($tok, -1, 1)) { // check to see if we just added last component if ('}' === substr($tok, -1, 1)) { // check to see if we just added last component
$res[] = $this->strToArray(implode(',', $subarr[$in_subarr])); $res[] = strToArray(implode(',', $subarr[$in_subarr]));
$in_subarr--; $in_subarr--;
} }
} elseif ($tok{0} === '{') { // we're inside a new sub-array } elseif ($tok{0} === '{') { // we're inside a new sub-array
if ('}' !== substr($tok, -1, 1)) { if ('}' !== substr($tok, -1, 1)) {
$in_subarr++; $in_subarr++;
// if sub-array has more than one element // if sub-array has more than one element
$subarr[$in_subarr] = array(); $subarr[$in_subarr] = array();
$subarr[$in_subarr][] = $tok; $subarr[$in_subarr][] = $tok;
} else { } else {
$res[] = $this->strToArray($tok); $res[] = strToArray($tok);
} }
} else { // not sub-array } else { // not sub-array
$val = trim($tok, '"'); // remove " (surrounding strings) $val = trim($tok, '"'); // remove " (surrounding strings)
// perform type castng here? // perform type castng here?
$res[] = $val; $res[] = $val;
} }
} }
return $res; return $res;
} }
//Нормализация строк на русском
static function translit($st) { function normalizeRussian($str) {
$st = strtr($st,"абвгдеёзийклмнопрстуфхъыэ !№", "abvgdeeziyklmnoprstufh_ie__#"); $result = preg_replace('/\s+/',' ', $str);
$st = strtr($st,"АБВГДЕЁЗИЙКЛМНОПРСТУФХЪЫЭ", "ABVGDEEZIYKLMNOPRSTUFH_IE"); if (is_string($result)) {
$st = strtr($st, array( $result = trim($result); //Замена длинных пробелов на одинарные, пробелы по краям
"ж"=>"zh", "ц"=>"ts", "ч"=>"ch", "ш"=>"sh", $result = mb_strtolower($result);
"щ"=>"shch","ь"=>"", "ю"=>"yu", "я"=>"ya", $result = preg_replace('/ё/','е', $str); //е на ё
"Ж"=>"ZH", "Ц"=>"TS", "Ч"=>"CH", "Ш"=>"SH", }
"Щ"=>"SHCH","Ь"=>"", "Ю"=>"YU", "Я"=>"YA", return $result;
"ї"=>"i", "Ї"=>"Yi", "є"=>"ie", "Є"=>"Ye" }
));
return $st; //Проверка равенства двух строк на русском языке.
} 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);
} }

View file

@ -3,7 +3,7 @@
/** /**
* Проверка на число * Проверка на число
*/ */
class Validator_Rule_Alpha extends Rule_Abstract class Validator_Rule_Alpha extends Validator_Rule_Abstract
{ {
public function getErrorMsg() public function getErrorMsg()
{ {

View file

@ -3,7 +3,7 @@
/** /**
* Проверка формата даты * Проверка формата даты
*/ */
class Validator_Rule_Date extends Rule_Abstract class Validator_Rule_Date extends Validator_Rule_Abstract
{ {
private $split = "\\/"; private $split = "\\/";

View file

@ -3,7 +3,7 @@
/** /**
* Проверка формата электронной почты * Проверка формата электронной почты
*/ */
class Validator_Rule_Email extends Rule_Abstract class Validator_Rule_Email extends Validator_Rule_Abstract
{ {
public function getErrorMsg() public function getErrorMsg()
{ {

View file

@ -3,7 +3,7 @@
/** /**
* Проверка формата электронной почты * Проверка формата электронной почты
*/ */
class Validator_Rule_EmailList extends Rule_Abstract class Validator_Rule_EmailList extends Validator_Rule_Abstract
{ {
public function getErrorMsg() public function getErrorMsg()
{ {

View file

@ -3,7 +3,7 @@
/** /**
* Проверка на равентство двух полей * Проверка на равентство двух полей
*/ */
class Validator_Rule_Match extends Rule_Abstract class Validator_Rule_Match extends Validator_Rule_Abstract
{ {
public $same; public $same;
@ -12,14 +12,6 @@ class Validator_Rule_Match extends Rule_Abstract
return "Поля не совпадают"; return "Поля не совпадают";
} }
/* public function __construct($field, $refField, $errorMsg)
{
$this->field = $field;
$this->refField = $refField;
$this->errorMsg = $errorMsg;
}
*/
public function isValid(Collection $container, $status = null) { public function isValid(Collection $container, $status = null) {
return (strcmp($container->get($this->field), $container->get($this->same)) == 0); return (strcmp($container->get($this->field), $container->get($this->same)) == 0);
} }

View file

@ -3,7 +3,7 @@
/** /**
* Проверка на число * Проверка на число
*/ */
class Validator_Rule_Numeric extends Rule_Abstract class Validator_Rule_Numeric extends Validator_Rule_Abstract
{ {
public function getErrorMsg() public function getErrorMsg()
{ {

View file

@ -3,7 +3,7 @@
/** /**
* Проверка формата времени * Проверка формата времени
*/ */
class Validator_Rule_Time extends Rule_Abstract class Validator_Rule_Time extends Validator_Rule_Abstract
{ {
private $split = ":"; private $split = ":";

View file

@ -1,9 +1,8 @@
<?php <?php
/** /**
* Проверка формата времени
*/ */
class Validator_Rule_Unique extends Rule_Abstract class Validator_Rule_Unique extends Validator_Rule_Abstract
{ {
public function getErrorMsg() public function getErrorMsg()
{ {
@ -12,7 +11,7 @@ class Validator_Rule_Unique extends Rule_Abstract
public function isValid(Collection $container, $status = null) public function isValid(Collection $container, $status = null)
{ {
return $this->ctx->isUnique($container->get($this->field), $status); return $this->ctx->isUnique($container->get($this->field), $status, $container);
} }
} }

View file

@ -32,7 +32,8 @@ class Validator_Validator
'require' => 'Validator_Rule_Notnull', 'require' => 'Validator_Rule_Notnull',
'numeric' => 'Validator_Rule_Numeric', 'numeric' => 'Validator_Rule_Numeric',
'unique' => 'Validator_Rule_Unique', 'unique' => 'Validator_Rule_Unique',
'count' => 'Validator_Rule_Count', 'filename' => 'Validator_Rule_FileName',
'count' => 'Validator_Rule_Count',
'isfile' => 'Validator_Rule_IsFile', 'isfile' => 'Validator_Rule_IsFile',
'code' => 'Validator_Rule_Code' 'code' => 'Validator_Rule_Code'
); );
@ -41,8 +42,7 @@ class Validator_Validator
// Формат правила 'rule1|rule2,param1=value1|rule3,param1=value1,param2=value2' // Формат правила 'rule1|rule2,param1=value1|rule3,param1=value1,param2=value2'
foreach ($input as $value) { foreach ($input as $value) {
// Список правил // Список правил
if (!isset($value['validate']) || $value['validate'] == '') continue; if (! isset($value['validate'])) continue;
$rules = explode("|", $value['validate']); $rules = explode("|", $value['validate']);
foreach ($rules as $rule) { foreach ($rules as $rule) {
// Список параметров правила // Список параметров правила
@ -50,17 +50,17 @@ class Validator_Validator
$name = array_shift($rule_param); $name = array_shift($rule_param);
if (isset($type[$name])) { if (isset($type[$name])) {
$constructor = $type[$name]; // "Rule_" . ucfirst($name) $constructor = $type[$name];
$rule = new $constructor($value['name'], false); // Нужны шаблонные сообщения для правил $ruleObj = new $constructor($value['name'], false); // Нужны шаблонные сообщения для правил
if (isset($value['context'])) { if (isset($value['context'])) {
$rule->setContext($value['context']); $ruleObj->setContext($value['context']);
} }
foreach ($rule_param as $param) { foreach ($rule_param as $param) {
// Имя и значение параметра // Имя и значение параметра
list($name, $value) = explode("=", $param); list($p_name, $p_value) = explode("=", $param);
$rule->$name = $value; $ruleObj->$p_name = $p_value;
} }
$this->addRule($rule); $this->addRule($ruleObj);
} else { } else {
throw new Exception('Unknown validation rule "' . $rule . "'"); throw new Exception('Unknown validation rule "' . $rule . "'");
} }
@ -90,14 +90,17 @@ class Validator_Validator
public function validate(Collection $container, $rule = null, $status = null) public function validate(Collection $container, $rule = null, $status = null)
{ {
$fields = array();
if ($rule) { if ($rule) {
$this->chain = $rule; $this->chain = $rule;
} }
$this->errorMsg = array(); $this->errorMsg = array();
foreach ($this->chain as $key => $rule) { foreach ($this->chain as $rule) {
if (!$this->skip($rule, $container) && !$rule->isValid($container, $status)) { //echo $key;
if (!in_array($rule->field, $fields) && !$this->skip($rule, $container) && !$rule->isValid($container, $status)) {
$name = $rule->field; $name = $rule->field;
$this->errorMsg[$name] = $rule->getErrorMsg(); $this->errorMsg[$name] = $rule->getErrorMsg();
$fields [] = $name;
} }
} }
return $this->isValid(); return $this->isValid();

View file

@ -1,36 +1,37 @@
<?php <?php
/**
* @package system.view
*/
// CompositeView+PHPTAL // View_Base + PHPTAL = View_Template (View_Composite)
class View_Composite extends View_Top class View_Composite extends View_View
{ {
private $tal; private $tal;
function __construct($file) function __construct($file)
{ {
parent::__construct($file); parent::__construct();
$this->tal = new PHPTAL($file); $this->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->stripComments(true);
// $this->tal->addPreFilter(new PHPTAL_PreFilter_Normalize());
} }
function set($key, $val) function set($key, $val) {
{
if ($key == 'title') { if ($key == 'title') {
$this->setTitle($val); $this->setTitle($val);
} }
$this->tal->set($key, $val); $this->tal->set($key, $val);
} }
function __set($key, $val) function __set($key, $val) {
{
$this->tal->set($key, $val); $this->tal->set($key, $val);
} }
function setTranslator($tr)
{
$this->tal->setTranslator($tr);
}
function execute() function execute()
{ {
parent::execute(); parent::execute();

View file

@ -1,88 +1,139 @@
<?php <?php
class View_Top // AbstractCompositeView class View_Top extends View_Composite {
{
protected $_section = array(); // Вложенные шаблоны
// Блоки
protected $_stylesheet = array(); // Массив стилей текущего шаблона
protected $_script = array(); // Массив скриптов текущего шаблона
protected $_scriptstring = array();
protected $_startup = array();
protected $_title = null; // Заголовок текущего шаблона
public $alias = array();
function __construct()
{
}
/** /**
* Связывет переменную с вложенным шаблоном * Общая строка заголовка
*
* @param string $section переменная шаблона
* @param CompositeView $view вложенный шаблон
*/ */
public function setView($section, /*CompositeView*/ $view) public $mid = 0;
public $require = array();
public $deps = array();
public function getTitle()
{ {
$this->_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); foreach($groups as $key => $group) {
} if(in_array($file, $group)) {
return $key;
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;
} }
return false;
} }
/** private function groupFiles(array $list, $debug = true)
* Добавляет стили к текущему шаблону
*
* @param string $name путь к стилю
*/
public function addStyleSheet($name)
{ {
$this->_stylesheet [] = $name; $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 $list Имя свойства * @return string
* @param boolean $flatten
*/ */
private function doTree($list, $flatten = true) { public function render()
$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); $alias = $this->doTree('alias');
}
return $result; // 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 "<pre>";
print_r($this->require);
print_r(implode("", $startup));
echo "</pre>";*/
//$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'); 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')); return implode("\n", $this->doTree('_startup'));
} }
/*abstract*/ public function set($key, $value)
{
}
/** /**
* Массив имен файлов стилей * Массив имен файлов стилей
* *
@ -133,127 +171,4 @@ class View_Top // AbstractCompositeView
return $this->doTree('_stylesheet'); 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));
}
}
}
}
} }