Merge branch 'master' into noglob

This commit is contained in:
origami11@yandex.ru 2022-11-18 16:07:32 +03:00
commit 7d35a8f3f0
27 changed files with 430 additions and 288 deletions

View file

@ -88,6 +88,11 @@ class Component
} }
} }
public function getTemplateName($_registry/*: Settings*/) {
return (isset($_COOKIE['with_template']) && preg_match('/^[\w\d-]{3,20}$/', $_COOKIE['with_template']))
? $_COOKIE['with_template'] : ($_registry ? $_registry->get('site', 'template') : 'modern');
}
public function getView($name) public function getView($name)
{ {
if ($this->output == 'json') { if ($this->output == 'json') {
@ -96,12 +101,13 @@ class Component
$config/*: Registry*/ = $this->config; $config/*: Registry*/ = $this->config;
$default = $config->get('site', 'template'); $default = $config->get('site', 'template');
$template = ($this->template) ? $this->template : $default; $template = ($this->template) ? $this->template : $this->getTemplateName($config);
$selected = null; $selected = null;
foreach ($this->viewPath as $index => $viewPath) { foreach ($this->viewPath as $index => $viewPath) {
// Загружать шаблон по умолчанию если не найден текущий // Загружать шаблон по умолчанию если не найден текущий
if(is_dir(Path::join($this->viewPath[$index], 'templates', $template))) { $dir = Path::join($this->viewPath[$index], 'templates', $template);
if(is_dir($dir)) {
$tpl = new PHPTAL(Path::join($this->viewPath[$index], 'templates', $template, $name)); $tpl = new PHPTAL(Path::join($this->viewPath[$index], 'templates', $template, $name));
$tpl->setPhpCodeDestination(PHPTAL_PHP_CODE_DESTINATION); $tpl->setPhpCodeDestination(PHPTAL_PHP_CODE_DESTINATION);
$selected = $index; $selected = $index;
@ -110,10 +116,11 @@ class Component
} }
if ($selected === null) { if ($selected === null) {
$tpl = new PHPTAL(Path::join($this->viewPath[0], 'templates', 'modern', $name)); // Последний вариант viewPath, путь к папке компонента
$selected = count($this->viewPath) - 1;
$tpl = new PHPTAL(Path::join($this->viewPath[$selected], 'templates', 'modern', $name));
$tpl->setPhpCodeDestination(PHPTAL_PHP_CODE_DESTINATION); $tpl->setPhpCodeDestination(PHPTAL_PHP_CODE_DESTINATION);
$template = 'modern'; $template = 'modern';
$selected = 0;
} }
$tpl->stripComments(true); $tpl->stripComments(true);
@ -135,13 +142,26 @@ class Component
return $tpl; return $tpl;
} }
function _getDefaultPath() {
return $this->viewPath[count($this->viewPath) - 1];
}
public function getTemplatePath($name) { public function getTemplatePath($name) {
return Path::join($this->viewPath[0], 'templates', 'modern', $name); $registry/*: Settings*/ = $this->config;
// Брать настройки из куков если есть
$template = ($this->template) ? $this->template : $this->getTemplateName($registry);
foreach ($this->viewPath as $index => $viewPath) {
if(is_dir(Path::join($this->viewPath[$index], 'templates', $template))) {
return Path::join($this->viewPath[$index], 'templates', $template, $name);
}
}
return Path::join($this->viewPath[count($this->viewPath) - 1], 'templates', 'modern', $name);
} }
public function getTemplateWebPath() public function getTemplateWebPath()
{ {
return Path::join($this->webPath[0], 'templates', 'modern'); return Path::join($this->webPath[count($this->webPath) - 1], 'templates', 'modern');
} }
/** /**
@ -184,7 +204,7 @@ class Component
} }
function getInfo() { function getInfo() {
$filename = $this->findFile($this->viewPath, 'install.json'); $filename = Path::join($this->viewPath[count($this->viewPath) - 1], 'install.json');
if (file_exists($filename)) { if (file_exists($filename)) {
$settings = json_decode(File::getContents($filename), true); $settings = json_decode(File::getContents($filename), true);
return $settings; return $settings;
@ -224,7 +244,7 @@ class Component
} }
$name = $path; $name = $path;
$path = Path::join ($this->config->get('site', 'path'), 'components', $name, $name . '.php'); $path = Path::join ($site->config->get('site', 'path'), 'components', $name, $name . '.php');
$className = 'Component_' . $name; $className = 'Component_' . $name;
$component/*: Component*/ = null; $component/*: Component*/ = null;
@ -233,19 +253,37 @@ class Component
require_once ($path); require_once ($path);
$component = new $className(); $component = new $className();
$component->viewPath = array($this->config->get('site', 'path') . '/components/' . $name . '/'); $component->viewPath = array($site->config->get('site', 'path') . '/components/' . $name . '/');
$component->webPath = array($this->config->get('site', 'web') . '/components/' . $name); $component->webPath = array($site->config->get('site', 'web') . '/components/' . $name);
$component->COMPONENTS_WEB = $this->config->get('site', 'web') . '/components/'; $component->COMPONENTS_WEB = $site->config->get('site', 'web') . '/components/';
} else { } else {
$path = Path::join ($this->config->get('system', 'components'), $name, $name . '.php'); $path = Path::join ($site->config->get('system', 'components'), $name, $name . '.php');
require_once ($path); require_once ($path);
$component = new $className(); $component = new $className();
$component->viewPath = array($this->config->get('system', 'components') . '/' . $name . '/', $this->config->get('site', 'path') . '/components/' . $name . '/'); $template = $component->getTemplateName($registry);
$component->viewPath = array(
// Сначало ищем локально
$site->config->get('site', 'path') . '/templates/' . $template . '/_components/' . $name . '/',
$site->config->get('site', 'path') . '/components/' . $name . '/',
// Потом в общем хранилище
CMS_PATH . '/../templates/' . $template . '/_components/' . $name . '/',
$site->config->get('system', 'components') . '/' . $name . '/',
);
if (defined('COMPONENTS_WEB')) { if (defined('COMPONENTS_WEB')) {
$component->webPath = array($this->config->get('system', 'components_web') . '/' . $name, $this->config->get('site', 'web') . '/components/' . $name); $component->webPath = array(
$component->COMPONENTS_WEB = $this->config->get('system', 'components_web'); // Сначало локально
$site->config->get('site', 'web') . '/templates/' . $template . '/_components/' . $name,
$site->config->get('site', 'web') . '/components/' . $name,
// Потом в общем хранилище
TEMPLATE_WEB . '/' . $template . '/_components/' . $name,
COMPONENTS_WEB . '/' . $name,
);
$component->COMPONENTS_WEB = COMPONENTS_WEB;
} else {
$component->webPath = array('', $site->config->get('site', 'web') . '/components/' . $name, '');
} }
} }

View file

@ -41,7 +41,7 @@ class Front extends Action
/** /**
* Создает экземпляр модуля и выполняет действия для него * Создает экземпляр модуля и выполняет действия для него
* @param string $name Имя модуля * @param string $name Имя модуля
* @param request $request Имя модуля * @param Request $request Имя модуля
* @return string * @return string
*/ */
public function loadModule($name, Collection $request, $controller = null) public function loadModule($name, Collection $request, $controller = null)
@ -55,8 +55,6 @@ class Front extends Action
$moulesPath = Path::join($config->get('system', 'path'), 'modules'); $moulesPath = Path::join($config->get('system', 'path'), 'modules');
$logPath = Path::join($config->get('site', 'path'), $config->get('system', 'access.log')); $logPath = Path::join($config->get('site', 'path'), $config->get('system', 'access.log'));
$moduleFile = Path::join($moulesPath, $name, 'classes', $controller ? $controller : $name);
$ucname = ucfirst($name); $ucname = ucfirst($name);
$moduleClass = "Modules\\$ucname\\$ucname"; $moduleClass = "Modules\\$ucname\\$ucname";
$module = new $moduleClass(); $module = new $moduleClass();

View file

@ -12,7 +12,7 @@ class Request {
$this->id = $id; $this->id = $id;
} }
function get($name, $def) { function get($name, $def = null) {
$v = $this->r->get($name); $v = $this->r->get($name);
$id = $this->id; $id = $this->id;
if ($id && is_array($v)) { if ($id && is_array($v)) {

View file

@ -5,6 +5,7 @@
*/ */
namespace ctiso\Controller; namespace ctiso\Controller;
use ctiso\Path, use ctiso\Path,
ctiso\File,
ctiso\Registry, ctiso\Registry,
ctiso\Database\PDOStatement; ctiso\Database\PDOStatement;
@ -30,7 +31,7 @@ class Service
} }
/** /**
* @param $name Имя модели * @param string $name Имя модели
*/ */
private function getModelPath($name) private function getModelPath($name)
{ {
@ -40,7 +41,7 @@ class Service
/** /**
* Создает модель * Создает модель
* @param string $name * @param string $name
* @return model * @return Model
*/ */
public function getModel($name) public function getModel($name)
{ {
@ -66,5 +67,14 @@ class Service
} }
return $result; return $result;
} }
function getInfo() {
$filename = Path::join($this->viewPath[0], 'install.json');
if (file_exists($filename)) {
$settings = json_decode(File::getContents($filename), true);
return $settings;
}
return array();
}
} }

View file

@ -18,7 +18,7 @@ use PDO,
/** /**
* Класс оболочка для PDO для замены Creole * Класс оболочка для PDO для замены Creole
*/ */
class Database extends PDO class Database/*<Database_PDOStatement>*/ extends PDO
{ {
public $dsn; public $dsn;
@ -26,9 +26,15 @@ class Database extends PDO
{ {
parent::__construct($dsn, $username, $password); parent::__construct($dsn, $username, $password);
$this->setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION); $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('ctiso\\Database\\PDOStatement', array())); $this->setAttribute(PDO::ATTR_STATEMENT_CLASS, array('ctiso\\Database\\PDOStatement', array()));
} }
function prepare($sql, $args = []) {
$result/*: PDOStatement*/ = parent::prepare($sql, $args);
return $result;
}
public function getDSN() public function getDSN()
{ {
return $this->dsn; return $this->dsn;
@ -48,6 +54,10 @@ class Database extends PDO
if ($dsn['phptype'] == 'pgsql') { if ($dsn['phptype'] == 'pgsql') {
$connection->query('SET client_encoding="UTF-8"'); $connection->query('SET client_encoding="UTF-8"');
} }
if (isset($dsn['schema'])) {
$connection->query('SET search_path TO ' . $dsn['schema']);
}
} }
if ($dsn['phptype'] == 'sqlite') { if ($dsn['phptype'] == 'sqlite') {
$connection/*: Database*/ = new static("{$dsn['phptype']}:{$dsn['database']}"); $connection/*: Database*/ = new static("{$dsn['phptype']}:{$dsn['database']}");
@ -133,7 +143,6 @@ class Database extends PDO
$sql = "INSERT INTO $table (" . implode(",", array_keys($values)) $sql = "INSERT INTO $table (" . implode(",", array_keys($values))
. ") VALUES (" . implode(",", array_keys($prep)). ")"; . ") VALUES (" . implode(",", array_keys($prep)). ")";
if ($return_id) { if ($return_id) {
if ($this->isPostgres()){ if ($this->isPostgres()){
$sql = $sql." RETURNING $index"; $sql = $sql." RETURNING $index";
@ -181,11 +190,6 @@ class Database extends PDO
return $result['nextval']; return $result['nextval'];
} }
function prepare($query, $options = NULL) {
$result/*: PDOStatement*/ = parent::prepare($query);
return $result;
}
function close() { function close() {
return null; return null;
} }

View file

@ -12,7 +12,7 @@ class PDOStatement extends \PDOStatement implements \IteratorAggregate
public $cache = array(); public $cache = array();
public $fields; public $fields;
function getIterator() { function getIterator(): Iterator {
return new StatementIterator($this); return new StatementIterator($this);
} }
@ -72,6 +72,9 @@ class PDOStatement extends \PDOStatement implements \IteratorAggregate
} }
function getInt($name) { function getInt($name) {
if (!$this->fields) {
throw new Error('no fields');
}
return (int)$this->fields[$name]; return (int)$this->fields[$name];
} }
@ -80,7 +83,7 @@ class PDOStatement extends \PDOStatement implements \IteratorAggregate
} }
function getString($name) { function getString($name) {
return $this->fields[$name]; return isset($this->fields[$name]) ? $this->fields[$name]: null;
} }
function getBoolean($name) { function getBoolean($name) {
@ -98,4 +101,10 @@ class PDOStatement extends \PDOStatement implements \IteratorAggregate
function getRecordCount() { function getRecordCount() {
return count($this->cache); return count($this->cache);
} }
function execute($args = null) {
$result = parent::execute($args);
return $result;
}
} }

View file

@ -21,33 +21,27 @@ class Statement
$this->conn = $conn; $this->conn = $conn;
} }
function setInt($n, $value) function setInt($n, $value) {
{
$this->binds [] = array($n, $value, PDO::PARAM_INT); $this->binds [] = array($n, $value, PDO::PARAM_INT);
} }
function setString($n, $value) function setString($n, $value) {
{
$this->binds [] = array($n, $value, PDO::PARAM_STR); $this->binds [] = array($n, $value, PDO::PARAM_STR);
} }
function setBlob($n, $value) function setBlob($n, $value) {
{
$this->binds [] = array($n, $value, PDO::PARAM_LOB); $this->binds [] = array($n, $value, PDO::PARAM_LOB);
} }
function setLimit($limit) function setLimit($limit) {
{
$this->limit = $limit; $this->limit = $limit;
} }
function setOffset($offset) function setOffset($offset) {
{
$this->offset = $offset; $this->offset = $offset;
} }
function executeQuery() function executeQuery() {
{
if ($this->limit) { if ($this->limit) {
$this->query .= " LIMIT {$this->limit} OFFSET {$this->offset}"; $this->query .= " LIMIT {$this->limit} OFFSET {$this->offset}";
} }

View file

@ -8,7 +8,7 @@ class Number
function __construct($value) function __construct($value)
{ {
$this->value = (int)$value; $this->value = (int)($value);
} }
function getString() function getString()

View file

@ -28,8 +28,8 @@ class ActionLogger
function execute(HttpRequest $request) { function execute(HttpRequest $request) {
$action = $request->getAction(); $action = $request->getAction();
if(in_array($action, $this->before)) { if(in_array($action, $this->before)) {
$message = ["time" => date("r", time()), "query" => array_merge($_POST, $_GET), "user" => $this->user->getName()]; $line = ['time' => time(), 'user' => $this->user->getName(), 'sid' => session_id(), 'query' => array_merge($_POST, $_GET)];
fwrite($this->file, json_encode($message) . "\n"); fwrite($this->file, json_encode($line) . "\n");
} }
return $this->processor->execute($request); return $this->processor->execute($request);
} }

View file

@ -12,27 +12,32 @@ namespace ctiso\Filter;
use ctiso\Filter\Filter, use ctiso\Filter\Filter,
ctiso\HttpRequest, ctiso\HttpRequest,
ctiso\Settings, ctiso\Settings,
ctiso\Registry,
ctiso\Database, ctiso\Database,
ctiso\Role\User, ctiso\Role\User,
ctiso\Collection; ctiso\Collection,
ctiso\Path;
class Login extends Filter class Login extends Filter
{ {
const SESSION_BROWSER_SIGN_SECRET = '@w3dsju45Msk#'; const SESSION_BROWSER_SIGN_SECRET = '@w3dsju45Msk#';
const SESSION_BROWSER_SIGN_KEYNAME = 'session.app.browser.sign'; const SESSION_BROWSER_SIGN_KEYNAME = 'session.app.browser.sign';
const AUTH_MAX_ATTEMPT = 10;
const AUTH_LAST_ATTEMPT_TIMER = 600;
public $mode = 'ajax'; public $mode = 'ajax';
public $user; public $user;
public $role/*: User*/; public $role;
public $whitelist; public $config;
function __construct($processor, $role, $whitelist = []) { function __construct($processor, User $role, Registry $config) {
parent::__construct($processor); parent::__construct($processor);
$this->role = $role; $this->role = $role;
$this->whitelist = $whitelist; $this->config = $config;
} }
/** /**
* Проверка авторизации * Проверка авторизации
* @param HttpRequest $request
* @return Boolean Авторизовани пользователь или нет * @return Boolean Авторизовани пользователь или нет
*/ */
public function isLoggin(HttpRequest $request) public function isLoggin(HttpRequest $request)
@ -48,10 +53,38 @@ class Login extends Filter
$result = $this->role->getUserByLogin($login); // Поиск по логину $result = $this->role->getUserByLogin($login); // Поиск по логину
if ($result) { if ($result) {
$userPassword = $this->role->getUserPassword($result); $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'));
$db = Database::getConnection($dsn);
$user = $db->fetchOneArray("SELECT * FROM users WHERE login = :login", ['login' => $login]);
$userPassword = $user['password'];
} /*else if (time() - $result->getInt('lastupdate') > 60*60*24*60) {
// Проверить давность пароля, 60 дней
$request->set('error', true);
$request->set('lastupdate', true);
return false;
}*/
// Проверка на количества попыток авторизации
$lastAttempt = $result;
if ($lastAttempt->get('trie_count') >= self::AUTH_MAX_ATTEMPT /*&& time() - $lastAttempt['trie_time'] < self::AUTH_LAST_ATTEMPT_TIMER*/) {
if (time() - $lastAttempt->get('trie_time') < self::AUTH_LAST_ATTEMPT_TIMER) {
$request->set('timeout_error', true);
break;
} else {
$this->role->resetTries($request->get('login'));
}
}
// Извлечнеие пользователя из родительской CMS, для проверки пароля // Извлечнеие пользователя из родительской CMS, для проверки пароля
if (md5($password) == $userPassword) { // password if (md5($password) == $userPassword) { // password
$this->enter($result); $this->enter($result);
return true; return true;
} else {
// Обновление количества неудачных попыток входа
$this->role->updateTries($login);
} }
} }
$request->set('error', true); $request->set('error', true);
@ -59,7 +92,8 @@ class Login extends Filter
case 'logout': // Выход case 'logout': // Выход
session_destroy(); session_destroy();
break; break;
// Вход по временному паролю // Вход по временному паролю, не используется
/*
case 'enter': case 'enter':
$login = $request->get('login'); $login = $request->get('login');
$password = $request->get('sid'); $password = $request->get('sid');
@ -72,6 +106,7 @@ class Login extends Filter
} }
} }
break; break;
*/
default: default:
$hash = $this->getBrowserSign(); $hash = $this->getBrowserSign();
// Если $hash не совпадает $_SESSION['hash'] то удаляем сессию // Если $hash не совпадает $_SESSION['hash'] то удаляем сессию
@ -107,9 +142,9 @@ class Login extends Filter
$random = rand(0, 1024 * 1024); $random = rand(0, 1024 * 1024);
$this->role->setSID($random, $result); $this->role->setSID($random, $result);
// $_SESSION["group"] = $result->getInt('access'); $_SESSION["group"] = $result->getInt('access');
$_SESSION["access"] = $result->getInt('id_user'); $_SESSION["access"] = $result->getInt('id_user'); // id_user
$_SESSION["random"] = $random; $_SESSION["random"] = $random; // id_user
$_SESSION[self::SESSION_BROWSER_SIGN_KEYNAME] = $this->getBrowserSign(); $_SESSION[self::SESSION_BROWSER_SIGN_KEYNAME] = $this->getBrowserSign();
$_SESSION["time"] = time(); $_SESSION["time"] = time();
} }
@ -141,7 +176,7 @@ class Login extends Filter
// Параметры при неправильной авторизации // Параметры при неправильной авторизации
// Действия по умолчанию !! Возможно переход на форму регистрации // Действия по умолчанию !! Возможно переход на форму регистрации
if ($request->get('mode') == 'ajax') { if ($request->get('mode') == 'ajax') {
if (!$this->requestIsWhite($request, $this->whitelist)) { if (!$this->requestIsWhite($request)) {
return json_encode(array('result' => 'fail', 'message' =>"NOT_AUTHORIZED")); return json_encode(array('result' => 'fail', 'message' =>"NOT_AUTHORIZED"));
} }
} else { } else {
@ -163,11 +198,16 @@ class Login extends Filter
/* --------------------- /* ---------------------
* Проверка на попадание реквеста в белый список * Проверка на попадание реквеста в белый список
*/ */
public function requestIsWhite(HttpRequest $request, $whiteRequestList){ public function requestIsWhite(Collection $request) {
$module = $request->get('module'); $module = $request->get('module');
$action = $request->get('action'); $action = $request->get('action');
foreach ($whiteRequestList as $whiteRequest) {
if ($module == $whiteRequest['module'] && $action == $whiteRequest['action']) { $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);
if (in_array($action, $whiteList)) {
return true; return true;
} }
} }
@ -175,4 +215,3 @@ class Login extends Filter
return false; return false;
} }
} }

