Merge branch 'new-validator' into 'master'
New validator See merge request composer/PHP_Library!10
This commit is contained in:
commit
0a4762ccc3
109 changed files with 1781 additions and 1385 deletions
|
|
@ -8,8 +8,8 @@
|
|||
}
|
||||
],
|
||||
"autoload": {
|
||||
"psr-0": {
|
||||
"": "src/"
|
||||
"psr-4": {
|
||||
"ctiso\\": "src/"
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,5 +1,8 @@
|
|||
<?php
|
||||
|
||||
|
||||
namespace ctiso;
|
||||
|
||||
/**
|
||||
* Интерфейс к массиву и обьекту как к коллекции
|
||||
*/
|
||||
|
|
|
|||
|
|
@ -1,5 +1,8 @@
|
|||
<?php
|
||||
|
||||
|
||||
namespace ctiso;
|
||||
|
||||
class Arr {
|
||||
static function get($data, $key, $default = null) {
|
||||
return isset($data[$key]) ? $data[$key] : $default;
|
||||
|
|
|
|||
|
|
@ -1,9 +1,11 @@
|
|||
<?php
|
||||
|
||||
namespace ctiso;
|
||||
/**
|
||||
* Коллекция
|
||||
*
|
||||
*/
|
||||
class Collection implements ArrayAccess
|
||||
class Collection implements \ArrayAccess
|
||||
{
|
||||
/**
|
||||
* Holds collective request data
|
||||
|
|
@ -63,7 +65,7 @@ class Collection implements ArrayAccess
|
|||
|
||||
public function getString($key, $default = '')
|
||||
{
|
||||
return ((string) $this->get($key, $default));
|
||||
return (string)$this->get($key, $default);
|
||||
}
|
||||
|
||||
public function getNat($key, $default = 1)
|
||||
|
|
|
|||
36
src/ComponentRequest.php
Normal file
36
src/ComponentRequest.php
Normal file
|
|
@ -0,0 +1,36 @@
|
|||
<?php
|
||||
|
||||
namespace ctiso;
|
||||
|
||||
use ctiso\HttpRequest,
|
||||
ctiso\Arr;
|
||||
|
||||
class ComponentRequest {
|
||||
public $component_id;
|
||||
public $component_title;
|
||||
public $r;
|
||||
|
||||
function __construct($c, HttpRequest $r) {
|
||||
$this->component_id = $c;
|
||||
$this->r = $r;
|
||||
}
|
||||
|
||||
function get($key, $default = null) {
|
||||
if ($key == 'active_page') {
|
||||
return $this->r->get($key);
|
||||
}
|
||||
$arr = $this->r->get($key);
|
||||
if (!is_null($arr)) {
|
||||
if (is_array($arr)) {
|
||||
return Arr::get($arr, $this->component_id, $default);
|
||||
} else {
|
||||
return $arr;
|
||||
}
|
||||
}
|
||||
return $default;
|
||||
}
|
||||
|
||||
function getAction() {
|
||||
return $this->r->getAction();
|
||||
}
|
||||
}
|
||||
|
|
@ -1,6 +1,9 @@
|
|||
<?php
|
||||
|
||||
class Connection_HttpRequest
|
||||
namespace ctiso\Connection;
|
||||
use ctiso\File;
|
||||
|
||||
class HttpRequest
|
||||
{
|
||||
const POST = "POST";
|
||||
const GET = "GET";
|
||||
|
|
|
|||
|
|
@ -3,7 +3,9 @@
|
|||
/**
|
||||
* Обрабатывает HTTP ответ
|
||||
*/
|
||||
class Connection_HttpResponse
|
||||
namespace ctiso\Connection;
|
||||
|
||||
class HttpResponse
|
||||
{
|
||||
private $offset;
|
||||
private $param = array ();
|
||||
|
|
@ -36,12 +38,12 @@ class Connection_HttpResponse
|
|||
|
||||
if (isset($this->param['Transfer-Encoding']) && $this->param['Transfer-Encoding'] == 'chunked') {
|
||||
//$this->data = substr($this->response, $this->offset);
|
||||
$nline = hexdec($this->getLine());
|
||||
$index = hexdec($this->getLine());
|
||||
$chunk = array();
|
||||
while ($nline > 0) {
|
||||
$chunk [] = substr($this->response, $this->offset, $nline);
|
||||
$this->offset += $nline;
|
||||
$nline = hexdec($this->getLine());
|
||||
while ($index > 0) {
|
||||
$chunk [] = substr($this->response, $this->offset, $index);
|
||||
$this->offset += $index;
|
||||
$index = hexdec($this->getLine());
|
||||
}
|
||||
|
||||
$this->data = implode("", $chunk);
|
||||
|
|
|
|||
|
|
@ -1,49 +1,52 @@
|
|||
<?php
|
||||
|
||||
function forceUrl($name)
|
||||
{
|
||||
if (is_callable($name)) {
|
||||
return call_user_func($name);
|
||||
}
|
||||
return $name;
|
||||
}
|
||||
|
||||
namespace ctiso\Controller;
|
||||
use Exception,
|
||||
ctiso\Path,
|
||||
ctiso\Url,
|
||||
ctiso\Model\Factory,
|
||||
ctiso\HttpRequest,
|
||||
ctiso\Functions,
|
||||
ctiso\Settings,
|
||||
ctiso\Registry,
|
||||
ctiso\Role\User,
|
||||
ctiso\View\Composite,
|
||||
ctiso\Filter\ActionAccess,
|
||||
ctiso\View\View,
|
||||
ctiso\Controller\State;
|
||||
/**
|
||||
* Контроллер страниц
|
||||
*/
|
||||
class Controller_Action
|
||||
class Action
|
||||
{
|
||||
|
||||
const TEMPLATE_EXTENSION = ".html"; // Расширение для шаблонов
|
||||
const ACTION_PREFIX = "action"; // Префикс для функций действий
|
||||
|
||||
public $jsPath; // Глобальный путь к скриптам
|
||||
public $themePath; // Глобальный путь к текущей теме
|
||||
|
||||
// Параметры устанавливаются при создании контроллера
|
||||
// Параметры устанавливаются при создании контроллера
|
||||
public $name = ''; // Имя модуля
|
||||
public $viewPath = null; // Путь к шаблонам контроллера
|
||||
public $viewPathPrefix = null; // Путь к шаблонам контроллера
|
||||
public $front;
|
||||
|
||||
public $moduleTitle = "";
|
||||
public $modulePath = null; // Путь к модулю
|
||||
public $moduleTitle = '';
|
||||
|
||||
public $viewPathPrefix = null; // Путь к шаблонам контроллера
|
||||
|
||||
/**
|
||||
* Соединение с базой данных
|
||||
*/
|
||||
public $db;
|
||||
|
||||
// Фильтры
|
||||
// Фильтры
|
||||
public $access = null; // Обьект хранит параметры доступа
|
||||
public $logger = null; // Обьект для ведения лога
|
||||
|
||||
private $factory = null; // Ссылка на обьект создания модели
|
||||
private $helpers = array(); // Помошники для действий
|
||||
public $param = array(); // Параметры для ссылки
|
||||
private $factory = null; // Ссылка на обьект создания модели
|
||||
private $helpers = array(); // Помошники для действий
|
||||
public $part = null; // Параметры для ссылки
|
||||
|
||||
public $_registry/*: Registry*/; // Ссылка на реестр
|
||||
public $_shortcut;
|
||||
public $modulePrefix = '';
|
||||
public $iconPath = '';
|
||||
public $config/*: Registry*/; // Ссылка на настройки
|
||||
public $user/*: User*/; // Обьект пользователя
|
||||
|
||||
// Для Widgets
|
||||
public $view = null;
|
||||
|
|
@ -52,16 +55,19 @@ class Controller_Action
|
|||
public $childViews = array();
|
||||
|
||||
function __construct() {
|
||||
$this->part = new Url();
|
||||
}
|
||||
|
||||
public function setUp() {
|
||||
}
|
||||
|
||||
public function loadConfig($name) {
|
||||
$filename = Shortcut::getUrl('config', $name);
|
||||
$basePath = $this->config->get('site', 'path');
|
||||
|
||||
$filename = Path::join($basePath, 'modules', $name);
|
||||
$settings = [];
|
||||
if (file_exists($filename)) {
|
||||
include($filename);
|
||||
$settings = include($filename);
|
||||
} else {
|
||||
throw new Exception('Невозможно загрузить файл настроек ' . $name);
|
||||
}
|
||||
|
|
@ -75,37 +81,39 @@ class Controller_Action
|
|||
|
||||
public function installPath($name)
|
||||
{
|
||||
return Path::join(CMS_PATH, "modules", $name);
|
||||
$basePath = $this->config->get('system', 'path');
|
||||
return Path::join($basePath, "modules", $name);
|
||||
}
|
||||
|
||||
public function addSuggest(View_View $view, $name)
|
||||
{
|
||||
public function addSuggest(View $view, $name) {
|
||||
$suggest = array();
|
||||
$file = Path::join($this->viewPath, 'help', $name . '.suggest');
|
||||
$file = Path::join($this->modulePath, 'help', $name . '.suggest');
|
||||
if (file_exists($file)) {
|
||||
include($file);
|
||||
$view->suggestions = $suggest;
|
||||
$view->suggestions = include($file);
|
||||
}
|
||||
}
|
||||
|
||||
function findIcon($icon, $size)
|
||||
{
|
||||
return Path::join($this->iconPath, $size . 'x' . $size, $icon . '.png');
|
||||
function findIcon($icon, $size) {
|
||||
$webPath = $this->config->get('site', 'web');
|
||||
return Path::join($webPath, 'icons', $size . 'x' . $size, $icon . '.png');
|
||||
}
|
||||
|
||||
/**
|
||||
* Создает представление
|
||||
* @param $name String
|
||||
* @param $viewClass String
|
||||
* @return View_Composite
|
||||
* @param string
|
||||
* @param string $viewClass
|
||||
* @return Composite
|
||||
*/
|
||||
public function getView($name, $viewClass = 'View_Composite')
|
||||
public function getView($name, $viewClass = 'ctiso\\View\\Composite')
|
||||
{
|
||||
$file = $name . self::TEMPLATE_EXTENSION;
|
||||
|
||||
$basePath = $this->config->get('system', 'path');
|
||||
$webPath = $this->config->get('system', 'web');
|
||||
|
||||
$list = array(
|
||||
Path::join($this->viewPath, TEMPLATES, $this->viewPathPrefix) => Path::join(WWW_PATH, "modules", $this->name, TEMPLATES, $this->viewPathPrefix),
|
||||
Path::join(CMS_PATH, "templates") => Path::join(WWW_PATH, "templates")
|
||||
Path::join($this->modulePath, 'templates', $this->viewPathPrefix) => Path::join($webPath, "modules", $this->name, 'templates', $this->viewPathPrefix),
|
||||
Path::join($basePath, "templates") => Path::join($webPath, "templates")
|
||||
);
|
||||
|
||||
// Поиск файла для шаблона
|
||||
|
|
@ -114,19 +122,22 @@ class Controller_Action
|
|||
if(file_exists($template)) { break; }
|
||||
}
|
||||
|
||||
$tpl/*: View_Composite*/ = new $viewClass($template);
|
||||
$tpl/*: Composite*/ = new $viewClass($template);
|
||||
$tpl->config = $this->config;
|
||||
|
||||
$assets = Path::join(enableHttps(WWW_PATH), "assets", "css");
|
||||
$tpl->set('icons', $this->iconPath); // Путь к файлам текущей темы
|
||||
$tpl->set('media', $this->themePath); // Путь к файлам текущей темы
|
||||
$tpl->set('assets', $assets);
|
||||
$tpl->set('script', $this->jsPath); // Путь к файлам скриптов
|
||||
$stylePath = Path::join($webPath, "assets", "css");
|
||||
$iconsPath = Path::join($webPath, 'icons');
|
||||
$scriptPath = Path::join($webPath, 'assets');
|
||||
|
||||
$tpl->set('icons', $iconsPath); // Путь к файлам текущей темы
|
||||
$tpl->set('assets', $stylePath);
|
||||
$tpl->set('script', $scriptPath); // Путь к файлам скриптов
|
||||
$tpl->set('template', $path); // Путь к файлам текущего шаблона
|
||||
|
||||
$tpl->setAlias(array(
|
||||
'assets' => $assets,
|
||||
'icons' => $this->iconPath,
|
||||
'script' => $this->jsPath,
|
||||
'assets' => $stylePath,
|
||||
'icons' => $iconsPath,
|
||||
'script' => $scriptPath,
|
||||
// Для media и template поиск происходит как для файлов шаблонов
|
||||
'media' => $list,
|
||||
'template' => $list
|
||||
|
|
@ -141,7 +152,7 @@ class Controller_Action
|
|||
public function getModel($name)
|
||||
{
|
||||
if (!$this->factory) {
|
||||
$this->factory = new Model_Factory($this->db, $this->_registry);
|
||||
$this->factory = new Factory($this->db, $this->config, $this->user);
|
||||
}
|
||||
return $this->factory->getModel($name);
|
||||
}
|
||||
|
|
@ -151,25 +162,25 @@ class Controller_Action
|
|||
* Т.к действия являются методами класса то
|
||||
* 1. Можно переопределить действия
|
||||
* 2. Использовать наследование чтобы добавить к старому обработчику новое поведение
|
||||
* @param $request Обьект запроса
|
||||
* @param HttpRequest $request запроса
|
||||
*/
|
||||
public function preprocess(HttpRequest $request)
|
||||
public function preProcess(HttpRequest $request)
|
||||
{
|
||||
$action = self::ACTION_PREFIX . ucfirst($request->getAction());
|
||||
if (!method_exists($this, $action)) {
|
||||
$action = "actionIndex";
|
||||
}
|
||||
$view = $this->forward($action, $request);
|
||||
if ($view instanceof View_View) {
|
||||
$view->active_module = get_class($this);
|
||||
$view->module_action = $action;
|
||||
}
|
||||
return $view;
|
||||
if ($view instanceof View) {
|
||||
$view->active_module = get_class($this);
|
||||
$view->module_action = $action;
|
||||
}
|
||||
return $view;
|
||||
}
|
||||
|
||||
|
||||
public function execute(HttpRequest $request)
|
||||
{
|
||||
$result = $this->preprocess($request);
|
||||
$result = $this->preProcess($request);
|
||||
if (!empty($result)) {
|
||||
$this->view = $result;
|
||||
}
|
||||
|
|
@ -189,13 +200,8 @@ class Controller_Action
|
|||
return "";
|
||||
}
|
||||
|
||||
public function postUrl($name, $param)
|
||||
{
|
||||
$uri = array_merge(array('module' =>
|
||||
strtr($this->modulePrefix . strtolower(get_class($this)), array('module_' => '')), "action" => $name),
|
||||
$this->param, $param);
|
||||
|
||||
return "?" . http_build_query($uri);
|
||||
public function addUrlPart($key, $value) {
|
||||
$this->part->addQueryParam($key, $value);
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
@ -203,31 +209,28 @@ class Controller_Action
|
|||
* @param string $name Действие
|
||||
* @param array $param Дополнительные параметры
|
||||
* 'mode' означает что элемент до отправки обрабатывается javascript
|
||||
* @return array|null
|
||||
* @return Url|null
|
||||
*/
|
||||
public function nUrl($name, array $param = array())
|
||||
{
|
||||
$access/*: Filter_ActionAccess*/ = $this->access;
|
||||
$access/*: ActionAccess*/ = $this->access;
|
||||
$url = new Url();
|
||||
|
||||
if ($access == null || $access->checkAction($name)) {
|
||||
return Functions::lcurry(array($this, 'postUrl'), $name, $param);
|
||||
}
|
||||
return null;
|
||||
}
|
||||
$moduleName = explode("\\", strtolower(get_class($this)));
|
||||
if (count($moduleName) > 2) {
|
||||
array_shift($moduleName);
|
||||
if ($moduleName[0] == $moduleName[1]) {
|
||||
array_shift($moduleName);
|
||||
}
|
||||
}
|
||||
$param = array_merge(array('module' => implode("\\", $moduleName), "action" => $name), $param);
|
||||
|
||||
public function fUrl($name, array $param = array())
|
||||
{
|
||||
return forceUrl($this->nUrl($name, $param));
|
||||
}
|
||||
|
||||
/**
|
||||
* Добавляет параметр для всех ссылок создаваемых функцией nUrl, aUrl
|
||||
*/
|
||||
public function addParameter($name, $value)
|
||||
{
|
||||
if ($value) {
|
||||
$this->param [$name] = $value;
|
||||
$url->setParent($this->part);
|
||||
$url->setQuery($param);
|
||||
}
|
||||
|
||||
return $url;
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
@ -235,14 +238,14 @@ class Controller_Action
|
|||
* Ajax определяется автоматически mode = ajax используется для смены layout
|
||||
* @param $name
|
||||
* @param array $param
|
||||
* @return array|null
|
||||
* @return Url|null
|
||||
*
|
||||
* @example ?action=$name&mode=ajax
|
||||
* {$param[i].key = $param[i].value}
|
||||
*/
|
||||
public function aUrl($name, array $param = array())
|
||||
{
|
||||
return $this->nUrl($name, array_merge(array('mode' => 'ajax'), $param)); // FIXME
|
||||
return $this->nUrl($name, array_merge(array('mode' => 'ajax'), $param));
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
@ -295,29 +298,29 @@ class Controller_Action
|
|||
|
||||
/**
|
||||
* Установка заголовка для отображения
|
||||
*/
|
||||
*/
|
||||
public function setTitle($title)
|
||||
{
|
||||
$this->view->setTitle($title);
|
||||
}
|
||||
|
||||
/**
|
||||
* Добавление widget к отображению
|
||||
* Добавление widget к отображению
|
||||
*/
|
||||
public function addChild(/*Widget*/ $section, $node)
|
||||
public function addChild($section, $node)
|
||||
{
|
||||
$this->childNodes[$section] = $node;
|
||||
}
|
||||
|
||||
public function setValue(/*Widget*/ $name, $value)
|
||||
public function setValue($name, $value)
|
||||
{
|
||||
$this->ctrlValues[$name] = $value;
|
||||
}
|
||||
|
||||
/**
|
||||
* Добавление дочернего отображения к текущему отображению
|
||||
* Добавление дочернего отображения к текущему отображению
|
||||
*/
|
||||
public function addView(/*CompositeView*/ $section, $node)
|
||||
public function addView($section, $node)
|
||||
{
|
||||
$this->childViews[$section] = $node;
|
||||
}
|
||||
|
|
@ -326,12 +329,13 @@ class Controller_Action
|
|||
* Генерация содержания
|
||||
* Путаница c execute и render
|
||||
*/
|
||||
public function render()
|
||||
public function render()
|
||||
{
|
||||
if ($this->view instanceof View_View) {
|
||||
$this->view->assignValues($this->ctrlValues);
|
||||
$view = $this->view;
|
||||
if ($view instanceof View) {
|
||||
$this->view->assignValues($this->ctrlValues);
|
||||
|
||||
$node/*: Widgets_Widget*/ = null;
|
||||
$node/*: Composite*/ = null;
|
||||
foreach ($this->childNodes as $name => $node) {
|
||||
$node->make($this);
|
||||
$this->view->setView($name, $node->view);
|
||||
|
|
@ -340,18 +344,17 @@ class Controller_Action
|
|||
foreach ($this->childViews as $name => $node) {
|
||||
$this->view->setView($name, $node);
|
||||
}
|
||||
}
|
||||
}
|
||||
return $this->view;
|
||||
}
|
||||
|
||||
function getPageId(HttpRequest $request)
|
||||
{
|
||||
$pageId = time();
|
||||
function getPageId(HttpRequest $request) {
|
||||
$pageId = time();
|
||||
$request->session()->set('page', $pageId);
|
||||
return $pageId;
|
||||
}
|
||||
|
||||
function checkPageId(HttpRequest $request, $page)
|
||||
function checkPageId(HttpRequest $request, $page)
|
||||
{
|
||||
if ($request->get('__forced__')) {
|
||||
return true;
|
||||
|
|
@ -362,19 +365,17 @@ class Controller_Action
|
|||
return $result;
|
||||
}
|
||||
|
||||
function _getActionPath()
|
||||
{
|
||||
return new Controller_State('index');
|
||||
function _getActionPath() {
|
||||
return new State('index');
|
||||
}
|
||||
|
||||
// Тоже убрать в метод Controller_Model
|
||||
function getActionPath(HttpRequest $request, $action = null)
|
||||
{
|
||||
function getActionPath(HttpRequest $request, $action = null) {
|
||||
$this->_getActionPath()->getPath($this, ($action) ? $action : $request->getAction());
|
||||
}
|
||||
|
||||
function redirect($action) {
|
||||
header('location: ' . $this->fUrl($action));
|
||||
function redirect($action/*: string*/) {
|
||||
header('location: ' . $action);
|
||||
exit();
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,48 +1,42 @@
|
|||
<?php
|
||||
|
||||
function replaceContent($match) {
|
||||
$result = phptal_component(htmlspecialchars_decode($match[3]));
|
||||
return $result;
|
||||
}
|
||||
namespace ctiso\Controller;
|
||||
use ctiso\HttpRequest,
|
||||
ctiso\ComponentRequest,
|
||||
ctiso\Arr,
|
||||
ctiso\Path,
|
||||
ctiso\File,
|
||||
ctiso\Form\Form,
|
||||
ctiso\View\Composite,
|
||||
ctiso\Database,
|
||||
ctiso\Database\PDOStatement,
|
||||
ctiso\Collection,
|
||||
ctiso\Registry,
|
||||
ctiso\Controller\SiteInterface,
|
||||
PHPTAL,
|
||||
PHPTAL_PreFilter_Normalize;
|
||||
|
||||
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 $component_title;
|
||||
public $r;
|
||||
|
||||
function __construct($c, HttpRequest $r) {
|
||||
$this->component_id = $c;
|
||||
$this->r = $r;
|
||||
class FakeTemplate {
|
||||
public $_data = [];
|
||||
public $_name = '';
|
||||
|
||||
function __construct($name) {
|
||||
$this->_name = $name;
|
||||
}
|
||||
|
||||
function get($key, $default = null) {
|
||||
if ($key == 'active_page') {
|
||||
return $this->r->get($key);
|
||||
}
|
||||
$arr = $this->r->get($key);
|
||||
if ($arr !== NULL) {
|
||||
if (is_array($arr)) {
|
||||
return Arr::get($arr, $this->component_id, $default);
|
||||
} else {
|
||||
return $arr;
|
||||
}
|
||||
}
|
||||
return $default;
|
||||
}
|
||||
function __set($key, $value) {
|
||||
$this->_data[$key] = $value;
|
||||
}
|
||||
|
||||
function getAction() {
|
||||
return $this->r->getAction();
|
||||
function execute() {
|
||||
return json_encode($this->_data);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Класс компонента
|
||||
*/
|
||||
class Controller_Component
|
||||
class Component
|
||||
{
|
||||
public $viewPath = array();
|
||||
public $webPath = array();
|
||||
|
|
@ -52,19 +46,28 @@ class Controller_Component
|
|||
|
||||
public $component_id;
|
||||
public $component_title;
|
||||
|
||||
public $COMPONENTS_WEB;
|
||||
|
||||
public $registry/*: Settings*/;
|
||||
public $config/*: Registry*/;
|
||||
public $db/*: Database*/;
|
||||
public $parameter/*: Collection*/;
|
||||
|
||||
public $output = 'html';
|
||||
|
||||
public $module;
|
||||
public $item_module;
|
||||
public $site;
|
||||
|
||||
function before() {
|
||||
}
|
||||
|
||||
function get($request, $key, $default) {
|
||||
static function replaceContent($match) {
|
||||
return \ctiso\Tales::phptal_component(htmlspecialchars_decode($match[3]));
|
||||
}
|
||||
|
||||
static function applyComponents($text) {
|
||||
return preg_replace_callback('/<(\w+)(\s+[a-zA-Z\-]+=\"[^\"]*\")*\s+tal:replace="structure\s+component:([^\"]*)"[^>]*>/u', 'ctiso\\Controller\\Component::replaceContent', $text);
|
||||
}
|
||||
|
||||
function execute(HttpRequest $request, $has_id = true) {
|
||||
|
|
@ -85,16 +88,20 @@ class Controller_Component
|
|||
}
|
||||
}
|
||||
|
||||
public function getTemplateName($_registry/*: Settings*/) {
|
||||
public function getTemplateName($_registry/*: \ctiso\Settings*/) {
|
||||
return (isset($_COOKIE['with_template']) && preg_match('/^[\w\d-]{3,20}$/', $_COOKIE['with_template']))
|
||||
? $_COOKIE['with_template'] : ($_registry ? $_registry->readKey(array('system', 'template')) : 'modern');
|
||||
? $_COOKIE['with_template'] : ($_registry ? $_registry->get('site', 'template') : 'modern');
|
||||
}
|
||||
|
||||
public function getView($name)
|
||||
{
|
||||
//
|
||||
$registry/*: Settings*/ = $this->registry;
|
||||
$template = ($this->template) ? $this->template : $this->getTemplateName($registry);
|
||||
if ($this->output == 'json') {
|
||||
return new FakeTemplate($name);
|
||||
}
|
||||
|
||||
$config/*: Registry*/ = $this->config;
|
||||
$default = $config->get('site', 'template');
|
||||
$template = ($this->template) ? $this->template : $this->getTemplateName($config);
|
||||
|
||||
$selected = null;
|
||||
foreach ($this->viewPath as $index => $viewPath) {
|
||||
|
|
@ -119,13 +126,14 @@ class Controller_Component
|
|||
$tpl->stripComments(true);
|
||||
$tpl->addPreFilter(new PHPTAL_PreFilter_Normalize());
|
||||
|
||||
$tpl->set('common', Path::join(WWW_PATH, '../', 'common'));
|
||||
$tpl->set('script', Path::join(WWW_PATH, 'js'));
|
||||
$tpl->set('media', Path::join(TEMPLATE_WEB, $template));
|
||||
if ($registry) {
|
||||
$tpl->set('site_template', SITE_WWW_PATH . '/templates/' . $registry->readKey(array('system', 'template')));
|
||||
$tpl->set('common', Path::join($this->config->get('system', 'web'), '../', 'common'));
|
||||
$tpl->set('script', Path::join($this->config->get('system', 'web'), 'js'));
|
||||
$tpl->set('media', Path::join($this->config->get('system', 'templates.web'), $template));
|
||||
|
||||
if ($default) {
|
||||
$tpl->set('site_template', Path::join($this->config->get('site', 'templates.web'), $default));
|
||||
}
|
||||
$tpl->set('base', SITE_WWW_PATH);
|
||||
$tpl->set('base', $this->config->get('site', 'web'));
|
||||
|
||||
$tpl->set('component_base', $this->webPath[$selected]);
|
||||
$tpl->set('component', Path::join($this->webPath[$selected], 'templates', $template));
|
||||
|
|
@ -139,7 +147,7 @@ class Controller_Component
|
|||
}
|
||||
|
||||
public function getTemplatePath($name) {
|
||||
$registry/*: Settings*/ = $this->registry;
|
||||
$registry/*: \ctiso\Settings*/ = $this->config;
|
||||
// Брать настройки из куков если есть
|
||||
$template = ($this->template) ? $this->template : $this->getTemplateName($registry);
|
||||
foreach ($this->viewPath as $index => $viewPath) {
|
||||
|
|
@ -163,13 +171,14 @@ class Controller_Component
|
|||
*/
|
||||
public function getModel($name)
|
||||
{
|
||||
$modelName = "Mapper_" . $name;
|
||||
$modelName = "App\\Mapper\\" . $name;
|
||||
$model = new $modelName();
|
||||
$model->config = $this->config;
|
||||
$model->db = $this->db;
|
||||
return $model;
|
||||
}
|
||||
|
||||
public function options($key, $val, $res/*: Database_PDOStatement*/) {
|
||||
public function options($key, $val, $res/*: PDOStatement*/) {
|
||||
$result = array();
|
||||
while($res->next()) {
|
||||
$result[] = array('value' => $res->getString($key), 'name' => $res->getString($val));
|
||||
|
|
@ -185,22 +194,33 @@ class Controller_Component
|
|||
return $result;
|
||||
}
|
||||
|
||||
function findFile($pathList, $name) {
|
||||
foreach($pathList as $item) {
|
||||
$filename = Path::join($item, $name);
|
||||
if (file_exists($filename)) {
|
||||
return $filename;
|
||||
}
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
function getInfo() {
|
||||
$filename = Path::join($this->viewPath[count($this->viewPath) - 1], 'install.json');
|
||||
if (file_exists($filename)) {
|
||||
$settings = json_decode(File::getContents($filename), true);
|
||||
return $settings;
|
||||
if ($settings) {
|
||||
return $settings;
|
||||
}
|
||||
}
|
||||
return array();
|
||||
return array('parameter' => []);
|
||||
}
|
||||
|
||||
/**
|
||||
* Генерация интерфейса для выбора галлереи фотографии
|
||||
*/
|
||||
public function setParameters($view/*: View_Composite*/)
|
||||
public function setParameters($view/*: Composite*/, $options = null)
|
||||
{
|
||||
$form = new Form_Form();
|
||||
$options = new Form_OptionFactory($this->db, $this->registry);
|
||||
$form = new Form();
|
||||
|
||||
$settings = $this->getInfo();
|
||||
$form->addFieldList($settings['parameter'], $options);
|
||||
|
|
@ -210,7 +230,7 @@ class Controller_Component
|
|||
$view->component_title = $settings['title'];
|
||||
}
|
||||
|
||||
static function loadComponent($expression, Database $db, $registry/*: Registry*/)
|
||||
static function loadComponent($expression, $site/*: SiteInterface*/)
|
||||
{
|
||||
|
||||
$expression = htmlspecialchars_decode($expression);
|
||||
|
|
@ -226,55 +246,54 @@ class Controller_Component
|
|||
parse_str($query, $arguments);
|
||||
}
|
||||
$name = $path;
|
||||
$config = $site->config;
|
||||
|
||||
$path = Path::join (BASE_PATH, 'components', $name, $name . '.php');
|
||||
$className = 'Component_' . $name;
|
||||
$filename = ucfirst($name);
|
||||
$path = Path::join ($config->get('site', 'components'), $name, $filename . '.php');
|
||||
$className = implode("\\", ['Components', ucfirst($name), $filename]);
|
||||
|
||||
$component/*: Controller_Component*/ = null;
|
||||
$component/*: Component*/ = null;
|
||||
|
||||
if (file_exists($path)) {
|
||||
require_once ($path);
|
||||
|
||||
// require_once ($path);
|
||||
$component = new $className();
|
||||
$component->db = $db;
|
||||
$component->registry = $registry;
|
||||
|
||||
$component->viewPath = array(BASE_PATH . '/components/' . $name . '/');
|
||||
$component->webPath = array(SITE_WWW_PATH . '/components/' . $name);
|
||||
|
||||
$component->COMPONENTS_WEB = SITE_WWW_PATH . '/components/';
|
||||
$component->viewPath = array($config->get('site', 'components') . '/' . $name . '/');
|
||||
$component->webPath = array($config->get('site', 'components.web') . '/' . $name);
|
||||
$component->COMPONENTS_WEB = $config->get('site', 'web') . '/components/';
|
||||
|
||||
} else {
|
||||
$path = Path::join (COMPONENTS, $name, $name . '.php');
|
||||
require_once ($path);
|
||||
$component = new $className();
|
||||
$component->db = $db;
|
||||
$component->registry = $registry;
|
||||
|
||||
$template = $component->getTemplateName($registry);
|
||||
$template = $component->getTemplateName($site->config);
|
||||
|
||||
$component->viewPath = array(
|
||||
// Сначало ищем локально
|
||||
BASE_PATH . '/templates/' . $template . '/_components/' . $name . '/',
|
||||
BASE_PATH . '/components/' . $name . '/',
|
||||
$config->get('site', 'templates') . '/'. $template . '/_components/' . $name . '/',
|
||||
$config->get('site', 'components') . '/' . $name . '/',
|
||||
// Потом в общем хранилище
|
||||
CMS_PATH . '/../templates/' . $template . '/_components/' . $name . '/',
|
||||
COMPONENTS . '/' . $name . '/',
|
||||
$config->get('system', 'templates'). '/' . $template . '/_components/' . $name . '/',
|
||||
$config->get('system', 'components') . '/' . $name . '/',
|
||||
);
|
||||
if (defined('COMPONENTS_WEB')) {
|
||||
$component->webPath = array(
|
||||
// Сначало локально
|
||||
SITE_WWW_PATH . '/templates/' . $template . '/_components/' . $name,
|
||||
SITE_WWW_PATH . '/components/' . $name,
|
||||
$config->get('site', 'templates.web') . '/' . $template . '/_components/' . $name,
|
||||
$config->get('site', 'components.web') . '/' . $name,
|
||||
// Потом в общем хранилище
|
||||
TEMPLATE_WEB . '/' . $template . '/_components/' . $name,
|
||||
COMPONENTS_WEB . '/' . $name,
|
||||
$config->get('system', 'templates.web') . '/' . $template . '/_components/' . $name,
|
||||
$config->get('system', 'components.web') . '/' . $name,
|
||||
);
|
||||
$component->COMPONENTS_WEB = COMPONENTS_WEB;
|
||||
$component->COMPONENTS_WEB = $config->get('system', 'components.web');
|
||||
} else {
|
||||
$component->webPath = array('', SITE_WWW_PATH . '/components/' . $name, '');
|
||||
$component->webPath = array('', $config->get('site', 'components.web') . '/' . $name, '');
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
$db = $site->getDatabase();
|
||||
|
||||
$component->db = $db;
|
||||
$component->config = $site->config;
|
||||
$component->site = $site;
|
||||
|
||||
$stmt = $db->prepareStatement("SELECT * FROM component WHERE code = ?");
|
||||
$stmt->setString(1, $expression);
|
||||
|
|
@ -302,18 +321,13 @@ class Controller_Component
|
|||
|
||||
$params = new Collection();
|
||||
$params->import(array_merge($_GET, $arguments));
|
||||
|
||||
$component->parameter = $params;
|
||||
$component->template = $params->get('template', false);
|
||||
|
||||
$editor = $component->getEditUrl();
|
||||
if ($editor) {
|
||||
if(class_exists("Controller_Site")){ //Если мы в CMS2
|
||||
$instance = Controller_Site::getInstance();
|
||||
$instance->componentsConfig[] = $editor;
|
||||
} else {
|
||||
global $componentsConfig;
|
||||
$componentsConfig[] = $editor;
|
||||
}
|
||||
$site->componentsConfig[] = $editor;
|
||||
}
|
||||
|
||||
return $component;
|
||||
|
|
@ -358,15 +372,10 @@ class Controller_Component
|
|||
return '?' . http_build_query($arr);
|
||||
}
|
||||
|
||||
/**
|
||||
* @deprecated В CMS2 перенесено в контроллер сайта!
|
||||
*/
|
||||
|
||||
function addRequireJsPath($name, $path, $shim = null) {
|
||||
Controller_Site::addRequireJsPath($name, $path, $shim);
|
||||
$this->site->addRequireJsPath($name, $path, $shim);
|
||||
}
|
||||
|
||||
function actionIndex($request/*: ComponentRequest*/) {
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -4,76 +4,85 @@
|
|||
* Первичный контроллер контроллер страниц
|
||||
* @package system.controller
|
||||
*/
|
||||
class Controller_Front extends Controller_Action
|
||||
namespace ctiso\Controller;
|
||||
use ctiso\Controller\Action,
|
||||
ctiso\Settings,
|
||||
ctiso\Database,
|
||||
ctiso\Collection,
|
||||
ctiso\Filter\ActionAccess,
|
||||
ctiso\Filter\ActionLogger,
|
||||
ctiso\Path,
|
||||
ctiso\UserMessageException,
|
||||
ctiso\HttpRequest;
|
||||
|
||||
class Front extends Action
|
||||
{
|
||||
|
||||
/** @var Shortcut */
|
||||
protected $shortcut; // Ярлык к модулю
|
||||
protected $_param; // Параметр по которому выбирается модуль
|
||||
protected $default; // Значение параметра по умолчанию
|
||||
|
||||
protected $modules = array();
|
||||
|
||||
/**
|
||||
* @param Settings $_registry
|
||||
* @param Shortcut $_shortcut
|
||||
* @param Settings $settings
|
||||
*/
|
||||
public function __construct(Settings $_registry, $_shortcut) // $db, $installer, $shortcut
|
||||
{
|
||||
public function __construct($db, $config, $user, $default) {
|
||||
parent::__construct();
|
||||
$registry = $_registry;
|
||||
$this->_registry = $_registry;
|
||||
$this->_shortcut = $_shortcut; // $cc->newShortcut();
|
||||
|
||||
$dsn = $registry->readKey(array('system', 'dsn'));
|
||||
$this->db = Database::getConnection($dsn); // $cc->newConnection();
|
||||
$this->config = $config;
|
||||
$this->db = $db;
|
||||
$this->user = $user;
|
||||
$this->default = $default;
|
||||
}
|
||||
|
||||
public function isLoaded($name)
|
||||
{
|
||||
public function isLoaded($name) {
|
||||
return isset($this->modules[$name]);
|
||||
}
|
||||
|
||||
/**
|
||||
* Создает экземпляр модуля и выполняет действия для него
|
||||
* @param string $name Имя модуля
|
||||
* @param request $request Имя модуля
|
||||
* @param Request $request Имя модуля
|
||||
* @return string
|
||||
*/
|
||||
public function loadModule($name, Collection $request, $controller = false)
|
||||
public function loadModule($name, Collection $request)
|
||||
{
|
||||
if ($this->isLoaded($name)) {
|
||||
$module = $this->modules[$name];
|
||||
return $module->access->execute($request);
|
||||
}
|
||||
|
||||
$suffix = ($controller) ? $controller : $name;
|
||||
$moduleFile = Shortcut::getUrl($this->shortcut, $name, $suffix); // ModuleLoader (2)
|
||||
$parts = explode('\\', $name);
|
||||
|
||||
$config = $this->config;
|
||||
|
||||
$moulesPath = Path::join($config->get('system', 'path'), 'modules');
|
||||
$logPath = Path::join($config->get('site', 'path'), $config->get('system', 'access.log'));
|
||||
|
||||
$module = $this->loadClass($moduleFile, null, 'Module_');
|
||||
$first = $parts[0];
|
||||
$second = (count($parts) >= 2) ? $parts[1] : $parts[0];
|
||||
|
||||
$ucname = ucfirst($first);
|
||||
$ucpart = ucfirst($second);
|
||||
|
||||
$moduleClass = "Modules\\$ucname\\$ucpart";
|
||||
$module = new $moduleClass();
|
||||
if ($module) {
|
||||
// Инициализация модуля
|
||||
$module->front = $this;
|
||||
$module->viewPath = Shortcut::getUrl('modulepath', $name);
|
||||
$modPath = Path::join($moulesPath, $first);
|
||||
$module->modulePath = $modPath;
|
||||
$module->name = $name;
|
||||
|
||||
$module->param = $this->param;
|
||||
//
|
||||
$module->_registry = $this->_registry;
|
||||
$module->_shortcut = $this->_shortcut;
|
||||
|
||||
$module->iconPath = $this->iconPath; // -> Registry
|
||||
$module->themePath = $this->themePath; // -> Registry
|
||||
$module->jsPath = $this->jsPath; // -> Registry
|
||||
$module->config = $this->config;
|
||||
$module->db = $this->db;
|
||||
// Не для всех приложений нужно вести лог действий
|
||||
$module->user = $this->user;
|
||||
$module->front = $this;
|
||||
// Ведение лога
|
||||
$logger = $this->loadClass(__DIR__ . '/../Filter/ActionLogger.php', $module, 'Filter_');
|
||||
$logger->before = $this->loadSettings(Shortcut::getUrl('logger', $name));
|
||||
$logger = new ActionLogger($module, $logPath, $this->user);
|
||||
$filename = Path::join($modPath, 'filters', 'logger.json');
|
||||
$logger->before = $this->loadSettings($filename);
|
||||
// Управление доступом
|
||||
$module->access = $this->loadClass(__DIR__ . '/../Filter/ActionAccess.php', $logger, 'Filter_');
|
||||
$module->access->name = $suffix;
|
||||
$module->access->access = $this->loadSettings(Shortcut::getUrl('access', $name));
|
||||
$module->access = new ActionAccess($logger, $this->user);
|
||||
$module->access->access = $this->loadSettings(Path::join($modPath, 'filters', 'access.json'));
|
||||
|
||||
$module->setUp();
|
||||
|
||||
|
|
@ -84,27 +93,15 @@ class Controller_Front extends Controller_Action
|
|||
return null; // throw new FileNotFoundException();
|
||||
}
|
||||
|
||||
public function setParameter($shortcut, $param, $name)
|
||||
{
|
||||
$this->shortcut = $shortcut;
|
||||
// Параметр
|
||||
$this->_param = $param;
|
||||
$this->default = $name;
|
||||
}
|
||||
|
||||
public function execute(HttpRequest $request)
|
||||
{
|
||||
$name = explode("_", $request->get($this->_param, $this->default));
|
||||
if (count($name) >= 2) {
|
||||
$controller = $name[1];
|
||||
} else {
|
||||
$controller = false;
|
||||
}
|
||||
try{
|
||||
return $this->loadModule($name[0], $request, $controller);
|
||||
$name = $request->get('module', $this->default);
|
||||
try {
|
||||
return $this->loadModule($name, $request);
|
||||
} catch (UserMessageException $ex) { //Исключение с понятным пользователю сообщением
|
||||
$mode = $request->get('mode');
|
||||
if($mode == 'ajax' || $mode == 'json'){
|
||||
if ($mode == 'ajax' || $mode == 'json') {
|
||||
return json_encode(['result'=>'fail', 'message'=> $ex->userMessage]);
|
||||
} else {
|
||||
return $ex->userMessage;
|
||||
|
|
|
|||
|
|
@ -1,6 +1,11 @@
|
|||
<?php
|
||||
|
||||
class Controller_Installer
|
||||
namespace ctiso\Controller;
|
||||
use ctiso\Settings,
|
||||
ctiso\Path,
|
||||
ctiso\Database\JsonInstall;
|
||||
|
||||
class Installer
|
||||
{
|
||||
protected $db_manager;
|
||||
protected $installPath;
|
||||
|
|
@ -30,7 +35,7 @@ class Controller_Installer
|
|||
// Проверка версии обновления
|
||||
function isChanged($name) // Информация о модулях
|
||||
{
|
||||
$item = $this->_registry->readKey(array($name));
|
||||
$item = $this->_registry->get('system', $name);
|
||||
if ($item) {
|
||||
$setup = $this->getSetupFile($name);
|
||||
if (file_exists($setup) && (filemtime($setup) > $item['time'])) {
|
||||
|
|
@ -44,7 +49,7 @@ class Controller_Installer
|
|||
function installSQL(array $sql, $version_new, $version_old, $name)
|
||||
{
|
||||
$result = [];
|
||||
$json_installer = new Database_JsonInstall($this->db_manager);
|
||||
$json_installer = new JsonInstall($this->db_manager);
|
||||
foreach ($sql as $version => $install) {
|
||||
if (version_compare($version, $version_new, "<=") && version_compare($version, $version_old, ">")) {
|
||||
$file = Path::join(call_user_func($this->installPath, $name), "sql", $install);
|
||||
|
|
@ -58,7 +63,7 @@ class Controller_Installer
|
|||
function uninstall($name){
|
||||
$uninstall = $this->getUninstallFile($name);
|
||||
if (file_exists($uninstall)) {
|
||||
$json_installer = new Database_JsonInstall($this->db_manager);
|
||||
$json_installer = new JsonInstall($this->db_manager);
|
||||
$json_installer->install($uninstall,null);
|
||||
}
|
||||
$this->_registry->removeKey($name);
|
||||
|
|
@ -76,7 +81,7 @@ class Controller_Installer
|
|||
$settings = new Settings($setup);
|
||||
$settings->read();
|
||||
|
||||
$item = $registry->readKey(array($name));
|
||||
$item = $registry->get('system', $name);
|
||||
|
||||
$version_new = $settings->get('version');
|
||||
if ($item) {
|
||||
|
|
@ -89,26 +94,27 @@ class Controller_Installer
|
|||
$sql = $settings->get('sql');
|
||||
if (is_array($sql)) {
|
||||
$res = $this->installSQL($sql, $version_new, $version_old, $name);
|
||||
if($res){
|
||||
if ($res) {
|
||||
$result[]=$res;
|
||||
}
|
||||
}
|
||||
|
||||
// Обновление версии меню
|
||||
$registry->removeKey($name);
|
||||
$registry->writeKey(array($name), $settings->get('settings'));
|
||||
$registry->writeKey(array($name),
|
||||
array('version' => $version_new,
|
||||
'time' => filemtime($setup)));
|
||||
}
|
||||
|
||||
// Обновление версии меню
|
||||
$registry->removeKey($name);
|
||||
$registry->set($name, [
|
||||
'version' => $version_new,
|
||||
'time' => filemtime($setup)
|
||||
]);
|
||||
$registry->writeKey([$name], $settings->get('settings'));
|
||||
|
||||
$registry->write();
|
||||
}
|
||||
return $result;
|
||||
}
|
||||
|
||||
function install($dbinit_path, $dbfill_path = null) {
|
||||
$json_installer = new Database_JsonInstall($this->db_manager);
|
||||
$json_installer = new JsonInstall($this->db_manager);
|
||||
$json_installer->install($dbinit_path, $dbfill_path);
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,10 +1,13 @@
|
|||
<?php
|
||||
|
||||
class Controller_Request {
|
||||
namespace ctiso\Controller;
|
||||
use ctiso\HttpRequest;
|
||||
|
||||
class Request {
|
||||
public $r;
|
||||
public $id;
|
||||
|
||||
function __construct($request, $id) {
|
||||
function __construct($request/*: HttpRequest*/, $id) {
|
||||
$this->r = $request;
|
||||
$this->id = $id;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -3,11 +3,17 @@
|
|||
/**
|
||||
* Класс сервиса = Упрощенный компонент
|
||||
*/
|
||||
class Controller_Service
|
||||
namespace ctiso\Controller;
|
||||
use ctiso\Path,
|
||||
ctiso\File,
|
||||
ctiso\Registry,
|
||||
ctiso\Database\PDOStatement;
|
||||
|
||||
class Service
|
||||
{
|
||||
public $viewPath = [];
|
||||
public $webPath = [];
|
||||
public $registry; // Registry->getInstance
|
||||
public $config/*: Registry*/;
|
||||
public $template;
|
||||
public $templatePath;
|
||||
public $COMPONENTS_WEB;
|
||||
|
|
@ -25,17 +31,17 @@ class Controller_Service
|
|||
}
|
||||
|
||||
/**
|
||||
* @param $name Имя модели
|
||||
* @param string $name Имя модели
|
||||
*/
|
||||
private function getModelPath($name)
|
||||
{
|
||||
return Path::join (CMS_PATH, "model", $name . ".php");
|
||||
return Path::join ($this->config->get('system', 'path'), "model", $name . ".php");
|
||||
}
|
||||
|
||||
/**
|
||||
* Создает модель
|
||||
* @param string $name
|
||||
* @return model
|
||||
* @return Model
|
||||
*/
|
||||
public function getModel($name)
|
||||
{
|
||||
|
|
@ -46,7 +52,7 @@ class Controller_Service
|
|||
return $model;
|
||||
}
|
||||
|
||||
public function options($key, $val, $res) {
|
||||
public function options($key, $val, $res/*: PDOStatement*/) {
|
||||
$result = array();
|
||||
while($res->next()) {
|
||||
$result[] = array('value' => $res->getInt($key), 'name' => $res->getString($val));
|
||||
|
|
|
|||
12
src/Controller/SiteInterface.php
Normal file
12
src/Controller/SiteInterface.php
Normal file
|
|
@ -0,0 +1,12 @@
|
|||
<?php
|
||||
|
||||
namespace ctiso\Controller;
|
||||
|
||||
interface SiteInterface {
|
||||
function getResource();
|
||||
function loadComponent($expression);
|
||||
function getDatabase();
|
||||
function getConfig();
|
||||
function setComponentConfig($config);
|
||||
function addRequireJsPath($name, $path, $schim = null);
|
||||
}
|
||||
|
|
@ -1,6 +1,10 @@
|
|||
<?php
|
||||
|
||||
class Controller_State
|
||||
namespace ctiso\Controller;
|
||||
use ctiso\Controller\Action,
|
||||
ctiso\Url;
|
||||
|
||||
class State
|
||||
{
|
||||
public $action = '';
|
||||
public $states = array();
|
||||
|
|
@ -13,7 +17,7 @@ class Controller_State
|
|||
|
||||
static function make($action)
|
||||
{
|
||||
return new Controller_State($action);
|
||||
return new State($action);
|
||||
}
|
||||
|
||||
public function addTitle($name, $url = array())
|
||||
|
|
@ -22,7 +26,7 @@ class Controller_State
|
|||
return $this;
|
||||
}
|
||||
|
||||
public function addState(Controller_State $state)
|
||||
public function addState(State $state)
|
||||
{
|
||||
$this->states [$state->getAction()] = $state;
|
||||
return $this;
|
||||
|
|
@ -49,7 +53,7 @@ class Controller_State
|
|||
return false;
|
||||
}
|
||||
|
||||
function makeTitle(Controller_Action $module)
|
||||
function makeTitle(Action $module)
|
||||
{
|
||||
foreach ($this->titles as $item) {
|
||||
$module->path->addMenuItem($module->nUrl($this->action, $item[1]), $item[0]);
|
||||
|
|
|
|||
|
|
@ -1,6 +1,19 @@
|
|||
<?php
|
||||
///<reference path="Database/PDOStatement.php" />
|
||||
require_once "Database/PDOStatement.php";
|
||||
|
||||
namespace {
|
||||
if(!function_exists('sqliteLower')){
|
||||
function sqliteLower($str) {
|
||||
return mb_strtolower($str, 'UTF-8');
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
namespace ctiso {
|
||||
use PDO,
|
||||
ctiso\Database\Statement,
|
||||
ctiso\Database\PDOStatement,
|
||||
ctiso\Database\IdGenerator;
|
||||
|
||||
/**
|
||||
* Класс оболочка для PDO для замены Creole
|
||||
|
|
@ -14,11 +27,11 @@ class Database/*<Database_PDOStatement>*/ extends PDO
|
|||
parent::__construct($dsn, $username, $password);
|
||||
$this->setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION);
|
||||
$this->setAttribute(PDO::ATTR_DEFAULT_FETCH_MODE, PDO::FETCH_ASSOC);
|
||||
$this->setAttribute(PDO::ATTR_STATEMENT_CLASS, array('Database_PDOStatement', array()));
|
||||
$this->setAttribute(PDO::ATTR_STATEMENT_CLASS, array('ctiso\\Database\\PDOStatement', array()));
|
||||
}
|
||||
|
||||
function prepare($sql, $args = []) {
|
||||
$result = parent::prepare($sql, $args);
|
||||
function prepare($sql, $args = []) {
|
||||
$result/*: PDOStatement*/ = parent::prepare($sql, $args);
|
||||
return $result;
|
||||
}
|
||||
|
||||
|
|
@ -35,8 +48,8 @@ class Database/*<Database_PDOStatement>*/ extends PDO
|
|||
static function getConnection(array $dsn)
|
||||
{
|
||||
|
||||
if ($dsn['phptype'] == 'pgsql' || $dsn['phptype'] == 'mysql') {
|
||||
$port = (isset($dsn['port'])) ? "port={$dsn['port']};" : "";
|
||||
if ($dsn['phptype'] == 'pgsql' || $dsn['phptype'] == 'mysql') {
|
||||
$port = (isset($dsn['port'])) ? "port={$dsn['port']};" : "";
|
||||
$connection/*: Database*/ = new static("{$dsn['phptype']}:host={$dsn['hostspec']}; $port dbname={$dsn['database']}", $dsn['username'], $dsn['password']);
|
||||
if ($dsn['phptype'] == 'pgsql') {
|
||||
$connection->query('SET client_encoding="UTF-8"');
|
||||
|
|
@ -51,13 +64,7 @@ class Database/*<Database_PDOStatement>*/ extends PDO
|
|||
$connection->setAttribute(PDO::ATTR_TIMEOUT, 5);
|
||||
$mode = defined('SQLITE_JOURNAL_MODE') ? SQLITE_JOURNAL_MODE : 'WAL';
|
||||
$connection->query("PRAGMA journal_mode=$mode");
|
||||
|
||||
if(!function_exists('sqliteLower')){
|
||||
function sqliteLower($str) {
|
||||
return mb_strtolower($str, 'UTF-8');
|
||||
}
|
||||
$connection->sqliteCreateFunction('LOWER', 'sqliteLower', 1);
|
||||
}
|
||||
$connection->sqliteCreateFunction('LOWER', 'sqliteLower', 1);
|
||||
}
|
||||
$connection->dsn = $dsn;
|
||||
return $connection;
|
||||
|
|
@ -65,7 +72,7 @@ class Database/*<Database_PDOStatement>*/ extends PDO
|
|||
|
||||
public function executeQuery($query, $values=null)
|
||||
{
|
||||
$stmt/*: Database_PDOStatement*/ = $this->prepare($query);
|
||||
$stmt/*: PDOStatement*/ = $this->prepare($query);
|
||||
|
||||
$stmt->execute($values);
|
||||
$stmt->cache = $stmt->fetchAll(PDO::FETCH_ASSOC);
|
||||
|
|
@ -74,7 +81,7 @@ class Database/*<Database_PDOStatement>*/ extends PDO
|
|||
|
||||
public function prepareStatement($query)
|
||||
{
|
||||
return new Database_Statement($query, $this);
|
||||
return new Statement($query, $this);
|
||||
}
|
||||
|
||||
// Для совместимости со старым представлением баз данных CIS
|
||||
|
|
@ -83,7 +90,7 @@ class Database/*<Database_PDOStatement>*/ extends PDO
|
|||
*/
|
||||
public function fetchAllArray($query, $values = null)
|
||||
{
|
||||
$sth/*: Database_PDOStatement*/ = $this->prepare($query);
|
||||
$sth/*: PDOStatement*/ = $this->prepare($query);
|
||||
$prep = $this->prepareValues($values);
|
||||
$sth->execute($prep);
|
||||
return $sth->fetchAll(PDO::FETCH_ASSOC);
|
||||
|
|
@ -94,7 +101,7 @@ class Database/*<Database_PDOStatement>*/ extends PDO
|
|||
*/
|
||||
public function fetchOneArray($query, $values = null)
|
||||
{
|
||||
$sth/*: Database_PDOStatement*/ = $this->prepare($query);
|
||||
$sth/*: PDOStatement*/ = $this->prepare($query);
|
||||
$prep = $this->prepareValues($values);
|
||||
$sth->execute($prep);
|
||||
return $sth->fetch(PDO::FETCH_ASSOC);
|
||||
|
|
@ -170,7 +177,7 @@ class Database/*<Database_PDOStatement>*/ extends PDO
|
|||
}
|
||||
|
||||
function getIdGenerator() {
|
||||
return new Database_IdGenerator($this);
|
||||
return new IdGenerator($this);
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
@ -183,8 +190,7 @@ class Database/*<Database_PDOStatement>*/ extends PDO
|
|||
return $result['nextval'];
|
||||
}
|
||||
|
||||
function close()
|
||||
{
|
||||
function close() {
|
||||
return null;
|
||||
}
|
||||
}
|
||||
}}
|
||||
|
|
|
|||
|
|
@ -1,6 +1,9 @@
|
|||
<?php
|
||||
|
||||
class Database_IdGenerator {
|
||||
namespace ctiso\Database;
|
||||
use ctiso\Database;
|
||||
|
||||
class IdGenerator {
|
||||
private $db;
|
||||
|
||||
function __construct(Database $db) {
|
||||
|
|
@ -21,6 +24,6 @@ class Database_IdGenerator {
|
|||
} else {
|
||||
$result = $this->db->fetchOneArray("SELECT last_insert_rowid() AS nextval");
|
||||
}
|
||||
return intval($result['nextval']);
|
||||
return (int)$result['nextval'];
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,143 +1,146 @@
|
|||
<?php
|
||||
//Действия с базой данных согласно json файлу.
|
||||
|
||||
class Database_JsonInstall {
|
||||
namespace ctiso\Database;
|
||||
use ctiso\Database\Manager;
|
||||
|
||||
class JsonInstall {
|
||||
public $db_manager;
|
||||
public $serialColumns;
|
||||
|
||||
public function __construct(Database_Manager $db_manager) {
|
||||
$this->db_manager = $db_manager;
|
||||
}
|
||||
public function __construct(Manager $db_manager) {
|
||||
$this->db_manager = $db_manager;
|
||||
}
|
||||
|
||||
function install($dbinit_path, $dbfill_path = null) {
|
||||
$dbinit_file = file_get_contents($dbinit_path);
|
||||
if (is_string($dbinit_file)) {
|
||||
$initActions = json_decode($dbinit_file, true);
|
||||
if (!$initActions) {
|
||||
echo "Invalid ".$dbinit_path;
|
||||
return 0;
|
||||
}
|
||||
} else {
|
||||
echo "No ".$dbinit_path;
|
||||
return 0;
|
||||
}
|
||||
function install($dbinit_path, $dbfill_path = null) {
|
||||
$dbinit_file = file_get_contents($dbinit_path);
|
||||
if (is_string($dbinit_file)) {
|
||||
$initActions = json_decode($dbinit_file, true);
|
||||
if (!$initActions) {
|
||||
echo "Invalid ".$dbinit_path;
|
||||
return 0;
|
||||
}
|
||||
} else {
|
||||
echo "No ".$dbinit_path;
|
||||
return 0;
|
||||
}
|
||||
|
||||
$this->initDataBase($initActions, $dbinit_path);
|
||||
if ($dbfill_path) {
|
||||
$this->fillDataBase($dbfill_path);
|
||||
}
|
||||
$this->makeConstraints($initActions);
|
||||
}
|
||||
$this->initDataBase($initActions, $dbinit_path);
|
||||
if ($dbfill_path) {
|
||||
$this->fillDataBase($dbfill_path);
|
||||
}
|
||||
$this->makeConstraints($initActions);
|
||||
}
|
||||
|
||||
function missingTables($tables) {
|
||||
$actual_tables = $this->db_manager->GetAllTableNames();
|
||||
$missingTables = [];
|
||||
foreach ($tables as $table) {
|
||||
if (!in_array($table, $actual_tables))
|
||||
$missingTables[] = $table;
|
||||
}
|
||||
return $missingTables;
|
||||
}
|
||||
function missingTables($tables) {
|
||||
$actual_tables = $this->db_manager->GetAllTableNames();
|
||||
$missingTables = [];
|
||||
foreach ($tables as $table) {
|
||||
if (!in_array($table, $actual_tables))
|
||||
$missingTables[] = $table;
|
||||
}
|
||||
return $missingTables;
|
||||
}
|
||||
|
||||
//Создать таблицы
|
||||
function initDataBase($initActions/*: array*/, $dbinit_path) {
|
||||
$pg = $this->db_manager->db->isPostgres();
|
||||
if (!$pg) {
|
||||
$refs = [];
|
||||
//В sqlite нет alter reference. Референсы надо создавать при создании таблицы.
|
||||
foreach ($initActions as $action) {
|
||||
if ($action["type"] == "alterReference") {
|
||||
if (!isset($refs[$action["table"]]))
|
||||
$refs[$action["table"]] = [];
|
||||
$refs[$action["table"]][]=$action;//добавить к списку референсов для таблицы
|
||||
}
|
||||
}
|
||||
}
|
||||
//Создать таблицы
|
||||
function initDataBase($initActions/*: array*/, $dbinit_path) {
|
||||
$pg = $this->db_manager->db->isPostgres();
|
||||
if (!$pg) {
|
||||
$refs = [];
|
||||
//В sqlite нет alter reference. Референсы надо создавать при создании таблицы.
|
||||
foreach ($initActions as $action) {
|
||||
if ($action["type"] == "alterReference") {
|
||||
if (!isset($refs[$action["table"]]))
|
||||
$refs[$action["table"]] = [];
|
||||
$refs[$action["table"]][]=$action;//добавить к списку референсов для таблицы
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
foreach ($initActions as $action) {
|
||||
if (!$pg) {
|
||||
if ($action["type"] == "createTable") {
|
||||
$table_name = $action["table_name"];
|
||||
if (isset($refs[$table_name])) {
|
||||
foreach ($refs[$table_name] as $value) {
|
||||
$action['fields'][$value['column']]['references'] =
|
||||
$value['refTable']."(".$value['refColumn'].")";
|
||||
}
|
||||
}
|
||||
foreach ($initActions as $action) {
|
||||
if (!$pg) {
|
||||
if ($action["type"] == "createTable") {
|
||||
$table_name = $action["table_name"];
|
||||
if (isset($refs[$table_name])) {
|
||||
foreach ($refs[$table_name] as $value) {
|
||||
$action['fields'][$value['column']]['references'] =
|
||||
$value['refTable']."(".$value['refColumn'].")";
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
if ($action["type"] != "alterReference") {
|
||||
$this->db_manager->ExecuteAction($action, $dbinit_path);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
if ($action["type"] != "alterReference") {
|
||||
$this->db_manager->ExecuteAction($action, $dbinit_path);
|
||||
}
|
||||
}
|
||||
|
||||
//Запомнить все колонки serial
|
||||
$this->serialColumns = [];
|
||||
if ($pg) {
|
||||
foreach ($initActions as $action) {
|
||||
if ($action["type"] == "createTable") {
|
||||
foreach ($action["fields"] as $name => $field) {
|
||||
if ($field["type"]=="serial") {
|
||||
$this->serialColumns[] = [
|
||||
//Запомнить все колонки serial
|
||||
$this->serialColumns = [];
|
||||
if ($pg) {
|
||||
foreach ($initActions as $action) {
|
||||
if ($action["type"] == "createTable") {
|
||||
foreach ($action["fields"] as $name => $field) {
|
||||
if ($field["type"]=="serial") {
|
||||
$this->serialColumns[] = [
|
||||
"table"=>$action["table_name"],
|
||||
"column"=>$name
|
||||
"column"=>$name
|
||||
];
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
//Заполнить данными
|
||||
function fillDataBase($dbfill_file_path) {
|
||||
$dbfill_file = file_get_contents($dbfill_file_path);
|
||||
if (is_string($dbfill_file)) {
|
||||
$actions = json_decode($dbfill_file,true);
|
||||
if ($actions) {
|
||||
|
||||
//Проверка что упоминаемые в списке действий таблицы уже есть в базе
|
||||
$affected_tables = [];
|
||||
foreach ($actions as $action) {
|
||||
if ($action["table_name"]) {
|
||||
$affected_tables[$action["table_name"]] = 1;
|
||||
//Заполнить данными
|
||||
function fillDataBase($dbfill_file_path) {
|
||||
$dbfill_file = file_get_contents($dbfill_file_path);
|
||||
if (is_string($dbfill_file)) {
|
||||
$actions = json_decode($dbfill_file,true);
|
||||
if ($actions) {
|
||||
|
||||
//Проверка что упоминаемые в списке действий таблицы уже есть в базе
|
||||
$affected_tables = [];
|
||||
foreach ($actions as $action) {
|
||||
if ($action["table_name"]) {
|
||||
$affected_tables[$action["table_name"]] = 1;
|
||||
}
|
||||
}
|
||||
|
||||
$missing = $this->missingTables(array_keys($affected_tables));
|
||||
if (!empty($missing)) {
|
||||
echo "dbfill error. Missing tables: ".implode(" ", $missing);
|
||||
return;
|
||||
}
|
||||
|
||||
//Выполнение действий
|
||||
foreach ($actions as $action) {
|
||||
$this->db_manager->ExecuteAction($action, $dbfill_file_path);
|
||||
}
|
||||
} else {
|
||||
echo "Invalid dbfill.json";
|
||||
}
|
||||
} else {
|
||||
echo "No dbfill.json";
|
||||
}
|
||||
}
|
||||
|
||||
//Обновить ключи serial и создать ограничения
|
||||
function makeConstraints($initActions) {
|
||||
$pg = $this->db_manager->db->isPostgres();
|
||||
if ($pg) {
|
||||
foreach ($this->serialColumns as $serialColumn) {
|
||||
$this->db_manager->UpdateSerial($serialColumn["table"], $serialColumn["column"]);
|
||||
}
|
||||
|
||||
|
||||
foreach ($initActions as $action) {
|
||||
if ($action["type"] == "alterReference") {
|
||||
$this->db_manager->ExecuteAction($action);
|
||||
$missing = $this->missingTables(array_keys($affected_tables));
|
||||
if (!empty($missing)) {
|
||||
echo "dbfill error. Missing tables: ".implode(" ", $missing);
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
//Выполнение действий
|
||||
foreach ($actions as $action) {
|
||||
$this->db_manager->ExecuteAction($action, $dbfill_file_path);
|
||||
}
|
||||
} else {
|
||||
echo "Invalid dbfill.json";
|
||||
}
|
||||
} else {
|
||||
echo "No dbfill.json";
|
||||
}
|
||||
}
|
||||
|
||||
//Обновить ключи serial и создать ограничения
|
||||
function makeConstraints($initActions) {
|
||||
$pg = $this->db_manager->db->isPostgres();
|
||||
if ($pg) {
|
||||
foreach ($this->serialColumns as $serialColumn) {
|
||||
$this->db_manager->UpdateSerial($serialColumn["table"], $serialColumn["column"]);
|
||||
}
|
||||
|
||||
|
||||
foreach ($initActions as $action) {
|
||||
if ($action["type"] == "alterReference") {
|
||||
$this->db_manager->ExecuteAction($action);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
|
@ -1,221 +1,255 @@
|
|||
<?php
|
||||
<?php
|
||||
|
||||
class Database_Manager
|
||||
namespace ctiso\Database;
|
||||
|
||||
use ctiso\Database;
|
||||
use ctiso\Tools\SQLStatementExtractor;
|
||||
use ctiso\Path;
|
||||
use Exception;
|
||||
|
||||
class Manager
|
||||
{
|
||||
public $db/*: Database*/;
|
||||
|
||||
function __construct(Database $db) {
|
||||
$this->db = $db;
|
||||
}
|
||||
public function __construct(Database $db)
|
||||
{
|
||||
$this->db = $db;
|
||||
}
|
||||
|
||||
public function ExecuteAction($action/*: array*/, $db_file = "") {
|
||||
switch($action["type"]) {
|
||||
case "dropTable":
|
||||
$this->DropTableQuery($action["table_name"], true);
|
||||
break;
|
||||
case "createTable":
|
||||
$constraints = isset($action["constraints"]) ? $action["constraints"] : NULL;
|
||||
$this->CreateTableQuery($action["table_name"], $action["fields"], $constraints);
|
||||
break;
|
||||
case "addColumn":
|
||||
$this->AddColumn($action["table_name"], $action["column_name"], $action["field"]);
|
||||
break;
|
||||
case "insert":
|
||||
$this->db->insertQuery($action["table_name"], $action["values"]);
|
||||
break;
|
||||
case "alterReference":
|
||||
$this->AlterReference($action["table"], $action["column"], $action["refTable"], $action["refColumn"]);
|
||||
break;
|
||||
case "renameColumn":
|
||||
$this->RenameColumn($action["table"], $action["old_name"], $action["new_name"]);
|
||||
public function ExecuteAction($action/*: array*/, $db_file = "")
|
||||
{
|
||||
switch($action["type"]) {
|
||||
case "dropTable":
|
||||
$this->DropTableQuery($action["table_name"], true);
|
||||
break;
|
||||
case "executeFile":
|
||||
case "createTable":
|
||||
$constraints = isset($action["constraints"]) ? $action["constraints"] : null;
|
||||
$this->CreateTableQuery($action["table_name"], $action["fields"], $constraints);
|
||||
break;
|
||||
case "addColumn":
|
||||
$this->AddColumn($action["table_name"], $action["column_name"], $action["field"]);
|
||||
break;
|
||||
case "insert":
|
||||
$this->db->insertQuery($action["table_name"], $action["values"]);
|
||||
break;
|
||||
case "alterReference":
|
||||
$this->AlterReference($action["table"], $action["column"], $action["refTable"], $action["refColumn"]);
|
||||
break;
|
||||
case "renameColumn":
|
||||
$this->RenameColumn($action["table"], $action["old_name"], $action["new_name"]);
|
||||
break;
|
||||
case "createView":
|
||||
$this->recreateView($action["view"], $action["select"]);
|
||||
break;
|
||||
case "executeFile":
|
||||
if ($this->db->isPostgres() && isset($action["pgsql"])) {
|
||||
$file = $action["pgsql"];
|
||||
$file = $action["pgsql"];
|
||||
} else {
|
||||
$file = $action["source"];
|
||||
$file = $action["source"];
|
||||
}
|
||||
|
||||
$stmtList = Tools_SQLStatementExtractor::extractFile(Path::join(dirname($db_file), $file));
|
||||
foreach($stmtList as $stmt) {
|
||||
$stmtList = SQLStatementExtractor::extractFile(Path::join(dirname($db_file), $file));
|
||||
foreach ($stmtList as $stmt) {
|
||||
$this->db->executeQuery($stmt);
|
||||
}
|
||||
|
||||
break;
|
||||
default:
|
||||
throw new Exception("unknown action ". $action["type"] . PHP_EOL);
|
||||
}
|
||||
}
|
||||
default:
|
||||
throw new Exception("unknown action ". $action["type"] . PHP_EOL);
|
||||
}
|
||||
}
|
||||
|
||||
public function DropTableQuery($table, $cascade=false) {
|
||||
$statement = "DROP TABLE IF EXISTS ".$table;
|
||||
if ($this->db->isPostgres()&&$cascade) {
|
||||
$statement = $statement." CASCADE";
|
||||
}
|
||||
$this->db->query($statement);
|
||||
}
|
||||
//Дропает и создаёт SQL VIEW
|
||||
public function recreateView($viewName, $selectStatement)
|
||||
{
|
||||
$this->db->query("DROP VIEW ".$viewName);
|
||||
$this->db->query("CREATE VIEW ".$viewName." AS ".$selectStatement);
|
||||
}
|
||||
|
||||
public function AlterReference($table,$column,$refTable,$refColumn) {
|
||||
$this->db->query("ALTER TABLE ".$table." ADD CONSTRAINT ".$table."_".$column."fk"." FOREIGN KEY (".$column.") REFERENCES ".$refTable." (".$refColumn.")");
|
||||
}
|
||||
public function DropTableQuery($table, $cascade=false)
|
||||
{
|
||||
$statement = "DROP TABLE IF EXISTS ".$table;
|
||||
if ($this->db->isPostgres()&&$cascade) {
|
||||
$statement = $statement." CASCADE";
|
||||
}
|
||||
$this->db->query($statement);
|
||||
}
|
||||
|
||||
//Извлечение информации о полях таблицы
|
||||
public function TableInfo($table) {
|
||||
$pg = $this->db->isPostgres();
|
||||
if ($pg) {
|
||||
throw new Exception("Not implemented for postgres");
|
||||
} else {
|
||||
$results = $this->db->fetchAllArray("PRAGMA table_info(".$table.");");
|
||||
if (empty($results)) {
|
||||
return null;
|
||||
public function AlterReference($table, $column, $refTable, $refColumn)
|
||||
{
|
||||
$this->db->query("ALTER TABLE ".$table." ADD CONSTRAINT ".$table."_".$column."fk"." FOREIGN KEY (".$column.") REFERENCES ".$refTable." (".$refColumn.")");
|
||||
}
|
||||
|
||||
//Извлечение информации о полях таблицы
|
||||
public function TableInfo($table)
|
||||
{
|
||||
$pg = $this->db->isPostgres();
|
||||
if ($pg) {
|
||||
throw new Exception("Not implemented for postgres");
|
||||
} else {
|
||||
$results = $this->db->fetchAllArray("PRAGMA table_info(".$table.");");
|
||||
if (empty($results)) {
|
||||
return null;
|
||||
}
|
||||
$fields = [];
|
||||
foreach ($results as $result) {
|
||||
$fields[$result["name"]] = [
|
||||
"type"=> $result["type"],
|
||||
"not_null"=> boolval($result["notnull"]),
|
||||
"constraint"=> ((boolean) $result["pk"]) ? "PRIMARY KEY" : null
|
||||
$fields = [];
|
||||
foreach ($results as $result) {
|
||||
$fields[$result["name"]] = [
|
||||
"type"=> $result["type"],
|
||||
"not_null"=> boolval($result["notnull"]),
|
||||
"constraint"=> ((bool) $result["pk"]) ? "PRIMARY KEY" : null
|
||||
];
|
||||
}
|
||||
return $fields;
|
||||
}
|
||||
}
|
||||
}
|
||||
return $fields;
|
||||
}
|
||||
}
|
||||
|
||||
public function RenameColumn($table, $old_name, $new_name) {
|
||||
$pg = $this->db->isPostgres();
|
||||
if ($pg) {
|
||||
$this->db->query("ALTER TABLE ".$table." RENAME COLUMN ".$old_name." TO ".$new_name);
|
||||
} else {
|
||||
$tmp_table = "tmp_" . $table;
|
||||
$this->DropTableQuery($tmp_table);
|
||||
$table_info = $this->TableInfo($table);
|
||||
public function RenameColumn($table, $old_name, $new_name)
|
||||
{
|
||||
$pg = $this->db->isPostgres();
|
||||
if ($pg) {
|
||||
$this->db->query("ALTER TABLE ".$table." RENAME COLUMN ".$old_name." TO ".$new_name);
|
||||
} else {
|
||||
$tmp_table = "tmp_" . $table;
|
||||
$this->DropTableQuery($tmp_table);
|
||||
$table_info = $this->TableInfo($table);
|
||||
|
||||
if (isset($table_info[$new_name])) {
|
||||
return;
|
||||
if (isset($table_info[$new_name])) {
|
||||
return;
|
||||
}
|
||||
|
||||
$data/*: array*/ = $this->DumpTable($table);
|
||||
$data/*: array*/ = $this->DumpTable($table);
|
||||
|
||||
$this->db->query("ALTER TABLE ".$table." RENAME TO ".$tmp_table.";");
|
||||
$table_info[$new_name] = $table_info[$old_name];
|
||||
unset($table_info[$old_name]);
|
||||
$this->CreateTableQuery($table,$table_info,null);
|
||||
$this->db->query("ALTER TABLE ".$table." RENAME TO ".$tmp_table.";");
|
||||
$table_info[$new_name] = $table_info[$old_name];
|
||||
unset($table_info[$old_name]);
|
||||
$this->CreateTableQuery($table, $table_info, null);
|
||||
|
||||
foreach ($data as $row) {
|
||||
$values = $row['values'];
|
||||
$values[$new_name] = $values[$old_name];
|
||||
unset($values[$old_name]);
|
||||
$this->db->insertQuery($table, $values);
|
||||
}
|
||||
$this->DropTableQuery($tmp_table);
|
||||
}
|
||||
}
|
||||
foreach ($data as $row) {
|
||||
$values = $row['values'];
|
||||
$values[$new_name] = $values[$old_name];
|
||||
unset($values[$old_name]);
|
||||
$this->db->insertQuery($table, $values);
|
||||
}
|
||||
$this->DropTableQuery($tmp_table);
|
||||
}
|
||||
}
|
||||
|
||||
//Обновление ключа serial после ручной вставки
|
||||
public function UpdateSerial($table,$column) {
|
||||
$this->db->query("SELECT setval(pg_get_serial_sequence('".$table."', '".$column."'), coalesce(max(".$column."),0) + 1, false) FROM ".$table);
|
||||
}
|
||||
//Обновление ключа serial после ручной вставки
|
||||
public function UpdateSerial($table, $column)
|
||||
{
|
||||
$this->db->query("SELECT setval(pg_get_serial_sequence('".$table."', '".$column."'), coalesce(max(".$column."),0) + 1, false) FROM ".$table);
|
||||
}
|
||||
|
||||
public function Column_Definition($name,$data,$pg){
|
||||
$constraint = isset($data['constraint'])?" ".$data['constraint']:"";
|
||||
$references = "";
|
||||
if (isset($data['references'])) {
|
||||
$references = " REFERENCES ".$data['references'];
|
||||
}
|
||||
if (isset($data["not_null"]) && $data["not_null"])
|
||||
$constraint .=" NOT NULL";
|
||||
$type = $data['type'];
|
||||
if (!$pg) {
|
||||
if (strtolower($type)=="serial")
|
||||
$type = "integer";
|
||||
//if (strtolower($type)=="boolean")
|
||||
// $type = "integer";
|
||||
}
|
||||
return $name." ".$type.$references.$constraint;
|
||||
}
|
||||
public function Column_Definition($name, $data, $pg)
|
||||
{
|
||||
$constraint = isset($data['constraint']) ? " ".$data['constraint'] : "";
|
||||
$references = "";
|
||||
if (isset($data['references'])) {
|
||||
$references = " REFERENCES ".$data['references'];
|
||||
}
|
||||
if (isset($data["not_null"]) && $data["not_null"]) {
|
||||
$constraint .=" NOT NULL";
|
||||
}
|
||||
$type = $data['type'];
|
||||
if (!$pg) {
|
||||
if (strtolower($type)=="serial") {
|
||||
$type = "integer";
|
||||
}
|
||||
//if (strtolower($type)=="boolean")
|
||||
// $type = "integer";
|
||||
}
|
||||
return $name." ".$type.$references.$constraint;
|
||||
}
|
||||
|
||||
public function AddColumn($table_name,$column_name,$field){
|
||||
$pg = $this->db->isPostgres();
|
||||
$q = "ALTER TABLE ".$table_name." ADD COLUMN ".
|
||||
$this->Column_Definition($column_name, $field, $pg);
|
||||
$this->db->query($q);
|
||||
}
|
||||
public function AddColumn($table_name, $column_name, $field)
|
||||
{
|
||||
$pg = $this->db->isPostgres();
|
||||
$q = "ALTER TABLE ".$table_name." ADD COLUMN ".
|
||||
$this->Column_Definition($column_name, $field, $pg);
|
||||
$this->db->query($q);
|
||||
}
|
||||
|
||||
function getConstraintDef($c/*: array*/) {
|
||||
public function getConstraintDef($c/*: array*/)
|
||||
{
|
||||
if ($c['type'] == 'unique') {
|
||||
return "UNIQUE(" . implode(", ", $c['fields']) . ")";
|
||||
}
|
||||
return "";
|
||||
}
|
||||
|
||||
//CreateTableQuery('users',['id'=>['type'=>'integer','constraint'=>'PRIMARY KEY']])
|
||||
public function CreateTableQuery($table, $fields, $constraints) {
|
||||
$pg = $this->db->isPostgres();
|
||||
if ($constraints) {
|
||||
//CreateTableQuery('users',['id'=>['type'=>'integer','constraint'=>'PRIMARY KEY']])
|
||||
public function CreateTableQuery($table, $fields, $constraints)
|
||||
{
|
||||
$pg = $this->db->isPostgres();
|
||||
if ($constraints) {
|
||||
if (is_array($constraints)) {
|
||||
$constraints = $this->getConstraintDef($constraints);
|
||||
}
|
||||
$constraints = ", " . $constraints;
|
||||
$constraints = ", " . $constraints;
|
||||
}
|
||||
|
||||
$statement = "CREATE TABLE $table (" . implode(",",
|
||||
array_map(function($name,$data) use ($pg) {
|
||||
return $this->Column_Definition($name,$data,$pg);
|
||||
}, array_keys($fields), array_values($fields))
|
||||
) . " " . $constraints . ")";
|
||||
$this->db->query($statement);
|
||||
}
|
||||
$statement = "CREATE TABLE $table (" . implode(
|
||||
",",
|
||||
array_map(function ($name, $data) use ($pg) {
|
||||
return $this->Column_Definition($name, $data, $pg);
|
||||
}, array_keys($fields), array_values($fields))
|
||||
) . " " . $constraints . ")";
|
||||
$this->db->query($statement);
|
||||
}
|
||||
|
||||
public function DumpTable($table_name) {
|
||||
$pg = $this->db->isPostgres();
|
||||
public function DumpTable($table_name)
|
||||
{
|
||||
$pg = $this->db->isPostgres();
|
||||
|
||||
$result/*: array*/ = array();
|
||||
$data/*: array*/ = $this->db->fetchAllArray("SELECT * FROM ".$table_name.";");
|
||||
$result/*: array*/ = array();
|
||||
$data/*: array*/ = $this->db->fetchAllArray("SELECT * FROM ".$table_name.";");
|
||||
|
||||
if (!$pg) {
|
||||
$table_fields = $this->TableInfo($table_name);
|
||||
foreach ($table_fields as $name => $value) {
|
||||
$type = strtolower($value['type']);
|
||||
if ($type == "boolean") {
|
||||
foreach ($data as &$row) {
|
||||
if (!$pg) {
|
||||
$table_fields = $this->TableInfo($table_name);
|
||||
foreach ($table_fields as $name => $value) {
|
||||
$type = strtolower($value['type']);
|
||||
if ($type == "boolean") {
|
||||
foreach ($data as &$row) {
|
||||
$row/*: array*/ = $row;
|
||||
if (isset($row[$name])) {
|
||||
$row[$name] = boolval($row[$name]);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
foreach ($data as $r) {
|
||||
$result[] = array(
|
||||
"type" => "insert",
|
||||
"table_name" => $table_name,
|
||||
"values" => $r
|
||||
if (isset($row[$name])) {
|
||||
$row[$name] = boolval($row[$name]);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
foreach ($data as $r) {
|
||||
$result[] = array(
|
||||
"type" => "insert",
|
||||
"table_name" => $table_name,
|
||||
"values" => $r
|
||||
);
|
||||
}
|
||||
return $result;
|
||||
}
|
||||
|
||||
public function GetAllTableNames() {
|
||||
$result = [];
|
||||
if ($this->db->isPostgres()) {
|
||||
$query = "SELECT table_name as name FROM information_schema.tables WHERE table_schema='public'";
|
||||
} else {
|
||||
$query = "SELECT * FROM sqlite_master WHERE type='table'";
|
||||
}
|
||||
$tables = $this->db->fetchAllArray($query);
|
||||
foreach ($tables as $table) {
|
||||
$result[] = $table['name'];
|
||||
}
|
||||
return $result;
|
||||
}
|
||||
return $result;
|
||||
}
|
||||
|
||||
public function DumpInserts() {
|
||||
$table_names = $this->GetAllTableNames();
|
||||
$result = array();
|
||||
foreach ($table_names as $table_name) {
|
||||
$result = array_merge($result, $this->DumpTable($table_name));
|
||||
}
|
||||
return $result;
|
||||
}
|
||||
}
|
||||
public function GetAllTableNames()
|
||||
{
|
||||
$result = [];
|
||||
if ($this->db->isPostgres()) {
|
||||
$query = "SELECT table_name as name FROM information_schema.tables WHERE table_schema='public'";
|
||||
} else {
|
||||
$query = "SELECT * FROM sqlite_master WHERE type='table'";
|
||||
}
|
||||
$tables = $this->db->fetchAllArray($query);
|
||||
foreach ($tables as $table) {
|
||||
$result[] = $table['name'];
|
||||
}
|
||||
return $result;
|
||||
}
|
||||
|
||||
public function DumpInserts()
|
||||
{
|
||||
$table_names = $this->GetAllTableNames();
|
||||
$result = array();
|
||||
foreach ($table_names as $table_name) {
|
||||
$result = array_merge($result, $this->DumpTable($table_name));
|
||||
}
|
||||
return $result;
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,35 +1,42 @@
|
|||
<?php
|
||||
|
||||
class Database_PDOStatement extends PDOStatement implements IteratorAggregate
|
||||
namespace ctiso\Database;
|
||||
|
||||
use ctiso\Database\StatementIterator,
|
||||
ctiso\Tools\StringUtil,
|
||||
PDO;
|
||||
use TheSeer\Tokenizer\Exception;
|
||||
|
||||
class PDOStatement extends \PDOStatement implements \IteratorAggregate
|
||||
{
|
||||
protected $cursorPos = 0;
|
||||
public $cache = array();
|
||||
public $cache = array();
|
||||
public $fields;
|
||||
|
||||
function getIterator(): Iterator {
|
||||
return new Database_StatementIterator($this);
|
||||
function getIterator(): \Iterator {
|
||||
return new StatementIterator($this);
|
||||
}
|
||||
|
||||
protected function __construct() {
|
||||
protected function __construct() {
|
||||
}
|
||||
|
||||
function rewind() {
|
||||
function rewind() {
|
||||
$this->cursorPos = 0;
|
||||
}
|
||||
|
||||
public function seek($rownum) {
|
||||
if ($rownum < 0) {
|
||||
return false;
|
||||
}
|
||||
|
||||
// PostgreSQL rows start w/ 0, but this works, because we are
|
||||
// looking to move the position _before_ the next desired position
|
||||
$this->cursorPos = $rownum;
|
||||
return true;
|
||||
}
|
||||
public function seek($rownum) {
|
||||
if ($rownum < 0) {
|
||||
return false;
|
||||
}
|
||||
|
||||
// PostgreSQL rows start w/ 0, but this works, because we are
|
||||
// looking to move the position _before_ the next desired position
|
||||
$this->cursorPos = $rownum;
|
||||
return true;
|
||||
}
|
||||
|
||||
function valid() {
|
||||
return true;
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
|
|
@ -42,7 +49,7 @@ class Database_PDOStatement extends PDOStatement implements IteratorAggregate
|
|||
if ($this->getRecordCount() > $this->cursorPos) {
|
||||
if (!isset($this->cache[$this->cursorPos])) {
|
||||
$this->cache[$this->cursorPos] = $this->fetch(PDO::FETCH_ASSOC);
|
||||
}
|
||||
}
|
||||
$this->fields = $this->cache[$this->cursorPos];
|
||||
|
||||
$this->cursorPos++;
|
||||
|
|
@ -67,7 +74,7 @@ class Database_PDOStatement extends PDOStatement implements IteratorAggregate
|
|||
|
||||
function getInt($name) {
|
||||
if (!$this->fields) {
|
||||
throw new Error('no fields');
|
||||
throw new \Exception('no fields');
|
||||
}
|
||||
return (int)$this->fields[$name];
|
||||
}
|
||||
|
|
@ -89,13 +96,13 @@ class Database_PDOStatement extends PDOStatement implements IteratorAggregate
|
|||
}
|
||||
|
||||
function getArray($name) {
|
||||
return Tools_String::strToArray($this->fields[$name]);
|
||||
return StringUtil::strToArray($this->fields[$name]);
|
||||
}
|
||||
|
||||
function getRecordCount() {
|
||||
return count($this->cache);
|
||||
}
|
||||
|
||||
|
||||
function execute($args = null) {
|
||||
$result = parent::execute($args);
|
||||
return $result;
|
||||
|
|
|
|||
|
|
@ -3,7 +3,11 @@
|
|||
/**
|
||||
* Класс оболочка для PDOStatement для замены Creole
|
||||
*/
|
||||
class Database_Statement
|
||||
namespace ctiso\Database;
|
||||
use PDO,
|
||||
ctiso\Database;
|
||||
|
||||
class Statement
|
||||
{
|
||||
protected $limit = null;
|
||||
protected $offset = null;
|
||||
|
|
@ -41,7 +45,7 @@ class Database_Statement
|
|||
if ($this->limit) {
|
||||
$this->query .= " LIMIT {$this->limit} OFFSET {$this->offset}";
|
||||
}
|
||||
$stmt/*: Database_PDOStatement*/ = $this->conn->prepare($this->query);
|
||||
$stmt/*: PDOStatement*/ = $this->conn->prepare($this->query);
|
||||
foreach ($this->binds as $bind) {
|
||||
list($n, $value, $type) = $bind;
|
||||
$stmt->bindValue($n, $value, (int) $type);
|
||||
|
|
|
|||
|
|
@ -1,46 +1,49 @@
|
|||
<?php
|
||||
|
||||
class Database_StatementIterator implements Iterator
|
||||
namespace ctiso\Database;
|
||||
use PDO;
|
||||
|
||||
class StatementIterator implements \Iterator
|
||||
{
|
||||
|
||||
private $result;
|
||||
private $pos = 0;
|
||||
private $fetchmode;
|
||||
private $row_count;
|
||||
|
||||
public function __construct($rs/*: Database_PDOStatement*/) {
|
||||
|
||||
public function __construct($rs/*: PDOStatement*/) {
|
||||
$this->result = $rs;
|
||||
$this->row_count = $rs->getRecordCount();
|
||||
$this->row_count = $rs->getRecordCount();
|
||||
}
|
||||
|
||||
function rewind() {
|
||||
|
||||
function rewind() {
|
||||
$this->pos = 0;
|
||||
}
|
||||
|
||||
|
||||
function valid() {
|
||||
return ($this->pos < $this->row_count);
|
||||
return ($this->pos < $this->row_count);
|
||||
}
|
||||
|
||||
|
||||
function key() {
|
||||
return $this->pos;
|
||||
}
|
||||
|
||||
|
||||
function current() {
|
||||
if (!isset($this->result->cache[$this->pos])) {
|
||||
$this->result->cache[$this->pos] = $this->result->fetch(PDO::FETCH_ASSOC);
|
||||
}
|
||||
}
|
||||
return $this->result->cache[$this->pos];
|
||||
}
|
||||
|
||||
|
||||
function next() {
|
||||
$this->pos++;
|
||||
}
|
||||
|
||||
function seek($index) {
|
||||
$this->pos = $index;
|
||||
$this->pos = $index;
|
||||
}
|
||||
|
||||
function count() {
|
||||
return $this->row_count;
|
||||
return $this->row_count;
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,12 +1,14 @@
|
|||
<?php
|
||||
|
||||
class Excel_DateTime
|
||||
namespace ctiso\Excel;
|
||||
|
||||
class DateTime
|
||||
{
|
||||
public $value;
|
||||
|
||||
function __construct($value)
|
||||
{
|
||||
$this->value = intval($value);
|
||||
$this->value = (int)$value;
|
||||
}
|
||||
|
||||
function getString()
|
||||
|
|
|
|||
|
|
@ -3,7 +3,11 @@
|
|||
/**
|
||||
* Документ
|
||||
*/
|
||||
class Excel_Document {
|
||||
namespace ctiso\Excel;
|
||||
use XMLWriter,
|
||||
Exception;
|
||||
|
||||
class Document {
|
||||
static $ns = "urn:schemas-microsoft-com:office:spreadsheet";
|
||||
private $table = array ();
|
||||
protected $styles = array();
|
||||
|
|
@ -88,7 +92,7 @@ class Excel_Document {
|
|||
$this->createStyles($doc);
|
||||
|
||||
foreach ($this->table as $table) {
|
||||
if ($table instanceof Excel_Table) {
|
||||
if ($table instanceof Table) {
|
||||
$table->createTable($doc);
|
||||
} else {
|
||||
$table_data = call_user_func($table);
|
||||
|
|
|
|||
|
|
@ -1,6 +1,8 @@
|
|||
<?php
|
||||
|
||||
class Excel_Number
|
||||
namespace ctiso\Excel;
|
||||
|
||||
class Number
|
||||
{
|
||||
public $value;
|
||||
|
||||
|
|
|
|||
|
|
@ -3,6 +3,11 @@
|
|||
/**
|
||||
* Клетка таблицы
|
||||
*/
|
||||
namespace ctiso\Excel;
|
||||
use XMLWriter,
|
||||
ctiso\Excel\DateTime as Excel_DateTime,
|
||||
ctiso\Excel\Number as Excel_Number;
|
||||
|
||||
class TableCell
|
||||
{
|
||||
public $style = false;
|
||||
|
|
@ -38,7 +43,7 @@ class TableRow
|
|||
/**
|
||||
* Таблица
|
||||
*/
|
||||
class Excel_Table
|
||||
class Table
|
||||
{
|
||||
static $index;
|
||||
private $name;
|
||||
|
|
@ -50,7 +55,7 @@ class Excel_Table
|
|||
|
||||
function __construct()
|
||||
{
|
||||
$this->name = "Page " . intval(self::$index ++);
|
||||
$this->name = "Page " . ((int)self::$index ++);
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
@ -230,7 +235,7 @@ class Excel_Table
|
|||
} else {
|
||||
$doc->writeAttribute('ss:Type', "Number");
|
||||
}
|
||||
$doc->writeCData($this->encode($value));
|
||||
$doc->writeCdata($this->encode($value));
|
||||
}
|
||||
$doc->endElement();
|
||||
$doc->endElement();
|
||||
|
|
@ -308,4 +313,3 @@ class Excel_Table
|
|||
$doc->endElement();
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -1,8 +1,11 @@
|
|||
<?php
|
||||
|
||||
namespace ctiso;
|
||||
use Exception;
|
||||
|
||||
class File {
|
||||
static function getContents($filename) {
|
||||
$buffer = file_get_contents($filename);
|
||||
$buffer = @file_get_contents($filename);
|
||||
if ($buffer !== false) {
|
||||
return $buffer;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -3,14 +3,20 @@
|
|||
/**
|
||||
* Фильтр действий
|
||||
*/
|
||||
class Filter_ActionAccess
|
||||
namespace ctiso\Filter;
|
||||
use ctiso\Filter\UserAccess,
|
||||
ctiso\HttpRequest,
|
||||
ctiso\Role\User;
|
||||
|
||||
class ActionAccess
|
||||
{
|
||||
public $access = array();
|
||||
public $processor;
|
||||
public $name;
|
||||
public $user/*: User*/;
|
||||
|
||||
function __construct($processor/*: Filter_Filter*/) {
|
||||
function __construct($processor/*: Filter*/, $user) {
|
||||
$this->processor = $processor;
|
||||
$this->user = $user;
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
@ -20,8 +26,7 @@ class Filter_ActionAccess
|
|||
*/
|
||||
function checkAction($action) {
|
||||
// Импликация !! http://ru.wikipedia.org/wiki/Импликация
|
||||
$name = $this->name;
|
||||
return (!isset($this->access[$name][$action]) || in_array(Filter_UserAccess::$access, $this->access[$name][$action]));
|
||||
return (!isset($this->access[$action]) || in_array($this->user->access, $this->access[$action]));
|
||||
}
|
||||
|
||||
function execute(HttpRequest $request) {
|
||||
|
|
|
|||
|
|
@ -1,21 +1,34 @@
|
|||
<?php
|
||||
|
||||
class Filter_ActionLogger
|
||||
namespace ctiso\Filter;
|
||||
use ctiso\Role\UserInterface,
|
||||
ctiso\HttpRequest;
|
||||
|
||||
/* Переделать формат Логов на список json */
|
||||
class ActionLogger
|
||||
{
|
||||
public $before = array();
|
||||
public $file;
|
||||
public $user;
|
||||
public $action;
|
||||
public $processor;
|
||||
|
||||
function __construct($processor/*: Filter_Filter*/) {
|
||||
function __construct($processor/*: Filter*/, $logPath, $user/*: UserInterface*/) {
|
||||
$this->processor = $processor;
|
||||
$this->file = fopen(Shortcut::getUrl('access.log'), "a");
|
||||
$this->user = $user;
|
||||
|
||||
$file = fopen($logPath, "a");
|
||||
if (is_resource($file)) {
|
||||
$this->file = $file;
|
||||
} else {
|
||||
throw new \Exception('Ошибка открытия файла ' . $logPath);
|
||||
}
|
||||
}
|
||||
|
||||
function execute(HttpRequest $request) {
|
||||
$action = $request->getAction();
|
||||
if(in_array($action, $this->before)) {
|
||||
$line = ['time' => time(), 'user' => Filter_UserAccess::$name, 'sid' => session_id(), 'query' => array_merge($_POST, $_GET)];
|
||||
$line = ['time' => time(), 'user' => $this->user->getName(), 'sid' => session_id(), 'query' => array_merge($_POST, $_GET)];
|
||||
fwrite($this->file, json_encode($line) . "\n");
|
||||
}
|
||||
return $this->processor->execute($request);
|
||||
|
|
|
|||
|
|
@ -1,8 +1,15 @@
|
|||
<?php
|
||||
|
||||
class Filter_Authorization {
|
||||
namespace ctiso\Filter;
|
||||
|
||||
class Authorization {
|
||||
const SESSION_BROWSER_SIGN_SECRET = '@w3dsju45Msk#';
|
||||
const SESSION_BROWSER_SIGN_KEYNAME = 'session.app.browser.sign';
|
||||
public $group;
|
||||
|
||||
function __construct($group) {
|
||||
$this->group = $group;
|
||||
}
|
||||
|
||||
static function isLogged($group = 'access') {
|
||||
// echo session_status();
|
||||
|
|
@ -16,25 +23,23 @@ class Filter_Authorization {
|
|||
// UserAccess::getUserById($_SESSION ['access']); // Поиск по идентификатору
|
||||
return true;
|
||||
} else {
|
||||
return false;
|
||||
return false;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
static function enter($id, $group = 'access')
|
||||
{
|
||||
static function enter($id, $group = 'access') {
|
||||
// $db->executeQuery("UPDATE visitor SET sid = '' WHERE id_visitor = " . $result->getInt('id_user'));
|
||||
// session_register("access");
|
||||
// session_register("time");
|
||||
|
||||
// $_SESSION ["group"] = $result->getInt('access');
|
||||
$_SESSION [$group] = $id; // id_user
|
||||
$_SESSION [$group] = $id;
|
||||
$_SESSION [self::SESSION_BROWSER_SIGN_KEYNAME] = self::getBrowserSign();
|
||||
$_SESSION ["time"] = time();
|
||||
$_SESSION ["time"] = time();
|
||||
}
|
||||
|
||||
private static function getBrowserSign()
|
||||
static function getBrowserSign()
|
||||
{
|
||||
$rawSign = self::SESSION_BROWSER_SIGN_SECRET;
|
||||
// $signParts = array('HTTP_USER_AGENT', 'HTTP_ACCEPT_ENCODING');
|
||||
|
|
@ -46,7 +51,7 @@ class Filter_Authorization {
|
|||
return md5($rawSign);
|
||||
}
|
||||
|
||||
static function logout() {
|
||||
function logout() {
|
||||
session_destroy();
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -3,10 +3,15 @@
|
|||
/**
|
||||
* Попытка реализовать фильтр для запросов
|
||||
*/
|
||||
class Filter_Filter
|
||||
namespace ctiso\Filter;
|
||||
|
||||
use ctiso\Controller\Action,
|
||||
ctiso\HttpRequest;
|
||||
|
||||
class Filter
|
||||
{
|
||||
public $processor;
|
||||
public function __construct($processor/*: Controller_Action*/)
|
||||
public function __construct($processor/*: Action*/)
|
||||
{
|
||||
$this->processor = $processor;
|
||||
}
|
||||
|
|
@ -16,7 +21,7 @@ class Filter_Filter
|
|||
return $this->processor->execute($request);
|
||||
}
|
||||
|
||||
public function getView($name, $class = 'View_Top')
|
||||
public function getView($name, $class = 'ctiso\\View\\Top')
|
||||
{
|
||||
return $this->processor->getView($name, $class);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -8,7 +8,17 @@
|
|||
*/
|
||||
// В класс авторизации передавать обьект для управления пользователем
|
||||
// Вынести в отдельный файл
|
||||
class Filter_Login extends Filter_Filter
|
||||
namespace ctiso\Filter;
|
||||
use ctiso\Filter\Filter,
|
||||
ctiso\HttpRequest,
|
||||
ctiso\Settings,
|
||||
ctiso\Registry,
|
||||
ctiso\Database,
|
||||
ctiso\Role\User,
|
||||
ctiso\Collection,
|
||||
ctiso\Path;
|
||||
|
||||
class Login extends Filter
|
||||
{
|
||||
const SESSION_BROWSER_SIGN_SECRET = '@w3dsju45Msk#';
|
||||
const SESSION_BROWSER_SIGN_KEYNAME = 'session.app.browser.sign';
|
||||
|
|
@ -16,28 +26,34 @@ class Filter_Login extends Filter_Filter
|
|||
const AUTH_LAST_ATTEMPT_TIMER = 600;
|
||||
public $mode = 'ajax';
|
||||
public $user;
|
||||
public $role;
|
||||
public $config;
|
||||
|
||||
function __construct($processor, User $role, Registry $config) {
|
||||
parent::__construct($processor);
|
||||
$this->role = $role;
|
||||
$this->config = $config;
|
||||
}
|
||||
|
||||
/**
|
||||
* Проверка авторизации
|
||||
* @param HttpRequest $request
|
||||
* @return Boolean Авторизовани пользователь или нет
|
||||
*/
|
||||
public function isLoggin(HttpRequest $request)
|
||||
{
|
||||
// Авторизация
|
||||
session_start();
|
||||
$db = $this->getConnection();
|
||||
Filter_UserAccess::setUp($db); // Соединение
|
||||
|
||||
switch ($request->getAction()) {
|
||||
// Авторизация по постоянному паролю
|
||||
case 'login':
|
||||
$login = $request->get('login');
|
||||
$password = $request->get('password');
|
||||
|
||||
$result = Filter_UserAccess::getUserByLogin($login); // Поиск по логину
|
||||
$result = $this->role->getUserByLogin($login); // Поиск по логину
|
||||
if ($result) {
|
||||
$userPassword = $result->getString('password');
|
||||
if (Filter_UserAccess::$access == 'site_root' && defined('PARENT_PATH')) {
|
||||
$userPassword = $this->role->getUserPassword($result);
|
||||
if ($this->role->access == 'site_root' && defined('PARENT_PATH')) {
|
||||
$s = new Settings(PARENT_PATH . '/settings.json');
|
||||
$s->read();
|
||||
$dsn = $s->readKey(array('system', 'dsn'));
|
||||
|
|
@ -51,31 +67,24 @@ class Filter_Login extends Filter_Filter
|
|||
$request->set('lastupdate', true);
|
||||
return false;
|
||||
}*/
|
||||
// Проверка на количества попыток авторизации
|
||||
$lastAttempt = $db->fetchOneArray(
|
||||
"SELECT trie_count, trie_time FROM users WHERE login = :login", ['login' => $request->get('login')]);
|
||||
if ($lastAttempt['trie_count'] >= self::AUTH_MAX_ATTEMPT /*&& time() - $lastAttempt['trie_time'] < self::AUTH_LAST_ATTEMPT_TIMER*/) {
|
||||
if (time() - $lastAttempt['trie_time'] < self::AUTH_LAST_ATTEMPT_TIMER) {
|
||||
// Проверка на количества попыток авторизации
|
||||
$lastAttempt = $result;
|
||||
|
||||
if ($lastAttempt->get('trie_count') >= self::AUTH_MAX_ATTEMPT /*&& time() - $lastAttempt['trie_time'] < self::AUTH_LAST_ATTEMPT_TIMER*/) {
|
||||
if (time() - $lastAttempt->get('trie_time') < self::AUTH_LAST_ATTEMPT_TIMER) {
|
||||
$request->set('timeout_error', true);
|
||||
break;
|
||||
} else {
|
||||
$db->executeQuery(
|
||||
"UPDATE users SET trie_count = :count WHERE login = :login",
|
||||
['count' => 0, 'login' => $request->get('login')]
|
||||
);
|
||||
$this->role->resetTries($request->get('login'));
|
||||
}
|
||||
}
|
||||
// Извлечнеие пользователя из родительской CMS, для проверки пароля
|
||||
if (md5($password) == $userPassword) { // password
|
||||
$this->enter($db, $result);
|
||||
$this->enter($result);
|
||||
return true;
|
||||
} else {
|
||||
// Обновление количества неудачных попыток входа
|
||||
$user = $db->fetchOneArray("SELECT id_user, trie_count FROM users WHERE login = :login", ['login' => $login]);
|
||||
$db->executeQuery(
|
||||
"UPDATE users SET trie_time = :cur_time, trie_count = :count WHERE id_user = :id_user",
|
||||
['cur_time' => time(), 'count' => $user['trie_count']+=1, 'id_user' => $user['id_user']]
|
||||
);
|
||||
$this->role->updateTries($login);
|
||||
}
|
||||
}
|
||||
$request->set('error', true);
|
||||
|
|
@ -88,11 +97,11 @@ class Filter_Login extends Filter_Filter
|
|||
case 'enter':
|
||||
$login = $request->get('login');
|
||||
$password = $request->get('sid');
|
||||
$result = Filter_UserAccess::getUserByLogin($login); // Поиск по логину
|
||||
$result = $this->role->getUserByLogin($login); // Поиск по логину
|
||||
if ($result) {
|
||||
$temp = md5($result->getString('password') . $result->getString('login') . $result->getString('sid'));
|
||||
if ($password == $temp) {
|
||||
$this->enter($db, $result);
|
||||
if ($password == $temp) {
|
||||
$this->enter($result);
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
|
@ -103,7 +112,7 @@ class Filter_Login extends Filter_Filter
|
|||
// Если $hash не совпадает $_SESSION['hash'] то удаляем сессию
|
||||
if (isset($_SESSION ['access']) && isset($_SESSION[self::SESSION_BROWSER_SIGN_KEYNAME])) {
|
||||
if ($hash == $_SESSION[self::SESSION_BROWSER_SIGN_KEYNAME]) {
|
||||
$this->user = $user = Filter_UserAccess::getUserById($_SESSION['access']); // Поиск по идентификатору
|
||||
$this->user = $user = $this->role->getUserById($_SESSION['access']); // Поиск по идентификатору
|
||||
if ($user && isset($_SESSION['random']) && ($user->get('sid') == $_SESSION['random'])) {
|
||||
return true;
|
||||
}
|
||||
|
|
@ -116,8 +125,7 @@ class Filter_Login extends Filter_Filter
|
|||
return false;
|
||||
}
|
||||
|
||||
private function getBrowserSign()
|
||||
{
|
||||
private function getBrowserSign() {
|
||||
$rawSign = self::SESSION_BROWSER_SIGN_SECRET;
|
||||
//$signParts = array('HTTP_USER_AGENT', 'HTTP_ACCEPT_ENCODING');
|
||||
$signParts = array();
|
||||
|
|
@ -128,11 +136,11 @@ class Filter_Login extends Filter_Filter
|
|||
return md5($rawSign);
|
||||
}
|
||||
|
||||
private function enter($db, $result)
|
||||
private function enter($result)
|
||||
{
|
||||
$this->user = $result;
|
||||
$random = rand(0, 1024 * 1024);
|
||||
$db->executeQuery("UPDATE users SET sid = '$random', trie_count = 0 WHERE id_user = " . $result->getInt('id_user'));
|
||||
$this->role->setSID($random, $result);
|
||||
|
||||
$_SESSION["group"] = $result->getInt('access');
|
||||
$_SESSION["access"] = $result->getInt('id_user'); // id_user
|
||||
|
|
@ -149,7 +157,6 @@ class Filter_Login extends Filter_Filter
|
|||
$result = array();
|
||||
$result['fullname'] = $this->user->getString('patronymic') . " " . $this->user->getString('firstname');
|
||||
$result['email'] = $this->user->getString('email');
|
||||
$result['site'] = 187;
|
||||
$result['hash'] = sha1(self::SESSION_BROWSER_SIGN_SECRET . $this->user->getString('email'));
|
||||
return json_encode($result);
|
||||
} else {
|
||||
|
|
@ -191,13 +198,12 @@ class Filter_Login extends Filter_Filter
|
|||
/* ---------------------
|
||||
* Проверка на попадание реквеста в белый список
|
||||
*/
|
||||
|
||||
public function requestIsWhite(Collection $request) {
|
||||
$module = $request->get('module');
|
||||
$action = $request->get('action');
|
||||
|
||||
$moduleDir = explode('_',$module)[0];
|
||||
$file = Path::join(CMS_PATH, 'modules', $moduleDir, 'filters', 'white.json');
|
||||
$moduleDir = explode('\\',$module)[0];
|
||||
$file = Path::join($this->config->get('system', 'path'), 'modules', $moduleDir, 'filters', 'white.json');
|
||||
if (file_exists($file)) {
|
||||
$whiteList = json_decode(file_get_contents($file), true);
|
||||
|
||||
|
|
|
|||
|
|
@ -1,69 +0,0 @@
|
|||
<?php
|
||||
|
||||
// Класс должен быть в библиотеке приложения
|
||||
class Filter_UserAccess
|
||||
{
|
||||
const LIFE_TIME = 1800; // = 30min * 60sec;
|
||||
|
||||
static $fullname;
|
||||
static $name;
|
||||
static $access;
|
||||
static $password;
|
||||
static $id;
|
||||
static $db;
|
||||
|
||||
protected function __construct()
|
||||
{
|
||||
}
|
||||
|
||||
public static function setUp(Database $db)
|
||||
{
|
||||
self::$db = $db;
|
||||
}
|
||||
|
||||
public static function getUserByQuery(Database_Statement $stmt)
|
||||
{
|
||||
global $GROUPS;
|
||||
$result = $stmt->executeQuery();
|
||||
if ($result->next()) {
|
||||
self::$access = $GROUPS[$result->getString('access')];
|
||||
self::$name = $result->getString('login');
|
||||
self::$id = $result->getInt('id_user');
|
||||
self::$password = $result->getString('password');
|
||||
self::$fullname = implode(' ', array(
|
||||
$result->getString('surname'),
|
||||
$result->getString('firstname'),
|
||||
$result->getString('patronymic')));
|
||||
return $result;
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
public static function getUserByLogin($login)
|
||||
{
|
||||
$stmt = self::$db->prepareStatement("SELECT * FROM users WHERE login = ?");
|
||||
$stmt->setString(1, $login);
|
||||
$result = self::getUserByQuery($stmt);
|
||||
if ($result) {
|
||||
$time = time();
|
||||
$id = self::$id;
|
||||
self::$db->executeQuery("UPDATE users SET lasttime = $time WHERE id_user = $id"); // Время входа
|
||||
}
|
||||
return $result;
|
||||
}
|
||||
|
||||
public static function getUserById($id)
|
||||
{
|
||||
$stmt = self::$db->prepareStatement("SELECT * FROM users WHERE id_user = ?");
|
||||
$stmt->setInt(1, $_SESSION ['access']);
|
||||
$result = self::getUserByQuery($stmt);
|
||||
if ($result) {
|
||||
$lasttime = $result->getInt('lasttime');
|
||||
$time = time();
|
||||
if ($time - $lasttime > self::LIFE_TIME) return null; // Вышло время сессии
|
||||
$id = self::$id;
|
||||
// self::$db->executeQuery("UPDATE users SET lasttime = $time WHERE id_user = $id"); // Время последнего обращения входа
|
||||
}
|
||||
return $result;
|
||||
}
|
||||
}
|
||||
6
src/Form/BrowserInput.php
Normal file
6
src/Form/BrowserInput.php
Normal file
|
|
@ -0,0 +1,6 @@
|
|||
<?php
|
||||
namespace ctiso\Form;
|
||||
use ctiso\Form\Input;
|
||||
|
||||
class BrowserInput extends Input {
|
||||
}
|
||||
14
src/Form/CheckBox.php
Normal file
14
src/Form/CheckBox.php
Normal file
|
|
@ -0,0 +1,14 @@
|
|||
<?php
|
||||
|
||||
namespace ctiso\Form;
|
||||
use ctiso\Form\Field;
|
||||
|
||||
class Checkbox extends Field
|
||||
{
|
||||
public $checked = false;
|
||||
function setValue($value)
|
||||
{
|
||||
$this->value = $value;
|
||||
$this->checked = $value;
|
||||
}
|
||||
}
|
||||
|
|
@ -3,6 +3,9 @@
|
|||
/**
|
||||
* Поле с цветом
|
||||
*/
|
||||
class Form_Color extends Form_Field
|
||||
namespace ctiso\Form;
|
||||
use ctiso\Form\Field;
|
||||
|
||||
class Color extends Field
|
||||
{
|
||||
}
|
||||
|
|
@ -2,5 +2,8 @@
|
|||
/**
|
||||
* Поле с датой
|
||||
*/
|
||||
class Form_Date extends Form_Field {
|
||||
namespace ctiso\Form;
|
||||
use ctiso\Form\Field;
|
||||
|
||||
class Date extends Field {
|
||||
}
|
||||
7
src/Form/DateTime.php
Normal file
7
src/Form/DateTime.php
Normal file
|
|
@ -0,0 +1,7 @@
|
|||
<?php
|
||||
|
||||
namespace ctiso\Form;
|
||||
use ctiso\Form\Input;
|
||||
|
||||
class DateTime extends Input {
|
||||
}
|
||||
|
|
@ -2,7 +2,9 @@
|
|||
/**
|
||||
* Элемент формы
|
||||
*/
|
||||
class Form_Field
|
||||
namespace ctiso\Form;
|
||||
|
||||
class Field
|
||||
{
|
||||
public $hidden = false;
|
||||
public $name;
|
||||
|
|
|
|||
|
|
@ -4,54 +4,18 @@
|
|||
* При рендеринге каждому классу соответствует шаблон (см. themes/maxim/templates/macros.html)
|
||||
*/
|
||||
|
||||
class TCheckbox extends Form_Field
|
||||
{
|
||||
public $checked = false;
|
||||
function setValue($value)
|
||||
{
|
||||
$this->value = $value;
|
||||
$this->checked = $value;
|
||||
}
|
||||
}
|
||||
namespace ctiso\Form;
|
||||
use ctiso\Form\Field,
|
||||
ctiso\Form\Select,
|
||||
ctiso\Form\Input,
|
||||
ctiso\View\View,
|
||||
ctiso\Validator\Validator,
|
||||
ctiso\HttpRequest;
|
||||
|
||||
class TQuestionType extends Form_Select
|
||||
{
|
||||
function setValue($value)
|
||||
{
|
||||
// Установить selected у options
|
||||
$this->value = $value;
|
||||
foreach ($this->options as &$option) {
|
||||
$option['selected'] = ($option['value'] == $value);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
class TDateTime extends Form_Input {
|
||||
}
|
||||
|
||||
/**
|
||||
* Поле для ввода пароля
|
||||
*/
|
||||
class TSecret extends Form_Field {
|
||||
}
|
||||
|
||||
class TUpload extends Form_Field {
|
||||
}
|
||||
|
||||
class THidden extends Form_Input {
|
||||
public $hidden = true;
|
||||
}
|
||||
|
||||
class TComponentBrowserInput extends Form_Input {
|
||||
}
|
||||
|
||||
// вставка простого html
|
||||
class Html_Text extends Form_Field {
|
||||
}
|
||||
/**
|
||||
* Форма для ввода
|
||||
*/
|
||||
class Form_Form extends View_View {
|
||||
class Form extends View {
|
||||
public $field = array(); //Поля формы
|
||||
public $fieldsets = array(); //Группы полей (fieldset). Некоторые поля могут не принадлежать никаким группам
|
||||
|
||||
|
|
@ -72,33 +36,34 @@ class Form_Form extends View_View {
|
|||
public function __construct()
|
||||
{
|
||||
$this->constructor = array(
|
||||
'input' => 'Form_Input',
|
||||
'inputreq' => 'Form_Input', // input с проверкой на заполненность
|
||||
'input' => 'ctiso\\Form\\Input',
|
||||
// input с проверкой на заполненность
|
||||
'inputreq' => 'ctiso\\Form\\Input',
|
||||
|
||||
'date' => 'Form_Date',
|
||||
'datereq' => 'Form_Date',
|
||||
'datetime' => 'TDateTime',
|
||||
'date' => 'ctiso\\Form\\Date',
|
||||
'datereq' => 'ctiso\\Form\\Date',
|
||||
'datetime' => 'ctiso\\Form\\DateTime',
|
||||
|
||||
'color' => 'Form_Color',
|
||||
'textarea' => 'Form_TextArea',
|
||||
'text' => 'Form_TextArea',
|
||||
'multiselect' => 'Form_SelectMany',
|
||||
// 'selectmany' => 'TSelectMany',
|
||||
'select1' => 'Form_SelectOne',
|
||||
'select' => 'Form_SelectOne',
|
||||
'questiontype'=> 'TQuestionType',
|
||||
'secret' => 'TSecret',
|
||||
'upload' => 'TUpload',
|
||||
'image' => 'TUpload',
|
||||
'checkbox' => 'TCheckbox',
|
||||
'checkmany' => 'Form_SelectMany',
|
||||
'hidden' => 'THidden',
|
||||
'radio' => 'Form_SelectOne',
|
||||
'filebrowser' => 'TComponentBrowserInput',
|
||||
'documents' => 'TComponentBrowserInput',
|
||||
'chooser' => 'Form_Input',
|
||||
'select_chooser' => 'Form_SelectOne',
|
||||
'html_text' => 'Html_Text'
|
||||
'color' => 'ctiso\\Form\\Color',
|
||||
'textarea' => 'ctiso\\Form\\TextArea',
|
||||
'text' => 'ctiso\\Form\\TextArea',
|
||||
'multiselect' => 'ctiso\\Form\\SelectMany',
|
||||
'select1' => 'ctiso\\Form\\SelectOne',
|
||||
'select' => 'ctiso\\Form\\SelectOne',
|
||||
|
||||
'questiontype'=> 'ctiso\\Form\\QuestionType',
|
||||
'secret' => 'ctiso\\Form\\Secret',
|
||||
'upload' => 'ctiso\\Form\\Upload',
|
||||
'image' => 'ctiso\\Form\\Upload',
|
||||
'checkbox' => 'ctiso\\Form\\CheckBox',
|
||||
'checkmany' => 'ctiso\\Form\\SelectMany',
|
||||
'hidden' => 'ctiso\\Form\\Hidden',
|
||||
'radio' => 'ctiso\\Form\\SelectOne',
|
||||
'filebrowser' => 'ctiso\\Form\\BrowserInput',
|
||||
'documents' => 'ctiso\\Form\\BrowserInput',
|
||||
'chooser' => 'ctiso\\Form\\Input',
|
||||
'select_chooser' => 'ctiso\\Form\\SelectOne',
|
||||
'html_text' => 'ctiso\\Form\\HtmlText'
|
||||
);
|
||||
|
||||
}
|
||||
|
|
@ -131,7 +96,7 @@ class Form_Form extends View_View {
|
|||
$el->hint = $init['hint'];
|
||||
}
|
||||
|
||||
$this->field [$init['name']] = $el;
|
||||
$this->field[$init['name']] = $el;
|
||||
return $el;
|
||||
}
|
||||
|
||||
|
|
@ -169,7 +134,7 @@ class Form_Form extends View_View {
|
|||
/**
|
||||
* Устанавливает ошибки после проверки
|
||||
*/
|
||||
function setError(Validator_Validator $validator)
|
||||
function setError(Validator $validator)
|
||||
{
|
||||
foreach ($validator->getErrorMsg() as $name => $error)
|
||||
{
|
||||
|
|
@ -203,7 +168,7 @@ class Form_Form extends View_View {
|
|||
{
|
||||
foreach ($schema as $key => $conv) {
|
||||
list($value, $type) = $conv;
|
||||
$this->field [$key]->setValue(call_user_func(array('Primitive', 'from_' . $type), $data->$value));
|
||||
$this->field [$key]->setValue(call_user_func(array('ctiso\\Primitive', 'from_' . $type), $data->$value));
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
|||
8
src/Form/Hidden.php
Normal file
8
src/Form/Hidden.php
Normal file
|
|
@ -0,0 +1,8 @@
|
|||
<?php
|
||||
|
||||
namespace ctiso\Form;
|
||||
use ctiso\Form\Input;
|
||||
|
||||
class Hidden extends Input {
|
||||
public $hidden = true;
|
||||
}
|
||||
8
src/Form/HtmlText.php
Normal file
8
src/Form/HtmlText.php
Normal file
|
|
@ -0,0 +1,8 @@
|
|||
<?php
|
||||
|
||||
namespace ctiso\Form;
|
||||
use ctiso\Form\Field;
|
||||
|
||||
// вставка простого html
|
||||
class HtmlText extends Field {
|
||||
}
|
||||
|
|
@ -3,5 +3,8 @@
|
|||
/**
|
||||
* Поле ввода Input
|
||||
*/
|
||||
class Form_Input extends Form_Field {
|
||||
namespace ctiso\Form;
|
||||
use ctiso\Form\Field;
|
||||
|
||||
class Input extends Field {
|
||||
}
|
||||
|
|
@ -1,87 +0,0 @@
|
|||
<?php
|
||||
|
||||
class Form_OptionFactory {
|
||||
public $db;
|
||||
public $registry;
|
||||
|
||||
function __construct($db, $registry = null) {
|
||||
$this->db = $db;
|
||||
$this->registry = $registry;
|
||||
}
|
||||
|
||||
function create(Form_Select $field, $input) {
|
||||
if (isset($input['options.resid'])) {
|
||||
$type = $input['options.resid'];
|
||||
|
||||
$res = new Model_Resources($this->db);
|
||||
$field->options = $this->optionsArray('id_section', 'title', $res->getSubsections('', $type));
|
||||
|
||||
} else if (isset($input['options.res'])) {
|
||||
$type = $input['options.res'];
|
||||
|
||||
$res = new Model_Resources($this->db);
|
||||
$field->options = $this->optionsArray('path', 'title', $res->getSubsections('', $type));
|
||||
|
||||
} else if (isset($input['options.all_res'])) {
|
||||
$type = $input['options.all_res'];
|
||||
|
||||
$res = new Model_Resources($this->db);
|
||||
$field->options = $this->optionsArray('id_resource', 'subtitle', $res->getAllResource($type));
|
||||
|
||||
} else if (isset($input['options.db'])) {
|
||||
list($table, $keyvalue) = explode(":", $input['options.db']);
|
||||
list($key, $value) = explode(",", $keyvalue);
|
||||
try {
|
||||
$query_result = $this->db->executeQuery("SELECT * FROM $table");
|
||||
$field->options = $this->optionsDB($key, $value, $query_result);
|
||||
} catch(Exception $ex) {
|
||||
$field->options = [];
|
||||
}
|
||||
} elseif (isset($input['options.pair'])) {
|
||||
$field->options = $this->optionsPair($input['options.pair']);
|
||||
} elseif (isset($input['options.model'])) {
|
||||
$factory = new Model_Factory($this->db, $this->registry);
|
||||
$model = $factory->getModel($input['options.model']);
|
||||
$field->options = $model->getAllAsOptions();
|
||||
} else {
|
||||
$field->options = $input['options'];
|
||||
}
|
||||
if (isset($input['default'])) {
|
||||
array_unshift($field->options, ['value' => 0, 'name' => $input['default']]);
|
||||
}
|
||||
|
||||
// Ставим корневой каталог в начало списка (скорее всего он будет в конце массива)
|
||||
if ($field->options)
|
||||
{
|
||||
$root_elem = array_pop($field->options);
|
||||
if ($root_elem['value'] == '/')
|
||||
array_unshift($field->options, $root_elem);
|
||||
else
|
||||
array_push($field->options, $root_elem);
|
||||
}
|
||||
}
|
||||
|
||||
public function optionsDB($key, $val, $res) {
|
||||
$result = array();
|
||||
while($res->next()) {
|
||||
$result[] = array('value' => $res->getInt($key), 'name' => $res->getString($val));
|
||||
}
|
||||
return $result;
|
||||
}
|
||||
|
||||
public function optionsArray($key, $val, $res) {
|
||||
$result = array();
|
||||
foreach($res as $item) {
|
||||
$result[] = array('value' => $item->{$key}, 'name' => $item->{$val});
|
||||
}
|
||||
return $result;
|
||||
}
|
||||
|
||||
public function optionsPair($list, $selected = false) {
|
||||
$result = array();
|
||||
foreach ($list as $key => $value) {
|
||||
$result [] = array('value' => $key, 'name' => $value, 'selected' => $key == $selected);
|
||||
}
|
||||
return $result;
|
||||
}
|
||||
}
|
||||
16
src/Form/QuestionType.php
Normal file
16
src/Form/QuestionType.php
Normal file
|
|
@ -0,0 +1,16 @@
|
|||
<?php
|
||||
|
||||
namespace ctiso\Form;
|
||||
use ctiso\Form\Select;
|
||||
|
||||
class QuestionType extends Select
|
||||
{
|
||||
function setValue($value)
|
||||
{
|
||||
// Установить selected у options
|
||||
$this->value = $value;
|
||||
foreach ($this->options as &$option) {
|
||||
$option['selected'] = ($option['value'] == $value);
|
||||
}
|
||||
}
|
||||
}
|
||||
10
src/Form/Secret.php
Normal file
10
src/Form/Secret.php
Normal file
|
|
@ -0,0 +1,10 @@
|
|||
<?php
|
||||
|
||||
namespace ctiso\Form;
|
||||
use ctiso\Form\Field;
|
||||
|
||||
/**
|
||||
* Поле для ввода пароля
|
||||
*/
|
||||
class Secret extends Field {
|
||||
}
|
||||
|
|
@ -1,6 +1,9 @@
|
|||
<?php
|
||||
|
||||
class Form_Select extends Form_Field
|
||||
namespace ctiso\Form;
|
||||
use ctiso\Form\Field;
|
||||
|
||||
class Select extends Field
|
||||
{
|
||||
public $options = array();
|
||||
|
||||
|
|
|
|||
|
|
@ -1,6 +1,9 @@
|
|||
<?php
|
||||
|
||||
class Form_SelectMany extends Form_Select
|
||||
namespace ctiso\Form;
|
||||
use ctiso\Form\Select;
|
||||
|
||||
class SelectMany extends Select
|
||||
{
|
||||
function setValue($value)
|
||||
{
|
||||
|
|
|
|||
|
|
@ -3,7 +3,10 @@
|
|||
/**
|
||||
* Выбор из одного элемента
|
||||
*/
|
||||
class Form_SelectOne extends Form_Select
|
||||
namespace ctiso\Form;
|
||||
use ctiso\Form\Select;
|
||||
|
||||
class SelectOne extends Select
|
||||
{
|
||||
function setValue($value)
|
||||
{
|
||||
|
|
|
|||
|
|
@ -3,7 +3,10 @@
|
|||
/**
|
||||
* Текстовое поле
|
||||
*/
|
||||
class Form_TextArea extends Form_Field {
|
||||
namespace ctiso\Form;
|
||||
use ctiso\Form\Field;
|
||||
|
||||
class TextArea extends Field {
|
||||
function setValue($value)
|
||||
{
|
||||
$this->value = $value;
|
||||
|
|
|
|||
7
src/Form/Upload.php
Normal file
7
src/Form/Upload.php
Normal file
|
|
@ -0,0 +1,7 @@
|
|||
<?php
|
||||
|
||||
namespace ctiso\Form;
|
||||
use ctiso\Form\Field;
|
||||
|
||||
class Upload extends Field {
|
||||
}
|
||||
|
|
@ -4,7 +4,9 @@
|
|||
* http://www.alternateinterior.com/2006/09/a-viewstate-for-php.html
|
||||
* Управление состоянием между страницами
|
||||
*/
|
||||
class Form_ViewState // extends Collection
|
||||
namespace ctiso\Form;
|
||||
|
||||
class ViewState // extends Collection
|
||||
{
|
||||
private $values = array();
|
||||
|
||||
|
|
|
|||
|
|
@ -8,7 +8,9 @@
|
|||
/**
|
||||
* Эмуляция каррированой функции
|
||||
*/
|
||||
class __right {
|
||||
namespace ctiso;
|
||||
|
||||
class right {
|
||||
protected $params;
|
||||
protected $fn;
|
||||
|
||||
|
|
@ -24,7 +26,7 @@ class __right {
|
|||
}
|
||||
}
|
||||
|
||||
class __left {
|
||||
class left {
|
||||
protected $params;
|
||||
protected $fn;
|
||||
|
||||
|
|
@ -41,7 +43,7 @@ class __left {
|
|||
}
|
||||
|
||||
define('__', '_ARGUMENT_PLACE_');
|
||||
class __partial {
|
||||
class partial {
|
||||
protected $params;
|
||||
protected $fn;
|
||||
|
||||
|
|
@ -53,7 +55,8 @@ class __partial {
|
|||
function apply() {
|
||||
$params = func_get_args();
|
||||
$result = array();
|
||||
for($i = 0, $j = 0; $i < count($this->params); $i++) {
|
||||
$count = count($this->params);
|
||||
for($i = 0, $j = 0; $i < $count; $i++) {
|
||||
if ($this->params[$i] == __) {
|
||||
$result [] = $params[$j];
|
||||
$j++;
|
||||
|
|
@ -68,7 +71,7 @@ class __partial {
|
|||
/**
|
||||
* Композиция функций
|
||||
*/
|
||||
class __compose {
|
||||
class compose {
|
||||
protected $fns;
|
||||
function __construct($list) {
|
||||
$this->fns = array_reverse($list);
|
||||
|
|
@ -77,7 +80,8 @@ class __compose {
|
|||
function apply () {
|
||||
$params = func_get_args ();
|
||||
$result = call_user_func_array($this->fns[0], $params);
|
||||
for ($i = 1; $i < count($this->fns); $i++) {
|
||||
$count = count($this->fns);
|
||||
for ($i = 1; $i < $count; $i++) {
|
||||
$result = call_user_func($this->fns[$i], $result);
|
||||
}
|
||||
return $result;
|
||||
|
|
@ -86,8 +90,8 @@ class __compose {
|
|||
|
||||
class Functions {
|
||||
|
||||
static function partial() {
|
||||
$closure = new __partial(func_get_args());
|
||||
static function partial($_rest) {
|
||||
$closure = new partial(func_get_args());
|
||||
return array($closure, 'apply');
|
||||
}
|
||||
|
||||
|
|
@ -97,30 +101,30 @@ class Functions {
|
|||
* @param mixed $a
|
||||
* @param mixed $b
|
||||
*
|
||||
* @return array[int]mixed
|
||||
* @return mixed
|
||||
*/
|
||||
static function compose() {
|
||||
$closure = new __compose(func_get_args());
|
||||
static function compose($_rest) {
|
||||
$closure = new compose(func_get_args());
|
||||
return array($closure, 'apply');
|
||||
}
|
||||
|
||||
/**
|
||||
* Карирование справа
|
||||
*
|
||||
* @return array[int]mixed
|
||||
* @return mixed
|
||||
*/
|
||||
static function rcurry($_rest) {
|
||||
$closure = new __right(func_get_args ());
|
||||
$closure = new right(func_get_args ());
|
||||
return array($closure, 'apply');
|
||||
}
|
||||
|
||||
/**
|
||||
* Карирование слева
|
||||
*
|
||||
* @return array[int]mixed
|
||||
* @return mixed
|
||||
*/
|
||||
static function lcurry($_rest) {
|
||||
$closure = new __left(func_get_args ());
|
||||
$closure = new left(func_get_args ());
|
||||
return array($closure, 'apply');
|
||||
}
|
||||
|
||||
|
|
@ -129,7 +133,7 @@ class Functions {
|
|||
* @param mixed $pred Условие по которому разделяется массив
|
||||
* @param array $lst
|
||||
*
|
||||
* @return array[int]mixed
|
||||
* @return mixed
|
||||
*/
|
||||
static function partition($pred, $lst) {
|
||||
$left = array ();
|
||||
|
|
@ -222,7 +226,7 @@ class Functions {
|
|||
*
|
||||
* @return mixed
|
||||
*/
|
||||
static function key_values($key, /*array|ArrayIterator*/ $array) {
|
||||
static function key_values($key, $array/*: array|ArrayIterator*/) {
|
||||
$result = array();
|
||||
|
||||
foreach($array as $item) {
|
||||
|
|
@ -231,7 +235,7 @@ class Functions {
|
|||
return $result;
|
||||
}
|
||||
|
||||
static function key_values_object($key, /*array|ArrayIterator*/ $array) {
|
||||
static function key_values_object($key, $array/*: array|ArrayIterator*/) {
|
||||
$result = array();
|
||||
|
||||
foreach($array as $item) {
|
||||
|
|
@ -306,7 +310,8 @@ class Functions {
|
|||
assert(is_int($length));
|
||||
|
||||
$result = array();
|
||||
for($i = 0; $i < count($array); $i += $length) {
|
||||
$count = count($array);
|
||||
for($i = 0; $i < $count; $i += $length) {
|
||||
$result [] = array_slice($array, $i, $length);
|
||||
}
|
||||
return $result;
|
||||
|
|
@ -324,19 +329,20 @@ class Functions {
|
|||
|
||||
/**
|
||||
* Поиск элемента в массиве
|
||||
* @param function $cb сравнение с элементом массива
|
||||
* @param array $hs массив в котором ищется значение
|
||||
* @param mixed $cb сравнение с элементом массива
|
||||
* @param Array $hs массив в котором ищется значение
|
||||
*
|
||||
* @return int|string ключ найденого элемента в массиве
|
||||
*/
|
||||
static function array_usearch($cb, array $hs, $strict = false) {
|
||||
foreach($hs as $key => $value) if (call_user_func_array($cb, array($value, $key, $strict))) return $key;
|
||||
return null;
|
||||
}
|
||||
|
||||
/**
|
||||
* Выбирает все сроки из таблицы с уникальными значениями ключа
|
||||
* @param $name Имя ключа
|
||||
* @param $table Двухмерный массив
|
||||
* @param string $name Имя ключа
|
||||
* @param Array $table Двухмерный массив
|
||||
* @example
|
||||
* key_unique_values ('name', array (array ('name' => 1), array ('name' => 2), array ('name' => 1)))
|
||||
=> array (1, 2)
|
||||
|
|
@ -354,11 +360,11 @@ class Functions {
|
|||
|
||||
/**
|
||||
* Сортировка двумерного массива по заданному ключу
|
||||
* @param $array Массив
|
||||
* @param $key Имя ключа по значению которого будет идти сравнение
|
||||
* @return Отсортированный массив
|
||||
* @param Array $array Массив
|
||||
* @param string $key Имя ключа по значению которого будет идти сравнение
|
||||
* @return Array Отсортированный массив
|
||||
*/
|
||||
static function sortOn($array, $key, $fn = 'Functions::__cmp') {
|
||||
static function sortOn($array, $key, $fn = '\\ctiso\\Functions::__cmp') {
|
||||
usort ($array, Functions::rcurry($fn, $key));
|
||||
//usort ($array, create_function ('$x,$y', 'return __cmp ($x, $y, "'.$key.'");'));
|
||||
return $array;
|
||||
|
|
@ -368,7 +374,7 @@ class Functions {
|
|||
* Преобразует ключи элементов для многомерного массива
|
||||
* @return mixed
|
||||
*/
|
||||
static function hash_key ($key_name,$array/*: array*/) {
|
||||
static function hash_key ($key_name,$array/*: array */) {
|
||||
$result = array();
|
||||
|
||||
foreach($array as $value) {
|
||||
|
|
|
|||
|
|
@ -3,9 +3,11 @@
|
|||
/**
|
||||
* Неверный запрос
|
||||
*/
|
||||
class WrongRequestException extends Exception
|
||||
{
|
||||
}
|
||||
namespace ctiso;
|
||||
use Exception,
|
||||
ArrayAccess,
|
||||
ctiso\Collection,
|
||||
ctiso\Session;
|
||||
|
||||
// HTTPRequest = ArrayAccess
|
||||
class HttpRequest extends Collection implements ArrayAccess
|
||||
|
|
@ -127,4 +129,8 @@ class HttpRequest extends Collection implements ArrayAccess
|
|||
|
||||
public function offsetGet($key) {
|
||||
}
|
||||
|
||||
static function getProtocol() {
|
||||
return (!empty($_SERVER['HTTPS']) && $_SERVER['HTTPS'] !== 'off' || $_SERVER['SERVER_PORT'] == 443) ? "https://" : "http://";
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -3,7 +3,11 @@
|
|||
/**
|
||||
* Самый простой макет
|
||||
*/
|
||||
class Layout_Empty extends Filter_Filter
|
||||
namespace ctiso\Layout;
|
||||
use ctiso\Filter\Filter,
|
||||
ctiso\HttpRequest;
|
||||
|
||||
class Blank extends Filter
|
||||
{
|
||||
function execute(HttpRequest $request)
|
||||
{
|
||||
|
|
@ -4,7 +4,12 @@
|
|||
* Выбор макета страницы.
|
||||
* Выбор оформления страницы осуществляется если было совпадение с каким либо условием
|
||||
*/
|
||||
class Layout_Manager extends Filter_Filter
|
||||
namespace ctiso\Layout;
|
||||
use ctiso\Filter\Filter,
|
||||
ctiso\Functions,
|
||||
ctiso\HttpRequest;
|
||||
|
||||
class Manager extends Filter
|
||||
{
|
||||
// Массив условий с их макетами
|
||||
protected $condition = array();
|
||||
|
|
@ -17,7 +22,7 @@ class Layout_Manager extends Filter_Filter
|
|||
* addConditionGet(array('module' => 'personal'), 'personal')
|
||||
* addConditionGet(array('module' => 'login'), 'login')
|
||||
*/
|
||||
public function addConditionGet($get, Filter_Filter $layout)
|
||||
public function addConditionGet($get, Filter $layout)
|
||||
{
|
||||
$this->addCondition(Functions::rcurry(array($this, 'checkGet'), $get), $layout);
|
||||
}
|
||||
|
|
@ -25,12 +30,12 @@ class Layout_Manager extends Filter_Filter
|
|||
/**
|
||||
* Условие для аякс запросов. Тоже самое что и addConditionGet но еще проверяется является ли запрос ajax
|
||||
*/
|
||||
public function addConditionXHR($get, Filter_Filter $layout)
|
||||
public function addConditionXHR($get, Filter $layout)
|
||||
{
|
||||
$this->addCondition(Functions::rcurry(array($this, 'checkXHR'), $get), $layout);
|
||||
}
|
||||
|
||||
public function checkGet($request, $get)
|
||||
public function checkGet($request/*: HttpRequest*/, $get)
|
||||
{
|
||||
if (is_array($get)) {
|
||||
foreach ($get as $key => $value) {
|
||||
|
|
@ -42,7 +47,7 @@ class Layout_Manager extends Filter_Filter
|
|||
return true;
|
||||
}
|
||||
|
||||
public function checkXHR($request, $get)
|
||||
public function checkXHR($request/*: HttpRequest*/, $get)
|
||||
{
|
||||
return $request->isAjax() && $this->checkGet($request, $get);
|
||||
}
|
||||
|
|
@ -52,7 +57,7 @@ class Layout_Manager extends Filter_Filter
|
|||
* @parma $get function(HttpRequest) Функция
|
||||
* @parma $layout Layout Макет
|
||||
*/
|
||||
public function addCondition($get, Filter_Filter $layout)
|
||||
public function addCondition($get, Filter $layout)
|
||||
{
|
||||
$this->condition [] = array($get, $layout);
|
||||
}
|
||||
|
|
@ -67,11 +72,10 @@ class Layout_Manager extends Filter_Filter
|
|||
$layout = $condition[1];
|
||||
$view = $layout->execute($request);
|
||||
if (is_object($view)) {
|
||||
echo $view->render();
|
||||
return $view->render();
|
||||
} else {
|
||||
echo $view;
|
||||
return $view;
|
||||
}
|
||||
return null;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -4,6 +4,10 @@
|
|||
* Класс для работы с почтой
|
||||
* http://en.wikipedia.org/wiki/MIME
|
||||
*/
|
||||
namespace ctiso;
|
||||
use ctiso\Path,
|
||||
Exception;
|
||||
|
||||
class Mail
|
||||
{
|
||||
public $_from;
|
||||
|
|
|
|||
|
|
@ -1,5 +1,8 @@
|
|||
<?php
|
||||
|
||||
namespace ctiso;
|
||||
use PHPMailer;
|
||||
|
||||
class MailAlt
|
||||
{
|
||||
public $mailer;
|
||||
|
|
|
|||
6
src/Model/BaseMapper.php
Normal file
6
src/Model/BaseMapper.php
Normal file
|
|
@ -0,0 +1,6 @@
|
|||
<?php
|
||||
|
||||
namespace ctiso\Model;
|
||||
|
||||
class BaseMapper {
|
||||
}
|
||||
|
|
@ -1,30 +1,35 @@
|
|||
<?php
|
||||
|
||||
class Model_Factory
|
||||
{
|
||||
static $shortcut = "model";
|
||||
public $db;
|
||||
public $_registry;
|
||||
public $_shortcut;
|
||||
namespace ctiso\Model;
|
||||
use ctiso\Registry,
|
||||
ctiso\Database,
|
||||
ctiso\Role\User;
|
||||
|
||||
public function __construct ($db/*: Database*/, Settings $_registry = null)
|
||||
class Factory
|
||||
{
|
||||
public $db;
|
||||
public $config;
|
||||
|
||||
public function __construct (Database $db, Registry $config = null, User $user = null)
|
||||
{
|
||||
$this->db = $db;
|
||||
$this->_registry = $_registry;
|
||||
$this->config = $config;
|
||||
$this->user = $user;
|
||||
}
|
||||
|
||||
/**
|
||||
* Создает модель
|
||||
* @param string $name
|
||||
* @return model
|
||||
* @return BaseMapper
|
||||
*/
|
||||
public function getModel ($name)
|
||||
{
|
||||
$modelName = "Mapper_" . $name;
|
||||
$modelName = "App\\Mapper\\" . $name;
|
||||
$model = new $modelName();
|
||||
$model->db = $this->db;
|
||||
$model->factory = $this;
|
||||
$model->_registry = $this->_registry;
|
||||
$model->config = $this->config;
|
||||
$model->user = $this->user;
|
||||
$model->setUp();
|
||||
//
|
||||
return $model;
|
||||
|
|
|
|||
|
|
@ -1,5 +1,7 @@
|
|||
<?php
|
||||
|
||||
namespace ctiso;
|
||||
|
||||
class Numbers
|
||||
{
|
||||
static function roman($i)
|
||||
|
|
@ -15,7 +17,8 @@ class Numbers
|
|||
static function prefix($prefix, array $array, $key = false)
|
||||
{
|
||||
$result = array();
|
||||
for ($i = 0; $i < count($array); $i++) {
|
||||
$count = count($array);
|
||||
for ($i = 0; $i < $count; $i++) {
|
||||
$result [] = call_user_func($prefix, $i + 1) . '. ' . $array[$i];
|
||||
}
|
||||
return $result;
|
||||
|
|
|
|||
23
src/Path.php
23
src/Path.php
|
|
@ -6,6 +6,8 @@
|
|||
*
|
||||
*/
|
||||
|
||||
namespace ctiso;
|
||||
|
||||
class Path
|
||||
{
|
||||
const SEPARATOR = "/";
|
||||
|
|
@ -160,8 +162,9 @@ class Path
|
|||
// Сравнение двух путей на равентство
|
||||
public function equal($path/*: Path*/)
|
||||
{
|
||||
if (count($this->path) == count($path->path)) {
|
||||
for ($i = 0; $i < count($this->path); $i++) {
|
||||
$count = count($this->path);
|
||||
if ($count == count($path->path)) {
|
||||
for ($i = 0; $i < $count; $i++) {
|
||||
if ($this->path[$i] != $path->path[$i]) {
|
||||
return false;
|
||||
}
|
||||
|
|
@ -210,8 +213,9 @@ class Path
|
|||
if (isset($this->url['host']) && isset($path->url['host'])
|
||||
&& ($this->url['host'] != $path->url['host'])) return false;
|
||||
|
||||
if (count($path->path) > count($this->path)) {
|
||||
for ($i = 0; $i < count($this->path); $i++) {
|
||||
$count = count($this->path);
|
||||
if (count($path->path) > $count) {
|
||||
for ($i = 0; $i < $count; $i++) {
|
||||
if ($path->path[$i] != $this->path[$i]) {
|
||||
return false;
|
||||
}
|
||||
|
|
@ -255,15 +259,18 @@ class Path
|
|||
$list_path = $list->getParts();
|
||||
|
||||
$result = array();
|
||||
for ($i = 0; $i < count($list_path); $i++) {
|
||||
$count = count($list_path);
|
||||
for ($i = 0; $i < $count; $i++) {
|
||||
if (($i >= count($self_path)) || $list_path[$i] != $self_path[$i]) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
for($j = $i; $j < count($list_path); $j++) {
|
||||
$list_count = count($list_path);
|
||||
for($j = $i; $j < $list_count; $j++) {
|
||||
array_push($result, '..');
|
||||
}
|
||||
for($j = $i; $j < count($self_path); $j++) {
|
||||
$self_count = count($self_path);
|
||||
for($j = $i; $j < $self_count; $j++) {
|
||||
array_push($result, $self_path[$j]);
|
||||
}
|
||||
return implode("/", $result);
|
||||
|
|
@ -369,7 +376,7 @@ class Path
|
|||
*/
|
||||
public function getContent($allow = null, $ignore = array())
|
||||
{
|
||||
$ignore = array_merge(array(".", ".."), $ignore);
|
||||
$ignore = array_merge(array(".", ".."), $ignore);
|
||||
return self::fileList($this->__toString(), $allow, $ignore);
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -6,6 +6,8 @@
|
|||
* @package system
|
||||
*/
|
||||
|
||||
namespace ctiso;
|
||||
|
||||
class Primitive {
|
||||
// varchar
|
||||
public static function to_varchar($value)
|
||||
|
|
@ -48,9 +50,9 @@ class Primitive {
|
|||
if (!empty($tmp)) {
|
||||
if (count($tmp) != 3) return $result;
|
||||
|
||||
$year = intval($tmp[2]);
|
||||
$month = intval($tmp[1]);
|
||||
$day = intval($tmp[0]);
|
||||
$year = (int)$tmp[2];
|
||||
$month = (int)$tmp[1];
|
||||
$day = (int)$tmp[0];
|
||||
|
||||
if ($month != 0 && $day != 0 && $year != 0) {
|
||||
if (checkdate($month, $day, $year)) {
|
||||
|
|
|
|||
|
|
@ -1,5 +1,7 @@
|
|||
<?php
|
||||
|
||||
namespace ctiso;
|
||||
|
||||
if (!function_exists('str_getcsv')) {
|
||||
function str_getcsv($input, $delimiter = ",", $enclosure = '"', $escape = "\\") {
|
||||
$fiveMBs = 1024;
|
||||
|
|
@ -1,40 +1,51 @@
|
|||
<?php
|
||||
|
||||
///<reference path="Settings.php" />
|
||||
namespace ctiso;
|
||||
use ctiso\File,
|
||||
Exception;
|
||||
|
||||
/**
|
||||
* http://www.patternsforphp.com/wiki/Registry
|
||||
* http://www.patternsforphp.com/wiki/Singleton
|
||||
* http://www.phppatterns.com/docs/design/the_registry?s=registry
|
||||
*/
|
||||
class Registry {
|
||||
public $namespace = [];
|
||||
public $data;
|
||||
|
||||
class Registry extends Settings
|
||||
{
|
||||
static $instance = null;
|
||||
|
||||
/**
|
||||
*/
|
||||
static public function getInstance()
|
||||
{
|
||||
if (self::$instance == null) {
|
||||
self::$instance = new Registry();
|
||||
function importFile($namespace, $filePath = null) {
|
||||
$data = json_decode(File::getContents($filePath), true);
|
||||
$data['_file'] = $filePath;
|
||||
$this->namespace[$namespace] = [
|
||||
'path' => $filePath,
|
||||
'data' => $data
|
||||
];
|
||||
}
|
||||
|
||||
function importArray($namespace, $data = []) {
|
||||
if (isset($this->namespace[$namespace])) {
|
||||
$data = array_merge($this->namespace[$namespace]['data'], $data);
|
||||
}
|
||||
$this->namespace[$namespace] = [
|
||||
'path' => null,
|
||||
'data' => $data
|
||||
];
|
||||
}
|
||||
|
||||
public function get($ns, $key) {
|
||||
if (isset($this->namespace[$ns]['data'][$key])) {
|
||||
return $this->namespace[$ns]['data'][$key];
|
||||
}
|
||||
return self::$instance;
|
||||
throw new Exception('Unknown key ' . $ns . '::' . $key);
|
||||
}
|
||||
|
||||
/**
|
||||
* Список модулей
|
||||
*/
|
||||
public function getModules()
|
||||
{
|
||||
return array_keys($this->data);
|
||||
public function getOpt($ns, $key) {
|
||||
if (isset($this->namespace[$ns]['data'][$key])) {
|
||||
return $this->namespace[$ns]['data'][$key];
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
/**
|
||||
* Проверка наличия модуля
|
||||
*/
|
||||
public function hasModule($name)
|
||||
{
|
||||
return isset($this->data[$name]);
|
||||
public function has($ns, $key) {
|
||||
return isset($this->namespace[$ns]['data'][$key]);
|
||||
}
|
||||
|
||||
function set($ns, $key, $value) {
|
||||
$this->namespace[$ns]['data'][$key] = $value;
|
||||
}
|
||||
}
|
||||
|
|
|
|||
104
src/Role/User.php
Normal file
104
src/Role/User.php
Normal file
|
|
@ -0,0 +1,104 @@
|
|||
<?php
|
||||
|
||||
namespace ctiso\Role;
|
||||
use ctiso\Database,
|
||||
ctiso\Database\Statement;
|
||||
|
||||
// Класс должен быть в библиотеке приложения
|
||||
class User implements UserInterface
|
||||
{
|
||||
const LIFE_TIME = 1800; // = 30min * 60sec;
|
||||
|
||||
public $fullname;
|
||||
public $name;
|
||||
public $access;
|
||||
public $password;
|
||||
public $id;
|
||||
public $db;
|
||||
public $groups;
|
||||
|
||||
function __construct($db, $groups) {
|
||||
$this->db = $db;
|
||||
$this->groups = $groups;
|
||||
}
|
||||
|
||||
public function setDB(Database $db) {
|
||||
$this->db = $db;
|
||||
}
|
||||
|
||||
public function getName() {
|
||||
return $this->name;
|
||||
}
|
||||
|
||||
function isLogged() {
|
||||
return \ctiso\Filter\Authorization::isLogged();
|
||||
}
|
||||
|
||||
|
||||
public function getUserByQuery(Statement $stmt)
|
||||
{
|
||||
$result = $stmt->executeQuery();
|
||||
if ($result->next()) {
|
||||
$this->access = $this->groups[$result->getString('access')];
|
||||
$this->name = $result->getString('login');
|
||||
$this->id = $result->getInt('id_user');
|
||||
$this->password = $result->getString('password');
|
||||
$this->fullname = implode(' ', array(
|
||||
$result->getString('surname'),
|
||||
$result->getString('firstname'),
|
||||
$result->getString('patronymic')));
|
||||
return $result;
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
function getUserPassword($result) {
|
||||
return $result->get('password');
|
||||
}
|
||||
|
||||
public function getUserByLogin($login)
|
||||
{
|
||||
$stmt = $this->db->prepareStatement("SELECT * FROM users WHERE login = ?");
|
||||
$stmt->setString(1, $login);
|
||||
$result = $this->getUserByQuery($stmt);
|
||||
if ($result) {
|
||||
$time = time();
|
||||
$id = $this->id;
|
||||
$this->db->executeQuery("UPDATE users SET lasttime = $time WHERE id_user = $id"); // Время входа
|
||||
}
|
||||
return $result;
|
||||
}
|
||||
|
||||
public function getUserById($id)
|
||||
{
|
||||
$stmt = $this->db->prepareStatement("SELECT * FROM users WHERE id_user = ?");
|
||||
$stmt->setInt(1, $_SESSION ['access']);
|
||||
$result = $this->getUserByQuery($stmt);
|
||||
if ($result) {
|
||||
$lasttime = $result->getInt('lasttime');
|
||||
$time = time();
|
||||
if ($time - $lasttime > self::LIFE_TIME) return null; // Вышло время сессии
|
||||
$id = $this->id;
|
||||
}
|
||||
return $result;
|
||||
}
|
||||
|
||||
function setSID($random, $result) {
|
||||
return $this->db->executeQuery("UPDATE users SET sid = '$random', trie_count = 0 WHERE id_user = " . $result->getInt('id_user'));
|
||||
}
|
||||
|
||||
function resetTries($login) {
|
||||
$this->db->executeQuery(
|
||||
"UPDATE users SET trie_count = :count WHERE login = :login",
|
||||
['count' => 0, 'login' => $login]
|
||||
);
|
||||
}
|
||||
|
||||
function updateTries($login) {
|
||||
$user = $this->db->fetchOneArray("SELECT id_user, trie_count FROM users WHERE login = :login", ['login' => $login]);
|
||||
$this->db->executeQuery(
|
||||
"UPDATE users SET trie_time = :cur_time, trie_count = :count WHERE id_user = :id_user",
|
||||
['cur_time' => time(), 'count' => $user['trie_count']+1, 'id_user' => $user['id_user']]
|
||||
);
|
||||
}
|
||||
}
|
||||
12
src/Role/UserInterface.php
Normal file
12
src/Role/UserInterface.php
Normal file
|
|
@ -0,0 +1,12 @@
|
|||
<?php
|
||||
|
||||
namespace ctiso\Role;
|
||||
use ctiso\Database\Statement;
|
||||
|
||||
interface UserInterface {
|
||||
function getUserByQuery(Statement $stmt);
|
||||
function getUserByLogin($login);
|
||||
function getUserById($id);
|
||||
function getName();
|
||||
function setSID($random, $result);
|
||||
}
|
||||
|
|
@ -1,5 +1,7 @@
|
|||
<?php
|
||||
|
||||
namespace ctiso;
|
||||
|
||||
class Security {
|
||||
static function generatePassword($length = 9, $strength = 0) {
|
||||
$vowels = 'aeuy';
|
||||
|
|
|
|||
|
|
@ -1,5 +1,7 @@
|
|||
<?php
|
||||
|
||||
namespace ctiso;
|
||||
|
||||
class Session
|
||||
{
|
||||
function get($key)
|
||||
|
|
|
|||
|
|
@ -1,5 +1,9 @@
|
|||
<?php
|
||||
|
||||
namespace ctiso;
|
||||
use ctiso\File,
|
||||
Exception;
|
||||
|
||||
/**
|
||||
* Класс реестра
|
||||
* Реестр организован как ассоциативный многомерный массив
|
||||
|
|
@ -9,10 +13,12 @@
|
|||
* parameters1, parameters1 - Массивы с параметрами модуля
|
||||
* Имя необходимо чтобы потом легко было удалить ненужные ветки дерева
|
||||
*/
|
||||
class Settings extends Collection
|
||||
class Settings
|
||||
{
|
||||
public $data = [];
|
||||
protected $file;
|
||||
protected $format = 'php';
|
||||
protected $is_read = false;
|
||||
|
||||
public function __construct ($file = null, $format = false)
|
||||
{
|
||||
|
|
@ -30,6 +36,7 @@ class Settings extends Collection
|
|||
public function read()
|
||||
{
|
||||
if (!file_exists ($this->file)) {
|
||||
$this->is_read = true;
|
||||
return false;
|
||||
}
|
||||
// Не include_once т.к читать настройки можно несколько раз
|
||||
|
|
@ -37,13 +44,16 @@ class Settings extends Collection
|
|||
if ($this->format == 'json') {
|
||||
$settings = json_decode(File::getContents($this->file), true);
|
||||
} else {
|
||||
include ($this->file);
|
||||
$settings = include ($this->file);
|
||||
}
|
||||
|
||||
if (!is_array($settings)) {
|
||||
throw new Exception($this->file);
|
||||
throw new Exception('no data in ' . $this->file);
|
||||
}
|
||||
return $this->import($settings);
|
||||
|
||||
$this->is_read = true;
|
||||
$this->data = $settings;
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
@ -88,7 +98,7 @@ class Settings extends Collection
|
|||
|
||||
/**
|
||||
* Чтение ключа из реестра
|
||||
* @param $args Путь к значению ключа
|
||||
* @param mixed $args Путь к значению ключа
|
||||
*/
|
||||
public function readKey(array $key)
|
||||
{
|
||||
|
|
@ -118,7 +128,7 @@ class Settings extends Collection
|
|||
|
||||
/**
|
||||
* Чтение ключа из реестра (Собирает все ключи с определенным значением во всех модулях)
|
||||
* @param $key Путь к значению ключа внутри модуля
|
||||
* @param mixed $key Путь к значению ключа внутри модуля
|
||||
*/
|
||||
public function readKeyList($_rest)
|
||||
{
|
||||
|
|
@ -149,27 +159,58 @@ class Settings extends Collection
|
|||
$name = array_shift($key);
|
||||
unset($data[$name]);
|
||||
}
|
||||
|
||||
public function getOwner()
|
||||
{
|
||||
return array_keys($this->data);
|
||||
}
|
||||
|
||||
/**
|
||||
* Запись настроек в файл (Может переименовать в store)
|
||||
*
|
||||
* @param File $file
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
public function write($file = null)
|
||||
{
|
||||
if (!$this->is_read) {
|
||||
throw new Exception('read settings before write');
|
||||
}
|
||||
|
||||
if ($this->format == 'json') {
|
||||
$result = json_encode($this->data, JSON_PRETTY_PRINT | JSON_UNESCAPED_UNICODE);
|
||||
} else {
|
||||
$result = var_export($this->data, true);
|
||||
$result = "<?php\n\$settings = ".$result.";\n?>";
|
||||
$result = "<?php\nreturn ".$result.";\n?>";
|
||||
}
|
||||
file_put_contents (($file) ? $file : $this->file, $result);
|
||||
}
|
||||
|
||||
public function set($key, $value) {
|
||||
$this->data[$key] = $value;
|
||||
}
|
||||
|
||||
public function get($key, $default = null)
|
||||
{
|
||||
return isset($this->data[$key]) && $this->data[$key] != '' ? $this->data[$key] : $default;
|
||||
}
|
||||
|
||||
function export() {
|
||||
return $this->data;
|
||||
}
|
||||
|
||||
function import($data) {
|
||||
$this->data = $data;
|
||||
}
|
||||
|
||||
/**
|
||||
* Список модулей/ключей
|
||||
*/
|
||||
public function getKeys()
|
||||
{
|
||||
return array_keys($this->data);
|
||||
}
|
||||
|
||||
/**
|
||||
* Проверка наличия ключа
|
||||
*/
|
||||
public function hasKey($name)
|
||||
{
|
||||
return isset($this->data[$name]);
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -7,6 +7,10 @@
|
|||
* $setup->executeActions('install');
|
||||
* </code>
|
||||
*/
|
||||
namespace ctiso;
|
||||
use ZipArchive,
|
||||
ctiso\Tools\SQLStatementExtractor;
|
||||
|
||||
class Setup
|
||||
{
|
||||
protected $actions = array();
|
||||
|
|
@ -119,7 +123,7 @@ class Setup
|
|||
return;
|
||||
}
|
||||
|
||||
$item/*: SimpleXMLElement*/ = $this->stack[count($this->stack) - 1];
|
||||
$item/*: \SimpleXMLElement*/ = $this->stack[count($this->stack) - 1];
|
||||
$root = $item->children();
|
||||
foreach ($root as $node)
|
||||
{
|
||||
|
|
@ -198,7 +202,7 @@ class Setup
|
|||
*/
|
||||
function batchSQLZip($conn/*: Database*/, $file)
|
||||
{
|
||||
$stmtList = Tools_SQLStatementExtractor::extract($this->zip->getFromName($file));
|
||||
$stmtList = SQLStatementExtractor::extract($this->zip->getFromName($file));
|
||||
foreach ($stmtList as $stmt) {
|
||||
$conn->executeQuery ($stmt);
|
||||
}
|
||||
|
|
@ -206,7 +210,7 @@ class Setup
|
|||
|
||||
static function batchSQL($conn/*: Database*/, $file)
|
||||
{
|
||||
$stmtList = Tools_SQLStatementExtractor::extractFile($file);
|
||||
$stmtList = SQLStatementExtractor::extractFile($file);
|
||||
foreach ($stmtList as $stmt) {
|
||||
$conn->executeQuery ($stmt);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,66 +0,0 @@
|
|||
<?php
|
||||
|
||||
/**
|
||||
* Класс для короткого доступа к файлам / папкам
|
||||
*/
|
||||
class Shortcut
|
||||
{
|
||||
static $instance = null;
|
||||
public $variables = array();
|
||||
public $list = array();
|
||||
|
||||
// Singleton pattern
|
||||
static public function getInstance()
|
||||
{
|
||||
if (self::$instance == null) {
|
||||
self::$instance = new Shortcut();
|
||||
}
|
||||
return self::$instance;
|
||||
}
|
||||
|
||||
/**
|
||||
* Добавляет ярлык с именем $prefix
|
||||
* Путь может содержать переменные
|
||||
*/
|
||||
public function addUrl($prefix, $path)
|
||||
{
|
||||
$this->list[$prefix] = $path;
|
||||
}
|
||||
|
||||
/**
|
||||
*
|
||||
*/
|
||||
public function addVar($name, $value)
|
||||
{
|
||||
$this->variables['$' . $name] = $value;
|
||||
}
|
||||
|
||||
/**
|
||||
* Возвращает путь по имени ярлыка
|
||||
*/
|
||||
static function getUrl($prefix, $name = null, $name1 = null)
|
||||
{
|
||||
$shortcut = self::getInstance();
|
||||
|
||||
$names = $shortcut->variables;
|
||||
if ($name) {
|
||||
$names['$name'] = $name;
|
||||
}
|
||||
if ($name1) {
|
||||
$names['$name1'] = $name1;
|
||||
}
|
||||
|
||||
if (isset($shortcut->list[$prefix])) {
|
||||
return strtr($shortcut->list[$prefix], $names);
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
static function expand($path)
|
||||
{
|
||||
$shortcut = self::getInstance();
|
||||
$names = $shortcut->variables;
|
||||
return strtr($path, $names);
|
||||
}
|
||||
|
||||
}
|
||||
|
|
@ -1,5 +1,7 @@
|
|||
<?php
|
||||
|
||||
namespace ctiso;
|
||||
|
||||
class SortRecord
|
||||
{
|
||||
public $key;
|
||||
|
|
|
|||
37
src/TableTree.php
Normal file
37
src/TableTree.php
Normal file
|
|
@ -0,0 +1,37 @@
|
|||
<?php
|
||||
|
||||
/**
|
||||
* Преобразование дерева из модели Plain в массив массивов (Adjacency List)
|
||||
*/
|
||||
|
||||
/**
|
||||
* Обходит таблицу как дерево
|
||||
* $fn ($name, $index, $rows, $cc)
|
||||
* $name Ключ уровня
|
||||
* $index Значение ключа уровня
|
||||
* $rows Все столбцы текущго уровня
|
||||
* $cc Столбцы более низкого уровня
|
||||
*
|
||||
* @param Array $level Уровни вложенности
|
||||
* @param array $table Таблица
|
||||
* @param Function $fn Функция которая применяется к каждой ветке дерева
|
||||
*/
|
||||
namespace ctiso;
|
||||
use ctiso\Functions;
|
||||
|
||||
class TableTree {
|
||||
static function walk($level, $table, $fn) {
|
||||
if (empty ($level)) return $table;
|
||||
$name = array_shift ($level);
|
||||
|
||||
$keys = Functions::key_unique_values($name, $table);
|
||||
$data = array ();
|
||||
foreach ($keys as $index) {
|
||||
list($rows, $table) = Functions::partition (Functions::lcurry(['\ctiso\Functions', '__index'], $index, $name), $table);
|
||||
// $rows = array_filter ($table, lcurry('__index', intval($index), $name));
|
||||
//$rows = array_filter ($table, create_function ('$x', 'return __index ('.intval($index).', \''.$name.'\', $x);'));
|
||||
$data[$index] = call_user_func ($fn, $name, $index, $rows, self::walk ($level, $rows, $fn));
|
||||
}
|
||||
return $data;
|
||||
}
|
||||
}
|
||||
85
src/Tales.php
Normal file
85
src/Tales.php
Normal file
|
|
@ -0,0 +1,85 @@
|
|||
<?php
|
||||
|
||||
/**
|
||||
* Расширения для PHPTAL для отображения времени и даты
|
||||
*/
|
||||
namespace ctiso;
|
||||
use PHPTAL_Php_TalesInternal,
|
||||
ctiso\Controller\SiteInterface,
|
||||
ctiso\Controller\Component,
|
||||
ctiso\HttpRequest,
|
||||
PHPTAL_Tales,
|
||||
PHPTAL_TalesRegistry;
|
||||
|
||||
class Tales_DateTime implements PHPTAL_Tales
|
||||
{
|
||||
static public function date($expression, $nothrow = false) {
|
||||
return "ctiso\\Tales::phptal_date(".PHPTAL_Php_TalesInternal::path($expression).")";
|
||||
}
|
||||
|
||||
static public function time($expression, $nothrow = false) {
|
||||
return "ctiso\\Tales::phptal_time(".PHPTAL_Php_TalesInternal::path($expression).")";
|
||||
}
|
||||
}
|
||||
|
||||
class Tales_Component implements PHPTAL_Tales
|
||||
{
|
||||
static public function component($expression, $nothrow = false)
|
||||
{
|
||||
$s = PHPTAL_Php_TalesInternal::string($expression);
|
||||
return "ctiso\\Tales::phptal_component(" . $s . ")";
|
||||
}
|
||||
}
|
||||
|
||||
class Tales_Assets implements PHPTAL_Tales
|
||||
{
|
||||
static public function assets($expression, $nothrow = false)
|
||||
{
|
||||
$s = PHPTAL_Php_TalesInternal::string($expression);
|
||||
return "ctiso\\Tales::phptal_asset(" . $s . ")";
|
||||
}
|
||||
}
|
||||
|
||||
class Tales {
|
||||
static $site/*: SiteInterface*/;
|
||||
|
||||
static function phptal_date ($e) {
|
||||
return date("d.m.Y", $e);
|
||||
}
|
||||
|
||||
static function phptal_time ($e) {
|
||||
return date("H:i", $e);
|
||||
}
|
||||
|
||||
static function phptal_asset($s) {
|
||||
self::$site->addStyleSheet($s);
|
||||
return "";
|
||||
}
|
||||
|
||||
/**
|
||||
* Функция подключения компонента
|
||||
*/
|
||||
static function phptal_component ($expression) {
|
||||
$begin = floatval(microtime(true));
|
||||
$component/*: Component*/ = null;
|
||||
|
||||
$component = self::$site->loadComponent($expression);
|
||||
$req = new HttpRequest();
|
||||
$result = $component->execute($req);
|
||||
|
||||
echo "<!-- ", $expression, ", ", round(floatval(microtime(true)) - $begin, 4), "sec -->";
|
||||
return $result;
|
||||
}
|
||||
|
||||
|
||||
static function register($site) {
|
||||
self::$site = $site;
|
||||
|
||||
/* Регистрация нового префикса для подключения компонента */
|
||||
$tales = PHPTAL_TalesRegistry::getInstance();
|
||||
$tales->registerPrefix('component', array('ctiso\\Tales_Component', 'component'));
|
||||
$tales->registerPrefix('date', array('ctiso\\Tales_DateTime', 'date'));
|
||||
$tales->registerPrefix('time', array('ctiso\\Tales_DateTime', 'time'));
|
||||
$tales->registerPrefix('assets', array('ctiso\\Tales_Assets', 'assets'));
|
||||
}
|
||||
}
|
||||
|
|
@ -1,6 +1,8 @@
|
|||
<?php
|
||||
|
||||
class Tools_Drawing
|
||||
namespace ctiso\Tools;
|
||||
|
||||
class Drawing
|
||||
{
|
||||
const ALIGN_LEFT = "left";
|
||||
const ALIGN_TOP = "top";
|
||||
|
|
@ -40,7 +42,8 @@ class Tools_Drawing
|
|||
$first_word = true;
|
||||
|
||||
$last_width = 0;
|
||||
for ($i = 0; $i < count($words); $i++) {
|
||||
$count = count($words);
|
||||
for ($i = 0; $i < $count; $i++) {
|
||||
$item = $words[$i];
|
||||
$dimensions = imagettfbbox($size, $angle, $font, $current_line . ($first_word ? '' : ' ') . $item);
|
||||
$line_width = $dimensions[2] - $dimensions[0];
|
||||
|
|
|
|||
|
|
@ -1,7 +1,9 @@
|
|||
<?php
|
||||
|
||||
class Tools_Image
|
||||
{
|
||||
namespace ctiso\Tools;
|
||||
|
||||
class Image
|
||||
{
|
||||
static function load($uri)
|
||||
{
|
||||
$e = strtolower(pathinfo($uri, PATHINFO_EXTENSION));
|
||||
|
|
|
|||
|
|
@ -26,7 +26,10 @@
|
|||
* @version $Revision: 1.5 $
|
||||
* @package creole.util.sql
|
||||
*/
|
||||
class Tools_SQLStatementExtractor {
|
||||
namespace ctiso\Tools;
|
||||
use Exception;
|
||||
|
||||
class SQLStatementExtractor {
|
||||
|
||||
protected static $delimiter = ';';
|
||||
|
||||
|
|
|
|||
|
|
@ -1,6 +1,8 @@
|
|||
<?php
|
||||
|
||||
class Tools_String {
|
||||
namespace ctiso\Tools;
|
||||
|
||||
class StringUtil {
|
||||
|
||||
// from creole
|
||||
static function strToArray($str) {
|
||||
|
|
@ -3,7 +3,10 @@
|
|||
/**
|
||||
* Формат для композиции изображений
|
||||
*/
|
||||
class Tools_TemplateImage
|
||||
namespace ctiso\Tools;
|
||||
use ctiso\Tools\Drawing;
|
||||
|
||||
class TemplateImage
|
||||
{
|
||||
static $listfiles = array('jpg' => 'jpeg', 'gif' => 'gif', 'png' => 'png', 'bmp' => 'wbmp');
|
||||
static $listfonts = array(
|
||||
|
|
@ -33,15 +36,18 @@ class Tools_TemplateImage
|
|||
protected $data = array();
|
||||
protected $base = "c:\\windows\\fonts\\";
|
||||
protected $image;
|
||||
protected $prepare = true;
|
||||
protected $_prepare = true;
|
||||
public $debug = false;
|
||||
public $filename;
|
||||
public $resource;
|
||||
|
||||
function __construct ($template = false)
|
||||
public $resource;
|
||||
public $filename;
|
||||
|
||||
function __construct ($template = null)
|
||||
{
|
||||
// assert(is_string($src));
|
||||
if($template) {
|
||||
if ($template) {
|
||||
$this->data = $template;
|
||||
}
|
||||
}
|
||||
|
|
@ -118,7 +124,7 @@ class Tools_TemplateImage
|
|||
return "";
|
||||
}
|
||||
|
||||
function imageText($text, $value/*: stdClass*/)
|
||||
function imageText($text, $value/*: \stdClass*/)
|
||||
{
|
||||
assert(is_string($text));
|
||||
|
||||
|
|
@ -127,23 +133,23 @@ class Tools_TemplateImage
|
|||
$fontfile = $this->getFontFile($value->fontFamily . $this->fontSuffix($value->fontStyle));
|
||||
|
||||
$color = intval(substr($value->color, 1), 16);
|
||||
if ($value->align[0]) {
|
||||
$align = Tools_Drawing::ALIGN_LEFT;
|
||||
} elseif ($value->align[2]) {
|
||||
$align = Tools_Drawing::ALIGN_RIGHT;
|
||||
if ($value->align[0]) {
|
||||
$align = Drawing::ALIGN_LEFT;
|
||||
} elseif ($value->align[2]) {
|
||||
$align = Drawing::ALIGN_RIGHT;
|
||||
} else {
|
||||
$align = Tools_Drawing::ALIGN_CENTER;
|
||||
$align = Drawing::ALIGN_CENTER;
|
||||
}
|
||||
|
||||
if ($value->valign[0]) {
|
||||
$valign = Tools_Drawing::ALIGN_TOP;
|
||||
} elseif ($value->valign[1]) {
|
||||
$valign = Tools_Drawing::ALIGN_CENTER;
|
||||
if ($value->valign[0]) {
|
||||
$valign = Drawing::ALIGN_TOP;
|
||||
} elseif ($value->valign[1]) {
|
||||
$valign = Drawing::ALIGN_CENTER;
|
||||
} else {
|
||||
$valign = Tools_Drawing::ALIGN_BOTTOM;
|
||||
$valign = Drawing::ALIGN_BOTTOM;
|
||||
}
|
||||
|
||||
Tools_Drawing::imagettftextbox($this->image, $size, 0, $value->left, $value->top, $color, $fontfile, $text,
|
||||
Drawing::imagettftextbox($this->image, $size, 0, $value->left, $value->top, $color, $fontfile, $text,
|
||||
$value->width, $value->height,
|
||||
$align, $valign);
|
||||
}
|
||||
|
|
@ -161,7 +167,7 @@ class Tools_TemplateImage
|
|||
{
|
||||
$width = imagesx($this->image);
|
||||
$height = imagesy($this->image);
|
||||
if($new_height == false) {
|
||||
if ($new_height == null) {
|
||||
$new_height = ceil($height * $new_width / $width);
|
||||
}
|
||||
|
||||
|
|
@ -173,8 +179,8 @@ class Tools_TemplateImage
|
|||
}
|
||||
|
||||
function prepare() {
|
||||
if($this->prepare) {
|
||||
$this->prepare = false;
|
||||
if($this->_prepare) {
|
||||
$this->_prepare = false;
|
||||
foreach ($this->data as $value) {
|
||||
$this->imageText($value->text, $value); // break;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,5 +1,7 @@
|
|||
<?php
|
||||
|
||||
namespace ctiso;
|
||||
|
||||
class UTF8 {
|
||||
static function str_split($str, $split_length = 1) {
|
||||
$split_length = (int) $split_length;
|
||||
|
|
|
|||
27
src/Url.php
Normal file
27
src/Url.php
Normal file
|
|
@ -0,0 +1,27 @@
|
|||
<?php
|
||||
|
||||
namespace ctiso;
|
||||
|
||||
class Url {
|
||||
public $parts = [];
|
||||
public $parent/*: Url*/;
|
||||
|
||||
function __construct() {
|
||||
}
|
||||
|
||||
function setParent($parent) {
|
||||
$this->parent = $parent;
|
||||
}
|
||||
|
||||
function setQuery($parts) {
|
||||
$this->parts = $parts;
|
||||
}
|
||||
|
||||
function addQueryParam($key, $value) {
|
||||
$this->parts[$key] = $value;
|
||||
}
|
||||
|
||||
function toString() {
|
||||
return '?' . http_build_query(array_merge($this->parts, $this->parent ? $this->parent->parts : []));
|
||||
}
|
||||
}
|
||||
|
|
@ -1,14 +1,11 @@
|
|||
<?php
|
||||
/**
|
||||
* UserMessageException.php
|
||||
*
|
||||
*/
|
||||
|
||||
/**
|
||||
* Исключение с понятным пользователю сообщением, которое имеет смысл ему показать.
|
||||
* @see Controller_Front
|
||||
*/
|
||||
class UserMessageException extends Exception {
|
||||
namespace ctiso;
|
||||
|
||||
class UserMessageException extends \Exception {
|
||||
public $userMessage;
|
||||
public function __construct($message) {
|
||||
parent::__construct($message);
|
||||
|
|
|
|||
|
|
@ -1,6 +1,9 @@
|
|||
<?php
|
||||
|
||||
abstract class Validator_Rule_Abstract
|
||||
namespace ctiso\Validator\Rule;
|
||||
use ctiso\Collection;
|
||||
|
||||
abstract class AbstractRule
|
||||
{
|
||||
public $field;
|
||||
protected $errorMsg;
|
||||
|
|
@ -3,7 +3,11 @@
|
|||
/**
|
||||
* Проверка на число
|
||||
*/
|
||||
class Validator_Rule_Alpha extends Validator_Rule_Abstract
|
||||
namespace ctiso\Validator\Rule;
|
||||
use ctiso\Validator\Rule\AbstractRule,
|
||||
ctiso\Collection;
|
||||
|
||||
class Alpha extends AbstractRule
|
||||
{
|
||||
public function getErrorMsg()
|
||||
{
|
||||
|
|
|
|||
|
|
@ -3,7 +3,11 @@
|
|||
/**
|
||||
* Проверка формата электронной почты
|
||||
*/
|
||||
class Validator_Rule_Code extends Validator_Rule_Abstract
|
||||
namespace ctiso\Validator\Rule;
|
||||
use ctiso\Validator\Rule\AbstractRule,
|
||||
ctiso\Collection;
|
||||
|
||||
class Code extends AbstractRule
|
||||
{
|
||||
public function getErrorMsg()
|
||||
{
|
||||
|
|
@ -25,7 +29,8 @@ class Validator_Rule_Code extends Validator_Rule_Abstract
|
|||
$name = $this->field;
|
||||
|
||||
if (is_array($_POST[$name . '_code_genre'])) {
|
||||
for($n = 0; $n < count($_POST[$name . '_code_genre']); $n++) {
|
||||
$count = count($_POST[$name . '_code_genre']);
|
||||
for($n = 0; $n < $count; $n++) {
|
||||
$code = array(
|
||||
$_POST[$name . '_code_genre'][$n],
|
||||
$_POST[$name . '_code_f'][$n],
|
||||
|
|
|
|||
|
|
@ -3,10 +3,14 @@
|
|||
/**
|
||||
* Проверка формата даты
|
||||
*/
|
||||
class Validator_Rule_Count extends Validator_Rule_Abstract
|
||||
namespace ctiso\Validator\Rule;
|
||||
use ctiso\Validator\Rule\AbstractRule,
|
||||
ctiso\Collection;
|
||||
|
||||
class Count extends AbstractRule
|
||||
{
|
||||
public $size = 1;
|
||||
public $max = false;
|
||||
public $max = null;
|
||||
|
||||
public function getErrorMsg()
|
||||
{
|
||||
|
|
@ -26,7 +30,7 @@ class Validator_Rule_Count extends Validator_Rule_Abstract
|
|||
$count = count(array_filter(array_map('trim',
|
||||
explode(";", $container->get($this->field))), array($this, 'not_empty')));
|
||||
|
||||
return $count >= $this->size && $count <= $this->max;
|
||||
return $count >= $this->size && $count <= ((int)$this->max);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -3,7 +3,11 @@
|
|||
/**
|
||||
* Проверка формата даты
|
||||
*/
|
||||
class Validator_Rule_Date extends Validator_Rule_Abstract
|
||||
namespace ctiso\Validator\Rule;
|
||||
use ctiso\Validator\Rule\AbstractRule,
|
||||
ctiso\Collection;
|
||||
|
||||
class Date extends AbstractRule
|
||||
{
|
||||
private $split = "\\/";
|
||||
|
||||
|
|
|
|||
|
|
@ -3,7 +3,11 @@
|
|||
/**
|
||||
* Проверка формата электронной почты
|
||||
*/
|
||||
class Validator_Rule_Email extends Validator_Rule_Abstract
|
||||
namespace ctiso\Validator\Rule;
|
||||
use ctiso\Validator\Rule\AbstractRule,
|
||||
ctiso\Collection;
|
||||
|
||||
class Email extends AbstractRule
|
||||
{
|
||||
public function getErrorMsg()
|
||||
{
|
||||
|
|
|
|||
|
|
@ -3,7 +3,11 @@
|
|||
/**
|
||||
* Проверка формата электронной почты
|
||||
*/
|
||||
class Validator_Rule_EmailList extends Validator_Rule_Abstract
|
||||
namespace ctiso\Validator\Rule;
|
||||
use ctiso\Validator\Rule\AbstractRule,
|
||||
ctiso\Collection;
|
||||
|
||||
class EmailList extends AbstractRule
|
||||
{
|
||||
public function getErrorMsg()
|
||||
{
|
||||
|
|
|
|||
|
|
@ -1,6 +1,11 @@
|
|||
<?php
|
||||
|
||||
class Validator_Rule_FileName extends Validator_Rule_Abstract {
|
||||
namespace ctiso\Validator\Rule;
|
||||
use ctiso\Validator\Rule\AbstractRule,
|
||||
ctiso\Collection,
|
||||
ctiso\Path;
|
||||
|
||||
class FileName extends AbstractRule {
|
||||
|
||||
public function getErrorMsg()
|
||||
{
|
||||
|
|
|
|||
|
|
@ -3,7 +3,11 @@
|
|||
/**
|
||||
* Проверка формата времени
|
||||
*/
|
||||
class Validator_Rule_IsFile extends Validator_Rule_Abstract
|
||||
namespace ctiso\Validator\Rule;
|
||||
use ctiso\Validator\Rule\AbstractRule,
|
||||
ctiso\Collection;
|
||||
|
||||
class IsFile extends AbstractRule
|
||||
{
|
||||
private $type = array();
|
||||
private $maxsize = 1024;
|
||||
|
|
|
|||
|
|
@ -3,7 +3,11 @@
|
|||
/**
|
||||
* Проверка на равентство двух полей
|
||||
*/
|
||||
class Validator_Rule_Match extends Validator_Rule_Abstract
|
||||
namespace ctiso\Validator\Rule;
|
||||
use ctiso\Validator\Rule\AbstractRule,
|
||||
ctiso\Collection;
|
||||
|
||||
class MatchRule extends AbstractRule
|
||||
{
|
||||
public $same;
|
||||
|
||||
|
|
@ -1,6 +1,10 @@
|
|||
<?php
|
||||
|
||||
class Validator_Rule_Notnull extends Validator_Rule_Abstract
|
||||
namespace ctiso\Validator\Rule;
|
||||
use ctiso\Validator\Rule\AbstractRule,
|
||||
ctiso\Collection;
|
||||
|
||||
class Notnull extends AbstractRule
|
||||
{
|
||||
function skipEmpty() {
|
||||
return false;
|
||||
|
|
|
|||
|
|
@ -3,7 +3,11 @@
|
|||
/**
|
||||
* Проверка на число
|
||||
*/
|
||||
class Validator_Rule_Numeric extends Validator_Rule_Abstract
|
||||
namespace ctiso\Validator\Rule;
|
||||
use ctiso\Validator\Rule\AbstractRule,
|
||||
ctiso\Collection;
|
||||
|
||||
class Numeric extends AbstractRule
|
||||
{
|
||||
public function getErrorMsg()
|
||||
{
|
||||
|
|
|
|||
|
|
@ -3,7 +3,11 @@
|
|||
/**
|
||||
* Проверка формата времени
|
||||
*/
|
||||
class Validator_Rule_Time extends Validator_Rule_Abstract
|
||||
namespace ctiso\Validator\Rule;
|
||||
use ctiso\Validator\Rule\AbstractRule,
|
||||
ctiso\Collection;
|
||||
|
||||
class Time extends AbstractRule
|
||||
{
|
||||
private $split = ":";
|
||||
|
||||
|
|
@ -23,7 +27,7 @@ class Validator_Rule_Time extends Validator_Rule_Abstract
|
|||
{
|
||||
$tmp = explode($this->split, $container->get($this->field), 2);
|
||||
if ($tmp) {
|
||||
if (self::checktime ($tmp[0], $tmp[1])) {
|
||||
if (self::checktime ((int)$tmp[0], (int)$tmp[1])) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -2,7 +2,11 @@
|
|||
|
||||
/**
|
||||
*/
|
||||
class Validator_Rule_Unique extends Validator_Rule_Abstract
|
||||
namespace ctiso\Validator\Rule;
|
||||
use ctiso\Validator\Rule\AbstractRule,
|
||||
ctiso\Collection;
|
||||
|
||||
class Unique extends AbstractRule
|
||||
{
|
||||
public function getErrorMsg()
|
||||
{
|
||||
|
|
|
|||
|
|
@ -3,41 +3,49 @@
|
|||
///<reference path="Rule/Notnull.php"/>
|
||||
|
||||
/**
|
||||
* Проверка коллекции
|
||||
* Проверка коллекции
|
||||
*/
|
||||
class Validator_Validator
|
||||
namespace ctiso\Validator;
|
||||
use Exception,
|
||||
ctiso\Validator\Rule\AbstractRule,
|
||||
ctiso\Collection;
|
||||
|
||||
class Validator
|
||||
{
|
||||
protected $chain = array(); // Массив правил
|
||||
protected $errorMsg = array(); // Массив ошибок
|
||||
protected $type = array(
|
||||
'date' => 'ctiso\\Validator\\Rule\\Date',
|
||||
'email' => 'ctiso\\Validator\\Rule\\Email',
|
||||
'emaillist'=> 'ctiso\\Validator\\Rule\\EmailList',
|
||||
'match' => 'ctiso\\Validator\\Rule\\MatchRule',
|
||||
'time' => 'ctiso\\Validator\\Rule\\Time',
|
||||
'alpha' => 'ctiso\\Validator\\Rule\\Alpha',
|
||||
'require' => 'ctiso\\Validator\\Rule\\Notnull',
|
||||
'numeric' => 'ctiso\\Validator\\Rule\\Numeric',
|
||||
'unique' => 'ctiso\\Validator\\Rule\\Unique',
|
||||
'filename' => 'ctiso\\Validator\\Rule\\FileName',
|
||||
'count' => 'ctiso\\Validator\\Rule\\Count',
|
||||
'isfile' => 'ctiso\\Validator\\Rule\\IsFile',
|
||||
'code' => 'ctiso\\Validator\\Rule\\Code'
|
||||
);
|
||||
|
||||
function __construct($rules = array()) {
|
||||
$this->addRuleList($rules);
|
||||
}
|
||||
|
||||
function addRuleType($name, $className) {
|
||||
$this->type[$name] = $className;
|
||||
}
|
||||
|
||||
/**
|
||||
* Добавление списка правил в специальном формате
|
||||
* array(array('name' => fieldname, 'validate' => ruletext), ...)
|
||||
* fieldname - Имя переменой для проверки
|
||||
* fieldname - Имя переменой для проверки
|
||||
* ruletext - Описание правила см. формат правила ниже
|
||||
*/
|
||||
public function addRuleList(array $input)
|
||||
{
|
||||
$type = array(
|
||||
'date' => 'Validator_Rule_Date',
|
||||
'email' => 'Validator_Rule_Email',
|
||||
'emaillist'=> 'Validator_Rule_EmailList',
|
||||
'match' => 'Validator_Rule_Match',
|
||||
'time' => 'Validator_Rule_Time',
|
||||
'alpha' => 'Validator_Rule_Alpha',
|
||||
'require' => 'Validator_Rule_Notnull',
|
||||
'numeric' => 'Validator_Rule_Numeric',
|
||||
'unique' => 'Validator_Rule_Unique',
|
||||
'filename' => 'Validator_Rule_FileName',
|
||||
'count' => 'Validator_Rule_Count',
|
||||
'isfile' => 'Validator_Rule_IsFile',
|
||||
'code' => 'Validator_Rule_Code'
|
||||
);
|
||||
|
||||
// Разбор правила проверки
|
||||
// Формат правила 'rule1|rule2,param1=value1|rule3,param1=value1,param2=value2'
|
||||
foreach ($input as $value) {
|
||||
|
|
@ -50,8 +58,8 @@ class Validator_Validator
|
|||
$rule_param = explode(",", $rule);
|
||||
$name = array_shift($rule_param);
|
||||
|
||||
if (isset($type[$name])) {
|
||||
$constructor = $type[$name];
|
||||
if (isset($this->type[$name])) {
|
||||
$constructor = $this->type[$name];
|
||||
$ruleObj = new $constructor($value['name'], false); // Нужны шаблонные сообщения для правил
|
||||
if (isset($value['context'])) {
|
||||
$ruleObj->setContext($value['context']);
|
||||
|
|
@ -76,8 +84,8 @@ class Validator_Validator
|
|||
$this->chain[] = $rule;
|
||||
}
|
||||
}
|
||||
|
||||
public function skip($rule/*: Validator_Rule_Abstract*/, $container/*: Collection*/) // -> Rule_Abstract
|
||||
|
||||
public function skip($rule/*: AbstractRule*/, $container/*: Collection*/) // -> Rule_Abstract
|
||||
{
|
||||
if ($rule->skipEmpty()) {
|
||||
$data = $container->get($rule->field);
|
||||
|
|
@ -85,10 +93,10 @@ class Validator_Validator
|
|||
$value = trim($data);
|
||||
return $value == '';
|
||||
}
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
public function validate(Collection $container, $rule = null, $status = null)
|
||||
{
|
||||
$fields = array();
|
||||
|
|
|
|||
|
|
@ -4,9 +4,14 @@
|
|||
*/
|
||||
|
||||
// View_Base + PHPTAL = View_Template (View_Composite)
|
||||
class View_Composite extends View_View
|
||||
namespace ctiso\View;
|
||||
use ctiso\View\View,
|
||||
PHPTAL;
|
||||
|
||||
class Composite extends View
|
||||
{
|
||||
private $tal;
|
||||
public $config;
|
||||
|
||||
function __construct($file)
|
||||
{
|
||||
|
|
@ -14,7 +19,7 @@ class View_Composite extends View_View
|
|||
|
||||
$this->tal = new PHPTAL($file);
|
||||
$this->tal->setPhpCodeDestination(PHPTAL_PHP_CODE_DESTINATION);
|
||||
$this->tal->setEncoding(PHPTAL_DEFAULT_ENCODING); // PHPTAL_DEFAULT_ENCODING !!
|
||||
$this->tal->setEncoding(PHPTAL_DEFAULT_ENCODING);
|
||||
$this->tal->setTemplateRepository(PHPTAL_TEMPLATE_REPOSITORY);
|
||||
$this->tal->setOutputMode(PHPTAL::HTML5);
|
||||
$this->tal->stripComments(true);
|
||||
|
|
@ -35,7 +40,6 @@ class View_Composite extends View_View
|
|||
function execute()
|
||||
{
|
||||
parent::execute();
|
||||
// postProcess
|
||||
return $this->tal->execute();
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -1,6 +1,9 @@
|
|||
<?php
|
||||
|
||||
class View_List extends View_View
|
||||
namespace ctiso\View;
|
||||
use ctiso\View\View;
|
||||
|
||||
class ListView extends View
|
||||
{
|
||||
function execute()
|
||||
{
|
||||
Some files were not shown because too many files have changed in this diff Show more
Loading…
Add table
Add a link
Reference in a new issue