View file

@ -98,6 +98,8 @@ class Form extends View {
'radio' => 'ctiso\\Form\\SelectOne', 'radio' => 'ctiso\\Form\\SelectOne',
'filebrowser' => 'ctiso\\Form\\BrowserInput', 'filebrowser' => 'ctiso\\Form\\BrowserInput',
'documents' => 'ctiso\\Form\\BrowserInput', 'documents' => 'ctiso\\Form\\BrowserInput',
'chooser' => 'ctiso\\Form\\Input',
'select_chooser' => 'ctiso\\Form\\SelectOne'
); );
} }

View file

@ -0,0 +1,87 @@
<?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;
}
}

View file

@ -20,11 +20,12 @@ class HttpRequest extends Collection implements ArrayAccess
*/ */
public function __construct() public function __construct()
{ {
$list = array ( $list = [
'data' => $_REQUEST, 'data' => $_REQUEST,
'get' => $_GET, 'get' => $_GET,
'post' => $_POST, 'post' => $_POST,
'cookie' => $_COOKIE); 'cookie' => $_COOKIE
];
$ajax = $this->isAjax(); $ajax = $this->isAjax();
foreach ($list as $key => $value) { foreach ($list as $key => $value) {

View file

@ -6,7 +6,6 @@ use ctiso\Registry,
class Factory class Factory
{ {
static $shortcut = "model";
public $db; public $db;
public $config; public $config;
@ -19,7 +18,7 @@ class Factory
/** /**
* Создает модель * Создает модель
* @param string $name * @param string $name
* @return model * @return Model
*/ */
public function getModel ($name) public function getModel ($name)
{ {

View file

@ -176,11 +176,14 @@ class Path
public static function makeUrl($path) public static function makeUrl($path)
{ {
$slash = (isset($path['host']) && (strlen($path['path']) > 0) && ($path['path'][0] != '/')) ? '/' : '';
return (isset($path['scheme']) ? $path['scheme'] . ':/' : '') return (isset($path['scheme']) ? $path['scheme'] . ':/' : '')
. (isset($path['host']) ? ('/' . (isset($path['host']) ? ('/'
. (isset($path['user']) ? $path['user'] . (isset($path['pass']) ? ':' . $path['pass'] : '') . '@' : '') . (isset($path['user']) ? $path['user'] . (isset($path['pass']) ? ':' . $path['pass'] : '') . '@' : '')
. $path['host'] . $path['host']
. (isset($path['port']) ? ':' . $path['port'] : '')) : '') . (isset($path['port']) ? ':' . $path['port'] : '')) : '')
. $slash
. $path['path'] . $path['path']
. (isset($path['query']) ? '?' . $path['query'] : '') . (isset($path['query']) ? '?' . $path['query'] : '')
. (isset($path['fragment']) ? '#' . $path['fragment'] : ''); . (isset($path['fragment']) ? '#' . $path['fragment'] : '');
@ -293,6 +296,7 @@ class Path
$parts = new Path($file); $parts = new Path($file);
$result [] = $parts->getParts(); $result [] = $parts->getParts();
} }
// При обьединении ссылок можно обьеденить path, query, fragment // При обьединении ссылок можно обьеденить path, query, fragment
$path = implode(self::SEPARATOR, self::optimize(call_user_func_array('array_merge', $result))); $path = implode(self::SEPARATOR, self::optimize(call_user_func_array('array_merge', $result)));
$parts0->url['path'] = ($parts0->isAbsolute()) ? '/' . $path : $path; $parts0->url['path'] = ($parts0->isAbsolute()) ? '/' . $path : $path;

View file

@ -6,6 +6,7 @@ use ctiso\File,
class Registry { class Registry {
public $namespace = []; public $namespace = [];
public $data;
function importFile($namespace, $filePath = null) { function importFile($namespace, $filePath = null) {
$data = json_decode(File::getContents($filePath), true); $data = json_decode(File::getContents($filePath), true);
@ -40,4 +41,20 @@ class Registry {
function set($ns, $key, $value) { function set($ns, $key, $value) {
$this->namespace[$ns]['data'][$key] = $value; $this->namespace[$ns]['data'][$key] = $value;
} }
/**
* Список модулей
*/
public function getModules()
{
return array_keys($this->data);
}
/**
* Проверка наличия модуля
*/
public function hasModule($name)
{
return isset($this->data[$name]);
}
} }

View file

@ -74,11 +74,26 @@ class User implements UserInterface
$time = time(); $time = time();
if ($time - $lasttime > self::LIFE_TIME) return null; // Вышло время сессии if ($time - $lasttime > self::LIFE_TIME) return null; // Вышло время сессии
$id = $this->id; $id = $this->id;
$this->db->executeQuery("UPDATE users SET lasttime = $time WHERE id_user = $id"); // Время последнего обращения входа
} }
return $result; return $result;
} }
function setSID() { 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']]
);
} }
} }

View file

@ -1,5 +1,9 @@
<?php <?php
namespace ctiso;
use ctiso\File,
Exception;
/** /**
* Класс реестра * Класс реестра
* Реестр организован как ассоциативный многомерный массив * Реестр организован как ассоциативный многомерный массив
@ -9,19 +13,18 @@
* parameters1, parameters1 - Массивы с параметрами модуля * parameters1, parameters1 - Массивы с параметрами модуля
* Имя необходимо чтобы потом легко было удалить ненужные ветки дерева * Имя необходимо чтобы потом легко было удалить ненужные ветки дерева
*/ */
namespace ctiso;
use ctiso\File,
Exception;
class Settings class Settings
{ {
public $data = []; public $data = [];
protected $file; protected $file;
protected $format = 'php'; protected $format = 'php';
public function __construct ($file = null) public function __construct ($file = null, $format = false)
{ {
$this->format = pathinfo($file, PATHINFO_EXTENSION); $fileFormat = ['theme' => 'json'];
$extname = pathinfo($file, PATHINFO_EXTENSION);
$this->format = $format ? $format : Arr::get($fileFormat, $extname, $extname);
$this->file = $file; $this->file = $file;
} }
@ -47,6 +50,7 @@ class Settings
} }
$this->data = $settings; $this->data = $settings;
return true;
} }
/** /**
@ -91,7 +95,7 @@ class Settings
/** /**
* Чтение ключа из реестра * Чтение ключа из реестра
* @param $args Путь к значению ключа * @param mixed $args Путь к значению ключа
*/ */
public function readKey(array $key) public function readKey(array $key)
{ {
@ -121,7 +125,7 @@ class Settings
/** /**
* Чтение ключа из реестра (Собирает все ключи с определенным значением во всех модулях) * Чтение ключа из реестра (Собирает все ключи с определенным значением во всех модулях)
* @param $key Путь к значению ключа внутри модуля * @param mixed $key Путь к значению ключа внутри модуля
*/ */
public function readKeyList($_rest) public function readKeyList($_rest)
{ {
@ -162,7 +166,6 @@ class Settings
* Запись настроек в файл (Может переименовать в store) * Запись настроек в файл (Может переименовать в store)
* *
* @param File $file * @param File $file
*
* @return void * @return void
*/ */
public function write($file = null) public function write($file = null)

View file

@ -146,7 +146,7 @@ class SQLStatementExtractor {
trigger_error("substring(), Endindex out of bounds must be $startpos<n<".($len-1), E_USER_ERROR); trigger_error("substring(), Endindex out of bounds must be $startpos<n<".($len-1), E_USER_ERROR);
} }
if ($startpos === $endpos) { if ($startpos === $endpos) {
return (string) $string{$startpos}; return (string) $string[$startpos];
} else { } else {
$len = $endpos-$startpos; $len = $endpos-$startpos;
} }

View file

@ -17,17 +17,17 @@ class StringUtil {
if ($in_subarr > 0) { // already in sub-array? if ($in_subarr > 0) { // already in sub-array?
$subarr[$in_subarr][] = $tok; $subarr[$in_subarr][] = $tok;
if ('}' === substr($tok, -1, 1)) { // check to see if we just added last component if ('}' === substr($tok, -1, 1)) { // check to see if we just added last component
$res[] = self::strToArray(implode(',', $subarr[$in_subarr])); $res[] = static::strToArray(implode(',', $subarr[$in_subarr]));
$in_subarr--; $in_subarr--;
} }
} elseif ($tok{0} === '{') { // we're inside a new sub-array } elseif ($tok[0] === '{') { // we're inside a new sub-array
if ('}' !== substr($tok, -1, 1)) { if ('}' !== substr($tok, -1, 1)) {
$in_subarr++; $in_subarr++;
// if sub-array has more than one element // if sub-array has more than one element
$subarr[$in_subarr] = array(); $subarr[$in_subarr] = array();
$subarr[$in_subarr][] = $tok; $subarr[$in_subarr][] = $tok;
} else { } else {
$res[] = self::strToArray($tok); $res[] = static::strToArray($tok);
} }
} else { // not sub-array } else { // not sub-array
$val = trim($tok, '"'); // remove " (surrounding strings) $val = trim($tok, '"'); // remove " (surrounding strings)
@ -81,7 +81,7 @@ class StringUtil {
} }
static function encodestring($st) { static function encodestring($st) {
$st = self::mb_strtr($st,"абвгдеёзийклмнопрстуфхъыэ !+-()", "abvgdeeziyklmnoprstufh_ie______"); $st = self::mb_strtr($st,"абвгдеёзийклмнопрстуфхъыэ !+()", "abvgdeeziyklmnoprstufh_ie_____");
$st = self::mb_strtr($st,"АБВГДЕЁЗИЙКЛМНОПРСТУФХЪЫЭ", "ABVGDEEZIYKLMNOPRSTUFH_IE"); $st = self::mb_strtr($st,"АБВГДЕЁЗИЙКЛМНОПРСТУФХЪЫЭ", "ABVGDEEZIYKLMNOPRSTUFH_IE");
$st = strtr($st, array( $st = strtr($st, array(
" " => '_', " " => '_',

View file

@ -38,6 +38,8 @@ class TemplateImage
protected $image; protected $image;
protected $_prepare = true; protected $_prepare = true;
public $debug = false; public $debug = false;
public $filename;
public $resource;
public $resource; public $resource;
public $filename; public $filename;
@ -205,4 +207,3 @@ class TemplateImage
} }
} }
} }

View file

@ -1,9 +1,4 @@
<?php <?php
/**
* UserMessageException.php
*
*/
/** /**
* Исключение с понятным пользователю сообщением, которое имеет смысл ему показать. * Исключение с понятным пользователю сообщением, которое имеет смысл ему показать.
* @see Controller_Front * @see Controller_Front

View file

@ -1,77 +0,0 @@
<?php
namespace ctiso\View;
use ctiso\View\View,
ctiso\Controller\SiteInterface,
ctiso\Controller\Component,
ctiso\HttpRequest;
class Page extends View
{
private $counter;
public $text;
public $site/*: SiteInterface*/;
function __construct($data, $site)
{
$this->site = $site;
// Вставка компонентов на странице
$pattern = '/<(\w+)(\s+[a-zA-Z\-]+=\"[^\"]*\")*\s+tal:replace="structure\s+component:([^\"]*)"[^>]*>/u';
$matches = array();
preg_match_all($pattern, $data, $matches, PREG_OFFSET_CAPTURE, 0);
$split = array();
$offset = 0;
foreach ($matches[0] as $key => $match) {
$text = $this->fixHTML(substr($data, $offset, $match[1] - $offset));
if (trim($text)) {
$split[] = array('type' => 'page-text', 'content' => $text, 'component' => '', 'module' => '');
}
$offset = $match[1] + strlen($match[0]);
$split[] = $this->replaceContent($matches[3][$key][0], $matches[3][$key][1]);
}
$text = $this->fixHTML(substr($data, $offset));
if (trim($text)) {
$split[] = array('type' => 'page-text', 'content' => $text, 'component' => '', 'module' => '');
}
$this->text = $this->merge($split);
}
function fixHTML($fragment) {
return $fragment;
}
function merge($data) {
if (count($data) == 0) {
$data[] = array('type' => 'page-text', 'content' =>"<p>Добавьте текст<p>", 'component' => '', 'module' => '');
}
$result = array();
foreach($data as $key => $part) {
$result[] = $part['content'];
}
return implode("", $result);
}
function replaceContent($match, $offset)
{
$component/*: Component*/ = $this->site->loadComponent($match);
$req = new HttpRequest();
unset($req['active_page']);
$info = $component->getInfo();
$result = $component->execute($req);
if (is_string($result)) {
return array('type' => 'page-component', 'content' => $result, 'component' => $match);
} else {
$this->setView('view' . $this->counter++, $result);
return array('type' => 'page-component', 'content' => $result->execute(), 'component' => $match);
}
}
function execute() {
return $this->text;
}
}

View file

@ -1,9 +1,11 @@
<?php <?php
namespace ctiso\View; namespace ctiso\View;
use ctiso\View\Composite; use ctiso\View\Composite;
class Top extends Composite { class Top extends Composite
{
/** /**
* Общая строка заголовка * Общая строка заголовка
*/ */
@ -52,7 +54,8 @@ class Top extends Composite {
} }
function getId($pref) { function getId($pref)
{
$this->mid++; $this->mid++;
return $pref . $this->mid; return $pref . $this->mid;
} }
@ -116,7 +119,8 @@ class Top extends Composite {
$this->set('startup', implode("", $startup) . $this->getScriptStartup()); $this->set('startup', implode("", $startup) . $this->getScriptStartup());
$this->set('require', implode(",", array_map(function ($x) { return "'$x'";}, array_keys($this->require)))); $this->set('require', implode(",", array_map(function ($x) {
return "'$x'"; }, array_keys($this->require))));
$this->set('deps', implode(",", array_values($this->require))); $this->set('deps', implode(",", array_values($this->require)));
$this->set('title', $this->getTitle()); $this->set('title', $this->getTitle());

View file

@ -33,4 +33,3 @@ function tableTreeWalk($level, $table, $fn) {
} }
return $data; return $data;
} }