Merge branch 'autoload' into 'master'

Autoload

See merge request !2
This commit is contained in:
Федор Подлеснов 2017-02-17 17:31:38 +03:00
commit 3defa8f38b
136 changed files with 5015 additions and 9243 deletions

1
.gitignore vendored Normal file
View file

@ -0,0 +1 @@
*.bak

View file

@ -7,5 +7,9 @@
"email": "phedor@edu.yar.ru" "email": "phedor@edu.yar.ru"
} }
], ],
"require": {} "autoload": {
"psr-0": {
"": "src/"
}
}
} }

View file

@ -1,4 +0,0 @@
<?php
foreach (glob(dirname(__FILE__) . "/*.php") as $file)
require_once $file;
?>

File diff suppressed because it is too large Load diff

View file

@ -1,433 +0,0 @@
<?php
/**
*
* @package Core
*/
require_once 'core/json.php';
require_once 'core/form/form.php';
require_once 'core/controller/controller.php';
require_once 'core/widgets/pagemenu.php';
require_once 'core/widgets/menu.php';
require_once 'core/widgets/search.php';
require_once 'core/widgets/setup.php';
require_once 'core/widgets/listtable.php';
/**
* Переименовать контроллер !! (StubController, CrudController, PageController, BaseController) ModelController
* Возможно нужен еще класс с мета действиями как для actionIndex <= metaActionIndex либо с классам для этих действий
* Есть класс для управлениями действиями а есть сами действия в виде классов или функций !!
*/
class Controller_Model extends Controller_Action
{
public $schema = array();
public $schemaSearch = array();
/**
* FIXME: Лучше $this->table->setHeader
*/
public $tableSchema = null;
public $formSchema = array();
public $menu;
public $path;
public $table;
public function __construct()
{
$this->path = new PathMenu();
$this->menu = new PageMenu();
$this->table = new ListTable();
}
/**
*/
function setUp()
{
$this->table->addMenuItem($this->aUrl('delete'), 'удалить', false, 'all', 'warning');
//$this->table->addMenuItem($this->nUrl('form'), 'редактировать', 'edit-24.png');
}
function saveParameters($args, $list)
{
foreach ($list as $item) {
$args->session()->set(array($this, $item), $args->get($item));
}
}
protected function getJSONList(/*Mapper*/ $model, Collection $request)
{
$result = array();
$this->saveParameters($request, array('size','page','desc', 'key'));
$result['list'] = $model->findAll($request, $request->get('ref'));
$result['size'] = $model->getCount($request, $request->get('ref'));
return json::encode($result);
}
/**
* Удаление сторк из таблицы
*/
public function actionDelete(HttpRequest $request)
{
$model = $this->getModel($this->useModel);
// Почему table_item ???
$list = ($request->get('table_item')) ? $request->get('table_item'): $request->get('id');
$model->deleteList($list);
return $this->getJSONList($model, $request);
}
/**
* Ответ на запрос по поиску
*/
public function actionSearch(HttpRequest $request)
{
$model = $this->getModel($this->useModel);
$model->addFilter($model->requestToSQL($request, $this->formSchema));
return $this->getJSONList($model, $request);
}
/**
* Список элементов
*/
public function actionList(HttpRequest $request)
{
$model = $this->getModel($this->useModel);
return $this->getJSONList($model, $request);
}
private function setFormSchema()
{
require_once 'core/mapper/uimapper.php';
$model = $this->getModel($this->useModel);
$ui = new UIMapper($model);
$this->formSchema = $ui->getFormSchema();
}
/**
* Сохранение формы
*/
function beforeSave(/*Model*/ $item, Collection $request)
{
if (empty($this->formSchema)) {
$this->setFormSchema();
}
// Сделать отображение Формы в обьект и обратно <-- Убрать в beforeSave
foreach ($this->formSchema as $key => $conv) {
list($value, $type) = $conv;
$item->$value = call_user_func(array('Cast', 'to_' . $type), $request->get($key)); // Здесть нужно преобразовывать тип значения
}
}
/**
* Обновление формы
*/
function formUpdate(TForm $form, Collection $request)
{
}
/**
* Загрузка формы
*/
function beforeLoad(/*Model*/ $item, TForm $form)
{
if (empty($this->formSchema)) {
$this->setFormSchema();
}
// Вставка значений из данных в форму
// Отображение обьекта в поля формы
$form->fill($item, $this->formSchema);
}
// Проверка ввода
protected function validate($validator, $request)
{
}
/**
* Действие для проверки формы
*/
public function actionValidate($request)
{
require_once "core/validator/validator.php";
$validator = new Validator();
$validator->addRuleList($this->schema);
// Действия до проверки формы
$this->validate($validator, $request); // <--|
$validator->validate($request); // --|
// Проверка формы
if (!$validator->isValid()) {
return json::encode($validator->getErrorMsg());
}
return json::encode(true);
}
/**
* Инициализация формы
*/
protected function formSetup($form, $id = null, $ref = null)
{
if (empty($this->schema)) {
$model = $this->getModel($this->useModel);
$ui = new UIMapper($model);
$schema = $ui->getEditSchema();
$form->addFieldList($schema);
} else {
$form->addFieldList($this->schema);
}
}
/**
* Добавление пользователя
*/
public function actionAdd(HttpRequest $request)
{
require_once "core/validator/validator.php";
// {{{ тоже может быть один ref или несколько
$ref = $request->get('ref');
$this->addParameter('ref', $ref); // Добавляет параметр в url
/// }}}
if ($this->checkPageId($request, $request->get('page'))) {
// Проверка
$validator = new Validator();
$validator->addRuleList($this->schema);
// Действия до проверки формы
$this->validate($validator, $request); // <--|
$validator->validate($request); // --|
// Проверка формы
if (!$validator->isValid()) {
$request->setAction('form');
$this->getActionPath($request);
$form = new TForm();
$this->formSetup($form, $request->get('id'), $request->get('ref')); // Инициализация формы
$form->setValues($request); // <-- Убрать в formUpdate
$this->formUpdate($form, $request);
$form->setError($validator); // Установка ошибок для формы
$tpl = $this->formPage($form, $request);
$id = $request->get('id');
if ($id) { // Редактирование
$tpl->action = forceUrl($this->nUrl('add', array('id' => $id, 'page' => $this->getPageId($request)))); // action Совйство формы
}
return $tpl /*->execute()*/;
}
// Нужен тест для формы
$model = $this->getModel($this->useModel);
$className = $model->className;
$item = new $className();
// Сохраняем значение в базе данных
$item->id = $request->get('id');
// Если таблица связана с другой таблицей
if ($request->get('ref') && $model->reference[1]) {
$ref_id = $model->reference[1];
$item->$ref_id = $request->get('ref');
}
// Подготовка к сохранению
$this->beforeSave($item, $request); // Сюдаже и истрия переходов
// nextId ??? или выход или новая форма для создания новости
$model->saveDB($item, $request);
}
// Для страницы со списком id -> идентефикатор родительской таблицы !!??
// $request->set('id', $request->get('ref'));
if ($request->get('apply')) {
$request->setAction('form');
return $this->forward('actionForm', $request);
}
return $this->forward('actionIndex', $request);
}
/**
* Заголовок
*/
private function setTitlePath($ref)
{
if ($ref) {
$model = $this->getModel($this->useModel);
if (is_array($model->reference) && $model->reference[0]) {
$refmodel = $this->getModel($model->reference[0]);
try {
$parent = $refmodel->findById($ref);
$this->path->addTitle($parent->getTitle()); // Заголовок к подписям путей
} catch (Exception $e) {
// Не найден заголовок потому что неправильно определен родительский элемент
}
}
}
}
/**
* Форма для редактирования
*/
public function actionForm(HttpRequest $request)
{
$this->getActionPath($request);
$ref = $request->get('ref');
$this->addParameter('ref', $ref); // Добавляет параметр в url
$this->setTitlePath($ref);
$model = $this->getModel($this->useModel);
$form = new TForm(); // Показываем форму
$form->header = 'Редактирование записи';
$this->formSetup($form, $request->get('id'), $request->get('ref')); // Инициализация формы
$list = $request->get('table_item');
$id = ($list[0]) ? $list[0] : $request->get('id');
$tpl = $this->formPage ($form, $request);
if ($id) { // Редактирование
$form->action = forceUrl($this->nUrl('add', array('id' => $id, 'page' => $this->getPageId($request)))); // action Свойство формы
$item = $model->findById($id);
// Загрузка формы
$this->beforeLoad($item, $form);
///
}
return $tpl;
}
/**
*/
function tableSetup($table, $id = null, $ref = null)
{
// FIXME: После замены везде $tableSchema -> table->setHeader удалить!
if ($this->tableSchema) {
$table->setHeader($this->tableSchema);
} else {
// Настройка таблицы отображения по схеме данных
require_once 'core/mapper/uimapper.php';
$model = $this->getModel($this->useModel);
$ui = new UIMapper($model);
$schema = $ui->getTableSchema();
$schema[0]['action'] = $table->getFirstItem();
$table->setHeader($schema);
}
}
/**
*/
public function actionIndex(HttpRequest $request)
{
$this->getActionPath($request, 'index');
// Такое мета действие наверное можно вынести в отдельный класс
return $this->metaActionIndex($request, array($this, 'tableSetup'), $this->aUrl('list'));
}
/**
* Страница по умолчанию
*/
public function metaActionIndex(HttpRequest $request, $setup, $list)
{
// может быть одно ref или несколько
// {{{ история переходов
$ref = null;
if ($request->get('ref')) {
$ref = $request->get('ref');
} else if ($request->session()->get('ref')) {
$ref = $request->session()->get('ref');
}
$request->session->set('ref', $ref);
$this->addParameter('ref', $ref);
// }}}
$this->setTitlePath($ref);
$tpl = $this->getView('list');
// Помошники действий
$this->callHelpers($request);
// Таблица
if ($request->session()->get(strtolower(get_class($this)))) {
$session = $request->session()->get(strtolower(get_class($this)));
if (isset($session['view'])) {
$this->table->setView($session['view']);
}
$this->table->setData('state', array(
'page' => $session['page'],
'size' => $session['size'],
'desc' => $session['desc']));
$this->table->setData('sorter', $session['key']);
if (isset($session['desc'])) {
$this->table->setData('desc', $session['desc']);
}
}
call_user_func($setup, $this->table, $request->get('id'), $ref);// --> Эквивалент formSetup
$this->table->setAction($list);
//
$tpl->menu_path = $this->path->getItems();
// Поиск
$search = new SearchDialog();
$search->setTitle('Поиск');
$search->setAction($this->aUrl('search'));
$search->setFriend($this->table);
$search->addFields($this->schemaSearch);
// Настройки
$setup = new SetupDialog();
$setup->setTitle('Настройки');
$setup->setAction($this->nUrl('setup'));
$setup->setFriend($this->table);
// Меню
$this->menu->addMenuItem('?menu=toggle&id=' . $search->getName(), 'поиск', 'actions/system-search'); // Стандартный размер для иконок 22-24px
$this->menu->addMenuItem('?menu=toggle&id=' . $setup->getName(), 'настройки', 'categories/applications-system');
// Добавление компонентов
$this->addChild('menu', $this->menu);
$this->addChild('search', $search);
$this->addChild('setup', $setup);
$this->addChild('table', $this->table);
//
return $tpl;
}
/**
*/
public function actionSetup($request)
{
$left = explode(",", $request->get('left'));
$right = explode(",", $request->get('right'));
$$request->session()->set(strtolower(get_class($this)),
array('view' => array('left' => $left, 'right' => $right)));
return $this->forward('actionIndex', $request);
}
/**
*/
private function formPage($form, $request)
{
$view = $this->getView('form');
$view->setView('form', $form);
$view->action = forceUrl($this->nUrl('add', array('page' => $this->getPageId($request)))); // Действие для формы
$view->menu_path = $this->path->getItems();
$view->back = $this->path->getPrev();
return $view;
}
// Тоже убрать в метод Controller_Model
function getActionPath(HttpRequest $request/*, $action = false*/)
{
require_once 'state.php';
$this->_getActionPath()->getPath($this, ($action) ? $action : $request->getAction());
}
}

View file

@ -1,185 +0,0 @@
<?php
require_once 'core/path.php';
class FileNotFountException extends Exception
{
}
/**
* Класс компонента
*/
class Component
{
static $_uid = 1;
public $uid; // UID компонента создается при создании страницы, вставки компонента, или это статическое свойство
public $viewPath;
public $registry; // Registry->getInstance
public $template;
function __construct()
{
self::$_uid ++;
$this->uid = self::$_uid;
}
function getUID()
{
return 'component:'. $this->uid;
}
public function getView($name)
{
require_once "core/view/compositeview.php";
//
$template = ($this->template) ? $this->template : $this->_registry->readKey(array('system', 'template'));
// Загружать шаблон по умолчанию если не найден текущий
if (is_dir(Path::join($this->viewPath, 'templates', $template))) {
$template_file = Path::join($this->viewPath, 'templates', $template, $name);
} else {
$template_file = Path::join($this->viewPath, 'templates', 'modern', $name);
}
$tpl = new View_Composite($template_file);
$tpl->script = $_script = Path::join(WWW_PATH, 'js');
$tpl->media = $_media = Path::join(TEMPLATE_WEB, $template);
$tpl->component = $_template = Path::join(COMPONENTS_WEB, strtolower(get_class($this)), 'templates', 'modern');
$tpl->setAlias(array(
'${media}' => $_media,
'${script}' => $_script,
'${template}' => $_template));
$tpl->loadImports(Path::skipExtension($template_file) . ".import");
return $tpl;
}
public function setParameters($view)
{
}
/**
* @param $name Имя модели
*/
private function getModelPath($name)
{
return Path::join (CMS_PATH, "model", $name . ".php");
}
/**
* Создает модель
* @param string $name
* @return model
*/
public function getModel($name)
{
require_once 'core/mapper/mapper.php';
require_once ($this->getModelPath ($name));
$modelName = $name . "Mapper";
$model = new $modelName ();
$model->db = $this->db;
return $model;
}
public function options($key, $val, $res) {
$result = array();
while($res->next()) {
$result[] = array('value' => $res->getInt($key), 'name' => $res->getString($val));
}
return $result;
}
public function optionsPair($list) {
$result = array();
foreach ($list as $key => $value) {
$result [] = array('value' => $key, 'name' => $value);
}
return $result;
}
/* В дальнейшем нужно зменить на методы
+ Методы могут быть и javascript
*/
protected $editUrl;
function setEditUrl($url)
{
$this->editUrl = $url;
}
function getEditUrl()
{
return $this->editUrl;
}
}
/**
* TALES для подключения компонентов
* component:name?param1=value1&param2=value2
*/
class Component_Tales implements PHPTAL_Tales
{
static public function component($expression, $nothrow = false)
{
return "phptal_component('" . $expression . "')";
}
}
function loadComponent($name, $db, $registry)
{
$path = Path::join(COMPONENTS, $name, $name . ".php");
// echo COMPONENTS, '<br />';
// echo $path;
if (file_exists($path)) {
require_once ($path);
$component = new $name();
$component->db = $db;
$component->_registry = $registry;
$component->viewPath = COMPONENTS."/".$name."/";
return $component;
}
throw new FileNotFountException();
}
/**
* Функция подключения компонента
*/
global $componentList;
$componentList = array();
function phptal_component ($real_expression, $offset = 0) {
global $db, $registry, $componentList; // Нужно както передавать параметры
$expression = htmlspecialchars_decode($real_expression);
$url = parse_url($expression);
parse_str($url['query'], $arguments);
$name = $url['path'];
$component = loadComponent($name, $db, $registry);
$req = new HttpRequest();
$params = new Collection();
$params->import(array_merge($_GET, $arguments));
$component->params = $params;
$componentList [] = array(
'uid' => $component->getUID(), 'params' => $expression, 'name' => $name, 'offset' => $offset,
'size' => strlen($real_expression),
/* Вместо ссылки на редактирование нужно передавать список методов для работы с компонентом
edit (редактирование содержание), new (новое содержание), шаблон коменнента ... вместе с иконками этих методов
! Компоненты могут содержать другие компоненты
*/
'editurl' => $component->getEditUrl(),
'newurl' => ''
);
unset($req['active_page']);
$component->template = $params->get('template', false);
return $component->execute($params, $req);
}
/* Регистрация нового префикса для подключения компонента */
$registry = PHPTAL_TalesRegistry::getInstance();
$registry->registerPrefix('component', array('Component_Tales', 'component'));

View file

@ -1,343 +0,0 @@
<?php
require_once 'core/path.php';
require_once 'core/mapper/factory.php';
require_once 'core/functions.php';
function forceUrl($name)
{
if (is_callable($name)) {
return call_user_func($name);
}
return $name;
}
/**
* Контроллер страниц
* @package core
*/
class Controller
{
const TEMPLATE_EXTENSION = ".html"; // Расширение для шаблонов
const ACTION_PREFIX = "action"; // Префикс для функций действий
public $jsPath; // Глобальный путь к скриптам
public $themePath; // Глобальный путь к текущей теме
// Параметры устанавливаются при создании контроллера
public $name; // Имя модуля
public $viewPath = null; // Путь к шаблонам контроллера
public $db; // Соединение с базой данных
// Фильтры
public $access; // Обьект хранит параметры доступа
public $logger; // Обьект для ведения лога
private $factory; // Ссылка на обьект создания модели
private $helpers = array(); // Помошники для действий
public $param = array(); // Параметры для ссылки
public $_registry; // Ссылка на реестр
public $_shortcut;
public function __construct ()
{
//
}
public function setUp ()
{
// override this
}
public function loadConfig($name) {
$filename = Shortcut::getUrl('config', $name);
if (file_exists($filename)) {
include($filename);
} else {
throw new Exception('Невозможно загрузить файл настроек ' . $name);
}
return $settings;
}
public function getConnection()
{
return $this->db;
}
public function installPath($name)
{
return Path::join(CMS_PATH, "modules", $name, "install");
}
public function addSuggest($view, $name)
{
$suggest = array();
$file = Path::join($this->viewPath, 'help', $name . '.suggest');
if (file_exists($file) && include($file)) {
$view->addScriptRaw("add_suggest(".json::encode($suggest).");\n");
}
}
function findIcon($icon, $size)
{
return Path::join($this->iconPath, $size . 'x' . $size, $icon . '.png');
}
/**
* Создает представление
* @param string $file
* @return template
*/
public function getView($name)
{
require_once "core/view/compositeview.php";
$file = $name . self::TEMPLATE_EXTENSION;
// Список возможных директорий для поиска файла шаблона
$theme = $this->_registry->readKey(array('system', 'theme'));
$icon_theme = $this->_registry->readKey(array('system', 'icon_theme'));
$list = array(
Path::join($this->viewPath, TEMPLATES) => Path::join(WWW_PATH, "modules", $this->name, TEMPLATES),
PHPTAL_TEMPLATE_REPOSITORY => "");
// Поиск файла для шаблона
foreach($list as $ospath => $path) {
$template = Path::join($ospath, $file);
if(file_exists($template)) { break; }
}
$tpl = new View_Composite($template);
$tpl->icons = $this->iconPath; // Путь к файлам текущей темы
$tpl->media = $this->themePath; // Путь к файлам текущей темы
$tpl->script = $this->jsPath; // Путь к файлам скриптов
$tpl->template = $path; // Путь к файлам текущего шаблона
$tpl->setAlias(array(
'${icons}' => $this->iconPath,
'${media}' => $this->themePath,
'${script}' => $this->jsPath,
'${template}' => $path));
$tpl->loadImports(Path::skipExtension($template) . ".import");
$this->addSuggest($tpl, $name);
return $tpl;
}
public function getModel($name)
{
if (!$this->factory) {
$this->factory = new ModelFactory($this->db, $this->_registry, $this->_shortcut);
}
return $this->factory->getModel($name);
}
/**
* Выбор действия
* Т.к действия являются методами класса то
* 1. Можно переопределить действия
* 2. Использовать наследование чтобы добавить к старому обработчику новое поведение
* @param $request Обьект запроса
*/
public function execute1(HTTPRequest $request)
{
$action = self::ACTION_PREFIX . ucfirst($request->getAction());
if (method_exists($this, $action)) {
return $this->forward($action, $request);
} else {
return $this->forward("actionIndex", $request);
}
}
public function execute(HTTPRequest $request)
{
$result = $this->execute1($request);
if ($result) {
$this->view = $result;
}
return $this->render();
}
public function forward($action, HTTPRequest $args)
{
// Действия до вызова основного обработчика
/*foreach($this->_aspect as $aspect) {
if (isset($aspect->before[$action])) {
call_user_func ($aspect->before[$action], $action, $args);
}
}*/
return call_user_func(array($this, $action), $args);
}
/**
* Страница по умолчанию
*/
public function actionIndex(HttpRequest $request)
{
return "";
}
public function postUrl($name, $param)
{
return "?" . http_build_query(
array_merge(array('module' => strtolower(get_class($this)), "action" => $name),
$this->param, $param));
}
/**
* Генерация ссылки c учетом прав пользователя на ссылки
*
* @parma string $name Действие
* @parma string $param Дополнительные параметры
*/
public function nUrl($name, array $param = array())
{
if (!$this->access || $this->access->checkAction($name)) {
return lcurry(array($this, 'postUrl'), $name, $param);
}
return null;
}
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;
}
}
/**
* Генерация ссылки на действие контроллера
* Ajax определяется автоматически mode = ajax используется для смены layout
*/
public function aUrl($name, array $param = array())
{
return $this->nUrl($name, array_merge(array('mode' => 'ajax'), $param)); // FIXME
}
/**
* Добавление помошника контроллера
*/
public function addHelper($class)
{
$this->helpers [] = $class;
}
/**
* Вызов помошников контроллера
*/
public function callHelpers(HttpRequest $request)
{
$action = self::ACTION_PREFIX . $request->getAction();
foreach ($this->helpers as $helper) {
if (method_exists($helper, $action)) {
return call_user_func(array($helper, $action), $request, $this);
} else {
return $helper->actionIndex($request, $this); // Вместо return response ???
}
}
}
/**
* Загрузка файла класса
*/
public function loadClass($path, $setup = null)
{
if (file_exists($path)) {
require_once ($path);
$class = pathinfo($path, PATHINFO_FILENAME);
return new $class($setup);
}
return null;
}
public function loadSettings($path)
{
$result = new Settings($path);
$result->read();
return $result->export();
}
// Для Widgets
public $view = null;
public $childNodes = array();
public $childViews = array();
public function setView($name)
{
$this->view = $this->getView($name);
}
/**
* Установка заголовка для отображения
*/
public function setTitle($title)
{
$this->view->setTitle($title);
}
/**
* Добавление widget к отображению
*/
public function addChild(/*Widget*/ $section, $node)
{
$this->childNodes[$section] = $node;
}
/**
* Добавление дочернего отображения к текущему отображению
*/
public function addView(/*CompositeView*/ $section, $node)
{
$this->childViews[$section] = $node;
}
/**
* Генерация содержания
* Путаница c execute и render
*/
public function render()
{
foreach ($this->childNodes as $name => $node) {
$node->make($this);
$this->view->setView($name, $node->view);
}
foreach ($this->childViews as $name => $node) {
$this->view->setView($name, $node);
}
return $this->view;
}
function getPageId($request)
{
$pageId = time();
$request->session()->set('page', $pageId);
return $pageId;
}
function checkPageId($request, $page)
{
$_page = $request->session()->get('page');
$result = ($_page && $_page == $page);
$request->session()->clean('page');
return $result;
}
function redirect($action) {
header('location: ' . $this->fUrl($action));
exit();
}
}
class Controller_Action extends Controller {}

View file

@ -1,26 +0,0 @@
<?php
$settings = array
(
0 => '',
1 => 'Город Ярославль',
2 => 'Большесельский район',
3 => 'Борисоглебский район',
4 => 'Брейтовский район',
5 => 'Гаврилов-Ямский район',
6 => 'Даниловский район',
7 => 'Любимский район',
8 => 'Мышкинский район',
9 => 'Некоузский район',
10 => 'Некрасовский район',
11 => 'Переславский район',
12 => 'Первомайский район',
13 => 'Пошехонский район',
14 => 'Ростовский район',
15 => 'Рыбинский район',
16 => 'Тутаевский район',
17 => 'Угличский район',
18 => 'Ярославский район',
19 => 'Город Переславль',
20 => 'Город Рыбинск'
);

View file

@ -1,14 +0,0 @@
<?php
$settings = array(
0 => '',
1 => 'г.',
2 => 'с.',
3 => 'п.',
4 => 'д.',
5 => 'пгт.',
6 => 'р.п.',
7 => 'ст.',
8 => 'а.'
);

View file

@ -1,14 +0,0 @@
<?php
// Массив типов поселений
$settings = array(
// 0 => '',
1 => 'город',
2 => 'село',
3 => 'поселок',
4 => 'деревня',
5 => 'поселок городского типа',
6 => 'рабочий поселок',
7 => 'станица',
8 => 'аул'
);

View file

@ -1,196 +0,0 @@
<?php
/**
* http://www.w3schools.com/media/media_mimeref.asp
*/
$settings = array (
"" => "application/octet-stream",
"323" => "text/h323",
"acx" => "application/internet-property-stream",
"ai" => "application/postscript",
"aif" => "audio/x-aiff",
"aifc" => "audio/x-aiff",
"aiff" => "audio/x-aiff",
"asf" => "video/x-ms-asf",
"asr" => "video/x-ms-asf",
"asx" => "video/x-ms-asf",
"au" => "audio/basic",
"avi" => "video/x-msvideo",
"axs" => "application/olescript",
"bas" => "text/plain",
"bcpio" => "application/x-bcpio",
"bin" => "application/octet-stream",
"bmp" => "image/bmp",
"c" => "text/plain",
"cat" => "application/vnd.ms-pkiseccat",
"cdf" => "application/x-cdf",
"cer" => "application/x-x509-ca-cert",
"class" => "application/octet-stream",
"clp" => "application/x-msclip",
"cmx" => "image/x-cmx",
"cod" => "image/cis-cod",
"cpio" => "application/x-cpio",
"crd" => "application/x-mscardfile",
"crl" => "application/pkix-crl",
"crt" => "application/x-x509-ca-cert",
"csh" => "application/x-csh",
"css" => "text/css",
"dcr" => "application/x-director",
"der" => "application/x-x509-ca-cert",
"dir" => "application/x-director",
"dll" => "application/x-msdownload",
"dms" => "application/octet-stream",
"doc" => "application/msword",
"dot" => "application/msword",
"dvi" => "application/x-dvi",
"dxr" => "application/x-director",
"eps" => "application/postscript",
"etx" => "text/x-setext",
"evy" => "application/envoy",
"exe" => "application/octet-stream",
"fif" => "application/fractals",
"flr" => "x-world/x-vrml",
"gif" => "image/gif",
"gtar" => "application/x-gtar",
"gz" => "application/x-gzip",
"h" => "text/plain",
"hdf" => "application/x-hdf",
"hlp" => "application/winhlp",
"hqx" => "application/mac-binhex40",
"hta" => "application/hta",
"htc" => "text/x-component",
"htm" => "text/html",
"html" => "text/html",
"htt" => "text/webviewhtml",
"ico" => "image/x-icon",
"ief" => "image/ief",
"iii" => "application/x-iphone",
"ins" => "application/x-internet-signup",
"isp" => "application/x-internet-signup",
"jfif" => "image/pipeg",
"jpe" => "image/jpeg",
"jpeg" => "image/jpeg",
"jpg" => "image/jpeg",
"js" => "application/x-javascript",
"latex" => "application/x-latex",
"lha" => "application/octet-stream",
"lsf" => "video/x-la-asf",
"lsx" => "video/x-la-asf",
"lzh" => "application/octet-stream",
"m13" => "application/x-msmediaview",
"m14" => "application/x-msmediaview",
"m3u" => "audio/x-mpegurl",
"man" => "application/x-troff-man",
"mdb" => "application/x-msaccess",
"me" => "application/x-troff-me",
"mht" => "message/rfc822",
"mhtml" => "message/rfc822",
"mid" => "audio/mid",
"mny" => "application/x-msmoney",
"mov" => "video/quicktime",
"movie" => "video/x-sgi-movie",
"mp2" => "video/mpeg",
"mp3" => "audio/mpeg",
"mpa" => "video/mpeg",
"mpe" => "video/mpeg",
"mpeg" => "video/mpeg",
"mpg" => "video/mpeg",
"mpp" => "application/vnd.ms-project",
"mpv2" => "video/mpeg",
"ms" => "application/x-troff-ms",
"mvb" => "application/x-msmediaview",
"nws" => "message/rfc822",
"oda" => "application/oda",
"p10" => "application/pkcs10",
"p12" => "application/x-pkcs12",
"p7b" => "application/x-pkcs7-certificates",
"p7c" => "application/x-pkcs7-mime",
"p7m" => "application/x-pkcs7-mime",
"p7r" => "application/x-pkcs7-certreqresp",
"p7s" => "application/x-pkcs7-signature",
"pbm" => "image/x-portable-bitmap",
"pdf" => "application/pdf",
"pfx" => "application/x-pkcs12",
"pgm" => "image/x-portable-graymap",
"pko" => "application/ynd.ms-pkipko",
"pma" => "application/x-perfmon",
"pmc" => "application/x-perfmon",
"pml" => "application/x-perfmon",
"pmr" => "application/x-perfmon",
"pmw" => "application/x-perfmon",
"pnm" => "image/x-portable-anymap",
"pot," => "application/vnd.ms-powerpoint",
"ppm" => "image/x-portable-pixmap",
"pps" => "application/vnd.ms-powerpoint",
"ppt" => "application/vnd.ms-powerpoint",
"prf" => "application/pics-rules",
"ps" => "application/postscript",
"pub" => "application/x-mspublisher",
"qt" => "video/quicktime",
"ra" => "audio/x-pn-realaudio",
"ram" => "audio/x-pn-realaudio",
"ras" => "image/x-cmu-raster",
"rgb" => "image/x-rgb",
"rmi" => "audio/mid",
"roff" => "application/x-troff",
"rtf" => "application/rtf",
"rtx" => "text/richtext",
"scd" => "application/x-msschedule",
"sct" => "text/scriptlet",
"setpay" => "application/set-payment-initiation",
"setreg" => "application/set-registration-initiation",
"sh" => "application/x-sh",
"shar" => "application/x-shar",
"sit" => "application/x-stuffit",
"snd" => "audio/basic",
"spc" => "application/x-pkcs7-certificates",
"spl" => "application/futuresplash",
"src" => "application/x-wais-source",
"sst" => "application/vnd.ms-pkicertstore",
"stl" => "application/vnd.ms-pkistl",
"stm" => "text/html",
"svg" => "image/svg+xml",
"sv4cpio" => "application/x-sv4cpio",
"sv4crc" => "application/x-sv4crc",
"swf" => "application/x-shockwave-flash",
"t" => "application/x-troff",
"tar" => "application/x-tar",
"tcl" => "application/x-tcl",
"tex" => "application/x-tex",
"texi" => "application/x-texinfo",
"texinfo" => "application/x-texinfo",
"tgz" => "application/x-compressed",
"tif" => "image/tiff",
"tiff" => "image/tiff",
"tr" => "application/x-troff",
"trm" => "application/x-msterminal",
"tsv" => "text/tab-separated-values",
"txt" => "text/plain",
"uls" => "text/iuls",
"ustar" => "application/x-ustar",
"vcf" => "text/x-vcard",
"vrml" => "x-world/x-vrml",
"wav" => "audio/x-wav",
"wcm" => "application/vnd.ms-works",
"wdb" => "application/vnd.ms-works",
"wks" => "application/vnd.ms-works",
"wmf" => "application/x-msmetafile",
"wps" => "application/vnd.ms-works",
"wri" => "application/x-mswrite",
"wrl" => "x-world/x-vrml",
"wrz" => "x-world/x-vrml",
"xaf" => "x-world/x-vrml",
"xbm" => "image/x-xbitmap",
"xla" => "application/vnd.ms-excel",
"xlc" => "application/vnd.ms-excel",
"xlm" => "application/vnd.ms-excel",
"xls" => "application/vnd.ms-excel",
"xlt" => "application/vnd.ms-excel",
"xlw" => "application/vnd.ms-excel",
"xof" => "x-world/x-vrml",
"xpm" => "image/x-xpixmap",
"xwd" => "image/x-xwindowdump",
"z" => "application/x-compress",
"zip" => "application/zip",
);

View file

@ -1,35 +0,0 @@
<?php
// В ОКАТО приняты следующие сокращения:
// http://www.consultant.ru/online/base/?req=doc;base=LAW;n=62484
$settings = array (
"р" => "район",
"г" => "город",
"пгт" => "поселок городского типа",
"рп" => "рабочий поселок",
"кп" => "курортный поселок",
"к" => "кишлак",
"пс" => "поселковый совет",
"сс" => "сельсовет",
"смн" => "сомон",
"вл" => "волость",
"дп" => "дачный поселковый совет",
"п" => "поселок сельского типа",
"нп" => "населенный пункт",
"п. ст" => "поселок при станции",
"ж/д ст" => "железнодорожная станция",
"с" => "село",
"м" => "местечко",
"д" => "деревня",
"сл" => "слобода",
"ст" => "станция",
"ст-ца" => "станица",
"х" => "хутор",
"у" => "улус",
"рзд" => "разъезд",
"клх" => "колхоз",
"им" => "имени",
"свх" => "совхоз",
"зим" => "зимовье",
);

View file

@ -1,91 +0,0 @@
<?php
$settings = array (
0 => '',
2 => 'Алтайский край',
3 => 'Амурская область',
4 => 'Архангельская область',
5 => 'Астраханская область',
6 => 'Белгородская область',
7 => 'Брянская область',
8 => 'Владимирская область',
9 => 'Волгоградская область',
10 => 'Вологодская область',
11 => 'Воронежская область',
12 => 'г. Москва',
13 => 'г. Санкт-Петербург',
14 => 'Еврейская автономная область',
84 => 'Забайкальский край',
15 => 'Ивановская область',
16 => 'Иркутская область',
17 => 'Кабардино-Балкарская Республика',
18 => 'Калининградская область',
19 => 'Калужская область',
20 => 'Камчатский край',
21 => 'Карачаево-Черкесская Республика',
22 => 'Кемеровская область',
23 => 'Кировская область',
28 => 'Костромская область',
29 => 'Краснодарский край',
30 => 'Красноярский край',
31 => 'Курганская область',
32 => 'Курская область',
33 => 'Ленинградская область',
34 => 'Липецкая область',
35 => 'Магаданская область',
36 => 'Московская область',
37 => 'Мурманская область',
38 => 'Ненецкий автономный округ',
39 => 'Нижегородская область',
40 => 'Новгородская область',
41 => 'Новосибирская область',
42 => 'Омская область',
43 => 'Оренбургская область',
44 => 'Орловская область',
45 => 'Пензенская область',
46 => 'Пермский край',
47 => 'Приморский край',
48 => 'Псковская область',
49 => 'Республика Адыгея',
50 => 'Республика Алтай',
51 => 'Республика Башкортостан',
52 => 'Республика Бурятия',
25 => 'Республика Дагестан',
26 => 'Республика Ингушетия',
53 => 'Республика Калмыкия',
54 => 'Республика Карелия',
55 => 'Республика Коми',
56 => 'Республика Марий Эл',
57 => 'Республика Мордовия',
58 => 'Республика Саха(Якутия)',
59 => 'Республика Северная Осетия-Алания',
60 => 'Республика Татарстан',
61 => 'Республика Тыва',
62 => 'Республика Хакасия',
63 => 'Ростовская область',
64 => 'Рязанская область',
65 => 'Самарская область',
66 => 'Саратовская область',
67 => 'Сахалинская область',
68 => 'Свердловская область',
69 => 'Смоленская область',
70 => 'Ставропольский край',
71 => 'Таймырский (Долгано-Ненецкий) автономный округ',
72 => 'Тамбовская область',
73 => 'Тверская область',
74 => 'Томская область',
75 => 'Тульская область',
76 => 'Тюменская область',
77 => 'Удмуртская Республика',
78 => 'Ульяновская область',
80 => 'Хабаровский край',
81 => 'Ханты-Мансийский автономный округ',
82 => 'Челябинская область',
83 => 'Чеченская Республика',
85 => 'Чувашская Республика',
86 => 'Чукотский автономный округ',
87 => 'Эвенкийский автономный округ',
88 => 'Ямало-Ненецкий автономный округ',
89 => 'Ярославская область'
);

View file

@ -1,32 +0,0 @@
<?php
$settings = array (
0 => array('title' => ''),
1 => array(
'title' => 'Центральный федеральный округ',
'short' => 'ЦФО',
'regions' => array(6, 7, 8, 11, 12, 15, 19, 28, 32, 34, 36, 44, 64, 69, 72, 73, 75, 89)),
2 => array(
'title' => 'Южный федеральный округ',
'short' => 'ЮФО',
'regions' => array(5, 9, 17, 21, 29, 49, 25, 26, 53, 59, 63, 70, 83)),
3 => array(
'title' => 'Северо-западный федеральный округ',
'short' => 'СЗФО',
'regions' => array(4, 10, 13, 18, 33, 37, 38, 40, 48, 54, 55)),
4 => array(
'title' => 'Дальневосточный федеральный округ',
'short' => 'ДФО',
'regions' => array(3, 14, 20, 35, 47, 58, 67, 80, 86)),
5 => array(
'title' => 'Сибирский федеральный округ',
'short' => 'СФО',
'regions' => array(2, 16, 22, 30, 41, 42, 50, 52, 61, 62, 71, 74, 84, 86, 87)),
6 => array(
'title' => 'Уральский федеральный округ',
'short' => 'УФО',
'regions' => array(31, 68, 76, 81, 82, 88)),
7 => array(
'title' => 'Приволжский федеральный округ',
'short' => 'ПФО',
'regions' => array(23, 39, 43, 45, 46, 51, 56, 57, 60, 65, 66, 77, 78, 85)));

View file

@ -1,16 +0,0 @@
<?php
/**
* Простой класс(Factory) для работы с базами данных
*/
class Database
{
static function getConnection (array $dsn)
{
require_once "core/drivers/database." . strtolower($dsn['phptype']) . ".php";
$name = "Database_" . strtoupper($dsn['phptype']);
$database = new $name();
$database->connect($dsn);
return $database;
}
}

View file

@ -1,407 +0,0 @@
<?php
/**
* @package system.db
* Класс оболочка для PDO для замены Creole
*/
class Database extends PDO
{
public function __construct($dsn, $username = false, $password = false)
{
parent::__construct($dsn, $username, $password);
$this->setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION);
$this->setAttribute(PDO::ATTR_STATEMENT_CLASS, array('PDODatabaseStatement', array()));
}
public function getDSN()
{
return $this->dsn;
}
public function isPostgres(){
return ($this->dsn["phptype"] == "pgsql");
}
/**
* Создает соединение с базой данных
*/
static function getConnection(array $dsn)
{
if ($dsn['phptype'] == 'pgsql' || $dsn['phptype'] == 'mysql') {
$port = (isset($dsn['port'])) ? "port={$dsn['port']};" : "";
$connection = new Database("{$dsn['phptype']}:host={$dsn['hostspec']}; $port dbname={$dsn['database']}", $dsn['username'], $dsn['password']);
$connection->query('SET client_encoding = "UTF-8"');
}
if ($dsn['phptype'] == 'sqlite') {
$connection = new Database("{$dsn['phptype']}:{$dsn['database']}");
}
$connection->dsn = $dsn;
return $connection;
}
public function executeQuery($query)
{
$stmt = $this->prepare($query);
$stmt->setFetchMode(PDO::FETCH_ASSOC);
$stmt->execute();
$stmt->cache = $stmt->fetchAll();
return $stmt;//$sth->fetchAll();
}
public function prepareStatement($query)
{
return new DatabaseStatement($query, $this);
}
// Для совместимости со старым представлением баз данных CIS
/**
* Извлекает из базы все элементы по запросу
*/
public function fetchAllArray($query,$values=null)
{
$sth = $this->prepare($query);
$prep = $this->prepareValues($values);
$sth->execute($prep);
return $sth->fetchAll(PDO::FETCH_ASSOC);
}
/**
* Извлекает из базы первый элемент по запросу
*/
public function fetchOneArray($query,$values=null)
{
$sth = $this->prepare($query);
$prep = $this->prepareValues($values);
$sth->execute($prep);
return $sth->fetch(PDO::FETCH_ASSOC);
}
private function assignQuote($x, $y)
{
return $x . "=" . $this->quote($y);
}
private function prepareValues($values)
{
if (!$values) {
return null;
}
$pg = $this->isPostgres();
$prep = array();
foreach ($values as $key => $value) {
$result = null;
if(is_bool($value)) {
if ($pg) {
$result = $value ? 'true' : 'false';
} else {
$result = $value ? 1 : 0;
}
} else {
$result = $value;
}
$prep[":" . $key] = $result;
}
return $prep;
}
/**
* Создает INSERT запрос
*/
function insertQuery($table, array $values, $return_id = false, $index = null)
{
$prep = $this->prepareValues($values);
$sql = "INSERT INTO $table (" . implode(",", array_keys($values))
. ") VALUES (" . implode(",", array_keys($prep)). ")";
if($return_id){
if ($this->isPostgres()){
$sql = $sql." RETURNING $index";
}
}
$stmt = $this->prepare($sql);
$stmt->setFetchMode(PDO::FETCH_ASSOC);
$stmt->execute($prep);
$result = $stmt->fetch();
if ($return_id) {
if ($this->isPostgres()) {
return $result[$index];
} else {
$result = $this->fetchOneArray("SELECT $index AS lastid FROM $table WHERE OID = last_insert_rowid()");
return $result['lastid'];
}
}
}
/**
* Создает UPDATE запрос
*/
function updateQuery($table, array $values, $cond)
{
return $this->query("UPDATE $table SET " . implode(",",
array_map(array($this, 'assignQuote'), array_keys($values), array_values($values))) . " WHERE $cond");
}
function getIdGenerator() {
return new IdGenerator($this);
}
/**
* Замечание: Только для Postgres SQL
* @param string $seq Имя последовательности для ключа таблицы
* @return int Идентефикатор следующей записи
*/
function getNextId($seq)
{
$result = $this->fetchOneArray("SELECT nextval('$seq')");
return $result['nextval'];
}
function close()
{
return null;
}
}
class IdGenerator {
private $db;
function __construct($db) {
$this->db = $db;
}
function isBeforeInsert() {
return false;
}
function isAfterInsert() {
return true;
}
function getId($seq) {
$result = $this->db->fetchOneArray("SELECT nextval('$seq')");
return $result['nextval'];
// $result = $this->db->fetchOneArray("SELECT last_insert_rowid() AS nextval");
// return $result['nextval'];
}
}
class PDODatabaseStatementIterator implements Iterator
{
private $result;
private $pos = 0;
private $fetchmode;
private $row_count;
private $rs;
/**
* Construct the iterator.
* @param PgSQLResultSet $rs
*/
public function __construct($rs)
{
$this->result = $rs;
$this->row_count = $rs->getRecordCount();
}
function rewind()
{
$this->pos = 0;
}
function valid()
{
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;
}
function count ( ) {
return $this->row_count;
}
}
class PDODatabaseStatement extends PDOStatement implements IteratorAggregate
{
protected $cursorPos = 0;
public $cache = array();
function getIterator()
{
return new PDODatabaseStatementIterator($this);
}
protected function __construct() {
}
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;
}
function valid()
{
return ( true );
}
public function first()
{
if($this->cursorPos !== 0) { $this->seek(0); }
return $this->next();
}
function next()
{
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++;
return true;
} else {
$this->fields = null;
return false;
}
}
function key() {
return $this->cursorPos;
}
function current()
{
return $this->result->fetch(PDO::FETCH_ASSOC);
}
function getRow()
{
return $this->fields;
}
function getInt($name)
{
return intval($this->fields[$name]);
}
function getBlob($name)
{
return $this->fields[$name];
}
function getString($name)
{
return $this->fields[$name];
}
function getBoolean($name)
{
return (bool)$this->fields[$name];
}
function get($name)
{
return $this->fields[$name];
}
function getRecordCount()
{
return count($this->cache);
}
}
/**
* Класс оболочка для PDOStatement для замены Creole
*/
class DatabaseStatement
{
protected $limit = null;
protected $offset = null;
protected $statement = null;
protected $binds = array();
protected $conn;
protected $query;
function __construct($query, $conn) {
$this->query = $query;
$this->conn = $conn;
}
function setInt($n, $value)
{
$this->binds [] = array($n, $value, PDO::PARAM_INT);
}
function setString($n, $value)
{
$this->binds [] = array($n, $value, PDO::PARAM_STR);
}
function setBlob($n, $value)
{
$this->binds [] = array($n, $value, PDO::PARAM_LOB);
}
function setLimit($limit)
{
$this->limit = $limit;
}
function setOffset($offset)
{
$this->offset = $offset;
}
function executeQuery()
{
if ($this->limit) {
$this->query .= " LIMIT {$this->limit} OFFSET {$this->offset}";
}
$stmt = $this->conn->prepare($this->query);
foreach ($this->binds as $bind) {
list($n, $value, $type) = $bind;
$stmt->bindValue($n, $value, $type);
}
$stmt->setFetchMode(PDO::FETCH_ASSOC);
$stmt->execute();
$stmt->cache = $stmt->fetchAll();
return $stmt;
}
}

View file

@ -1,50 +0,0 @@
<?php
require_once 'core/drivers/db.php';
/**
* Простой класс для работы с базами данных
*/
class Database_MYSQL extends DB implements IDatabase
{
public function connect(array $dsn)
{
$db = @mysql_pconnect($dsn['hostspec'], $dsn['username'], $dsn['password'])
or die("Unable connect to database!");
mysql_select_db($dsn['database']);
return ($this->db = $db);
}
public function close()
{
return mysql_close($this->db);
}
public function query($query)
{
$res = mysql_query($this->db, $query)
or die("Error: wrong SQL query #$query#");
return $res;
}
public function fetchAllArray($query)
{
$res = $this->query($query);
while ($row = mysql_fetch_array ($res))
$rows[] = $row;
mysql_free_result($res);
return ($rows) ? $rows : array();
}
public function fetchOneArray($query)
{
$res = $this->query($query);
$row = mysql_fetch_array($res);
mysql_free_result($res);
return ($row) ? $row : array();
}
}
?>

View file

@ -1,54 +0,0 @@
<?php
require_once 'core/drivers/db.php';
/**
* Простой класс для работы с базами данных
*/
class Database_ODBC extends DB implements IDatabase
{
public function connect(array $dsn)
{
$db = @odbc_connect($dsn['database'], $dsn['username'], $dsn['password'])
or die("Unable connect to database!");
return ($this->db = $db);
}
public function close()
{
return odbc_close($this->db);
}
public function query($query)
{
$res = odbc_exec($this->db, $query)
or die("Error: wrong SQL query #$query#");
return $res;
}
public function fetchAllArray($query)
{
$res = $this->query($query);
$to = odbc_num_fields($res);
while (odbc_fetch_row($res)) {
for ($i = 1; $i <= $to; $i++) {
$row [odbc_field_name($res, $i)] = trim(odbc_result($res, $i));
}
$rows[] = $row;
}
return ($rows)? $rows : array();
}
public function fetchOneArray($query)
{
$res = $this->query($query);
if (!odbc_fetch_row($res)) return array ();
$to = odbc_num_fields($res);
for ($i = 1; $i <= $to; $i++) {
$row [odbc_field_name($res, $i)] = trim(odbc_result($res, $i));
}
return $row;
}
}
?>

View file

@ -1,74 +0,0 @@
<?php
require_once 'core/drivers/db.php';
/**
* Простой класс для работы с базами данных
*/
class Database_PGSQL extends DB implements IDatabase
{
public function connect(array $dsn)
{
if (isset($dsn['port'])) {
$port = "port={$dsn['port']}";
} else {
$port = "port=5432";
}
$str = "host={$dsn['hostspec']} $port dbname={$dsn['database']} user={$dsn['username']} password={$dsn['password']}";
$db = @pg_connect($str)
or die("Unable connect to database!");
return ($this->db = $db);
}
public function close()
{
return pg_close($this->db);
}
public function query($query)
{
$res = pg_query($this->db, $query)
or die("Error: wrong SQL query #$query#");
return $res;
}
public function fetchAllArray($query, $type = PGSQL_ASSOC)
{
$res = $this->query($query);
$rows = array();
while ($row = pg_fetch_array($res, NULL, $type)) {
$rows[] = $this->clean($row);
}
pg_free_result($res);
return ($rows) ? $rows : array();
}
public function affectedRows()
{
return pg_affected_rows($this->db);
}
private function clean($row)
{
foreach ($row as $key => $value) {
$row[$key] = trim($value);
}
return $row;
}
public function fetchOneArray($query, $type = PGSQL_ASSOC)
{
$res = $this->query($query);
$row = pg_fetch_array($res, NULL, $type);
pg_free_result($res);
return ($row) ? $this->clean($row) : array();
}
function getNextId($seq)
{
$result = $this->fetchOneArray("SELECT nextval('$seq')");
return $result['nextval'];
}
}

View file

@ -1,50 +0,0 @@
<?php
/**
* Интерфейс драйвера класса баз данных
*/
interface IDatabase
{
public function connect(array $dsn);
public function close();
public function query($query);
public function fetchAllArray($query);
public function fetchOneArray($query);
}
abstract class DB implements IDatabase
{
const limit = 1024;
protected $db;
public static function quote($x)
{
return "'" . $x . "'";
}
private static function assign_quote($x, $y)
{
return $x . "='" . $y . "'";
}
function insert($table, array $values)
{
return $this->query("INSERT INTO $table (" . implode(",", array_keys($values))
. ") VALUES (" . implode(",", array_map(array('self', 'quote'), array_values($values))) . ")");
}
function update($table, array $values, $cond)
{
return $this->query("UPDATE $table SET " . implode(",",
array_map(array('self', 'assign_quote'), array_keys($values), array_values($values))) . " WHERE $cond");
}
function check_text($text)
{
if(strlen($text) > self::limit) $text = substr($text, 0, self::limit);
$text = htmlspecialchars(trim($text));
return $text;
}
}
?>

View file

@ -1,86 +0,0 @@
<?php
// Report simple running errors
define('ERROR_FILE', 'phedor@edu.yar.ru');
define('ERROR_TYPE', 1);
ini_set('error_reporting', 0);
ini_set('display_errors', 0);
error_reporting(0);
function get_error_name($id) {
$names = array(1 => 'E_ERROR',
2 => 'E_WARNING',
4 => 'E_PARSE',
8 => 'E_NOTICE',
16 => 'E_CORE_ERROR',
32 => 'E_CORE_WARNING',
64 => 'E_COMPILE_ERROR',
128 => 'E_COMPILE_WARNING',
256 => 'E_USER_ERROR',
512 => 'E_USER_WARNING',
1024 => 'E_USER_NOTICE',
2048 => 'E_STRICT',
4096 => 'E_RECOVERABLE_ERROR',
8192 => 'E_DEPRECATED',
16384 => 'E_USER_DEPRECATED',
30719 => 'E_ALL');
return $names[$id];
}
function send_error($description) {
$message = "request: " . "http://".$_SERVER['SERVER_NAME'].$_SERVER['REQUEST_URI'] . "\n";
$message .= "from: " . $_SERVER['REMOTE_ADDR'] . "\n";
if(isset($_SERVER['HTTP_REFERER'])) $message .= "referer: " . $_SERVER['HTTP_REFERER'] . "\n";
$message .= "post:" . var_export($_POST, true) . "\n";
$message .= "description: " . $description;
// error_log($message, ERROR_TYPE, ERROR_FILE);
return false;
}
function error_handler($errno, $errstr, $errfile, $errline) {
$message = "request: " . "http://".$_SERVER['SERVER_NAME'].$_SERVER['REQUEST_URI'] . "\n";
$message .= "from: " . $_SERVER['REMOTE_ADDR'] . "\n";
if(isset($_SERVER['HTTP_REFERER'])) $message .= "referer: " . $_SERVER['HTTP_REFERER'] . "\n";
$message .= "post:" . var_export($_POST, true) . "\n";
$message .= "type: " . get_error_name($errno) . "\n"
. "error: " . $errstr . "\n"
. "line: " . $errline . "\n"
. "file: " . $errfile;
// error_log($message, ERROR_TYPE, ERROR_FILE);
return false;
}
function shutdown() {
$error = error_get_last();
$message = "request: " . "http://".$_SERVER['SERVER_NAME'].$_SERVER['REQUEST_URI'] . "\n";
$message .= "from: " . $_SERVER['REMOTE_ADDR'] . "\n";
if(isset($_SERVER['HTTP_REFERER'])) $message .= "referer: " . $_SERVER['HTTP_REFERER'] . "\n";
if (is_array($error)) {
foreach ($error as $info => $string) {
$message .= "{$info}: {$string}\n";
}
}
error_log($message, ERROR_TYPE, ERROR_FILE);
}
function exception_handler($exception) {
$message = "request: " . "http://".$_SERVER['SERVER_NAME'].$_SERVER['REQUEST_URI'] . "\n";
$message .= "from: " . $_SERVER['REMOTE_ADDR'] . "\n";
if(isset($_SERVER['HTTP_REFERER'])) $message .= "referer: " . $_SERVER['HTTP_REFERER'] . "\n";
$message .=
"file: " . $exception->getFile() . "\n"
. "line: " . $exception->getLine() . "\n"
. "message: " . $exception->getMessage() . "\n"
. "trace: " . $exception->getTraceAsString();
error_log($message, ERROR_TYPE, ERROR_FILE);
return true;
}
set_exception_handler('exception_handler');
set_error_handler("error_handler");
//register_shutdown_function('shutdown');

View file

@ -1,80 +0,0 @@
<?php
require_once 'core/sort.php';
//Становиться похоже на работу файлов через SPL возможно стоит реализовать на базе его
class FileRecord
{
public $file;
protected $src;
protected $parent;
function __construct(array $file, $src, $parent = false)
{
$this->file = $file;
$this->filename = $src;
$this->parent = $parent;
}
function get($name) {
return isset($this->file[$name]) ? $this->file[$name] : null;
}
function fileStat()
{
$type = is_dir($this->filename);
return array(
'name' => ($this->parent) ? ".." : $this->getName(),
'type' => $type,
'extension' => ($type) ? 'folder' : pathinfo($this->filename, PATHINFO_EXTENSION),
'date' => date("d.m.Y H:i", $this->getTime()),
'access' => 0,
'size' => ($type) ? "" : $this->getSizeString(),
'state' => isset($this->file['state']) ? $this->file['state'] : 'unknown',
'title' => $this->getTitle(),
/*'author' => $this->file['author'],
'description' => $this->file['description'],
'keywords' => $this->file['keywords'],*/
);
}
function isExpected()
{
if (isset($this->file['state'])) {
return ($this->file['state'] == 'expected');
}
return false;
}
function getSizeString()
{
$size = $this->getSize();
foreach (array('б ', 'Kб', 'Mб') as $suffix) {
if (($size / 1024) <= 1) {
return round($size, 0) . ' ' . $suffix;
}
$size /= 1024;
}
return round($size, 0) . ' GB';
}
function getSize()
{
return ($this->isExpected()) ? 0 : filesize($this->filename);
}
function getTime()
{
return ($this->isExpected()) ? 0 : filemtime($this->filename);
}
function getName()
{
return pathinfo($this->filename, PATHINFO_BASENAME);
}
function getTitle()
{
return isset($this->file['title']) ? $this->file['title'] : $this->getName();
}
}

View file

@ -1,105 +0,0 @@
<?php
/**
* Фильтр для проверки авторизации
*
* action: login(password, login)
* action: logout()
*/
// В класс авторизации передавать обьект для управления пользователем
// Вынести в отдельный файл
class LoginFilter extends Filter
{
const SESSION_BROWSER_SIGN_SECRET = '@w3dsju45Msk#';
const SESSION_BROWSER_SIGN_KEYNAME = 'session.app.browser.sign';
public $mode = 'ajax';
/**
* Проверка авторизации
* @return Boolean Авторизовани пользователь или нет
*/
public function isLoggin(HttpRequest $request)
{
// Авторизация
session_start();
$db = $this->getConnection();
UserAccess::setUp($db); // Соединение
switch ($request->getAction()) {
// Авторизация по постоянному паролю
case 'login':
$login = $request->get('login');
$password = $request->get('password');
$result = UserAccess::getUserByLogin($login); // Поиск по логину
if ($result) {
if (md5($password) == $result->getString('password')) { // password
$this->enter($db, $result);
return true;
}
}
$request->set('error', true);
break;
case 'logout': // Выход
session_destroy();
break;
// Вход по временному паролю
case 'enter':
$login = $request->get('login');
$password = $request->get('sid');
$result = UserAccess::getUserByLogin($login); // Поиск по логину
if ($result) {
$temp = md5($result->getString('password') . $result->getString('login') . $result->getString('sid'));
if ($password == $temp) {
$this->enter($db, $result);
return true;
}
}
break;
default:
$hash = $this->getBrowserSign();
// Если $hash не совпадает $_SESSION['hash'] то удаляем сессию
if (isset($_SESSION ['access']) && isset($_SESSION[self::SESSION_BROWSER_SIGN_SECRET])) {
if ($hash == $_SESSION[self::SESSION_BROWSER_SIGN_SECRET]) {
UserAccess::getUserById($_SESSION ['access']); // Поиск по идентификатору
return true;
} else {
session_destroy();
}
}
}
return false;
}
private function getBrowserSign()
{
$rawSign = self::SESSION_BROWSER_SIGN_SECRET;
$signParts = array('HTTP_USER_AGENT', 'HTTP_ACCEPT_ENCODING');
$rawSign = '';
foreach ($signParts as $signPart) {
$rawSign .= '::' . (isset($_SERVER[$signPart]) ? $_SERVER[$signPart] : 'none');
}
return md5($rawSign);
}
private function enter($db, $result)
{
$db->executeQuery("UPDATE users SET sid = '' WHERE id_user = " . $result->getInt('id_user'));
$_SESSION ["group"] = $result->getInt('access');
$_SESSION ["access"] = $result->getInt('id_user'); // id_user
$_SESSION [self::SESSION_BROWSER_SIGN_SECRET] = $this->getBrowserSign();
$_SESSION ["time"] = time();
}
public function execute(HttpRequest $request)
{
if (!$this->isLoggin($request)) {
// Параметры при неправильной авторизации
// Действия по умолчанию !! Возможно переход на форму регистрации
$request->set('module', 'login');
$request->set('mode', $this->mode);
}
return $this->processor->execute($request);
}
}

View file

@ -1,178 +0,0 @@
<?php
/**
* Элемент формы
* @package core
*/
class TField
{
public $name;
public $label; // Метка поля
public $value; // Значение поля
public $type; // Каждому типу элемента соответствует макрос TAL
public $error_msg = null;
public $error = false;
public $require = false;
public function __construct ($input)
{
$this->deafult = null;
if (isset($input['validate'])) {
$this->require = strpos($input['validate'], 'require') !== false;
}
// Инициализация свойст обьетка
foreach (array('label', 'name', 'type') as $name) {
$this->$name = $input[$name];
}
}
function setValue($value)
{
$this->value = $value;
}
}
/**
* Поле ввода Input
* @package core
*/
class TInput extends TField {
}
/**
* Выбор из одного элемента
*/
class TSelect1 extends TField
{
public $options = array ();
public function __construct ($input) {
parent::__construct($input);
$this->options = $input['options'];
}
function setValue($value)
{
// Установить selected у options
$this->value = $value;
}
}
/**
* Поле с датой
* @package core
*/
class TDate extends TField
{
}
/* *
* Текстовое поле
* @package core
*/
class TTextArea extends TField
{
}
/**
* Поле для ввода пароля
* @package core
*/
class TSecret extends TField
{
}
class TUpload extends TField
{
}
/**
* Форма для ввода
* @package core
*/
class TForm
{
public $field = array ();
public $action = "";
public $method = 'post';
protected $replace;
protected $before;
public function __construct ()
{
$this->constructor = array (
'input' => 'TInput',
'date' => 'TDate',
'textarea' => 'TTextArea',
'select' => 'TSelect',
'select1' => 'TSelect1',
'secret' => 'TSecret',
'upload' => 'TUpload'
);
}
/**
* Добавляет одно поле ввода на форму
*/
public function addField (array $init)
{
assert (isset($init['type']));
assert (isset($init['name']));
$constructor = $this->constructor[$init['type']];
$el = new $constructor ($init);
$el->type = $init['type'];
$this->field [$init['name']] = $el;
return $el;
}
/**
* Добавляет спсок полей для формы
* @param array $list
*/
public function addFieldList (array $list)
{
foreach ($list as $init) {
$this->addField ($init);
}
}
/**
* Устанавливает ошибки после проверки
*/
function setError (Validator $validator)
{
foreach ($validator->getErrorMsg() as $name => $error)
{
$this->field[$name]->error = true;
$this->field[$name]->error_msg = $error;
}
}
/**
* Устанавливает значения из масива
*/
function setValues (Collection $request) {
foreach ($this->field as $key => $el) {
$value = $request->getRawData ($this->method, $key);
$this->field[$key]->setValue($value);
}
}
/**
* Заполняет форму данными из обьекта
* @param object $data
* @param array $schema Связь между элементами формы и свойствами обьекта
*/
public function fill ($data, array $schema)
{
foreach ($schema as $key => $value) {
$this->field [$value]->setValue($data->$value->getString ());
}
}
public function set($name, $value)
{
$this->field[$name]->setValue($value);
}
}

View file

@ -1,52 +0,0 @@
<?php
/**
* Генерация файлов Grpahviz dot
*/
class Dot
{
static function getHeader ()
{
$header =
"digraph G {\n"
. "\toverlap=false; splines=true;\n"
. "\tfontname = \"Verdana\"\n"
. "\tfontsize = 8\n"
. "\tnode [\n"
. "\t\tfontname = \"Verdana\"\n"
. "\t\tfontsize = 8\n"
. "\t\tshape = \"record\"\n"
. "\t]\n"
. "\tedge [\n"
. "\t\tfontname = \"Verdana\"\n"
. "\t\tfontsize = 8\n"
. "\t]\n";
return $header;
}
static function getFooter ()
{
$footer = "}\n";
return $footer;
}
function assocToDot (array $array, array $label)
{
$result = array (self::getHeader());
// Метки
foreach ($label as $value) {
$result [] = "\t\"{$value[0]}\" [ label = \"{$value[1]}\" ] \n";
}
// Ассоциации
foreach ($array as $key => $value) {
foreach ($value as $n) {
$result [] = "\t\"$key\" -> \"$n\"\n";
}
}
$result [] = self::getFooter();
return implode("", $result);
}
}
?>

View file

@ -1,85 +0,0 @@
<?php
define ('URL_CLIP', 0);
define ('URL_DIRECTORY', 1);
class HAuthorize {
public $password;
public $uuid;
public $uuid_writeable;
public function __construct () {
$this->uuid = "*";
$this->uuid_writeable = 1;
}
public function getString () {
return "{$this->password};{$this->uuid};{$this->uuid_writeable}";
}
public function setPassword ($username, $realm, $password) {
$this->password = md5 ("$username:$realm:$password");
}
}
class HPermission {
public $url;
public $url_type;
public $permission_type;
public $expires;
public $debitted_time;
public function __construct ($url, $url_type) {
$this->url = $url;
$this->url_type = $url_type;
$this->expires = "*"; // MM/DD/YYYY:HH:MM:SS
$this->permission_type = 0;
$this->debitted_time = 0;
}
public function getString () {
return "{$this->url};{$this->url_type};{$this->permission_type};{$this->expires};{$this->debitted_time}";
}
}
class HFile {
public $authorize;
public $permission = array ();
public function addAuthorize ($name, $realm, $password) {
$this->authorize = new HAuthorize ();
$this->authorize->setPassword ($name, $realm, $password);
}
public function addPermission ($url, $url_type) {
$this->permission[] = new HPermission ($url, $url_type);
}
public function write ($name) {
$file = fopen ($name, 'w');
fwrite ($file, $this->getString ());
fclose ($file);
}
public function writeFTP ($ftp, $path) {
$file = tmpfile ();
fwrite ($file, $this->getString ());
fseek ($file, 0);
ftp_fput ($ftp, $path, $file, FTP_BINARY);
fclose ($file);
}
public function getString () {
$result = array ();
$result[] = $this->authorize->getString ();
$result[] = "\n";
foreach ($this->permission as $p) {
$result[] = $p->getString ();
$result[] = "\n";
}
return implode ("", $result);
}
}

View file

@ -1,12 +0,0 @@
<?php
class Point
{
public $left, $top;
function __construct ($left = 0, $top = 0)
{
$this->left = $left;
$this->top = $top;
}
}

View file

@ -1,51 +0,0 @@
<?php
require_once "core/geometry/point.php";
class Rectangle
{
public $left, $top, $width, $height;
function __construct($left = 0, $top = 0, $width = 0, $height = 0)
{
$this->left = $left;
$this->top = $top;
$this->width = $width;
$this->height = $height;
}
function __get($name)
{
switch ($name) {
case 'right': return $this->left + $this->width;
case 'bottom': return $this->top + $this->height;
}
}
function __set($name, $value)
{
switch ($name) {
case 'right': $this->width = $value - $this->left;
case 'bottom': $this->height = $value - $this->top;
}
}
/**
* Смещает прямоугольник на заданное положение
*/
function addPoint(Point $point)
{
$result = clone $this;
$result->left += $point->left;
$result->top += $point->top;
return $result;
}
/**
* Координаты точки при выравнивании прямоугольника относительно текущего
*/
function alignment(Rectangle $base)
{
return new Point((($base->left + $base->right) - ($this->left + $this->right)) / 2, $base->bottom - $this->height);
}
}

View file

@ -1,28 +0,0 @@
<?php
class ModelFactory
{
static $shortcut = "model";
public function __construct (Connection $db)
{
$this->db = $db;
}
/**
* Создает модель
* @param string $name
* @return model
*/
public function getModel ($name)
{
require_once 'core/mapper/mapper.php'; // ????
require_once (Shortcut::getUrl(self::$shortcut, $name));
$modelName = $name . "Mapper";
$model = new $modelName();
$model->db = $this->db;
$model->factory = $this;
return $model;
}
}

View file

@ -1,267 +0,0 @@
<?php
require_once 'core/primitive.php';
/**
* Использовать интерфейсы чтобы определить какие действия можно совершать с обьектом и таким образом
* Строить набор действий Action и отображений View для обьекта
* Т.к отображение данных может быть не только на таблицу баз данных
* И возможно реализованны все интерфейсы
*/
interface IDataList
{
function findAll (Collection $request, $id = null);
function findById ($id);
function getCount (Collection $request, $id);
}
interface IDataSave
{
function saveTo ($o);
function updateTo ($o);
}
/**
* Отображение таблицы базы данных в обьекты
* Mapper -> DataMapper implements IDataList, IDataSave, IDataSort, IDataDelete ...
*
* @package core
*/
class DataMapper implements IDataList
{
/* Хранить метаданные в статическом свойстве класса для ототбражения ?!, + Скрипт для генерации метаданных!!
*/
public $factory;
public $className; /* Класс на который будет отображаться строчка таблицы */
public $filter = ""; /* */
public $schema = array (); /* Соответствие между свойством обьекта и столбцом, добавить тип для записей !! */
public $database; /* Таблица */
public $index; /* Индексный столбец */
public $db; /* Соединение с базой данных */
public $reference = array (null, null);
public function __construct ()
{
}
public function setRange ($stmt, $page, $size)
{
$stmt->setLimit ($size);
$stmt->setOffset (($page-1) * $size);
}
public function listSQL (array $list)
{
return implode ($list, ",");
}
/**
* Поиск строки в таблице по идентификатору
* @param $id Значение идентификатора
* @return Обьект класса $className
*/
public function findById ($id)
{
// Строки запроса преобразовать в методы (getSQLSelect ...)
// Query::from($this->database)->where ($this->index, "=", $id)->select();
$stmt = $this->db->prepareStatement ("SELECT * FROM ".$this->database." WHERE ".$this->index." = ?");
$stmt->setInt (1, $id);
$rs = $stmt->executeQuery ();
$rs->next ();
return $this->mapOne ($rs);
}
/**
* Преобразует parseResult в обьект
*/
public /* private */ function mapOne ($rs)
{
$result = new $this->className ();
foreach ($this->schema as $key => $value) {
list($value) = $value;
$result->$value->setRes($rs, $key);
}
return $result;
}
public /* private */ function mapAll ($rs)
{
$result = array ();
// Преобразование SQL в обьект
while ($rs->next ()) {
$result[] = $this->mapOne ($rs);
}
return $result;
}
private function clean ($value) {
return strtolower(trim(iconv('utf-8', 'cp1251', $value)));
}
/**
* Преобразует параметры формы в SQL запрос WHERE
* @param array $params
* @param array $schema
* @return string
*/
public function requestToSQL (Collection $request, array $schema)
{
$result = array ();
foreach ($schema as $key => $value) {
$param = $request->get ($key);
if ($param) {
array_push ($result, "lower (".$value.") LIKE '".$this->clean ($param)."%'");
}
}
if (empty ($result)) return null;
return implode ($result, " AND ");
}
/**
* Удаление строк из таблицы с заданными индексами
* @param $list array Массив идентефикаторов
*/
public function deleteList (array $list)
{
// Query::from($this->database)->where($this->index, "in", $list)->delete();
$sql = "DELETE FROM " . $this->database . " WHERE " . $this->index . " IN (" . $this->listSQL ($list) . ")";
return $this->db->executeQuery ($sql);
}
public static function findKey (array $schema, $sort)
{
foreach ($schema as $key => $item) {
list($item) = $item;
if ($item == $sort) {
return $key;
}
}
return $sort;
}
public function getOrder (Collection $request)
{
$order = "";
$sort = $request->get('key');
$desc = ($request->get('desc') == 0)? 'DESC' : 'ASC';
if ($sort) {
$sort = self::findKey ($this->schema, $sort);
$order = " ORDER BY $sort $desc";
}
return $order;
}
/**
* Извлекает список записей из базы данных
*/
public function findAll (Collection $request, $id = null)
{
$name0 = $this->database;
$foreign = $this->reference[1];
// Переписать используя Query !!!
if ($foreign && $id) {
$filter = ($this->filter)?$filter = " AND ".$this->filter: "";
$sql = "SELECT t1.* FROM $name0 as t1 WHERE t1.$foreign = $id " . $filter.self::getOrder($request);
} else {
$filter = ($this->filter)?$filter = " WHERE " . $this->filter: "";
$sql = "SELECT * FROM $name0 " . $filter . self::getOrder($request);
}
$stmt = $this->db->prepareStatement ($sql);
$page = $request->get('page');
$limit = $request->get('size');
if ($page && $limit) {
$this->setRange($stmt, $page, $limit);
}
return $this->mapAll($stmt->executeQuery());
}
public function getCount (Collection $request, $id)
{
$name0 = $this->database;
$foreign = $this->reference[1];
// Переписать используя Query !!!
if ($foreign && $id) {
$filter = ($this->filter)?$filter = " AND " . $this->filter: "";
$sql = "SELECT count(t1.*) as length FROM $name0 as t1 WHERE t1.$foreign = $id " . $filter;
} else {
$filter = ($this->filter)?$filter = " WHERE " . $this->filter: "";
$sql = "SELECT count(*) as length FROM $name0 " . $filter;
}
$rs = $this->db->executeQuery($sql);
$rs->next();
return $rs->getInt('length');
}
/**
* Добавление записи в базу данных
* @param $o Обьект для записи в базу данных
*/
public function saveTo (Model $o)
{
$keys = array ();
$values = array ();
foreach ($this->schema as $key => $value) {
list($value) = $value;
if ($key != $this->index) {
$keys[] = $key;
$values[] = "'".$o->$value."'";
}
}
$stmt = $this->db->prepareStatement ("INSERT INTO ".$this->database." (".implode ($keys, ",").") VALUES (".implode ($values, ",").")");
$stmt->executeQuery ();
}
/**
* Обновляет запись в базе данных
* @param $o Обьект для обновления
*/
public function updateTo (Model $o)
{
$keys_values = array ();
foreach ($this->schema as $key => $value) {
list($value) = $value;
if ($key != $this->index && !($o->$value instanceof FKey)) {
$keys_values[] = $key." = '".$o->$value."'";
}
}
// Для всех должен быть идентефикатор id
$stmt = $this->db->prepareStatement ("UPDATE ".$this->database." SET ".implode($keys_values, ",")." WHERE ".$this->index." = ".$o->id);
$stmt->executeQuery ();
}
function saveDB (Model $o)
{
if ($o->id) {
$this->updateTo($o);
} else {
$this->saveTo($o);
}
}
function getModel($name)
{
require_once 'core/Mapper/Factory.php';
if (!$this->factory) {
$this->factory = new ModelFactory($this->db);
}
return $this->factory->getModel($name);
}
}
/**
*
*/
class Model
{
public function __construct ()
{
foreach (get_class_vars (get_class ($this)) as $key => $value) {
$this->$key = new Primitive ();
}
}
// __get, __set методы. В метаданных хранится тип свойств, проверять при присваивании!!
}
?>

View file

@ -1,78 +0,0 @@
<?php
/**
* Отображение списка папок с настройками на обьект
*/
class PathMapper
{
private $count;
private $base = null;
public $reference = null;
function plane (&$target, Collection $array)
{
$vars = get_class_vars(get_class($target));
foreach ($vars as $name => $value) {
$target->$name = $array->get($name);
}
}
function basePath ()
{
if ( ! $this->base) $this->base = $this->getBasePath();
return $this->base;
}
function findAll (Collection $request, $id = null)
{
require_once "core/settings.php";
require_once "core/path.php";
$this->reference = $id;
$base = $this->basePath ();
$path = new Path($base);
$list = $path->getContent();
$result = array ();
$this->count = 0;
foreach ($list as $name) {
if (is_dir (Path::join($this->basePath (), $name))
&& $module = $this->findById ($name)) {
$this->count++;
$result [] = $module;
}
}
return $result;
}
function findById ($name)
{
$file = Path::join($this->basePath(), $this->getSettingsFile ($name));
if (file_exists($file)) {
$settings = new Settings($file);
$settings->read();
return $this->settingsMap($name, $settings);
}
return null;
}
/**
* Число папок
*/
function getCount ()
{
return $this->count;
}
/**
* Удаление списка папок
*/
function deleteList(array $list)
{
foreach ($list as $name)
Path::delete(Path::join($this->getBasePath(), $name));
}
}
?>

View file

@ -1,113 +0,0 @@
<?php
/**
Copyright (c) 2007 Brady Mulhollem
Permission is hereby granted, free of charge, to any person obtaining a
copy of this software and associated documentation files (the
"Software"), to deal in the Software without restriction, including
without limitation the rights to use, copy, modify, merge, publish,
distribute, sublicense, and/or sell copies of the Software, and to
permit persons to whom the Software is furnished to do so, subject to
the following conditions:
The above copyright notice and this permission notice shall be included
in all copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
**/
class Simple_BB_Code{
//General Tags
var $tags = array('b' => 'strong','i' => 'em','u' => 'span style="text-decoration:underline"','quote' => 'blockquote','s' => 'span style="text-decoration: line-through"', 'list' => 'ul','\*' => 'li');
//Tags that must be mapped to diffierent parts
var $mapped = array('url' => array('a','href',true),'img' => array('img','src',false));
//Tags with atributes
var $tags_with_att = array('color' => array('font','color'),'size' => array('font','size'),'url' => array('a','href'));
//Gotta have smilies
var $smilies = array(':)' => 'smile.gif',':(' => 'frown.gif');
//Config Variables
//Convert new line charactes to linebreaks?
var $convert_newlines = true;
//Parse For smilies?
var $parse_smilies = true;
//auto link urls(http and ftp), and email addresses?
var $auto_links = true;
//Internal Storage
var $_code = '';
function Simple_BB_Code($new=true,$parse=true,$links=true){
$this->convert_newlines = $new;
$this->parse_smilies = $parse;
$this->auto_links = $links;
}
function parse($code){
$this->_code = $code;
$this->_strip_html();
$this->_parse_tags();
$this->_parse_mapped();
$this->_parse_tags_with_att();
$this->_parse_smilies();
$this->_parse_links();
$this->_convert_nl();
return $this->_code;
}
function _strip_html(){
$this->_code = strip_tags($this->_code);
}
function _convert_nl(){
if($this->convert_newlines){
$this->_code = nl2br($this->_code);
}
}
function _parse_tags(){
foreach($this->tags as $old=>$new){
$ex = explode(' ',$new);
$this->_code = preg_replace('/\['.$old.'\](.+?)\[\/'.$old.'\]/is','<'.$new.'>$1</'.$ex[0].'>',$this->_code);
}
}
function _parse_mapped(){
foreach($this->mapped as $tag=>$data){
$reg = '/\['.$tag.'\](.+?)\[\/'.$tag.'\]/is';
if($data[2]){
$this->_code = preg_replace($reg,'<'.$data[0].' '.$data[1].'="$1">$1</'.$data[0].'>',$this->_code);
}
else{
$this->_code = preg_replace($reg,'<'.$data[0].' '.$data[1].'="$1">',$this->_code);
}
}
}
function _parse_tags_with_att(){
foreach($this->tags_with_att as $tag=>$data){
$this->_code = preg_replace('/\['.$tag.'=(.+?)\](.+?)\[\/'.$tag.'\]/is','<'.$data[0].' '.$data[1].'="$1">$2</'.$data[0].'>',$this->_code);
}
}
function _parse_smilies(){
if($this->parse_smilies){
foreach($this->smilies as $s=>$im){
$this->_code = str_replace($s,'<img src="'.$im.'">',$this->_code);
}
}
}
function _parse_links(){
if($this->auto_links){
$this->_code = preg_replace('/([^"])(http:\/\/|ftp:\/\/)([^\s,]*)/i','$1<a href="$2$3">$2$3</a>',$this->_code);
$this->_code = preg_replace('/([^"])([A-Z0-9._%-]+@[A-Z0-9.-]+\.[A-Z]{2,4})/i','$1<a href="mailto:$2">$2</a>',$this->_code);
}
}
function addTag($old,$new){
$this->tags[$old] = $new;
}
function addMapped($bb,$html,$att,$end=true){
$this->mapped[$bb] = array($html,$att,$end);
}
function addTagWithAttribute($bb,$html,$att){
$this->tags_with_att[$bb] = array($html,$att);
}
function addSmiley($code,$src){
$this->smilies[$code] = $src;
}
}
?>

View file

@ -1,317 +0,0 @@
<?php
/*.
require_module 'standard';
.*/
/**
* Класс для работы с папками и путями
* Для итерации над файлами возможно лучше использовать SPL
*
* @package utils
*/
class Path
{
const SEPARATOR = "/";
protected $path;
public function __construct ($path)
{
assert(is_string($path));
$this->path = $this->fromString($path);
$this->optimize();
}
static function factory($path) {
return new Path($path);
}
/**
* Возвращает расширение файла
*
* @param string $fileName Полное имя файла
*
* @return string
*/
static function getExtension ($fileName)
{
assert(is_string($fileName));
return pathinfo($fileName, PATHINFO_EXTENSION);
}
/**
* Полное имя файла без расширения
*
* @param string $fileName Имя файла
*
* @return string
*/
static function skipExtension ($fileName)
{
assert(is_string($fileName));
$path = pathinfo($fileName);
if ($path['dirname'] == ".") {
return $path['filename'];
} else {
return self::join($path['dirname'], $path['filename']);
}
}
/**
* Возвращает имя файла без расширения
*
* @param string $fileName Полное имя файла
*
* @return string
*/
static function getFileName ($fileName)
{
assert(is_string($fileName));
return pathinfo($fileName, PATHINFO_FILENAME);
}
/**
* Список файлов в директории
*
* @param array $allow массив расширений для файлов
* @param array $ignore массив имен пааок которые не нужно обрабатывать
*
* @return array
*/
public function getContent ($allow = null, $ignore = array())
{
$ignore = array_merge(array (".", "..", $ignore));
return self::fileList($this->__toString(), $allow, $ignore);
}
// Использовать SPL ???
protected function fileList ($base, &$allow, &$ignore)
{
$result = array ();
if ($handle = opendir($base)) {
while (false !== ($file = readdir($handle))) {
if (! in_array ($file, $ignore)) {
$isDir = is_dir (Path::join ($base, $file));
if ($isDir || ($allow == null) || in_array (self::getExtension($file), $allow)) {
$result[] = $file;
}
}
}
closedir($handle);
}
return $result;
}
protected function fileListAll (&$result, $base, &$allow, &$ignore)
{
$files = self::fileList($base, $allow, $ignore);
foreach ($files as $name) {
$fullname = self::join($base, $name);
if (is_dir($fullname)) {
self::fileListAll($result, $fullname, $allow, $ignore);
} else {
array_push ($result, $fullname);
}
}
}
/**
* Список файлов в директориии и ее поддиректорий
*
* @param array $allow массив расширений разрешеных для файлов
* @param array $ignore массив имен пааок которые не нужно обрабатывать
*
* @return array
*/
function getContentRec ($allow = null, $ignore = array())
{
$result = array ();
$ignore = array_merge(array (".", ".."), $ignore);
self::fileListAll($result, $this->__toString(), $allow, $ignore);
return $result;
}
/**
* Рекурсивно копирует директорию
*
* @param string $source Папка из которой копируется
* @param string $target Папка в которую копируется
*/
public static function copy ($source, $target)
{
if (is_dir($source)) {
if (! file_exists($target)) mkdir ($target);
$path = new Path($source);
$files = $path->getContent();
foreach ($files as $file) {
$entry = self::join($source, $file);
if (is_dir($entry)) {
self::copy($entry, Path::join($target, $file));
} else {
copy($entry, Path::join($target, $file));
}
}
}
}
/**
* Рекурсивно удаляет директорию
*
* @param string $path Папка
*/
public static function delete ($path)
{
assert(is_string($path));
if (is_dir($path)) {
foreach(glob($path . '/*') as $sf) {
if (is_dir($sf) && !is_link($sf)) {
self::delete($sf);
} else {
unlink($sf);
}
}
rmdir($path);
}
}
/**
* Преобразует строку путя в массив
*
* @param string $path Путь
*
* @return array
*/
public function fromString ($path)
{
assert(is_string($path));
$list = preg_split("/[\/\\\\]/", $path);
return $list;
}
/**
* Преобразует относительный путь в абсолютный
*/
public function optimize ()
{
$result = array(current($this->path));
while (next($this->path) !== false) {
$n = current ($this->path);
switch ($n) {
case "": break;
case ".": break;
case "..": if (count($result) > 0) array_pop($result); break;
default:
array_push($result, $n);
}
}
reset($this->path);
$this->path = $result;
}
/**
* Преобразует путь в строку
*
* @return string
*/
public function __toString ()
{
$result = implode($this->path, self::SEPARATOR);
return $result;
}
/**
* Проверяет является ли папка родительской для другой папки
*
* @parma Path $path
*
* @return boolean
*/
public function isParent ($path)
{
if (count($path->path) > count($this->path)) {
for ($i = 0; $i < count($this->path); $i++) {
if ($path->path[$i] != $this->path[$i]) {
return false;
}
}
return true;
}
return false;
}
/**
* Находит путь относительно текущего путя
*
* @param string $name Полный путь к файлу
*
* @return string Относительный путь к файлу
*/
public function relPath ($name)
{
$path = new Path ($name);
foreach ($this->path as $n) {
array_shift($path->path);
}
return $path->__toString();
}
public function append ($path)
{
$base = $this->__toString();
return self::join($base, $path);
}
/**
* Создает недастающие папки для записи файла
*
* @param string $dst Полное имя файла
*
* @return void
*/
static function prepare ($dst)
{
$path_dst = pathinfo($dst, PATHINFO_DIRNAME);
if (! file_exists($path_dst)) {
mkdir($path_dst, 0700, true);
}
}
/**
* Подбирает новое временное имя для файла
*
* @param string $dst Предпологаемое имя файла
*
* @return string Новое имя файла
*/
static function resolveFile ($dst)
{
$i = 0;
$file = self::skipExtension($dst);
$suffix = self::getExtension($dst);
$temp = $dst;
while (file_exists($temp)) {
$i ++;
$temp = $file . "." . $i . "." . $suffix;
}
return $temp;
}
/**
* Обьединяет строки в путь соединяя необходимым разделителем
*
* @return string
*/
static function join ()
{
$args = func_get_args();
return implode(self::SEPARATOR, $args);
}
}

View file

@ -1,105 +0,0 @@
<?php
/**
* Класс преобразования типа значения поля класса в тип поля таблицы
* @package core
*/
class Primitive
{
public $value;
public $name;
public function __construct ($name = "")
{
$this->name = $name;
}
// Преобразование из внешнего вормата
public function setString ($value)
{
$this->value = $value;
}
// Преобразование из формата базы данных
public function setRes ($res, $key)
{
$this->value = $res->getString ($key);
}
public function __toString ()
{
return ((string) $this->value);
}
// Преобразование во внешний формат
public function getString ()
{
return $this->__toString ();
}
}
/**
* Отображение поля таблицы в целое число
* @package core
*/
class Int4 extends Primitive {
public function setRes ($res, $key) {
$this->value = $res->getInt ($key);
}
public function setString ($value) {
$this->value = ((int) $value);
}
}
/* Foreign key */
class FKey extends Int4 {}
/**
* Отображение поля таблицы в дату - время
*/
class Date extends Primitive
{
public function setRes ($res, $key)
{
$this->value = $res->getInt ($key);
}
public function setString ($value)
{
$this->value = 0;
if ($tmp = explode("/",$value,3)) {
if ($tmp[1] && $tmp[0] && $tmp[2]) {
if (checkdate($tmp[1], $tmp[0], $tmp[2])) {
$this->value = mktime(0, 0, 0, $tmp[1], $tmp[0], $tmp[2]);
}
}
}
}
public function getString ()
{
return date ("d/m/Y", $this->value);
}
}
/**
*
*/
class Password extends Primitive
{
public function setRes ($res, $key)
{
$this->value = $res->getString($key);
}
public function setString ($value)
{
$this->value = md5($value);
}
public function getString ()
{
return $this->value;
}
}
?>

View file

@ -1,9 +0,0 @@
<?php
/**
* Класс метаданных таблицы
*/
class Meta
{
}

View file

@ -1,205 +0,0 @@
<?php
require_once 'table.php';
require_once 'meta.php';
/**
* Класс для составления запроса
*/
class Query
{
static $alias = 0;
public $table;
public $filter = array ();
public $calc = array ();
public $order = array ();
/**
* Создает пустой зарос
*/
static function create()
{
return new Query();
}
/**
* Метаданные таблицы
* @param string $name Имя таблицы
*/
function getTableMeta($name)
{
}
/**
* Создает новый запрос
* @param string $name Имя таблицы
*
* @return Query
*/
public function from($name)
{
$result = clone $this;
$table = new Table();
$table->type = 'simple';
$table->name = $name;
$table->alias = "t" . self::$alias++;
$result->table = $table;
return $result;
}
/**
* Добавляет к запросу условие
* @param string $field Имя поля таблицы
* @param string $op Имя оператора
* @param $value Значение поля
*
* @return Query
*/
public function filter($field, $op, $value)
{
$result = clone $this;
$result->filter [] = $result->table->alias ."." . $field . $op . "'" . $value . "'";
return $result;
}
/**
* @param string $e Выражение
*/
public function calc($e)
{
$result = clone $this;
$result->calc [] = $e;
return $result;
}
public function joinOn($first, $e)
{
$result = $this->compose($first, array ('filter', 'calc', 'order'));
$e = strtr($e, array ("a." => $this->table->alias . ".",
"b." => $first->table->alias . "."));
$table = new Table ();
$table->type = 'join';
$table->name = $this->table->name;
$table->alias = $this->table->alias;
$table->join = $first->table;
$table->condition = $e;
$result->table = $table;
return $result;
}
/**
* Обьединяет параметры двух заросов
* @param Query $first
* @pram array $list Список параметров
*
* @return Query
*/
private function compose(Query $first, array $list)
{
$result = new Query();
foreach ($list as $name) {
$result->$name = array_merge($this->$name, $first->$name);
}
return $result;
}
/**
* Заковычивает значение
*/
public function quote ($value)
{
return "'" . $value . "'";
}
/**
* Компиляция таблицы
* @param Table $table
*
* @return string Часть строки SQL
*/
private function table(Table $table)
{
if ($table->type == 'simple') {
return $table->name ." AS ".$table->alias;
}
if ($table->type == 'join') {
return $table->name ." AS ".$table->alias. " JOIN " . $this->table ($table->join) . " ON " . $table->condition;
}
return "";
}
/**
* Компиляция WHERE
*
* @return string Часть строки SQL
*/
private function where ()
{
return implode(" AND ", $this->filter);
}
/**
* Компиляция запроса в SELECT SQL
*
* @return string SQL выражение
*/
public function select()
{
return "SELECT "
. ((!empty($this->calc))? implode (",", $this->calc): "*")
. " FROM " . $this->table($this->table)
. ((!empty ($this->filter))? " WHERE " . $this->where() : "");
}
/**
* Компиляция в DELETE
*/
public function delete()
{
return "DELETE FROM " . $this->table->name
. ((!empty ($this->filter))? " WHERE " . $this->where() : "");
}
private function add_prefix($prefix, $array) {
$result = array();
foreach ($array as $value) {
$result [] = $prefix . $value;
}
return $result;
}
/**
* Компиляция в UPDATE
* TODO: Разные типы запросов Query->update(); Query->select(), Query->insert();!!
* Возвраащают statement
*/
public function update($values)
{
$pairs = array ();
foreach ($values as $key => $value) { //
$pairs [] = $key . "=" . $this->quote ($value);
}
return "UPDATE " . $this->table->name . " SET "
. implode(",", $pairs)
. ((!empty($this->filter))? " WHERE " . $this->where() : "");
}
/**
* Компиляция в INSERT
*/
public function insert($values)
{
return "INSERT INTO ". $this->table->name . "("
. implode(",", array_keys($values))
. ") VALUES (" . implode(",", array_map(array($this, 'quote'), array_values($values))) . ")";
}
}

View file

@ -1,14 +0,0 @@
<?php
/**
* Класс таблицы
*/
class Table
{
public $type = 'simple';
public $name;
public $alias;
public $join;
public $condition;
}

View file

@ -1,35 +0,0 @@
<?php
require_once 'core/collection.php';
class SafeCollection extends Collection
{
protected function _clean()
{
if(get_magic_quotes_gpc()) {
$this->data = $this->_stripSlashes($this->data);
}
$this->data = $this->data;
}
function import(array $data)
{
parent::import($data);
$this->_clean();
}
/**
* Strip slashes code from php.net website.
*
* @param mixed $value
* @return array
*/
protected function _stripSlashes($value)
{
if(is_array($value)) {
return array_map(array($this,'_stripSlashes'), $value);
} else {
return stripslashes($value);
}
}
}

View file

@ -1,59 +0,0 @@
<?php
require_once 'core/path.php';
require_once 'creole/util/sql/SQLStatementExtractor.php';
/**
* Обработка файлов для установки
*/
class Setup
{
/**
* Содержимое PHP файла
*/
static function fileContent($file, array $tpl)
{
ob_start();
include $file;
$result = ob_get_contents();
ob_clean();
return $result;
}
/**
* Копирует файлы шаблонной директории
*/
static function copyTemplatePath($srcPath, $dstPath, array $tpl, $tplFile = 'tpl')
{
$out = new Path($srcPath);
$path = new Path($dstPath);
$files = $path->getContentRec(null, array(".svn"));
foreach ($files as $file) {
if (Path::getExtension($file) == $tplFile) {
// Шаблон
$dst = $out->append($path->relPath (Path::skipExtension($file)));
Path::prepare($dst);
file_put_contents($dst, self::fileContent($file, $tpl));
} else {
// Обычный файл
$dst = $out->append($path->relPath ($file));
Path::prepare($dst);
copy($file, $dst);
}
}
}
/**
* Выполнение Списка SQL команд
*/
static function batchSQL(Connection $conn, $file)
{
$stmtList = SQLStatementExtractor::extractFile ($file);
foreach ($stmtList as $stmt) {
$conn->executeQuery ($stmt);
}
}
}
?>

View file

@ -1,100 +0,0 @@
<?php
require_once 'core/search/htmlhelper.php';
/**
* Функции для проверки орфографии
* rename Spell -> SpellHelper ??
*/
class Spell
{
private $pspell;
public $autocorrect = false;
public function __construct ($language, $encoding)
{
$this->pspell = pspell_new($language, '', '', $encoding, PSPELL_NORMAL);
}
function spellCheckWord ($word)
{
$word = $word[0];
// Ignore ALL CAPS
if (preg_match('/^[A-Z0-9]*$/', $word)) return $word;
// Return dictionary words
if (pspell_check($this->pspell, $word))
return $word;
// Auto-correct with the first suggestion, color green
if ($this->autocorrect && $suggestions = pspell_suggest($this->pspell, $word))
return '<span class="spell-suggest">' . current($suggestions) . '</span>';
// No suggestions, color red
return '<span class="spell-nosuggest">' . $word . '</span>';
}
function isGoodWord ($word)
{
// Ignore ALL CAPS
if (preg_match('/^[A-Z]*$/', $word)) return true;
if (preg_match('/^[0-9]*$/', $word)) return true;
// Return dictionary words
if (pspell_check($this->pspell, $word))
return true;
return false;
}
function suggest ($string)
{
return preg_replace_callback('/\b\w+\b/', array($this, 'spellCheckWord'), $string);
}
/**
* Вызывает функцию для каждого найденного слова
*/
function eachWord ($call, $string)
{
$begin = indexLeft ($string, 'ctype_alpha', 0);
while ($begin !== false) {
$end = indexLeft ($string, 'not_ctype_alpha', $begin);
call_user_func ($call, $string, $begin, $end);
$begin = indexLeft ($string, 'ctype_alpha', $end);
}
return false;
}
/**
* Проверяет слово на соответствие со словарем
*
*/
function doWord (&$string, $begin, $end)
{
$word = substr($string, $begin, $end - $begin);
if (! $this->isGoodWord ($word)) {
$start = max(indexLeft ($string, 'not_ctype_alpha', $begin - 100), 0);
$offset = indexLeft ($string, 'not_ctype_alpha', $end + 100);
if (! $offset) {
$offset = strlen($string);
}
$length = $offset - $start;
throw new Exception ($this->suggest(substr($string, $start, $length)));
}
}
/**
* Часть текста содержащий неправильное слово
*/
function getError ($string)
{
try {
self::eachWord (array ($this, 'doWord'), $string);
} catch (Exception $e) {
return $e->getMessage();
}
return false;
}
}
?>

View file

@ -1,69 +0,0 @@
<?php
/**
* Преобразование дерева из модели Plain в массив массивов (Adjacency List)
*/
require_once 'core/functions.php';
define (SORT_DESC, 0); // descending
define (SORT_ASC, 1); // ascending
/**
* Выбирает все сроки из таблицы с уникальными значениями ключа
* @param $name Имя ключа
* @param $table Двухмерный массив
* @example
* key_unique_values ('name', array (array ('name' => 1), array ('name' => 2), array ('name' => 1)))
=> array (1, 2)
* @end example
*/
function key_unique_values ($name, $table) {
// Ищем уникальные значения для заданного ключа
$keys = array ();
foreach ($table as $row) {
if (!in_array ($row[$name], $keys))
$keys[] = $row[$name];
}
return $keys;
}
/**
* Сортировка двумерного массива по заданному ключу
* @param $array Массив
* @param $key Имя ключа по значению которого будет идти сравнение
* @return Отсортированный массив
*/
function sortOn($array, $key, $fn = '__cmp') {
usort ($array, rcurry($fn, $key));
//usort ($array, create_function ('$x,$y', 'return __cmp ($x, $y, "'.$key.'");'));
return $array;
}
/**
* Обходит таблицу как дерево
* @param $level Array Уровни вложенности
* @param $table Таблица
* @param $fn Функция которая применяется к каждой ветке дерева
* $fn ($name, $index, $rows, $cc)
* @param $name Ключ уровня
* @param $index Значение ключа уровня
* @param $rows Все столбцы текущго уровня
* @parma $cc Столбцы более низкого уровня
*/
function tableTreeWalk($level, $table, $fn) {
if (empty ($level)) return $table;
$name = array_shift ($level);
$keys = key_unique_values($name, $table);
$data = array ();
foreach ($keys as $index) {
list($rows, $table) = partition (lcurry('__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, tableTreeWalk ($level, $rows, $fn));
}
return $data;
}

View file

@ -1,34 +0,0 @@
<?php
/**
* Расширения для PHPTAL для отображения времени и даты
* package utils
*/
class DateTime_Tales implements PHPTAL_Tales
{
static public function date ($expression, $nothrow = false)
{
return "phptal_date(".PHPTAL_TalesInternal::path ($expression).")";
}
static public function time ($expression, $nothrow = false)
{
return "phptal_time(".PHPTAL_TalesInternal::path ($expression).")";
}
}
/* Регистрация нового префикса для подключения компонента */
$registry = PHPTAL_TalesRegistry::getInstance();
$registry->registerPrefix('date', array('DateTime_Tales', 'date'));
$registry->registerPrefix('time', array('DateTime_Tales', 'time'));
function phptal_date ($e)
{
return date ("d.m.Y", $e);
}
function phptal_time ($e)
{
return date ("H:i", $e);
}

View file

@ -1,32 +0,0 @@
<?php
function generatePassword($length = 9, $strength = 0) {
$vowels = 'aeuy';
$consonants = 'bdghjmnpqrstvz';
if ($strength & 1) {
$consonants .= 'BDGHJLMNPQRSTVWXZ';
}
if ($strength & 2) {
$vowels .= "AEUY";
}
if ($strength & 4) {
$consonants .= '23456789';
}
if ($strength & 8) {
$consonants .= '@#$%';
}
$password = '';
$alt = time() % 2;
for ($i = 0; $i < $length; $i++) {
if ($alt == 1) {
$password .= $consonants[(rand() % strlen($consonants))];
$alt = 0;
} else {
$password .= $vowels[(rand() % strlen($vowels))];
$alt = 1;
}
}
return $password;
}

View file

@ -1,37 +0,0 @@
<?php
// from creole
function strToArray($str)
{
$str = substr($str, 1, -1); // remove { }
$res = array();
$subarr = array();
$in_subarr = 0;
$toks = explode(',', $str);
foreach($toks as $tok) {
if ($in_subarr > 0) { // already in sub-array?
$subarr[$in_subarr][] = $tok;
if ('}' === substr($tok, -1, 1)) { // check to see if we just added last component
$res[] = $this->strToArray(implode(',', $subarr[$in_subarr]));
$in_subarr--;
}
} elseif ($tok{0} === '{') { // we're inside a new sub-array
if ('}' !== substr($tok, -1, 1)) {
$in_subarr++;
// if sub-array has more than one element
$subarr[$in_subarr] = array();
$subarr[$in_subarr][] = $tok;
} else {
$res[] = $this->strToArray($tok);
}
} else { // not sub-array
$val = trim($tok, '"'); // remove " (surrounding strings)
// perform type castng here?
$res[] = $val;
}
}
return $res;
}

View file

@ -1,94 +0,0 @@
<?php
class TableExcelView {
private $list = array();
private $data = array();
function setColumns(array $list) {
$this->list = $list;
}
function makeTable() {
$xls = new ExcelTable();
$xls->setRow(1, 1, array_keys($this->list));
foreach($this->data as $n => $item) {
$result = array();
foreach($this->list as $key => $c) {
if (is_callable($c)) {
$result [] = call_user_func($c, $item, $n);
} else {
if (is_numeric($item[$c])) {
$result [] = new Excel_Number($item[$c]);
} else {
$result [] = $item[$c];
}
}
}
$xls->addRow(1, $result);
}
return $xls;
}
function writeTable($data, $file) {
$this->data = $data;
$xls = new ExcelDocument();
$xls->addTable(array($this, 'makeTable'));
$xls->save($file);
}
}
class TableHTMLView {
private $list = array();
private $stack = array();
private $result = array();
function writeElement($name, $content) {
echo "<".$name.">";
echo $content;
echo "</".$name.">";
}
function startElement($name) {
array_push($this->stack, $name);
echo "<".$name.">";
}
function endElement() {
$name = array_pop($this->stack);
echo "</".$name.">";
}
function setColumns(array $list) {
$this->list = $list;
}
function writeTable($data) {
$this->startElement('table');
$this->startElement('thead');
$this->startElement('tr');
foreach($this->list as $key => $c) {
$this->writeElement('th', $key);
}
$this->endElement();
$this->endElement();
$this->startElement('tbody');
foreach($data as $n => $item) {
$this->startElement('tr');
foreach($this->list as $key => $c) {
if (is_callable($c)) {
$this->writeElement('td', call_user_func($c, $item, $n));
} else {
$this->writeElement('td', $item[$c]);
}
}
$this->endElement();
}
$this->endElement();
$this->endElement();
}
}

View file

@ -1,14 +0,0 @@
<?php
function translit($st) {
$st = strtr($st,"абвгдеёзийклмнопрстуфхъыэ !№", "abvgdeeziyklmnoprstufh_ie__#");
$st = strtr($st,"АБВГДЕЁЗИЙКЛМНОПРСТУФХЪЫЭ", "ABVGDEEZIYKLMNOPRSTUFH_IE");
$st = strtr($st, array(
"ж"=>"zh", "ц"=>"ts", "ч"=>"ch", "ш"=>"sh",
"щ"=>"shch","ь"=>"", "ю"=>"yu", "я"=>"ya",
"Ж"=>"ZH", "Ц"=>"TS", "Ч"=>"CH", "Ш"=>"SH",
"Щ"=>"SHCH","Ь"=>"", "Ю"=>"YU", "Я"=>"YA",
"ї"=>"i", "Ї"=>"Yi", "є"=>"ie", "Є"=>"Ye"
));
return $st;
}

View file

@ -1,135 +0,0 @@
<?php
//****************************************************************************
// phpDatabase 2.1
//****************************************************************************
// Author: Maxim Poltarak <maxx at e dash taller dot net>
// Category: Databases
//****************************************************************************
// The lib is FREEWARE. This means you may use it anywhere you want, you may
// do anything with it. The Author mentioned above is NOT responsible for any
// consequences of using this library.
// If you don't agree with this, you MAY NOT use the lib!
//****************************************************************************
// All improvings, feature requests, bug reports, etc. are gladly accepted.
//****************************************************************************
// Note: For best viewing of the code Tab size 4 is recommended
//****************************************************************************
class CDatabase
{
var $link;
var $db;
var $host, $user, $pass;
function CDatabase($db, $host = "localhost", $user = "", $pass = "")
{
$this->db = $db;
$this->host = $host;
$this->user = $user;
$this->pass = $pass;
$str = "host={$host} port=5432 dbname={$db} user={$user} password={$pass}";
$this->link = pg_connect($str);
}
function query($sql)
{
if (!$this->link) return 0;
return pg_query($this->link, $sql);
}
function affected_rows()
{
return pg_affected_rows($this->link);
}
function num_rows($q)
{
return pg_num_rows($q);
}
function fetch_array($q) // fetchAll
{
return pg_fetch_array($q, NULL);
}
function fetch_object($q) // fetchObject
{
return pg_fetch_object($q);
}
/* function data_seek($q, $n) {
return pg_data_seek($q, $n);
}
*/
function free_result($q)
{
return pg_free_result($q);
}
function insert_id($seq)
{
$query = "SELECT currval('$seq')";
$res = $this->query($query);
$row = pg_fetch_array($res, NULL, PGSQL_ASSOC);
pg_free_result($res);
return ($row) ? $row['currval'] : 0;
}
function error()
{
return pg_last_error($this->link);
}
function error_die($msg = '')
{
die(((empty($msg)) ? '' : $msg . ': ') . $this->error());
}
function sql2var($sql)
{
if ((empty($sql)) || (!($query = $this->query($sql)))) return false;
if ($this->num_rows($query) < 1) return false;
return $this->result2var($query);
}
function result2var($q)
{
if (!($Data = $this->fetch_array($q))) return false;
$this->free_result($q);
foreach($Data as $k => $v) $GLOBALS[$k] = $v;
return true;
}
/*function sql2array($sql, $keyField = '')
{
if ((empty($sql)) || (!($query = $this->query($sql)))) return false;
if ($this->num_rows($query) < 1) return false;
return $this->result2array($query, $keyField);
}*/
function result2array($q, $keyField = '')
{
$Result = array();
while ($Data = $this->fetch_array($q))
if (empty($keyField)) $Result[] = $Data;
else $Result[$Data[$keyField]] = $Data;
$this->free_result($q);
return $Result;
}
/*function list_tables()
{
return mysql_list_tables($this->db, $this->link);
}
function list_fields($table_name)
{
return mysql_list_fields($this->db, $table_name, $this->link);
}*/
};

View file

@ -1,636 +0,0 @@
<?php
//****************************************************************************
// phpDBTree 1.4
//****************************************************************************
// Author: Maxim Poltarak <maxx at e dash taller dot net>
// WWW: http://dev.e-taller.net/dbtree/
// Category: Databases
// Description: PHP class implementing a Nested Sets approach to storing
// tree-like structures in database tables. This technique was
// introduced by Joe Celko <http://www.celko.com/> and has some
// advantages over a widely used method called Adjacency Matrix.
//****************************************************************************
// The lib is FREEWARE. That means you may use it anywhere you want, you may
// do anything with it. The Author mentioned above is NOT responsible for any
// consequences of using this library.
// If you don't agree with this, you are NOT ALLOWED to use the lib!
//****************************************************************************
// You're welcome to send me all improvings, feature requests, bug reports...
//****************************************************************************
// SAMPLE DB TABLE STRUCTURE:
//
// CREATE TABLE categories (
// cat_id INT UNSIGNED NOT NULL AUTO_INCREMENT,
// cat_left INT UNSIGNED NOT NULL,
// cat_right INT UNSIGNED NOT NULL,
// cat_level INT UNSIGNED NOT NULL,
// PRIMARY KEY(cat_id),
// KEY(cat_left, cat_right, cat_level)
// );
//
// This is believed to be the optimal Nested Sets use case. Use `one-to-one`
// relations on `cat_id` field between this `structure` table and
// another `data` table in your database.
//
// Don't forget to make a single call to clear()
// to set up the Root node in an empty table.
//
//****************************************************************************
// NOTE: Although you may use this library to retrieve data from the table,
// it is recommended to write your own queries for doing that.
// The main purpose of the library is to provide a simpler way to
// create, update and delete records. Not to SELECT them.
//****************************************************************************
//
// IMPORTANT! DO NOT create either UNIQUE or PRIMARY keys on the set of
// fields (`cat_left`, `cat_right` and `cat_level`)!
// Unique keys will destroy the Nested Sets structure!
//
//****************************************************************************
// CHANGELOG:
// 16-Apr-2003 -=- 1.1
// - Added moveAll() method
// - Added fourth parameter to the constructor
// - Renamed getElementInfo() to getNodeInfo() /keeping BC/
// - Added "Sample Table Structure" comment
// - Now it trigger_error()'s in case of any serious error, because if not you
// will lose the Nested Sets structure in your table
// 19-Feb-2004 -=- 1.2
// - Fixed a bug in moveAll() method?
// Thanks to Maxim Matyukhin for the patch.
// 13-Jul-2004 -=- 1.3
// - Changed all die()'s for a more standard trigger_error()
// Thanks to Dmitry Romakhin for pointing out an issue with
// incorrect error message call.
// 09-Nov-2004 -=- 1.4
// - Added insertNear() method.
// Thanks to Michael Krenz who sent its implementation.
// - Removed IGNORE keyword from UPDATE clauses in insert() methods.
// It was dumb to have it there all the time. Sorry. Anyway, you had
// to follow the important note mencioned above. If you hadn't, you're
// in problem.
//
//****************************************************************************
// Note: For best viewing of the code Tab size 4 is recommended
//****************************************************************************
function _case($c, $then, $else) {
return " (CASE WHEN $c THEN $then ELSE $else END) ";
}
function _between($a, $x, $y) {
return " " . $a . " BETWEEN " . $x . " AND " . $y;
}
function _inside($a, $x, $y) {
return " " . $a . " > " . $x . " AND " . $a . " < " . $y;
}
class CDBTree
{
var $db; // CDatabase class to plug to
var $table; // Table with Nested Sets implemented
var $id; // Name of the ID-auto_increment-field in the table.
// These 3 variables are names of fields which are needed to implement
// Nested Sets. All 3 fields should exist in your table!
// However, you may want to change their names here to avoid name collisions.
var $left = 'cat_left';
var $right = 'cat_right';
var $level = 'cat_level';
var $qryParams = '';
var $qryFields = '';
var $qryTables = '';
var $qryWhere = '';
var $qryGroupBy = '';
var $qryHaving = '';
var $qryOrderBy = '';
var $qryLimit = '';
var $sqlNeedReset = true;
var $sql; // Last SQL query
//************************************************************************
// Constructor
// $DB : CDatabase class instance to link to
// $tableName : table in database where to implement nested sets
// $itemId : name of the field which will uniquely identify every record
// $fieldNames : optional configuration array to set field names. Example:
// array(
// 'left' => 'cat_left',
// 'right' => 'cat_right',
// 'level' => 'cat_level'
// )
function CDBTree(&$DB, $tableName, $itemId, $seq, $fieldNames = array())
{
if (empty($tableName)) trigger_error("phpDbTree: Unknown table", E_USER_ERROR);
if (empty($itemId)) trigger_error("phpDbTree: Unknown ID column", E_USER_ERROR);
$this->seq = $seq;
$this->db = $DB;
$this->table = $tableName;
$this->id = $itemId;
if (is_array($fieldNames) && sizeof($fieldNames))
foreach($fieldNames as $k => $v) $this->$k = $v;
}
//************************************************************************
// Returns a Left and Right IDs and Level of an element or false on error
// $ID : an ID of the element
function getElementInfo($ID)
{
return $this->getNodeInfo($ID);
}
function getNodeInfo($ID)
{
$this->sql = 'SELECT ' . $this->left . ',' . $this->right . ',' . $this->level . ' FROM ' . $this->table . ' WHERE ' . $this->id . '=\'' . $ID . '\'';
// print_r($this->sql);
if (($query = $this->db->query($this->sql)) && ($this->db->num_rows($query) == 1) && ($Data = $this->db->fetch_array($query))) return array(
(int)$Data[$this->left],
(int)$Data[$this->right],
(int)$Data[$this->level]
);
else trigger_error("phpDbTree error: " . $this->db->error() , E_USER_ERROR); // throw new Exception();
}
//************************************************************************
// Clears table and creates 'root' node
// $data : optional argument with data for the root node
function clear($data = array())
{
// clearing table
if ((!$this->db->query('TRUNCATE ' . $this->table)) && (!$this->db->query('DELETE FROM ' . $this->table))) trigger_error("phpDbTree error: " . $this->db->error() , E_USER_ERROR);
// preparing data to be inserted
if (sizeof($data)) {
$fld_names = implode(',', array_keys($data)) . ',';
if (sizeof($data)) $fld_values = '\'' . implode('\',\'', array_values($data)) . '\',';
}
$fld_names.= $this->left . ',' . $this->right . ',' . $this->level;
$fld_values.= '1,2,0';
// inserting new record
$this->sql = 'INSERT INTO ' . $this->table . '(' . $fld_names . ') VALUES(' . $fld_values . ')';
if (!($this->db->query($this->sql))) trigger_error("phpDbTree error: " . $this->db->error() , E_USER_ERROR);
return $this->db->insert_id($this->seq);
}
//************************************************************************
// Updates a record
// $ID : element ID
// $data : array with data to update: array(<field_name> => <fields_value>)
function update($ID, $data)
{
$sql_set = '';
foreach($data as $k => $v) $sql_set.= ',' . $k . '=\'' . addslashes($v) . '\'';
return $this->db->query('UPDATE ' . $this->table . ' SET ' . substr($sql_set, 1) . ' WHERE ' . $this->id . '=\'' . $ID . '\'');
}
//************************************************************************
// Inserts a record into the table with nested sets
// $ID : an ID of the parent element
// $data : array with data to be inserted: array(<field_name> => <field_value>)
// Returns : true on success, or false on error
function insert($ID, $data)
{
if (!(list($leftId, $rightId, $level) = $this->getNodeInfo($ID))) trigger_error("phpDbTree error: " . $this->db->error() , E_USER_ERROR);
// preparing data to be inserted
if (sizeof($data)) {
$fld_names = implode(',', array_keys($data)) . ',';
$fld_values = '\'' . implode('\',\'', array_values($data)) . '\',';
}
$fld_names.= $this->left . ',' . $this->right . ',' . $this->level;
$fld_values.= ($rightId) . ',' . ($rightId+1) . ',' . ($level+1);
// creating a place for the record being inserted
if ($ID) {
$this->sql = 'UPDATE ' . $this->table . ' SET ' . $this->left . '=' . _case($this->left . '>' . $rightId, $this->left . '+2', $this->left) . ',' . $this->right . '=' . _case($this->right . '>=' . $rightId, $this->right . '+2', $this->right) . 'WHERE ' . $this->right . '>=' . $rightId;
if (!($this->db->query($this->sql))) trigger_error("phpDbTree error: " . $this->db->error() , E_USER_ERROR);
}
// inserting new record
$this->sql = 'INSERT INTO ' . $this->table . '(' . $fld_names . ') VALUES(' . $fld_values . ')';
if (!($this->db->query($this->sql))) trigger_error("phpDbTree error: " . $this->db->error() , E_USER_ERROR);
return $this->db->insert_id($this->seq);
}
//************************************************************************
// Inserts a record into the table with nested sets
// $ID : ID of the element after which (i.e. at the same level) the new element
// is to be inserted
// $data : array with data to be inserted: array(<field_name> => <field_value>)
// Returns : true on success, or false on error
function insertNear($ID, $data)
{
if (!(list($leftId, $rightId, $level) = $this->getNodeInfo($ID))) trigger_error("phpDbTree error: " . $this->db->error() , E_USER_ERROR);
// preparing data to be inserted
if (sizeof($data)) {
$fld_names = implode(',', array_keys($data)) . ',';
$fld_values = '\'' . implode('\',\'', array_values($data)) . '\',';
}
$fld_names.= $this->left . ',' . $this->right . ',' . $this->level;
$fld_values.= ($rightId+1) . ',' . ($rightId+2) . ',' . ($level);
// creating a place for the record being inserted
if ($ID) {
$this->sql = 'UPDATE ' . $this->table . ' SET ' . $this->left . '=' . _case($this->left . '>' . $rightId, $this->left . '+2', $this->left) . $this->right . '=' . _case($this->right . '>' . $rightId, $this->right . '+2', $this->right) . 'WHERE ' . $this->right . '>' . $rightId;
if (!($this->db->query($this->sql))) trigger_error("phpDbTree error:" . $this->db->error() , E_USER_ERROR);
}
// inserting new record
$this->sql = 'INSERT INTO ' . $this->table . '(' . $fld_names . ') VALUES(' . $fld_values . ')';
if (!($this->db->query($this->sql))) trigger_error("phpDbTree error:" . $this->db->error() , E_USER_ERROR);
return $this->db->insert_id($this->seq);
}
//************************************************************************
// Assigns a node with all its children to another parent
// $ID : node ID
// $newParentID : ID of new parent node
// Returns : false on error
function moveAll($ID, $newParentId)
{
if (!(list($leftId, $rightId, $level) = $this->getNodeInfo($ID))) trigger_error("phpDbTree error: " . $this->db->error() , E_USER_ERROR);
if (!(list($leftIdP, $rightIdP, $levelP) = $this->getNodeInfo($newParentId))) trigger_error("phpDbTree error: " . $this->db->error() , E_USER_ERROR);
if ($ID == $newParentId || $leftId == $leftIdP || ($leftIdP >= $leftId && $leftIdP <= $rightId)) return false;
// whether it is being moved upwards along the path
if ($leftIdP < $leftId && $rightIdP > $rightId && $levelP < $level-1) {
$this->sql = 'UPDATE ' . $this->table . ' SET '
. $this->level . '=' . _case($this->left . ' BETWEEN ' . $leftId . ' AND ' . $rightId, $this->level . sprintf('%+d', -($level-1) +$levelP) , $this->level) . ","
. $this->right . '=' . _case($this->right . ' BETWEEN ' . ($rightId+1) . ' AND ' . ($rightIdP-1) , $this->right . '-' . ($rightId-$leftId+1)
, _case($this->left . ' BETWEEN ' . ($leftId) . ' AND ' . ($rightId) , $this->right . '+' . ((($rightIdP-$rightId-$level+$levelP) /2) *2+$level-$levelP-1) , $this->right)) . ","
. $this->left . '=' . _case($this->left . ' BETWEEN ' . ($rightId+1) . ' AND ' . ($rightIdP-1) , $this->left . '-' . ($rightId-$leftId+1) , _case($this->left . ' BETWEEN ' . $leftId . ' AND ' . ($rightId) , $this->left . '+' . ((($rightIdP-$rightId-$level+$levelP) /2) *2+$level-$levelP-1) , $this->left)) . 'WHERE ' . $this->left . ' BETWEEN ' . ($leftIdP+1) . ' AND ' . ($rightIdP-1);
} elseif ($leftIdP < $leftId) {
$this->sql = 'UPDATE ' . $this->table . ' SET '
. $this->level . '=' . _case($this->left . ' BETWEEN ' . $leftId . ' AND ' . $rightId, $this->level . sprintf('%+d', -($level-1) +$levelP) , $this->level) . ","
. $this->left . '=' . _case($this->left . ' BETWEEN ' . $rightIdP . ' AND ' . ($leftId-1) , $this->left . '+' . ($rightId-$leftId+1)
, _case($this->left . ' BETWEEN ' . $leftId . ' AND ' . $rightId, $this->left . '-' . ($leftId-$rightIdP) , $this->left)) . ","
. $this->right . '=' . _case($this->right . ' BETWEEN ' . $rightIdP . ' AND ' . $leftId, $this->right . '+' . ($rightId-$leftId+1) , _case($this->right . ' BETWEEN ' . $leftId . ' AND ' . $rightId, $this->right . '-' . ($leftId-$rightIdP) , $this->right)) . 'WHERE ' . $this->left . ' BETWEEN ' . $leftIdP . ' AND ' . $rightId
// !!! added this line (Maxim Matyukhin)
. ' OR ' . $this->right . ' BETWEEN ' . $leftIdP . ' AND ' . $rightId;
} else {
$this->sql = 'UPDATE ' . $this->table . ' SET '
. $this->level . '=' . _case($this->left . ' BETWEEN ' . $leftId . ' AND ' . $rightId, $this->level . sprintf('%+d', -($level-1) +$levelP) , $this->level) . ","
. $this->left . '=' . _case($this->left . ' BETWEEN ' . $rightId . ' AND ' . $rightIdP, $this->left . '-' . ($rightId-$leftId+1)
, _case($this->left . ' BETWEEN ' . $leftId . ' AND ' . $rightId, $this->left . '+' . ($rightIdP-1-$rightId), $this->left)) . ", "
. $this->right . '=' . _case($this->right . ' BETWEEN ' . ($rightId+1) . ' AND ' . ($rightIdP-1) , $this->right . '-' . ($rightId-$leftId+1) , _case($this->right . ' BETWEEN ' . $leftId . ' AND ' . $rightId, $this->right . '+' . ($rightIdP-1-$rightId) , $this->right)) . 'WHERE ' . $this->left . ' BETWEEN ' . $leftId . ' AND ' . $rightIdP
// !!! added this line (Maxim Matyukhin)
. ' OR ' . $this->right . ' BETWEEN ' . $leftId . ' AND ' . $rightIdP;
}
return $this->db->query($this->sql) or trigger_error("phpDbTree error: " . $this->db->error() , E_USER_ERROR);
}
// Перемещение всех детей ветки в другую ветку
function moveChildren($ID, $newParentId)
{
if (!(list($leftId, $rightId, $level) = $this->getNodeInfo($ID))) trigger_error("phpDbTree error: " . $this->db->error() , E_USER_ERROR);
if (!(list($leftIdP, $rightIdP, $levelP) = $this->getNodeInfo($newParentId))) trigger_error("phpDbTree error: " . $this->db->error() , E_USER_ERROR);
if ($ID == $newParentId || $leftId == $leftIdP || ($leftIdP >= $leftId && $leftIdP <= $rightId)) return false;
// whether it is being moved upwards along the path
if ($leftIdP < $leftId && $rightIdP > $rightId && $levelP < $level-1) {
// _update($this->table, array(), )
$this->sql = 'UPDATE ' . $this->table . ' SET '
// Меняем уровень
. $this->level . '=' .
_case(_between($this->left, $leftId, $rightId),
$this->level . sprintf('%+d', -($level-1) +$levelP) , $this->level)
// Меняем границы
. $this->left . '=' .
_case(_beetween($this->left, $rightId+1, $rightIdP-1), $this->left . '-' . $rightId-$leftId+1 ,
_case(_between($this->left, $leftId, $rightId), $this->left . '+' . ((($rightIdP-$rightId-$level+$levelP) /2) *2+$level-$levelP-1) , $this->left))
. $this->right . '=' .
_case(_between($this->right, $rightId+1, $rightIdP-1), $this->right . '-' . ($rightId-$leftId+1) ,
_case(_between($this->left, $leftId, $rightId), $this->right . '+' . ((($rightIdP-$rightId-$level+$levelP) /2) *2+$level-$levelP-1) , $this->right))
. 'WHERE ' . _between($this->left, ($leftIdP+1), ($rightIdP-1));
} elseif ($leftIdP < $leftId) {
$this->sql = 'UPDATE ' . $this->table . ' SET '
. $this->level . '=' .
_case(_between($this->left, $leftId, $rightId),
$this->level . sprintf('%+d', -($level-1) +$levelP) , $this->level)
. $this->left . '=' .
_case(_between($this->left, $rightIdP, $leftId-1), $this->left . '+' . ($rightId-$leftId+1),
_case(_between($this->left, $leftId, $rightId), $this->left . '-' . ($leftId-$rightIdP) , $this->left))
. $this->right . '=' .
_case(_between($this->right, $rightIdP, $leftId), $this->right . '+' . ($rightId-$leftId+1),
_case(_between($this->right, $leftId, $rightId), $this->right . '-' . ($leftId-$rightIdP) , $this->right))
. 'WHERE ' . _between($this->left, $leftIdP, $rightId)
// !!! added this line (Maxim Matyukhin)
. ' OR ' . _between($this->right, $leftIdP, $rightId);
} else {
$this->sql = 'UPDATE ' . $this->table . ' SET '
. $this->level . '='
. _case(_between($this->left, $leftId, $rightId),
$this->level . sprintf('%+d', -($level-1) +$levelP) , $this->level)
. $this->left . '=' .
_case(_between($this->left, $rightId, $rightIdP), $this->left . '-' . ($rightId-$leftId+1),
_case(_between($this->left, $leftId, $rightId), $this->left . '+' . ($rightIdP-1-$rightId), $this->left))
. $this->right . '=' .
_case(_between($this->right, $rightId+1, $rightIdP-1), $this->right . '-' . ($rightId-$leftId+1),
_case(_between($this->right, $leftId, $rightId), $this->right . '+' . ($rightIdP-1-$rightId) , $this->right))
. 'WHERE ' . _between($this->left, $leftId, $rightIdP)
// !!! added this line (Maxim Matyukhin)
. ' OR ' . _between($this->right, $leftId, $rightIdP);
}
return $this->db->query($this->sql) or trigger_error("phpDbTree error: " . $this->db->error() , E_USER_ERROR);
}
//************************************************************************
// Deletes a record wihtout deleting its children
// $ID : an ID of the element to be deleted
// Returns : true on success, or false on error
function delete($ID)
{
if (!(list($leftId, $rightId, $level) = $this->getNodeInfo($ID))) trigger_error("phpDbTree error: " . $this->db->error() , E_USER_ERROR);
// Deleting record
$this->sql = 'DELETE FROM ' . $this->table . ' WHERE ' . $this->id . '=\'' . $ID . '\'';
if (!$this->db->query($this->sql)) trigger_error("phpDbTree error: " . $this->db->error() , E_USER_ERROR);
// Clearing blank spaces in a tree
$this->sql = 'UPDATE ' . $this->table . ' SET '
. $this->left . '=' . _case($this->left . ' BETWEEN ' . $leftId . ' AND ' . $rightId, $this->left . '-1', $this->left) . ", "
. $this->right . '=' . _case($this->right . ' BETWEEN ' . $leftId . ' AND ' . $rightId, $this->right . '-1', $this->right) . ", "
. $this->level . '=' . _case($this->left . ' BETWEEN ' . $leftId . ' AND ' . $rightId, $this->level . '-1', $this->level) . ", "
. $this->left . '=' . _case($this->left . '>' . $rightId, $this->left . '-2', $this->left) . ", "
. $this->right . '=' . _case($this->right . '>' . $rightId, $this->right . '-2', $this->right)
. ' WHERE ' . $this->right . '>' . $leftId;
if (!$this->db->query($this->sql)) trigger_error("phpDbTree error: " . $this->db->error() , E_USER_ERROR);
return true;
}
//************************************************************************
// Deletes a record with all its children
// $ID : an ID of the element to be deleted
// Returns : true on success, or false on error
function deleteAll($ID)
{
if (!(list($leftId, $rightId, $level) = $this->getNodeInfo($ID))) trigger_error("phpDbTree error: " . $this->db->error() , E_USER_ERROR);
// Deleteing record(s)
$this->sql = 'DELETE FROM ' . $this->table . ' WHERE ' . $this->left . ' BETWEEN ' . $leftId . ' AND ' . $rightId;
if (!$this->db->query($this->sql)) trigger_error("phpDbTree error: " . $this->db->error() , E_USER_ERROR);
// Clearing blank spaces in a tree
$deltaId = ($rightId-$leftId) +1;
$this->sql = 'UPDATE ' . $this->table . ' SET '
. $this->left . '=' . _case($this->left . '>' . $leftId, $this->left . '-' . $deltaId, $this->left) . ", "
. $this->right . '=' . _case($this->right . '>' . $leftId, $this->right . '-' . $deltaId, $this->right)
. ' WHERE ' . $this->right . '>' . $rightId;
if (!$this->db->query($this->sql)) trigger_error("phpDbTree error: " . $this->db->error() , E_USER_ERROR);
return true;
}
//************************************************************************
// Enumerates children of an element
// $ID : an ID of an element which children to be enumerated
// $start_level : relative level from which start to enumerate children
// $end_level : the last relative level at which enumerate children
// 1. If $end_level isn't given, only children of
// $start_level levels are enumerated
// 2. Level values should always be greater than zero.
// Level 1 means direct children of the element
// Returns : a result id for using with other DB functions
function enumChildrenAll($ID)
{
return $this->enumChildren($ID, 1, 0);
}
function enumChildren($ID, $start_level = 1, $end_level = 1)
{
if ($start_level < 0) trigger_error("phpDbTree error: " . $this->db->error() , E_USER_ERROR);
// We could use sprintf() here, but it'd be too slow
$whereSql1 = ' AND ' . $this->table . '.' . $this->level;
$whereSql2 = '_' . $this->table . '.' . $this->level . '+';
if (!$end_level) $whereSql = $whereSql1 . '>=' . $whereSql2 . (int)$start_level;
else {
$whereSql = ($end_level <= $start_level) ? $whereSql1 . '=' . $whereSql2 . (int)$start_level : ' AND ' . $this->table . '.' . $this->level . ' BETWEEN _' . $this->table . '.' . $this->level . '+' . (int)$start_level . ' AND _' . $this->table . '.' . $this->level . '+' . (int)$end_level;
}
$this->sql = $this->sqlComposeSelect(array(
'', // Params
'', // Fields
$this->table . ' _' . $this->table . ', ' . $this->table, // Tables
'_' . $this->table . '.' . $this->id . '=\'' . $ID . '\'' . ' AND ' . $this->table . '.' . $this->left . ' BETWEEN _' . $this->table . '.' . $this->left . ' AND _' . $this->table . '.' . $this->right . $whereSql
));
return $this->db->query($this->sql);
}
function enumChildrenArray($ID, $start_level = 1, $end_level = 1)
{
return $this->db->result2array($this->enumChildren($ID, $start_level, $end_level));
}
//************************************************************************
// Enumerates the PATH from an element to its top level parent
// $ID : an ID of an element
// $showRoot : whether to show root node in a path
// Returns : a result id for using with other DB functions
function enumPath($ID, $showRoot = false)
{
$this->sql = $this->sqlComposeSelect(array(
'', // Params
'', // Fields
$this->table . ' _' . $this->table . ', ' . $this->table, // Tables
'_' . $this->table . '.' . $this->id . '=\'' . $ID . '\'' . ' AND _' . $this->table . '.' . $this->left . ' BETWEEN ' . $this->table . '.' . $this->left . ' AND ' . $this->table . '.' . $this->right . (($showRoot) ? '' : ' AND ' . $this->table . '.' . $this->level . '>0') , // Where
'', // GroupBy
'', // Having
$this->table . '.' . $this->left // OrderBy
));
return $this->db->query($this->sql);
}
function enumPathArray($ID, $showRoot = false)
{
return $this->db->result2array($this->enumPath($ID, $showRoot));
}
//************************************************************************
// Returns query result to fetch data of the element's parent
// $ID : an ID of an element which parent to be retrieved
// $level : Relative level of parent
// Returns : a result id for using with other DB functions
function getParent($ID, $level = 1)
{
if ($level < 1) trigger_error("phpDbTree error: " . $this->db->error() , E_USER_ERROR);
$this->sql = $this->sqlComposeSelect(array(
'', // Params
'', // Fields
$this->table . ' _' . $this->table . ', ' . $this->table, // Tables
'_' . $this->table . '.' . $this->id . '=\'' . $ID . '\'' . ' AND _' . $this->table . '.' . $this->left . ' BETWEEN ' . $this->table . '.' . $this->left . ' AND ' . $this->table . '.' . $this->right . ' AND ' . $this->table . '.' . $this->level . '=_' . $this->table . '.' . $this->level . '-' . (int)$level // Where
));
$result = $this->db->result2array($this->db->query($this->sql));
return (int)$result[0][$this->id];
}
//************************************************************************
function sqlReset()
{
$this->qryParams = '';
$this->qryFields = '';
$this->qryTables = '';
$this->qryWhere = '';
$this->qryGroupBy = '';
$this->qryHaving = '';
$this->qryOrderBy = '';
$this->qryLimit = '';
return true;
}
//************************************************************************
function sqlSetReset($resetMode)
{
$this->sqlNeedReset = ($resetMode) ? true : false;
}
//************************************************************************
function sqlParams($param = '')
{
return (empty($param)) ? $this->qryParams : $this->qryParams = $param;
}
function sqlFields($param = '')
{
return (empty($param)) ? $this->qryFields : $this->qryFields = $param;
}
function sqlSelect($param = '')
{
return $this->sqlFields($param);
}
function sqlTables($param = '')
{
return (empty($param)) ? $this->qryTables : $this->qryTables = $param;
}
function sqlFrom($param = '')
{
return $this->sqlTables($param);
}
function sqlWhere($param = '')
{
return (empty($param)) ? $this->qryWhere : $this->qryWhere = $param;
}
function sqlGroupBy($param = '')
{
return (empty($param)) ? $this->qryGroupBy : $this->qryGroupBy = $param;
}
function sqlHaving($param = '')
{
return (empty($param)) ? $this->qryHaving : $this->qryHaving = $param;
}
function sqlOrderBy($param = '')
{
return (empty($param)) ? $this->qryOrderBy : $this->qryOrderBy = $param;
}
function sqlLimit($param = '')
{
return (empty($param)) ? $this->qryLimit : $this->qryLimit = $param;
}
//************************************************************************
function sqlComposeSelect($arSql)
{
$joinTypes = array(
'join' => 1,
'cross' => 1,
'inner' => 1,
'straight' => 1,
'left' => 1,
'natural' => 1,
'right' => 1
);
$this->sql = 'SELECT ' . $arSql[0] . ' ';
if (!empty($this->qryParams)) $this->sql.= $this->sqlParams . ' ';
if (empty($arSql[1]) && empty($this->qryFields)) $this->sql.= $this->table . '.' . $this->id;
else {
if (!empty($arSql[1])) $this->sql.= $arSql[1];
if (!empty($this->qryFields)) $this->sql.= ((empty($arSql[1])) ? '' : ',') . $this->qryFields;
}
$this->sql.= ' FROM ';
// $tblAr = array(0 => 'join');
$isJoin = ($tblAr = explode(' ', trim($this->qryTables)))
&& /*($joinTypes[strtolower($tblAr[0]) ])*/ 1;
if (empty($arSql[2]) && empty($this->qryTables)) $this->sql.= $this->table;
else {
if (!empty($arSql[2])) $this->sql.= $arSql[2];
if (!empty($this->qryTables)) {
if (!empty($arSql[2])) $this->sql.= (($isJoin) ? ' ' : ',');
elseif ($isJoin) $this->sql.= $this->table . ' ';
$this->sql.= $this->qryTables;
}
}
if ((!empty($arSql[3])) || (!empty($this->qryWhere))) {
$this->sql.= ' WHERE ' . $arSql[3] . ' ';
if (!empty($this->qryWhere)) $this->sql.= (empty($arSql[3])) ? $this->qryWhere : 'AND(' . $this->qryWhere . ')';
}
if ((!empty($arSql[4])) || (!empty($this->qryGroupBy))) {
$this->sql.= ' GROUP BY ' . $arSql[4] . ' ';
if (!empty($this->qryGroupBy)) $this->sql.= (empty($arSql[4])) ? $this->qryGroupBy : ',' . $this->qryGroupBy;
}
if ((!empty($arSql[5])) || (!empty($this->qryHaving))) {
$this->sql.= ' HAVING ' . $arSql[5] . ' ';
if (!empty($this->qryHaving)) $this->sql.= (empty($arSql[5])) ? $this->qryHaving : 'AND(' . $this->qryHaving . ')';
}
if ((!empty($arSql[6])) || (!empty($this->qryOrderBy))) {
$this->sql.= ' ORDER BY ' . (isset($arSql[6]) ? $arSql[6] : '') . ' ';
if (!empty($this->qryOrderBy)) $this->sql.= (empty($arSql[6])) ? $this->qryOrderBy : ',' . $this->qryOrderBy;
}
if (!empty($arSql[7])) $this->sql.= ' LIMIT ' . $arSql[7];
elseif (!empty($this->qryLimit)) $this->sql.= ' LIMIT ' . $this->qryLimit;
if ($this->sqlNeedReset) $this->sqlReset();
return $this->sql;
}
//************************************************************************
}

View file

@ -1,79 +0,0 @@
<?php
/**
* Сортировка дерева в представлении Nested Set
* Для дерева которое хранится в базе данных используя представление Nested Set нет возможности отсортировать элементы дерева по
* произвольному полю. Поэтому после извлечения дерева из базы данных оно преобразуется в обычное представление сортируется и обратно
*
* Пример:
* $sort = new NestedSetSort();
* $data = $sort->sortBy($data, 'name');
*/
class NestedSetSort {
private $data = array();
private $result = array();
private $sortBy = '';
public function __construct() {
}
// Преобразуем Nested Set в дерево и сортируем
private function listTree(array $tree, $offset, $level) {
$result = array();
for ($i = $offset; $i < sizeof($tree); $i++) {
$leaf = $tree[$i];
$clevel = $leaf['cat_level'];
if ($clevel == $level) {
$result [] = array($i);
} else if ($clevel > $level) {
list($subtree, $i) = $this->listTree($tree, $i, $clevel);
$i--;
$result[sizeof($result) - 1][1] = $subtree;
} else {
$this->sortList($result, $tree);
return array($result, $i);
}
}
$this->sortList($result, $tree);
return array($result, $i);
}
// Сравнение двух элементов
private function compare($a, $b) {
$a1 = $this->data[$a[0]][$this->sortBy];
$b1 = $this->data[$b[0]][$this->sortBy];
return strcmp($a1, $b1);
}
// Сортировка списка
private function sortList(array &$list, $data) {
usort($list, array($this, 'compare'));
}
// Создает дерево в виде списка
private function reorder(array $tree) {
foreach($tree as $node) {
$this->result[] = $this->data[$node[0]];
if (isset($node[1])) {
$this->reorder($node[1]);
}
}
}
public function sortBy0(array $data, $sortBy)
{
$this->data = $data;
$this->sortBy = $sortBy;
$order = $this->listTree($data, 0, 0);
return $order[0];
}
// Сортировка по заданному полю
public function sortBy(array $data, $sortBy) {
$this->data = $data;
$this->sortBy = $sortBy;
$order = $this->listTree($data, 0, 0);
$this->reorder($order[0]);
return $this->result;
}
}

View file

@ -1,2 +0,0 @@
<?php
foreach (glob(dirname(__FILE__) . "/*.php") as $file) { require_once $file; }

View file

@ -1,298 +0,0 @@
<?php
class _View_Composite // AbstractCompositeView
{
protected $_section = array(); // Вложенные шаблоны
// Блоки
protected $_stylesheet = array(); // Массив стилей текущего шаблона
protected $_script = array(); // Массив скриптов текущего шаблона
protected $_scriptstring = array();
protected $_startup = array();
protected $_title = null; // Заголовок текущего шаблона
public $alias = array();
function __construct()
{
}
/**
* Связывет переменную с вложенным шаблоном
*
* @param string $section переменная шаблона
* @param CompositeView $view вложенный шаблон
*/
public function setView($section, /*CompositeView*/ $view)
{
$this->_section [$section] = $view;
}
public function jGrowl($message, $args)
{
$this->addScriptRaw('$.jGrowl("' . $message . '", ' . json::encode($args) . ");\n", true);
}
public function setGlobal($name, $args)
{
$this->addScriptRaw("var " . $name . " = " . json::encode($args) . ";\n", false);
}
/**
* Добавляет скипт к текущему шаблону
*
* @param string $name путь к скрипту
*/
public function addScript($name)
{
$this->_script [] = $name;
}
/**
* Добавляет код скипта к текущему шаблону
*
* @param string $name строка javascript кода
*/
public function addScriptRaw($name, $startup = false)
{
if ($startup) {
$this->_startup [] = $name;
} else {
$this->_scriptstring [] = $name;
}
}
/**
* Добавляет стили к текущему шаблону
*
* @param string $name путь к стилю
*/
public function addStyleSheet($name)
{
$this->_stylesheet [] = $name;
}
/**
* Рекурсивно извлекает из значение свойства обьекта
*
* @param string $list Имя свойства
* @param boolean $flatten
*/
private function doTree($list, $flatten = true) {
$result = ($flatten == true) ? $this->$list : array($this->$list);
foreach ($this->_section as $key => $value) {
if (is_object($value)) $result = array_merge($value->doTree($list, $flatten), $result);
}
return $result;
}
/**
* Массив имен файлов скриптов
*
* return array
*/
public function getScripts()
{
return $this->doTree('_script');
}
function resolveAlias($alias, $list)
{
$result = array();
foreach($list as $item) {
$result [] = strtr($item, $alias);
}
return $result;
}
/**
* Строка со скриптом
*
* @return string
*/
public function getScriptRaw()
{
return implode("\n", $this->doTree('_scriptstring'));
}
public function getScriptStartup()
{
return implode("\n", $this->doTree('_startup'));
}
/*abstract*/ public function set($key, $value)
{
}
/**
* Массив имен файлов стилей
*
* return array
*/
public function getStyleSheet()
{
return $this->doTree('_stylesheet');
}
/**
* Обработка всех вложенных шаблонов
*
* @return string
*/
public function execute()
{
foreach ($this->_section as $key => $value) {
$this->set($key, (is_object($value)) ? $value->execute() : $value); // ?
}
}
/**
* Установка заголовка шаблона
*
* @param string $title
*/
public function setTitle($title)
{
$this->_title = $title;
}
private function isNotNull($title)
{
return $title !== null;
}
/**
* Общая строка заголовка
*/
public function getTitle()
{
return implode(" - ", array_filter($this->doTree('_title', false), array($this, 'isNotNull')));
}
private function findGroup($groups, $file)
{
foreach($groups as $key => $group) {
if(in_array($file, $group)) {
return $key;
}
}
return false;
}
private function groupFiles(array $list, $debug)
{
$debug = ($debug) ? 'debug=1' : '';
$path = parse_url(WWW_PATH, PHP_URL_PATH);
$list = array_reverse($list);
// Группы нужно передвавать как параметр !!!
$groups = array(
'table' => array($path . '/js/table.js', $path . '/js/listtable.js',
$path . '/js/page.js', $path . '/js/pagemenu.js'),
'base' => array($path . '/js/admin.js', $path . '/js/cookie.js'),
);
$use = array();
$result = array();
foreach ($list as $file) {
$name = $this->findGroup($groups, $file);
if($name) {
$use [$name] = 1;
} else {
$result [] = $file;
}
}
$list = array();
foreach ($use as $name => $value) {
$list [] = WWW_PATH . "/min/?$debug&f=" . implode(",", $groups[$name]);
}
return array_merge($list, $result);
}
/**
* Обработка шаблона
*
* @return string
*/
public function render()
{
$alias = $this->doTree('alias');
// require_once 'minify.php';
// Скрипты и стили
$this->set('scripts', array_unique($this->groupFiles($this->resolveAlias($alias, $this->getScripts()), false)));
$this->set('stylesheet', array_unique($this->groupFiles($this->resolveAlias($alias, $this->getStyleSheet()), false)));
$this->set('scriptstring', $this->getScriptRaw());
$this->set('startup', $this->getScriptStartup());
$this->set('title', $this->getTitle());
//
return $this->execute(); // execute+phptal ??
}
function setAlias($alias)
{
$this->alias = $alias;
}
function addAlias($name, $path)
{
$this->alias['${' . $name . '}'] = $path;
$this->set($name, $path);
}
function loadImports($importFile)
{
// Подключение стилей и скриптов
if (file_exists($importFile)) {
$import = file_get_contents($importFile);
$files = explode("\n", $import);
foreach ($files as $file) {
if (strpos($file, ".js") !== false) {
$this->addScript(strtr(trim($file), $this->alias));
} else if(strpos($file, ".css") !== false) {
$this->addStyleSheet(strtr(trim($file), $this->alias));
}
}
}
}
}
// CompositeView+PHPTAL
class View_Composite extends _View_Composite
{
private $tal;
function __construct($file)
{
parent::__construct($file);
$this->tal = new PHPTAL($file);
$this->tal->setEncoding('WINDOWS-1251'); // PHP_TAL_DEFAULT_ENCODING !!
$this->tal->stripComments(true);
}
function set($key, $val)
{
if ($key == 'title') {
$this->setTitle($val);
}
$this->tal->set($key, $val);
}
function __set($key, $val)
{
$this->tal->set($key, $val);
}
function setTranslator($tr)
{
$this->tal->setTranslator($tr);
}
function execute()
{
parent::execute();
// postProcess
return $this->tal->execute();
}
}

View file

@ -1,82 +0,0 @@
<?php
/**
* Извлекает текст из HTML документа
*/
function stripText($document)
{
$search = array("'<script[^>]*?>.*?</script>'si" => "", // strip out javascript
"'<[\/\!]*?[^<>]*?>'si" => "", // strip out html tags
"'([\r\n])[\s]+'" => "\\1", // strip out white space
"'&(quot|#34|#034|#x22);'i" => "\"", // replace html entities
"'&(amp|#38|#038|#x26);'i" => "&", // added hexadecimal values
"'&(lt|#60|#060|#x3c);'i" => ">",
"'&(gt|#62|#062|#x3e);'i" => "<",
"'&(nbsp|#160|#xa0);'i" => " ",
"'&(iexcl|#161);'i" => chr(161),
"'&(cent|#162);'i" => chr(162),
"'&(pound|#163);'i" => chr(163),
"'&(copy|#169);'i" => chr(169),
"'&(reg|#174);'i" => chr(174),
"'&(deg|#176);'i" => chr(176));
$text = preg_replace(array_keys($search), array_values($search), $document);
return $text;
}
/**
* Разделение текста на массив слов
*/
function tokenize ($document)
{
$array = preg_split("/[\W]+/", $document);
return $array;
}
/**
* Ищет один из символов с конца строки
*
* @param string $haystack
* @param array $needle Массив символов для поиска
* @param int $offset Смещение от начала строки
*
* @return int Позицию первого совпадения
*/
function indexRight ($haystack, $needle, $offset = 0)
{
if ((bool)$offset === false) $offset = 0;
while ($offset >= 0) {
if (in_array ($haystack[$offset], $needle)) {
return $offset;
}
$offset --;
}
return false;
}
/**
* Ищет один из символов с начала строки
*
* @param string $haystack
* @param array $needle Массив символов для поиска
* @param int $offset Смещение от начала строки
*
* @return int Позицию первого совпадения
*/
function indexLeft ($haystack, $needle, $offset = 0)
{
if ($offset < 0) return false;
while ($offset < strlen($haystack)) {
if ((is_callable($needle) && call_user_func ($needle, $haystack[$offset]))
|| (is_array ($needle) && in_array ($haystack[$offset], $needle))) {
return $offset;
}
$offset ++;
}
return false;
}
function not_ctype_alpha ($ch)
{
return !ctype_alpha($ch);
}

View file

@ -1,84 +0,0 @@
<?php
require_once 'core/search/htmlhelper.php';
require_once 'core/search/stemmer.php';
require_once 'core/path.php';
/**
* Индексирование файлов
*/
class Index
{
const ARRAY_FILE = 0;
const ARRAY_TEXT = 1;
public $index = array ();
public $text = array ();
protected $count = 0;
function getTitle ($content) {
$title = "'<title[^>]*?>(.*?)</title>'si";
preg_match($title, $content, $matches);
if(isset($matches[1])) {
return $matches[1];
}
return "";
}
// Выбираем основу слова
function clean ($word)
{
return Stemmer::russian(strtolower($word));
}
function process ($base, $files)
{
$path = new Path($base);
// Список документов
foreach ($path->getContentRec($files) as $file) {
$content = file_get_contents ($file);
$text = stripText($content);
// $title = self::getTitle ($content);
$title = pathinfo($file, PATHINFO_BASENAME);
// echo $file, "\n";
// Список слов в документе
$list = tokenize($text);
foreach ($list as $word) {
$preword = self::clean($word);
if (isset($this->index[$preword])) {
$index = $this->index[$preword];
if ( ! in_array ($this->count, $index)) $this->index[$preword] [] = $this->count;
} else {
// Не записываем слова длинна которых меньше 2
if (strlen($preword) > 1) {
$this->index[$preword] = array ($this->count);
}
}
}
$this->text [] = array ($title, $path->relPath ($file), $text);
$this->count ++;
}
ksort($this->index);
}
/**
* Сохранение результата поиска
*/
function saveData ($file)
{
$file = fopen($file, "w");
// Количество слов и текстов
fwrite ($file, pack("SS", count($this->index), count($this->text)));
foreach ($this->index as $word => $value) {
$length = strlen($word);
array_unshift ($value, "SSa*S*", $length, count($value), $word);
fwrite($file, call_user_func_array ('pack', $value));
}
foreach ($this->text as $text) {
fwrite($file, pack("SSSa*a*a*",
strlen($text[0]), strlen($text[1]), strlen($text[2])
, $text[0], $text[1], $text[2]));
}
}
}

View file

@ -1,91 +0,0 @@
<?php
/**
* Разбирвет строку запроса на токены
*/
class Lexer
{
const TOKEN_NOT = 1;
const TOKEN_OR = 2;
const TOKEN_LPAREN = 3;
const TOKEN_RPAREN = 4;
const TOKEN_AND = 5;
const TOKEN_WORD = 6;
const TOKEN_EOL = 7;
protected $src;
private $offset = 0;
public $token;
public function __construct ()
{
}
function setSource ($src)
{
$this->src = $src;
$this->offset;
}
private function skipSpace ()
{
while (!$this->isEOL() && $this->getChar() == " ") {
$this->offset++;
}
}
private function getChar ()
{
return $this->src [$this->offset];
}
/**
* Проверяет на конец строки
*/
private function isEOL () {
return $this->offset >= strlen($this->src);
}
/**
* Односимвольный токен
*/
private function easyToken () {
$ch = $this->getChar ();
switch ($ch) {
case '~': $token = array(self::TOKEN_NOT, $ch); break;
case '|': $token = array(self::TOKEN_OR, $ch); break;
case '(': $token = array(self::TOKEN_LPAREN, $ch); break;
case ')': $token = array(self::TOKEN_RPAREN, $ch); break;
case '&': $token = array(self::TOKEN_AND, $ch); break;
default:
$this->offset++;
$token = $this->getToken();
}
$this->offset++;
return $token;
}
/**
* Возвращает следующий токен
*/
public function getToken ()
{
$this->skipSpace ();
if ($this->isEOL()) {
return array(self::TOKEN_EOL, "");
}
if (ctype_alpha($this->getChar())) {
$start = $this->offset;
while (!$this->isEOL() && ctype_alpha($this->getChar())) {
$this->offset ++;
}
return array(self::TOKEN_WORD, substr ($this->src, $start, $this->offset-$start));
}
return $this->easyToken();
}
public function nextToken ()
{
$this->token = $this->getToken();
}
}

View file

@ -1,97 +0,0 @@
<?php
require_once 'core/search/lexer.php';
require_once 'core/functions.php';
/**
* Поиск в индексе
*/
class Search
{
private $lexer;
private $index;
function __construct ($index)
{
$this->lexer = new Lexer();
$this->index = $index;
$this->op = array ($this, 'Op');
$this->binary = array ($this, 'binaryOp');
$this->union = array ($this, 'union');
$this->intersection = lcurry($this->op, 'array_uintersect', $this->union);
$this->notQuery = lcurry ($this->binary, Lexer::TOKEN_NOT,
lcurry($this->op, 'array_udiff', 'array_udiff'), array ($this, 'easyQuery'));
$this->orQuery = lcurry ($this->binary, Lexer::TOKEN_OR,
lcurry($this->op, $this->union, $this->union), $this->notQuery);
$this->andQuery = lcurry ($this->binary, Lexer::TOKEN_AND, $this->intersection, $this->orQuery);
}
function union ($a, $b, $callback)
{
return array_merge($a, $b);
}
function Eq ($a, $b)
{
return $a == $b;
}
function Op ($files, $words, $a, $b) {
return array (
'words' => call_user_func ($words, $a['words'], $b['words'], array ($this, 'eq')),
'files' => call_user_func ($files, $a['files'], $b['files'], array ($this, 'eq'))
);
}
public function getQuery ($source)
{
$this->lexer->setSource ($source);
$this->lexer->nextToken();
return $this->topQuery();
}
function topQuery ()
{
$result = call_user_func ($this->andQuery);
while ($this->lexer->token[0] == Lexer::TOKEN_LPAREN) {
$result = call_user_func ($this->intersection, $result, call_user_func ($this->andQuery));
}
return $result;
}
function easyQuery ()
{
$result = null;
if ($this->lexer->token[0] == Lexer::TOKEN_LPAREN) {
$this->lexer->nextToken ();
$result = $this->topQuery ();
if ($this->lexer->token[0] == Lexer::TOKEN_RPAREN) {
$this->lexer->nextToken ();
}
return $result;
} else {
$result = call_user_func ($this->index, $this->lexer->token[1]);
$this->lexer->nextToken ();
return $result;
}
}
/**
* @param int $type Тип лексемы
* @param function $op Функция при совпадении типа лексемы при запросе
* @param function $next Следующий обработчик запроса
*/
function binaryOp ($type, $op, $next)
{
$result = call_user_func($next);
while ($this->lexer->token[0] == $type) {
$this->lexer->nextToken();
$result = call_user_func($op, $result, call_user_func ($next));
}
return $result;
}
}

View file

@ -1,101 +0,0 @@
<?php
require_once 'core/search/search.php';
require_once 'core/search/htmlhelper.php';
require_once 'core/search/stemmer.php';
class Searcher {
/* protected */ public $index;
protected $text;
protected $search;
public function __construct ()
{
// Может передавать обьект метод по умлочанию getWordStat??
$this->search = new Search (array ($this, 'getWord'));
}
/**
* Читает содержимое индексного файла
*
* @param string $file Имя файла
*/
function setSource ($fileName)
{
$file = fopen($fileName, "r");
$words = fread($file, 4);
$all = unpack("Swords/Stexts", $words);
for ($i = 0; $i < $all['words']; $i++) {
$pos = fread($file, 4);
$size = unpack("Sword/Sindex", $pos);
$word = fread($file, $size['word']);
$index = unpack("S*", fread($file, $size['index']*2));
$this->index[$word] = $index;
}
for ($i = 0; $i < $all['texts']; $i++) {
$pos = fread($file, 6);
$size = unpack("Stitle/Surl/Stext", $pos);
//
$title = fread($file, $size['title']);
$url = fread($file, $size['url']);
$text = fread($file, $size['text']);
$this->text [] = array ($title, $url, $text);
}
}
// По слову возвращаем список файлов и слово
public function getWord ($word)
{
$preword = Stemmer::russian($word); // Index?? -> clean
if (isset($this->index[$preword])) { // Search??
return array ('files' => $this->index[$preword], 'words' => array ($preword));
}
return array ('files' => array (), 'words' => array ());
}
/**
* Список документов в которых встечается слово
*
*/
function getResult (&$query)
{
$result = array ();
$word = $query['words'];
$list = $query['files'];
//
foreach ($list as $n) {
$result [] = array (
'title' => $this->text[$n][0],
'file' => $this->text[$n][1],
'text' => self::getSlice ($word[0], $this->text[$n][2]));
}
return $result;
}
/**
* Часть документа в котором встречается слово
*
* @param $word Слово
* @param $text Текст содержащий слово
*/
function getSlice ($word, $text)
{
$pos = stripos($text, $word);
$offset = max(max ($pos-100, indexRight($text, array ("."), $pos) + 1), 0);
$real = substr($text, $pos, strlen($word)) ;
return substr($text, $offset, $pos - $offset)
. "<span style='color: red'>" . $real . "</span>" . substr ($text, $pos + strlen($word), 100);
}
/**
* Поиск по запросу
*
*/
function search ($query)
{
$result = $this->search->getQuery($query);
return $this->getResult($result);
}
}

View file

@ -1,180 +0,0 @@
<?php
/*
* PHP5 implementation of Martin Porter's stemming algorithm for Russian language.
* Written on a cold winter evening close to the end of 2005 by Dennis Kreminsky (etranger at etranger dot ru)
* Use the code freely, but don't hold me responsible if it breaks whatever it might break.
*
*/
define ('CHAR_LENGTH', '1'); // all Russian characters take 2 bytes in UTF-8, so instead of using (not supported by default) mb_*
// string functions, we use the standard ones with a dirty char-length trick.
// Should you want to use WIN-1251 (or any other charset), convert this source file to that encoding
// and then change CHAR_LENGTH to the proper value, which is likely to be '1' then.
//
class Stemmer {
static public function russian($word)
{
$a = self::rv($word);
$start = $a[0];
$rv = $a[1];
$rv = self::step1($rv);
$rv = self::step2($rv);
$rv = self::step3($rv);
$rv = self::step4($rv);
return $start.$rv;
}
static private function rv($word)
{
$vowels = array('а','е','и','о','у','ы','э','ю','я');
$flag = 0;
$rv = '';
$start = '';
for ($i=0; $i<strlen($word); $i+=CHAR_LENGTH) {
if ($flag==1)
$rv .= substr($word, $i, CHAR_LENGTH);
else
$start .= substr($word, $i, CHAR_LENGTH);
if (array_search(substr($word,$i,CHAR_LENGTH), $vowels) !== false)
$flag=1;
}
return array($start,$rv);
}
static function substitute ($word, &$suffix_list)
{
foreach ($suffix_list as $suffix) {
if (self::has_suffix($word, $suffix)) {
$word = self::cut_suffix($word, $suffix);
}
}
return $word;
}
static function has_suffix ($word, $suffix)
{
return substr($word, -(strlen($suffix))) == $suffix;
}
static function has_aya ($word, $suffix)
{
return (substr($word,-strlen($suffix)-CHAR_LENGTH,CHAR_LENGTH)=='а' || substr($word,-strlen($suffix)-CHAR_LENGTH,CHAR_LENGTH)=='я');
}
static function cut_suffix ($word, $suffix)
{
return substr($word, 0, strlen($word) - strlen($suffix));
}
static private function step1($word)
{
$perfective1 = array('в', 'вши', 'вшись');
foreach ($perfective1 as $suffix) {
if (self::has_suffix($word, $suffix) && self::has_aya ($word, $suffix)) {
return self::cut_suffix($word, $suffix);
}
}
$perfective2 = array('ив','ивши','ившись','ывши','ывшись');
foreach ($perfective2 as $suffix) {
if (self::has_suffix($word, $suffix)) {
return self::cut_suffix($word, $suffix);
}
}
$reflexive = array('ся', 'сь');
$word = self::substitute($word, $reflexive);
$adjective = array('ее','ие','ые','ое','ими','ыми','ей','ий','ый','ой','ем','им','ым','ом','его','ого','ему','ому','их','ых','ую','юю','ая','яя','ою','ею');
$participle2 = array('ем','нн','вш','ющ','щ');
$participle1 = array('ивш','ывш','ующ');
foreach ($adjective as $suffix) {
if (self::has_suffix($word, $suffix)) {
$word = self::cut_suffix($word, $suffix);
foreach ($participle1 as $suffix)
if (self::has_suffix($word, $suffix) && self::has_aya ($word, $suffix))
$word = self::cut_suffix($word, $suffix);
return self::substitute($word, $participle2);
}
}
$verb1 = array('ла','на','ете','йте','ли','й','л','ем','н','ло','но','ет','ют','ны','ть','ешь','нно');
foreach ($verb1 as $suffix)
if (self::has_suffix($word, $suffix) && self::has_aya ($word, $suffix))
return self::cut_suffix($word, $suffix);
$verb2 = array('ила','ыла','ена','ейте','уйте','ите','или','ыли','ей','уй','ил','ыл','им','ым','ен','ило','ыло','ено','ят','ует','уют','ит','ыт','ены','ить','ыть','ишь','ую','ю');
foreach ($verb2 as $suffix)
if (self::has_suffix($word, $suffix))
return self::cut_suffix($word, $suffix);
$noun = array('а','ев','ов','ие','ье','е','иями','ями','ами','еи','ии','и','ией','ей','ой','ий','й','иям','ям','ием','ем','ам','ом','о','у','ах','иях','ях','ы','ь','ию','ью','ю','ия','ья','я');
foreach ($noun as $suffix) {
if (self::has_suffix($word, $suffix))
return self::cut_suffix($word, $suffix);
}
return $word;
}
static private function step2($word)
{
if (substr($word,-CHAR_LENGTH,CHAR_LENGTH) == 'и')
$word = substr($word, 0, strlen($word)-CHAR_LENGTH);
return $word;
}
static private function step3($word)
{
$vowels = array('а','е','и','о','у','ы','э','ю','я');
$flag = 0;
$r1 = '';
$r2 = '';
for ($i=0; $i<strlen($word); $i+=CHAR_LENGTH)
{
if ($flag==2)
$r1.=substr($word, $i, CHAR_LENGTH);
if (array_search(substr($word,$i,CHAR_LENGTH), $vowels) !== false)
$flag=1;
if ($flag=1 && array_search(substr($word,$i,CHAR_LENGTH), $vowels) === false)
$flag=2;
}
$flag=0;
for ($i=0; $i<strlen($r1); $i+=CHAR_LENGTH)
{
if ($flag==2)
$r2.=substr($r1, $i, CHAR_LENGTH);
if (array_search(substr($r1,$i,CHAR_LENGTH), $vowels) !== false)
$flag=1;
if ($flag=1 && array_search(substr($r1,$i,CHAR_LENGTH), $vowels) === false)
$flag=2;
}
$derivational=array('ост', 'ость');
foreach ($derivational as $suffix)
if (substr($r2,-(strlen($suffix))) == $suffix)
$word=substr($word, 0, strlen($r2)-strlen($suffix));
return $word;
}
static private function step4($word)
{
if (substr($word,-CHAR_LENGTH*2)=='нн')
$word=substr($word, 0, strlen($word)-CHAR_LENGTH);
else
{
$superlative=array('ейш', 'ейше');
foreach ($superlative as $suffix)
if (substr($word,-(strlen($suffix))) == $suffix)
$word = substr($word, 0, strlen($word) - strlen($suffix));
if (substr($word,-CHAR_LENGTH*2) == 'нн')
$word = substr($word, 0, strlen($word) - CHAR_LENGTH);
}
// should there be a guard flag? can't think of a russian word that ends with ейшь or ннь anyways, though the algorithm states this is an "otherwise" case
if (substr($word,-CHAR_LENGTH,CHAR_LENGTH) == 'ь')
$word=substr($word, 0, strlen($word)-CHAR_LENGTH);
return $word;
}
}

View file

@ -14,7 +14,7 @@ class Adapter
public function get($name) public function get($name)
{ {
if (is_array ($this->adaptee)) { if (is_array ($this->adaptee)) {
return $this->adaptee [$name]; return $this->adaptee[$name];
} else { } else {
return $this->adaptee->$name; return $this->adaptee->$name;
} }

View file

@ -2,7 +2,6 @@
/** /**
* Коллекция * Коллекция
* *
* package core
*/ */
class Collection implements ArrayAccess class Collection implements ArrayAccess
{ {
@ -40,7 +39,7 @@ class Collection implements ArrayAccess
* *
* @return void * @return void
*/ */
public function set($key, $value) public function set(/*.string.*/$key, /*.any.*/$value)
{ {
$this->data[$key] = $value; $this->data[$key] = $value;
} }
@ -54,7 +53,7 @@ class Collection implements ArrayAccess
*/ */
public function get($key, $default = null) public function get($key, $default = null)
{ {
return isset($this->data[$key]) ? $this->data[$key] : $default; return isset($this->data[$key]) && $this->data[$key] != '' ? $this->data[$key] : $default;
} }
public function getInt($key, $default = 0) public function getInt($key, $default = 0)

View file

@ -1,7 +1,6 @@
<?php <?php
// HttpConncectionRequest class Connection_HttpRequest
class HttpConnection
{ {
const POST = "POST"; const POST = "POST";
const GET = "GET"; const GET = "GET";
@ -9,18 +8,23 @@ class HttpConnection
private $param = array(); // Параметры запроса private $param = array(); // Параметры запроса
public $data = null; // Содержание public $data = null; // Содержание
public $url; // Адресс public $url; // Адресс
public $method = self::GET; // Метод public $method; // Метод
public $port = 80; public $port = 80;
public $host = ""; public $host = "";
public $proxy_host = false; public $proxy_host = null;
public $proxy_port = false; public $proxy_port = null;
public $http_version = 'HTTP/1.1';
function __construct() {
$this->method = self::GET;
}
/** /**
* Возвращает заголовок соединения * Возвращает заголовок соединения
*/ */
public function getHeader() public function getHeader()
{ {
$result = $this->method . " " . $this->url . " HTTP/1.1\r\n"; $result = $this->method . " " . $this->url . " " . $this->http_version . "\r\n";
$result .= "Host: ". $this->host ."\r\n"; $result .= "Host: ". $this->host ."\r\n";
foreach ($this->param as $key => $value) { foreach ($this->param as $key => $value) {
$result .= $key . ": " . $value . "\r\n"; $result .= $key . ": " . $value . "\r\n";
@ -75,10 +79,10 @@ class HttpConnection
{ {
$host = ($this->proxy_host) ? $this->proxy_host : $this->host; $host = ($this->proxy_host) ? $this->proxy_host : $this->host;
$port = ($this->proxy_port) ? $this->proxy_port : $this->port; $port = ($this->proxy_port) ? $this->proxy_port : $this->port;
$errno = 0;
$errstr = '';
$socket = fsockopen($host, $port, $errno, $errstr, 30); $socket = fsockopen($host, $port, $errno, $errstr, 30);
if (! $socket) { if (is_resource($socket)) {
return null; // Exception
} else {
$header = $this->getHeader(); $header = $this->getHeader();
fwrite($socket, $header); fwrite($socket, $header);
@ -91,5 +95,17 @@ class HttpConnection
} }
return null; return null;
} }
static function getJSON($url, $data) {
$c = new Connection_HttpRequest();
$c->http_version = "HTTP/1.0";
$query = http_build_query($data);
$c->setUrl($q = $url . '?' . $query);
$page = $c->getPage();
$response = new Connection_HttpResponse($page);
return json_decode((string) preg_replace('/[\x00-\x09\x0B\x0C\x0E-\x1F\x7F]/', '', $response->getData()), true);
}
} }

View file

@ -3,11 +3,14 @@
/** /**
* Обрабатывает HTTP ответ * Обрабатывает HTTP ответ
*/ */
class HttpConnectionResponse class Connection_HttpResponse
{ {
private $offset; private $offset;
private $param = array (); private $param = array ();
private $code; private $code;
public $response;
public $version;
public $data;
public function __construct($response) public function __construct($response)
{ {

414
src/Controller/Action.php Normal file
View file

@ -0,0 +1,414 @@
<?php
require_once __DIR__ . '/../functions.php';
function forceUrl($name)
{
if (is_callable($name)) {
return call_user_func($name);
}
return $name;
}
/**
* Контроллер страниц
*/
class Controller_Action
{
const TEMPLATE_EXTENSION = ".html"; // Расширение для шаблонов
const ACTION_PREFIX = "action"; // Префикс для функций действий
public $jsPath; // Глобальный путь к скриптам
public $themePath; // Глобальный путь к текущей теме
// Параметры устанавливаются при создании контроллера
public $name = ''; // Имя модуля
public $viewPath = null; // Путь к шаблонам контроллера
public $viewPathPrefix = null; // Путь к шаблонам контроллера
public $moduleTitle = "";
/**
* Соединение с базой данных
*/
public $db;
// Фильтры
public $access = null; // Обьект хранит параметры доступа
public $logger = null; // Обьект для ведения лога
private $factory = null; // Ссылка на обьект создания модели
private $helpers = array(); // Помошники для действий
public $param = array(); // Параметры для ссылки
public /*.Registry.*/$_registry; // Ссылка на реестр
public $_shortcut;
public $modulePrefix = '';
public $iconPath = '';
public $path;
public function __construct () {
$this->path = new Widgets_PathMenu();
}
public function setUp() {
}
public function loadConfig($name) {
$filename = Shortcut::getUrl('config', $name);
if (file_exists($filename)) {
include($filename);
} else {
throw new Exception('Невозможно загрузить файл настроек ' . $name);
}
return $settings;
}
public function getConnection()
{
return $this->db;
}
public function installPath($name)
{
return Path::join(CMS_PATH, "modules", $name);
}
public function addSuggest(View_View $view, $name)
{
$suggest = array();
$file = Path::join($this->viewPath, 'help', $name . '.suggest');
if (file_exists($file)) {
include($file);
$view->suggestions = $suggest;
}
}
function findIcon($icon, $size)
{
return Path::join($this->iconPath, $size . 'x' . $size, $icon . '.png');
}
/**
* Создает представление
* @param $name String
* @param $viewClass String
* @return View_Composite
*/
public function getView($name, $viewClass = 'View_Composite')
{
$file = $name . self::TEMPLATE_EXTENSION;
$list = array(
Path::join($this->viewPath, TEMPLATES, $this->viewPathPrefix) => Path::join(WWW_PATH, "modules", $this->name, TEMPLATES, $this->viewPathPrefix),
Path::join(CMS_PATH, "templates") => Path::join(WWW_PATH, "templates")
);
// Поиск файла для шаблона
foreach($list as $ospath => $path) {
$template = Path::join($ospath, $file);
if(file_exists($template)) { break; }
}
/*.View_Composite.*/$tpl = new $viewClass($template);
$tpl->set('icons', $this->iconPath); // Путь к файлам текущей темы
$tpl->set('media', $this->themePath); // Путь к файлам текущей темы
$tpl->set('assets', Path::join(WWW_PATH, "assets", "css"));
$tpl->set('script', $this->jsPath); // Путь к файлам скриптов
$tpl->set('template', $path); // Путь к файлам текущего шаблона
$tpl->setAlias(array(
'icons' => $this->iconPath,
'script' => $this->jsPath,
// Для media и template поиск происходит как для файлов шаблонов
'media' => $list,
'template' => $list
));
$tpl->loadImports(Path::skipExtension($template) . ".import");
$this->addSuggest($tpl, $name);
return $tpl;
}
public function getModel($name)
{
if (!$this->factory) {
$this->factory = new Model_Factory($this->db, $this->_registry);
}
return $this->factory->getModel($name);
}
/**
* Выбор действия
* Т.к действия являются методами класса то
* 1. Можно переопределить действия
* 2. Использовать наследование чтобы добавить к старому обработчику новое поведение
* @param $request Обьект запроса
*/
public function execute1(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;
}
public function execute(HttpRequest $request)
{
$result = $this->execute1($request);
if (!empty($result)) {
$this->view = $result;
}
$text = $this->render();
return $text;
}
public function forward($action, HttpRequest $args) {
$value = call_user_func(array($this, $action), $args);
return $value;
}
/**
* Страница по умолчанию
*/
public function actionIndex(HttpRequest $request) {
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);
}
/**
* Генерация ссылки c учетом прав пользователя на ссылки
* @param string $name Действие
* @param array $param Дополнительные параметры
* 'mode' означает что элемент до отправки обрабатывается javascript
* @return array|null
*/
public function nUrl($name, array $param = array())
{
/*.Filter_ActionAccess.*/$access = $this->access;
if ($access != null || $access->checkAction($name)) {
return lcurry(array($this, 'postUrl'), $name, $param);
}
return null;
}
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;
}
}
/**
* Генерация ссылки на действие контроллера
* Ajax определяется автоматически mode = ajax используется для смены layout
* @param $name
* @param array $param
* @return array|null
*
* @example ?action=$name&mode=ajax
* {$param[i].key = $param[i].value}
*/
public function aUrl($name, array $param = array())
{
return $this->nUrl($name, array_merge(array('mode' => 'ajax'), $param)); // FIXME
}
/**
* Добавление помошника контроллера
*/
public function addHelper($class)
{
$this->helpers [] = $class;
}
/**
* Вызов помошников контроллера
*/
public function callHelpers(HttpRequest $request)
{
$action = self::ACTION_PREFIX . $request->getAction();
foreach ($this->helpers as $helper) {
if (method_exists($helper, $action)) {
return call_user_func(array($helper, $action), $request, $this);
} else {
return $helper->actionIndex($request, $this); // Вместо return response ???
}
}
}
/**
* Загрузка файла класса
*/
public function loadClass($path, $setup = null, $prefix = '')
{
if (file_exists($path)) {
require_once ($path);
$class = $prefix . pathinfo($path, PATHINFO_FILENAME);
return new $class($setup);
}
throw new Exception("NO CLASS $path");
}
public function loadSettings($path)
{
$result = new Settings($path);
$result->read();
return $result->export();
}
// Для Widgets
public $view = null;
public $childNodes = array();
public $ctrlValues = array();
public $childViews = array();
public function setView($name)
{
$this->view = $this->getView($name);
}
/**
* Установка заголовка для отображения
*/
public function setTitle($title)
{
$this->view->setTitle($title);
}
/**
* Добавление widget к отображению
*/
public function addChild(/*Widget*/ $section, $node)
{
$this->childNodes[$section] = $node;
}
public function setValue(/*Widget*/ $name, $value)
{
$this->ctrlValues[$name] = $value;
}
/**
* Добавление дочернего отображения к текущему отображению
*/
public function addView(/*CompositeView*/ $section, $node)
{
$this->childViews[$section] = $node;
}
/**
* Генерация содержания
* Путаница c execute и render
*/
public function render()
{
if ($this->view instanceof View_View) {
$this->view->assignValues($this->ctrlValues);
foreach ($this->childNodes as $name => $node) {
$node->make($this);
$this->view->setView($name, $node->view);
}
foreach ($this->childViews as $name => $node) {
$this->view->setView($name, $node);
}
}
return $this->view;
}
function getPageId(HttpRequest $request)
{
$pageId = time();
$request->session()->set('page', $pageId);
return $pageId;
}
function checkPageId(HttpRequest $request, $page)
{
if ($request->get('__forced__')) {
return true;
}
$_page = $request->session()->get('page');
$result = ($_page && $_page == $page);
$request->session()->clean('page');
return $result;
}
function _getActionPath()
{
return new Controller_State('index');
}
// Тоже убрать в метод Controller_Model
function getActionPath(HttpRequest $request, $action = null)
{
$this->_getActionPath()->getPath($this, ($action) ? $action : $request->getAction());
}
function addFilePathToPath($filePath, $type)
{
$pathToItem = $this->directoryPath($filePath, $type, 'default');
$this->path->addMenuItems($pathToItem['path']);
}
function directoryPath($path, $type, $action)
{
$path = empty($path) ? '/' : $path;
$base = new Path($path);
$parts = $base->getParts();
$_path = '/' . implode('/', $parts);
$rs = new Model_Resources($this->db);
$section_path = $rs->getSectionByPath($_path, $type);
$pathMenu = new Widgets_PathMenu();
$pathMenu->addTitle('title');
$modules = ['image' => 'images','page' => 'pages','document' => 'documents','media' => 'videos'];
while ($section_path->id_parent) {
$_path = '/' . implode('/', $parts);
$pathMenu->addMenuItem(
forceUrl($this->nUrl('', array('module'=>$modules[$type],'action' => $action, 'mode' => 'ajax', 'path' => $_path))),
$section_path->title
);
$section_path = $rs->getSectionById($section_path->id_parent);
array_pop($parts);
}
$pathMenu->addMenuItem(
forceUrl($this->nUrl('', array('module'=>$modules[$type],'action' => $action, 'mode' => 'ajax', 'path' => '/'))),
$this->moduleTitle
);
return $pathMenu->getItemsReverse();
}
}

View file

@ -0,0 +1,325 @@
<?php
function replaceContent($match) {
$result = phptal_component(htmlspecialchars_decode($match[3]));
return $result;
}
function applyComponents($text) {
return preg_replace_callback('/<(\w+)(\s+[a-zA-Z\-]+=\"[^\"]*\")*\s+tal:replace="structure\s+component:([^\"]*)"[^>]*>/u', 'replaceContent', $text);
}
class ComponentRequest {
public $component_id;
public $r;
function __construct($c, HttpRequest $r) {
$this->component_id = $c;
$this->r = $r;
}
function get($key, $default = null) {
if ($key == 'active_page') {
return $this->r->get($key);
}
if ($arr = $this->r->get($key)) {
if (is_array($arr)) {
return Arr::get($arr, $this->component_id, $default);
} else {
return $arr;
}
}
return $default;
}
function getAction() {
return $this->r->getAction();
}
}
/**
* Класс компонента
*/
class Controller_Component
{
public $viewPath = array();
public $webPath = array();
public $template = null;
public $templatePath;
public $component_id;
public $COMPONENTS_WEB;
public /*.Settings.*/$registry;
public /*.Database.*/$db;
public /*.Collection.*/$parameter;
public $module;
public $item_module;
function before() {
}
function get($request, $key, $default) {
}
function execute(HttpRequest $request, $has_id = true) {
$crequest = new ComponentRequest($this->component_id, $request);
$action = 'action' . ucfirst($request->get('action', 'index'));
$this->before();
if (method_exists($this, $action)) {
return call_user_func(array($this, $action), $crequest);
} else {
return $this->actionIndex($crequest);
}
}
public function getView($name)
{
//
/*.Settings.*/$registry = $this->registry;
$template = ($this->template) ? $this->template : $registry->readKey(array('system', 'template'));
$selected = null;
foreach ($this->viewPath as $index => $viewPath) {
// Загружать шаблон по умолчанию если не найден текущий
if(is_dir(Path::join($this->viewPath[$index], 'templates', $template))) {
$tpl = new PHPTAL(Path::join($this->viewPath[$index], 'templates', $template, $name));
$tpl->setPhpCodeDestination(PHPTAL_PHP_CODE_DESTINATION);
$selected = $index;
break;
}
}
if ($selected === null) {
$tpl = new PHPTAL(Path::join($this->viewPath[0], 'templates', 'modern', $name));
$tpl->setPhpCodeDestination(PHPTAL_PHP_CODE_DESTINATION);
$template = 'modern';
$selected = 0;
}
$tpl->stripComments(true);
$tpl->addPreFilter(new PHPTAL_PreFilter_Normalize());
$tpl->set('common', Path::join(WWW_PATH, '../', 'common'));
$tpl->set('script', Path::join(WWW_PATH, 'js'));
$tpl->set('media', Path::join(TEMPLATE_WEB, $template));
$tpl->set('site_template', SITE_WWW_PATH . '/templates' . $registry->readKey(array('system', 'template')));
$tpl->set('base', SITE_WWW_PATH);
$tpl->set('component_base', $this->webPath[$selected]);
$tpl->set('component', Path::join($this->webPath[$selected], 'templates', $template));
$tpl->set('component_id', $this->component_id);
return $tpl;
}
public function getTemplatePath($name) {
return Path::join($this->viewPath[0], 'templates', 'modern', $name);
}
public function getTemplateWebPath()
{
return Path::join($this->webPath[0], 'templates', 'modern');
}
/**
* @param $name Имя модели
*/
private function getModelPath($name)
{
return Path::join (CMS_PATH, "model", $name . ".php");
}
/**
* Создает модель
* @param string $name
* @return model
*/
public function getModel($name)
{
require_once ($this->getModelPath ($name));
$modelName = $name . "Mapper";
$model = new $modelName ();
$model->db = $this->db;
return $model;
}
public function options($key, $val, /*.Database_PDOStatement.*/$res) {
$result = array();
while($res->next()) {
$result[] = array('value' => $res->getString($key), 'name' => $res->getString($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;
}
function getInfo() {
$filename = Path::join($this->viewPath[0], 'install.json');
if (file_exists($filename)) {
$settings = json_decode(file_get_contents($filename), true);
return $settings;
}
return array();
}
/**
* Генерация интерфейса для выбора галлереи фотографии
*/
public function setParameters(/*.View_Composite.*/$view)
{
$form = new Form_Form();
$options = new OptionFactory($this->db);
$settings = $this->getInfo();
$form->addFieldList($settings['parameter'], $options);
$view->form = $form;
$view->component = $settings['component'];
$view->component_title = $settings['title'];
}
static function loadComponent($expression, Database $db, Settings $registry)
{
$expression = htmlspecialchars_decode($expression);
$offset = strpos($expression, '?');
$url = parse_url($expression);
$arguments = array();
if ($offset === false) {
$path = $expression;
} else if (is_int($offset)) {
$path = substr($expression, 0, $offset);
$query = substr($expression, $offset + 1);
parse_str($query, $arguments);
}
$name = $path;
$path = Path::join (BASE_PATH, 'components', $name, $name . '.php');
$className = 'Component_' . $name;
if (file_exists($path)) {
require_once ($path);
$component = new $className();
$component->db = $db;
$component->registry = $registry;
$component->viewPath = array(BASE_PATH . '/components/' . $name . '/');
$component->webPath = array(SITE_WWW_PATH . '/components/' . $name);
$component->COMPONENTS_WEB = SITE_WWW_PATH . '/components/';
} else {
$path = Path::join (COMPONENTS, $name, $name . '.php');
require_once ($path);
$component = new $className();
$component->db = $db;
$component->registry = $registry;
$component->viewPath = array(COMPONENTS . '/' . $name . '/', BASE_PATH . '/components/' . $name . '/');
if (defined('COMPONENTS_WEB')) {
$component->webPath = array(COMPONENTS_WEB . '/' . $name, SITE_WWW_PATH . '/components/' . $name);
$component->COMPONENTS_WEB = COMPONENTS_WEB;
}
}
$stmt = $db->prepareStatement("SELECT * FROM component WHERE code = ?");
$stmt->setString(1, $expression);
$cid = $stmt->executeQuery();
if ($cid->next()) {
$component->component_id = $cid->getInt('id_component');
} else {
$last = $db->getIdGenerator();
if ($last->isBeforeInsert()) {
$result = $last->getId('component_id_component_seq');
$stmt = $db->prepareStatement("INSERT INTO component (id_component, code) VALUES ($result, ?)");
$stmt->setString(1, $expression);
$stmt->executeQuery();
}
if ($last->isAfterInsert()) {
$stmt = $db->prepareStatement("INSERT INTO component (code) VALUES (?)");
$stmt->setString(1, $expression);
$stmt->executeQuery();
$result = $last->getId('component_id_component_seq');
}
$component->component_id = $result;
}
$params = new Collection();
$params->import(array_merge($_GET, $arguments));
$component->parameter = $params;
$component->template = $params->get('template', false);
global $componentsConfig;
$editor = $component->getEditUrl();
if ($editor) {
$componentsConfig[] = $editor;
}
return $component;
}
function getEditUrl() {
return null;
}
function raw_query(/*.ComponentRequest.*/ $request)
{
$arr = $request->r->export('get');
$param = array();
/*.Collection.*/$parameter = $this->parameter;
foreach($parameter->export() as $key => $value) {
$param[$key] = $value;
}
$data = array();
foreach($arr as $key => $value) {
if (is_array($value)) {
$data[$key] = Arr::get($value, $this->component_id);
} else {
$data[$key] = $value;
}
}
$data['param'] = $param;
return $data;
}
function query(/*.ComponentRequest.*/ $request, $list)
{
$arr = $request->r->export('get');
foreach($list as $key => $val) {
$arr[$key] [$this->component_id] = $val;
}
unset($arr['active_page']);
return '?' . http_build_query($arr);
}
function addRequireJsPath($name, $path, $shim = null) {
global $requireJsConfig;
$requireJsConfig['paths'][$name] = $path;
if ($shim) {
$requireJsConfig['shim'][$name] = $shim;
}
}
function actionIndex(/*.ComponentRequest.*/ $request) {
}
}

View file

@ -1,32 +1,38 @@
<?php <?php
require_once 'core/controller/controller.php';
require_once 'core/controller/installer.php';
/** /**
* Первичный контроллер контроллер страниц * Первичный контроллер контроллер страниц
* @package core * @package system.controller
*/ */
class Controller_Front extends Controller class Controller_Front extends Controller_Action
{ {
/** @var Shortcut */
protected $shortcut; // Ярлык к модулю protected $shortcut; // Ярлык к модулю
protected $_param; // Параметр по которому выбирается модуль protected $_param; // Параметр по которому выбирается модуль
protected $default; // Значение параметра по умолчанию protected $default; // Значение параметра по умолчанию
protected $installer;
public function __construct(Settings $_registry, $_shortcut) protected $modules = array();
/**
* @param Settings $_registry
* @param Shortcut $_shortcut
*/
public function __construct(Settings $_registry, $_shortcut) // $db, $installer, $shortcut
{ {
require_once 'core/database_pdo.php';
parent::__construct(); parent::__construct();
$registry = $_registry; $registry = $_registry;
$this->_registry = $_registry; $this->_registry = $_registry;
$this->_shortcut = $_shortcut; $this->_shortcut = $_shortcut; // $cc->newShortcut();
$this->db = Database::getConnection($registry->readKey(array('system', 'dsn'))); $dsn = $registry->readKey(array('system', 'dsn'));
$this->installer = new Installer($_registry); $this->db = Database::getConnection($dsn); // $cc->newConnection();
} }
public function isLoaded($name)
{
return isset($this->modules[$name]);
}
/** /**
* Создает экземпляр модуля и выполняет действия для него * Создает экземпляр модуля и выполняет действия для него
@ -34,17 +40,22 @@ class Controller_Front extends Controller
* @param request $request Имя модуля * @param request $request Имя модуля
* @return string * @return string
*/ */
public function loadModule($name, Collection $request) public function loadModule($name, Collection $request, $controller = false)
{ {
$this->installer->setUp($this->db, array($this, 'installPath')); if ($this->isLoaded($name)) {
$this->installer->doUpdates($name); // ModuleLoader (1) $module = $this->modules[$name];
return $module->access->execute($request);
}
$moduleFile = Shortcut::getUrl($this->shortcut, $name); // ModuleLoader (2) if ($controller) {
$module = $this->loadClass($moduleFile); $moduleFile = Shortcut::getUrl($this->shortcut, $name, $controller); // ModuleLoader (2)
} else {
$moduleFile = Shortcut::getUrl($this->shortcut, $name, $name); // ModuleLoader (2)
}
$module = $this->loadClass($moduleFile, null, 'Module_');
if ($module) { if ($module) {
// Инициализация модуля // Инициализация модуля
// $module->viewPath = dirname($moduleFile);
$module->viewPath = Shortcut::getUrl('modulepath', $name); $module->viewPath = Shortcut::getUrl('modulepath', $name);
$module->name = $name; $module->name = $name;
@ -59,15 +70,17 @@ class Controller_Front extends Controller
$module->db = $this->db; $module->db = $this->db;
// Не для всех приложений нужно вести лог действий // Не для всех приложений нужно вести лог действий
// Ведение лога // Ведение лога
$logger = $this->loadClass(FRAMEWORK_PATH . '/core/filter/actionlogger.php', $module); $logger = $this->loadClass(FRAMEWORK_PATH . '/filter/actionlogger.php', $module, 'Filter_');
$logger->before = $this->loadSettings(Shortcut::getUrl('logger', $name)); $logger->before = $this->loadSettings(Shortcut::getUrl('logger', $name));
// Управление доступом // Управление доступом
$module->access = $this->loadClass(FRAMEWORK_PATH . '/core/filter/actionaccess.php', $logger); $module->access = $this->loadClass(FRAMEWORK_PATH . '/filter/actionaccess.php', $logger, 'Filter_');
$module->access->access = $this->loadSettings(Shortcut::getUrl('access', $name)); $module->access->access = $this->loadSettings(Shortcut::getUrl('access', $name));
$module->setUp(); $module->setUp();
return $module->access->execute($request); $this->modules[$name] = $module;
$result = $module->access->execute($request);
return $result;
} }
return null; // throw new FileNotFoundException(); return null; // throw new FileNotFoundException();
} }
@ -80,13 +93,14 @@ class Controller_Front extends Controller
$this->default = $name; $this->default = $name;
} }
private function getParameter(Collection $list)
{
return ($list->get($this->_param)) ? $list->get($this->_param): $this->default;
}
public function execute(HTTPRequest $request) public function execute(HTTPRequest $request)
{ {
return $this->loadModule($this->getParameter($request), $request); $name = explode("_", $request->get($this->_param, $this->default));
if (count($name) >= 2) {
$controller = $name[1];
} else {
$controller = false;
}
return $this->loadModule($name[0], $request, $controller);
} }
} }

View file

@ -1,10 +1,8 @@
<?php <?php
require_once 'core/settings.php'; class Controller_Installer
class Installer
{ {
protected $db; protected $db_manager;
protected $installPath; protected $installPath;
public $_registry; public $_registry;
@ -13,15 +11,20 @@ class Installer
$this->_registry = $_registry; $this->_registry = $_registry;
} }
public function setUp($db, $installPath) public function setUp($db_manager, $installPath)
{ {
$this->db = $db; $this->db_manager = $db_manager;
$this->installPath = $installPath; $this->installPath = $installPath;
} }
function getSetupFile($name) function getSetupFile($name)
{ {
return Path::join(call_user_func($this->installPath, $name), "setup.php"); $setup = Path::join(call_user_func($this->installPath, $name), "install.json");
return $setup;
}
function getUninstallFile($name){
return Path::join(call_user_func($this->installPath, $name), "sql", "uninstall.json");
} }
// Проверка версии обновления // Проверка версии обновления
@ -40,22 +43,33 @@ class Installer
function installSQL(array $sql, $version_new, $version_old, $name) function installSQL(array $sql, $version_new, $version_old, $name)
{ {
require_once "core/setup.php"; $result = [];
$json_installer = new Database_JsonInstall($this->db_manager);
foreach ($sql as $version => $install) { foreach ($sql as $version => $install) {
if (version_compare($version, $version_new, "<=") && version_compare($version, $version_old, ">")) { if (version_compare($version, $version_new, "<=") && version_compare($version, $version_old, ">")) {
// this->installPath this->db
$file = Path::join(call_user_func($this->installPath, $name), "sql", $install); $file = Path::join(call_user_func($this->installPath, $name), "sql", $install);
Setup::batchSQL($this->db, $file); $json_installer->install($file,null);
$result[] = $version;
} }
} }
return $result;
} }
function uninstall($name){
$uninstall = $this->getUninstallFile($name);
if (file_exists($uninstall)) {
$json_installer = new Database_JsonInstall($this->db_manager);
$json_installer->install($uninstall,null);
}
$this->_registry->removeKey($name);
$this->_registry->write();
}
// Устанавливает обновления если есть // Устанавливает обновления если есть
function doUpdates($name, $force = false) // Установка модуля function doUpdates($name, $force = false) // Установка модуля
{ {
$result = array();
$setup = $this->getSetupFile($name); $setup = $this->getSetupFile($name);
if (file_exists($setup) && ($this->isChanged($name) || $force)) { if (file_exists($setup) && ($this->isChanged($name) || $force)) {
$registry = $this->_registry; $registry = $this->_registry;
$settings = new Settings($setup); $settings = new Settings($setup);
$settings->read(); $settings->read();
@ -69,21 +83,29 @@ class Installer
$version_old = "0.0"; $version_old = "0.0";
$registry->writeKey(array($name), array()); $registry->writeKey(array($name), array());
} }
if (version_compare($version_old, $settings->get('version'), "!=")) { if (version_compare($version_old, $settings->get('version'), "!=")) {
$sql = $settings->get('sql'); $sql = $settings->get('sql');
if (is_array($sql)) { if (is_array($sql)) {
$this->installSQL($sql, $version_new, $version_old, $name); $res = $this->installSQL($sql, $version_new, $version_old, $name);
if($res){
$result[]=$res;
}
} }
} }
// Обновление версии меню // Обновление версии меню
$registry->removeKey($name);
$registry->writeKey(array($name), $settings->get('settings')); $registry->writeKey(array($name), $settings->get('settings'));
$registry->writeKey(array($name), $registry->writeKey(array($name),
array('version' => $version_new, array('version' => $version_new,
'time' => filemtime($setup))); 'time' => filemtime($setup)));
$registry->write(); $registry->write();
} }
return $result;
}
function install($dbinit_path,$dbfill_path=null){
$json_installer = new Database_JsonInstall($this->db_manager);
$json_installer->install($dbinit_path,$dbfill_path);
} }
} }

520
src/Controller/Model.php Normal file
View file

@ -0,0 +1,520 @@
<?php
/**
* Переименовать контроллер !! (StubController, CrudController, PageController, BaseController) ModelController
* Возможно нужен еще класс с мета действиями как для actionIndex <= metaActionIndex либо с классам для этих действий
* Есть класс для управлениями действиями а есть сами действия в виде классов или функций !!
*
* @class Controller_Model в котором определены основные действия для редактирования, вывода списка, сохранения, поиска и т.д
* В модуле определяется только способ отображения этих данных
*/
class Controller_Model extends Controller_Action
{
public /*.array.*/$schema = array();
public /*.array.*/$schemaSearch = array();
/**
* FIXME: Лучше $this->table->setHeader
*/
public $tableSchema = null;
public /*.array.*/$formSchema = array();
public $menu;
public $table;
protected /*.string.*/$useModel;
protected /*.string.*/$itemModel;
public function __construct()
{
parent::__construct();
$this->menu = new Widgets_PageMenu();
$this->table = new Widgets_ReactListTable();
}
/**
*/
function setUp() {
parent::setUp();
$this->table->addMenuItem($this->aUrl('delete'), 'удалить', false, 'all', 'btn-danger', 'remove');
}
function saveParameters(HttpRequest $args, $list) {
foreach ($list as $item) {
$args->session()->set(array($this, $item), $args->get($item));
}
}
protected function getJSONList(/*.Model_Mapper.*/ $model, HttpRequest $request) {
$result = array();
$this->saveParameters($request, array('size','page','desc', 'key'));
$result['list'] = $model->findAll($request, $request->get('ref'));
$result['size'] = $model->getCount($request, $request->get('ref'));
return json_encode($result);
}
protected function getCSV(Model_Mapper $model, HttpRequest $request, $title) {
$ref = $request->get('ref');
$list = $model->findAll($request, $request->get('ref'));
header('Content-Type: text/csv; charset=utf-8');
header('Content-Disposition: attachment; filename='.$title.'.csv');
echo "\xEF\xBB\xBF"; //UTF-8 BOM.
$output = fopen('php://output', 'w');
if (is_resource($output)) {
foreach ($list as $row) {
fputcsv($output, (array)$row,';');
}
}
}
/**
* Удаление строк из таблицы
*/
public function actionDelete(HttpRequest $request)
{
$model = $this->getModel($this->useModel);
// Почему table_item ???
$list = ($request->get('table_item')) ? $request->get('table_item'): $request->get('id');
$model->deleteList($list);
// return $this->getJSONList($model, $request);
return json_encode(array('result' => 'ok'));
}
/**
* Ответ на запрос по поиску
*/
public function actionSearch(HttpRequest $request)
{
$model = $this->getModel($this->useModel);
$model->addFilter($model->requestToSQL($request, $this->formSchema));
return $this->getJSONList($model, $request);
}
/**
* Список элементов
*/
public function actionList(HttpRequest $request)
{
$model = $this->getModel($this->useModel);
if ($request->get('filter')) {
$data = new Collection();
$data->import($request->get('filter'));
$model->addFilter($model->requestToSQL($data, $this->formSchema));
}
return $this->getJSONList($model, $request);
}
public function actionCSV(HttpRequest $request)
{
$model = $this->getModel($this->useModel);
$title = $request->get("title");
if(!$title){
$title = "noname";
}
return $this->getCSV($model, $request, $title);
}
private function setFormSchema()
{
$model = $this->getModel($this->useModel);
$ui = new Model_UIMapper($model);
$this->formSchema = $ui->getFormSchema();
}
/**
* Сохранение формы
*/
function beforeSave(/*Model*/ $item, HttpRequest $request)
{
if (empty($this->formSchema)) {
$this->setFormSchema();
}
// Сделать отображение Формы в обьект и обратно
foreach ($this->formSchema as $key => $conv) {
list($value, $type) = $conv;
$item->$value = call_user_func(array('Primitive', 'to_' . $type), $request->get($key)); // Здесь нужно преобразовывать тип значения
}
}
/**
* Обновление формы
*/
function formUpdate(Form_Form $form, HttpRequest $request) {
$form->setValues($request);
}
/**
* Загрузка формы
*/
function beforeLoad(/*.Model_Model.*/$item, Form_Form $form)
{
if (empty($this->formSchema)) {
$this->setFormSchema();
}
// Вставка значений из данных в форму
// Отображение обьекта в поля формы
$form->fill($item, $this->formSchema);
}
function beforeFirstLoad(Form_Form $form)
{
}
// Проверка ввода
protected function validate(Validator_Validator $validator, Collection $request)
{
}
/**
* Действие для проверки формы
*/
public function actionValidate($request)
{
$validator = new Validator_Validator();
$validator->addRuleList($this->schema);
// Действия до проверки формы
$this->validate($validator, $request); // <--|
$validator->validate($request); // --|
// Проверка формы
if (!$validator->isValid()) {
return json_encode($validator->getErrorMsg());
}
return json_encode(true);
}
/**
* Инициализация формы
*/
protected function formSetup(Form_Form $form, $id = null, $ref = null)
{
if (empty($this->schema)) {
$model = $this->getModel($this->useModel);
$ui = new Model_UIMapper($model);
$schema = $ui->getEditSchema();
$form->addFieldList($schema);
} else {
$form->addFieldList($this->schema);
}
}
/**
* Добавление
*/
public function actionAdd(HttpRequest $request)
{
// {{{ тоже может быть один ref или несколько
$ref = $request->get('ref');
$this->addParameter('ref', $ref); // Добавляет параметр в url
/// }}}
// Проверка
$validator = new Validator_Validator();
$validator->addRuleList($this->schema);
// Действия до проверки формы
$this->validate($validator, $request); // <--|
$validator->validate($request); // --|
// Проверка формы
if (!$validator->isValid()) {
return json_encode(array('result'=>'fail','errors'=>$validator->getErrorMsg()));
}
// Нужен тест для формы
$model = $this->getModel($this->useModel);
$className = $model->className;
$item = new $className();
// Сохраняем значение в базе данных
$item->id = $request->get('id');
// Если таблица связана с другой таблицей
if ($request->get('ref') && $model->reference[1]) {
$ref_id = $model->reference[1];
$item->$ref_id = $request->get('ref');
}
// Подготовка к сохранению
$this->beforeSave($item, $request); // Сюдаже и истрия переходов
// nextId ??? или выход или новая форма для создания новости
$id = $model->saveDB($item, $request);
// Для страницы со списком id -> идентификатор родительской таблицы !!??
// $request->set('id', $request->get('ref'));
if ($request->get('apply')) {
$request->setAction('form');
return (string) $this->forward('actionForm', $request);
}
//$request->setAction('index');
$result = array('result'=>'ok');
if($id){
$result['action'] = forceUrl($this->nUrl('add', array('id' => $id, 'ref' => $request->get('ref'))));
}
return json_encode($result);
}
/**
* Заголовок
*/
private function setTitlePath($ref)
{
if ($ref) {
$model = $this->getModel($this->useModel);
if (is_array($model->reference) && $model->reference[0]) {
$refmodel = $this->getModel($model->reference[0]);
try {
$parent = $refmodel->findById($ref);
$this->path->addTitle($parent->getTitle()); // Заголовок к подписям путей
} catch (Exception $e) {
// Не найден заголовок потому что неправильно определен родительский элемент
}
}
}
}
/**
* Форма для редактирования
*/
public function actionForm(HttpRequest $request)
{
$this->getActionPath($request);
$ref = $request->get('ref');
$this->addParameter('ref', $ref); // Добавляет параметр в url
$this->setTitlePath($ref);
$model = $this->getModel($this->useModel);
$form = new Form_Form(); // Показываем форму
$form->header = 'Редактирование записи';
$this->formSetup($form, $request->get('id'), $request->get('ref')); // Инициализация формы
$list = $request->get('table_item');
$id = ($list[0]) ? $list[0] : $request->get('id');
//
$tpl = $this->formPage($form, $request);
if ($id) { // Редактирование
$form->action = forceUrl($this->nUrl('add', array('id' => $id, 'page' => $this->getPageId($request)))); // action Свойство формы
$item = $model->findById($id);
// Загрузка формы
$this->beforeLoad($item, $form);
}else{//Создание нового элемента
$this->beforeFirstLoad($form);
}
return json_encode($tpl);
}
/**
*/
function tableSetup(Widgets_ListTable $table, $id = null, $ref = null)
{
// FIXME: После замены везде $tableSchema -> table->setHeader удалить!
if ($this->tableSchema) {
$table->setHeader($this->tableSchema);
} else {
// Настройка таблицы отображения по схеме данных
$model = $this->getModel($this->useModel);
$ui = new Model_UIMapper($model);
$ui->hidden = $table->hidden;
$schema = $ui->getTableSchema();
$schema[0]['action'] = forceUrl($table->getFirstItem());
$table->setHeader($schema);
}
}
/**
*/
public function actionDefault(HttpRequest $request)
{
$this->getActionPath($request, 'index');
// Такое мета действие наверное можно вынести в отдельный класс
return $this->metaActionIndex($request, array($this, 'tableSetup'), $this->aUrl('list'));
}
/**
* Страница по умолчанию
*/
public function metaActionIndex(HttpRequest $request, $setup, $list)
{
// может быть одно ref или несколько
// {{{ история переходов
$ref = null;
if ($request->get('ref')) {
$ref = $request->get('ref');
} else if ($request->session()->get('ref')) {
$ref = $request->session()->get('ref');
}
$request->session()->set('ref', $ref);
$this->addParameter('ref', $ref);
// }}}
$this->setTitlePath($ref);
$tpl = new stdClass();
// Помощники действий
$this->callHelpers($request);
// Таблица
if ($request->session()->get(strtolower(get_class($this)))) {
$session = $request->session()->get(strtolower(get_class($this)));
if (isset($session['view'])) {
$this->table->setView($session['view']);
}
$this->table->setData('state', array(
'page' => $session['page'],
'size' => $session['size'],
'desc' => $session['desc']));
//$this->table->setData('sorter', $session['key']);
if (isset($session['desc'])) {
$this->table->setData('desc', $session['desc']);
}
}
call_user_func($setup, $this->table, $request->get('id'), $ref);// --> Эквивалент formSetup
$this->table->setAction($list);
if (!$this->table->getData('module')) {
$this->table->setData('module', strtolower($this->useModel));
}
$tpl->menu_path = $this->path->getItems();
$this->table->makeData();
$tpl->table = array('data' => $this->table->data);
$tpl->menu = $this->menu->menu->getItems();
$tpl->path = $this->path->getItems();
return json_encode($tpl);
}
/**
*/
public function actionSetup(HttpRequest $request) {
$left = explode(",", $request->get('left'));
$right = explode(",", $request->get('right'));
$request->session()->set(strtolower(get_class($this)),
array('view' => array('left' => $left, 'right' => $right), 'page' => 1, 'size' => 0, 'desc' => 'asc', 'key' => false));
return $this->forward('actionIndex', $request);
}
/**
*/
protected function formPage($form, $request, $template = 'form') {
$view = new stdClass();//$this->getView($template);
$view->form = $form;
$form->action = forceUrl($this->nUrl('add', array('page' => $this->getPageId($request)))); // Действие для формы
$view->path = $this->path->getItems();
$view->back = $this->path->getPrev();
return $view;
}
function _getActionPath() {
return new Controller_State('index');
}
// Тоже убрать в метод Controller_Model
function getActionPath(HttpRequest $request, $action = null) {
$this->_getActionPath()->getPath($this, ($action) ? $action : $request->getAction());
}
function parse_params($expression) {
$expression = htmlspecialchars_decode($expression);
$offset = strpos($expression, '?');
$url = parse_url($expression);
$arguments = array();
if ($offset === false) {
$path = $expression;
} else if (is_int($offset)) {
$path = substr($expression, 0, $offset);
$query = substr($expression, $offset+1);
parse_str($query, $arguments);
}
return $arguments;
}
public function actionFormPage(HttpRequest $request) {
//$tpl = $this->getView('formpage', 'View_Top');
$view = $this->getView('formpage', 'View_Top');
$params = $this->parse_params($request->get('params'));
// $model = $this->getModel($this->useModel);
$form = new Form_Form(); // Показываем форму
$form->header = 'Редактирование записи';
$this->formSetup($form, $request->get('id'), $request->get('ref')); // Инициализация формы
/*
$ui = new Model_UIMapper($model);
$schema = $ui->getEditSchema();
$form->addFieldList($schema);
*/
$list = $request->get('table_item');
$id = ($list[0]) ? $list[0] : $request->get('id');
// $tpl = $this->formPage($form, $request);
$view->setView('form', $form);
$view->action = forceUrl($this->nUrl('addpage', array('ref' => $params['id']))); // Действие для формы
// $view->menu_path = $this->path->getItems();
$view->back = '';
return $view;
// return $tpl;
}
/* Для поддержки редактрования на сайте */
public function actionAddPage(HttpRequest $request)
{
// {{{ тоже может быть один ref или несколько
$ref = $request->get('ref');
$this->addParameter('ref', $ref); // Добавляет параметр в url
/// }}}
$validator = new Validator_Validator();
$validator->addRuleList($this->schema);
// Действия до проверки формы
$this->validate($validator, $request); // <--|
$validator->validate($request); // --|
// Проверка формы
if (!$validator->isValid()) {
return $validator;
}
// Нужен тест для формы
$model = $this->getModel($this->useModel);
$className = $model->className;
$item = new $className();
// Сохраняем значение в базе данных
$item->id = $request->get('id');
// Если таблица связана с другой таблицей
if ($request->get('ref') && $model->reference[1]) {
$ref_id = $model->reference[1];
$item->$ref_id = $request->get('ref');
}
// Подготовка к сохранению
$this->beforeSave($item, $request); // Сюдаже и истрия переходов
$model->saveDB($item, $request);
return null;
}
}

View file

@ -0,0 +1,16 @@
<?php
class Controller_Request {
function __construct($request, $id) {
$this->r = $request;
$this->id = $id;
}
function get($name) {
$v = $this->r->get($name);
if ($id && is_array($v)) {
return isset($v[$id]) ? $v[$id] : $def;
}
return $v;
}
}

View file

@ -0,0 +1,64 @@
<?php
/**
* Класс сервиса = Упрощенный компонент
*/
class Controller_Service
{
public $viewPath = array();
public $registry; // Registry->getInstance
public $template;
public $templatePath;
public $COMPONENTS_WEB;
public function getTemplatePath($name)
{
return Path::join($this->viewPath[0], 'templates', 'modern', $name);
}
public function getTemplateWebPath()
{
return Path::join($this->webPath[0], strtolower(get_class($this)), 'templates', 'modern');
}
/**
* @param $name Имя модели
*/
private function getModelPath($name)
{
return Path::join (CMS_PATH, "model", $name . ".php");
}
/**
* Создает модель
* @param string $name
* @return model
*/
public function getModel($name)
{
require_once 'mapper/mapper.php';
require_once ($this->getModelPath ($name));
$modelName = $name . "Mapper";
$model = new $modelName ();
$model->db = $this->db;
return $model;
}
public function options($key, $val, $res) {
$result = array();
while($res->next()) {
$result[] = array('value' => $res->getInt($key), 'name' => $res->getString($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

@ -1,6 +1,6 @@
<?php <?php
class State class Controller_State
{ {
public $action = ''; public $action = '';
public $states = array(); public $states = array();
@ -13,7 +13,7 @@ class State
static function make($action) static function make($action)
{ {
return new State($action); return new Controller_State($action);
} }
public function addTitle($name, $url = array()) public function addTitle($name, $url = array())
@ -22,7 +22,7 @@ class State
return $this; return $this;
} }
public function addState(State $state) public function addState(Controller_State $state)
{ {
$this->states [$state->getAction()] = $state; $this->states [$state->getAction()] = $state;
return $this; return $this;
@ -49,7 +49,7 @@ class State
return false; return false;
} }
function makeTitle($module) function makeTitle(Controller_Action $module)
{ {
foreach ($this->titles as $item) { foreach ($this->titles as $item) {
$module->path->addMenuItem($module->nUrl($this->action, $item[1]), $item[0]); $module->path->addMenuItem($module->nUrl($this->action, $item[1]), $item[0]);
@ -68,12 +68,3 @@ class State
} }
} }
} }
/*
$path = State::make('index')
->addState(State::make('form'))
->addState(State::make('view'));
$path->getPath(0, 'form');
*/

180
src/Database.php Normal file
View file

@ -0,0 +1,180 @@
<?php
///<reference path="database/pdostatement.php" />
require_once "database/pdostatement.php";
/**
* Класс оболочка для PDO для замены Creole
*/
class Database extends PDO
{
public $dsn;
public function __construct($dsn, $username = null, $password = null)
{
parent::__construct($dsn, $username, $password);
$this->setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION);
$this->setAttribute(PDO::ATTR_STATEMENT_CLASS, array('Database_PDOStatement', array()));
}
public function getDSN()
{
return $this->dsn;
}
public function isPostgres(){
return ($this->dsn["phptype"] == "pgsql");
}
/**
* Создает соединение с базой данных
*/
static function getConnection(array $dsn)
{
if ($dsn['phptype'] == 'pgsql' || $dsn['phptype'] == 'mysql') {
$port = (isset($dsn['port'])) ? "port={$dsn['port']};" : "";
/*.Database.*/$connection = 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"');
}
}
if ($dsn['phptype'] == 'sqlite') {
/*.Database.*/$connection = new static("{$dsn['phptype']}:{$dsn['database']}");
$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->dsn = $dsn;
return $connection;
}
public function executeQuery($query, $values=null)
{
/*.Database_PDOStatement.*/$stmt = $this->prepare($query);
$stmt->execute($values);
$stmt->cache = $stmt->fetchAll(PDO::FETCH_ASSOC);
return $stmt;
}
public function prepareStatement($query)
{
return new Database_Statement($query, $this);
}
// Для совместимости со старым представлением баз данных CIS
/**
* Извлекает из базы все элементы по запросу
*/
public function fetchAllArray($query,$values=null)
{
/*.Database_PDOStatement.*/$sth = $this->prepare($query);
$prep = $this->prepareValues($values);
$sth->execute($prep);
return $sth->fetchAll(PDO::FETCH_ASSOC);
}
/**
* Извлекает из базы первый элемент по запросу
*/
public function fetchOneArray($query,$values=null)
{
/*.Database_PDOStatement.*/$sth = $this->prepare($query);
$prep = $this->prepareValues($values);
$sth->execute($prep);
return $sth->fetch(PDO::FETCH_ASSOC);
}
private static function assignQuote($x, $y)
{
return $x . "=" . $this->quote($y);
}
private function prepareValues($values)
{
if (!$values) {
return null;
}
$pg = $this->isPostgres();
$prep = array();
foreach ($values as $key => $value) {
$result = null;
if(is_bool($value)) {
if ($pg) {
$result = $value ? 'true' : 'false';
} else {
$result = $value ? 1 : 0;
}
} else {
$result = $value;
}
$prep[":" . $key] = $result;
}
return $prep;
}
/**
* Создает INSERT запрос
*/
function insertQuery($table, array $values, $return_id = false, $index = null)
{
$prep = $this->prepareValues($values);
$sql = "INSERT INTO $table (" . implode(",", array_keys($values))
. ") VALUES (" . implode(",", array_keys($prep)). ")";
if($return_id){
if ($this->isPostgres()){
$sql = $sql." RETURNING $index";
}
}
$stmt = $this->prepare($sql);
$stmt->setFetchMode(PDO::FETCH_ASSOC);
$stmt->execute($prep);
$result = $stmt->fetch();
if ($return_id) {
if ($this->isPostgres()) {
return $result[$index];
} else {
$result = $this->fetchOneArray("SELECT $index AS lastid FROM $table WHERE OID = last_insert_rowid()");
return $result['lastid'];
}
}
}
/**
* Создает UPDATE запрос
*/
function updateQuery($table, array $values, $cond)
{
$prep = $this->prepareValues($values);
$sql = "UPDATE $table SET " . implode(",",
array_map(function($k,$v){return $k."=".$v;}, array_keys($values), array_keys($prep))) . " WHERE $cond";
$stmt = $this->prepare($sql);
$stmt->setFetchMode(PDO::FETCH_ASSOC);
$stmt->execute($prep);
}
function getIdGenerator() {
return new Database_IdGenerator($this);
}
/**
* Замечание: Только для Postgres SQL
* @param string $seq Имя последовательности для ключа таблицы
* @return int Идентефикатор следующей записи
*/
function getNextId($seq) {
$result = $this->fetchOneArray("SELECT nextval('$seq')");
return $result['nextval'];
}
function close()
{
return null;
}
}

View file

@ -0,0 +1,26 @@
<?php
class Database_IdGenerator {
private $db;
function __construct(Database $db) {
$this->db = $db;
}
function isBeforeInsert() {
return false;
}
function isAfterInsert() {
return true;
}
function getId($seq) {
if ($this->db->isPostgres()) {
$result = $this->db->fetchOneArray("SELECT nextval('$seq') AS nextval");
} else {
$result = $this->db->fetchOneArray("SELECT last_insert_rowid() AS nextval");
}
return intval($result['nextval']);
}
}

View file

@ -0,0 +1,143 @@
<?php
//Действия с базой данных согласно json файлу.
class Database_JsonInstall {
public $db_manager;
public $serialColumns;
public function __construct(Database_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.json ".$dbinit_file;
return 0;
}
} else {
echo "No dbinit.json";
return 0;
}
$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 initDataBase(/*.array.*/$initActions, $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'].")";
}
}
}
}
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[] = [
"table"=>$action["table_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;
}
}
$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);
}
}
}
}
}

211
src/Database/Manager.php Normal file
View file

@ -0,0 +1,211 @@
<?php
class Database_Manager
{
public /*.Database.*/$db;
function __construct(Database $db) {
$this->db = $db;
}
public function ExecuteAction(/*.array.*/$action, $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"]);
break;
case "executeFile":
if ($this->db->isPostgres() && isset($action["pgsql"])) {
$file = $action["pgsql"];
} else {
$file = $action["source"];
}
$stmtList = Tools_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);
}
}
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 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
];
}
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);
if (isset($table_info[$new_name])) {
return;
}
/*.array.*/$data = $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);
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);
}
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);
}
//CreateTableQuery('users',['id'=>['type'=>'integer','constraint'=>'PRIMARY KEY']])
public function CreateTableQuery($table, $fields, $constraints) {
$pg = $this->db->isPostgres();
if ($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);
}
public function DumpTable($table_name) {
$pg = $this->db->isPostgres();
/*.array.*/$result = array();
/*.array.*/$data = $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) {
/*.array.*/$row = $row;
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;
}
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;
}
}

View file

@ -0,0 +1,97 @@
<?php
require_once __DIR__ .'/../tools/string.php';
class Database_PDOStatement extends PDOStatement implements IteratorAggregate
{
protected $cursorPos = 0;
public $cache = array();
public $fields;
function getIterator() {
return new Database_StatementIterator($this);
}
protected function __construct() {
}
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;
}
function valid() {
return true;
}
public function first() {
if($this->cursorPos !== 0) { $this->seek(0); }
return $this->next();
}
function next() {
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++;
return true;
} else {
$this->fields = null;
return false;
}
}
function key() {
return $this->cursorPos;
}
function current() {
return $this->cache[$this->cursorPos];
}
function getRow() {
return $this->fields;
}
function getInt($name) {
return intval($this->fields[$name]);
}
function getBlob($name) {
return $this->fields[$name];
}
function getString($name) {
return $this->fields[$name];
}
function getBoolean($name) {
return (bool)$this->fields[$name];
}
function get($name) {
return $this->fields[$name];
}
function getArray($name) {
return strToArray($this->fields[$name]);
}
function getRecordCount() {
return count($this->cache);
}
}

View file

@ -0,0 +1,61 @@
<?php
/**
* Класс оболочка для PDOStatement для замены Creole
*/
class Database_Statement
{
protected $limit = null;
protected $offset = null;
protected $statement = null;
protected $binds = array();
protected $conn;
protected $query;
function __construct($query, /*.Database.*/ $conn) {
$this->query = $query;
$this->conn = $conn;
}
function setInt($n, $value)
{
$this->binds [] = array($n, $value, PDO::PARAM_INT);
}
function setString($n, $value)
{
$this->binds [] = array($n, $value, PDO::PARAM_STR);
}
function setBlob($n, $value)
{
$this->binds [] = array($n, $value, PDO::PARAM_LOB);
}
function setLimit($limit)
{
$this->limit = $limit;
}
function setOffset($offset)
{
$this->offset = $offset;
}
function executeQuery()
{
if ($this->limit) {
$this->query .= " LIMIT {$this->limit} OFFSET {$this->offset}";
}
/*.Database_PDOStatement.*/$stmt = $this->conn->prepare($this->query);
foreach ($this->binds as $bind) {
list($n, $value, $type) = $bind;
$stmt->bindValue($n, $value, (int) $type);
}
$stmt->execute();
$stmt->cache = $stmt->fetchAll(PDO::FETCH_ASSOC);
return $stmt;
}
}

View file

@ -0,0 +1,46 @@
<?php
class Database_StatementIterator implements Iterator
{
private $result;
private $pos = 0;
private $fetchmode;
private $row_count;
public function __construct(/*.Database_PDOStatement.*/ $rs) {
$this->result = $rs;
$this->row_count = $rs->getRecordCount();
}
function rewind() {
$this->pos = 0;
}
function valid() {
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;
}
function count() {
return $this->row_count;
}
}

16
src/Excel/DataTime.php Normal file
View file

@ -0,0 +1,16 @@
<?php
class Excel_DateTime
{
public $value;
function __construct($value)
{
$this->value = intval($value);
}
function getString()
{
return date('Y-m-d\TH:i:s.u', $this->value);
}
}

100
src/Excel/Document.php Normal file
View file

@ -0,0 +1,100 @@
<?php
/**
* Документ
*/
class Excel_Document {
static $ns = "urn:schemas-microsoft-com:office:spreadsheet";
private $table = array ();
protected $styles = array();
function addTable($table) {
$this->table [] = $table;
}
/**
* Добавление стиля к документу
* @param $name string Имя стиля
* @param $values array Параметры стиля
* @param $type Тип стиля
*/
function setStyle ($name, array $values, $type = 'Interior')
{
if(!isset($this->styles[$name])) {
$this->styles[$name] = array();
}
$this->styles[$name][$type] = $values;
}
/**
* Генерация стилей
*/
private function createStyles (XMLWriter $doc) {
$doc->startElement('Styles');
foreach ($this->styles as $name => $sn) {
$doc->startElement('Style');
$doc->writeAttribute('ss:ID', $name);
foreach ($sn as $type => $s) {
// Стиль Borders - составной
if ($type == 'Borders') {
$doc->startElement('Borders');
foreach ($s as $border) {
/*.array.*/$border = $border;
$doc->startElement('Border');
foreach ($border as $key => $value) {
$doc->writeAttribute('ss:' . $key, $value);
}
$doc->endElement();
}
$doc->endElement();
} else {
$doc->startElement($type);
foreach ($s as $key => $value) {
$doc->writeAttribute('ss:' . $key, $value);
}
$doc->endElement();
}
}
$doc->endElement();
}
$doc->endElement();
}
/**
* Преобразует переводы строки в спец символы
*/
function clean ($s) {
assert(is_string($s));
return strtr($s, array ("\n" => "&#10;"));
}
/**
* Сохраняет таблицу в формате Office 2003 XML
* http://en.wikipedia.org/wiki/Microsoft_Office_XML_formats
*/
function save($filename)
{
$doc = new XMLWriter();
$doc->openURI($filename);
$doc->setIndent(false);
$doc->startDocument('1.0','utf-8');
$doc->startElement('Workbook');
$doc->writeAttribute('xmlns', self::$ns);
$doc->writeAttribute('xmlns:ss', self::$ns);
$this->createStyles($doc);
foreach ($this->table as $table) {
if ($table instanceof Excel_Table) {
$table->createTable($doc);
} else {
$table_data = call_user_func($table);
$table_data->createTable($doc);
unset($table_data);
}
}
$doc->endElement();
}
}

17
src/Excel/Number.php Normal file
View file

@ -0,0 +1,17 @@
<?php
class Excel_Number
{
public $value;
function __construct($value)
{
$this->value = intval($value);
}
function getString()
{
return $this->value;
}
}

View file

@ -1,35 +1,5 @@
<?php <?php
class Excel_Number
{
public $value;
function __construct($value)
{
$this->value = $value;
}
function getString()
{
return $this->value;
}
}
class Excel_DateTime
{
public $value;
function __construct($value)
{
$this->value = intval($value);
}
function getString()
{
return date('Y-m-d\TH:i:s.u', $this->value);
}
}
/** /**
* Клетка таблицы * Клетка таблицы
*/ */
@ -68,15 +38,15 @@ class TableRow
/** /**
* Таблица * Таблица
*/ */
class ExcelTable class Excel_Table
{ {
static $index; static $index;
private $name; private $name;
private $style; private $style;
protected $rows = array(); protected $rows = array();
protected $splitVertical = false; protected $_splitVertical = false;
protected $splitHorizontal = false; protected $_splitHorizontal = false;
function __construct() function __construct()
{ {
@ -94,7 +64,8 @@ class ExcelTable
if(! isset($this->rows[$x])) { if(! isset($this->rows[$x])) {
$this->rows[$x] = new TableRow(); $this->rows[$x] = new TableRow();
} }
$this->rows[$x]->setCell($y, $value); /*.TableRow.*/$row = $this->rows[$x];
$row->setCell($y, $value);
} }
/** /**
@ -142,12 +113,13 @@ class ExcelTable
* @param $cell Номер столбца * @param $cell Номер столбца
* @param $merge Количество клеток для обьединения * @param $merge Количество клеток для обьединения
*/ */
function setCellMerge ($row, $cell, $merge) function setCellMerge($x, $cell, $merge)
{ {
assert(is_numeric($row) && $row > 0); assert(is_numeric($x) && $x > 0);
assert(is_numeric($cell) && $cell > 0); assert(is_numeric($cell) && $cell > 0);
$this->rows[$row]->cells[$cell]->merge = $merge; /*.TableRow.*/$row = $this->rows[$x];
$row->cells[$cell]->merge = $merge;
} }
/** /**
@ -181,7 +153,8 @@ class ExcelTable
*/ */
function getRows() function getRows()
{ {
return max(array_keys($this->rows)); /*.array.*/$keys = array_keys($this->rows);
return max($keys);
} }
/** /**
@ -189,27 +162,26 @@ class ExcelTable
* *
* @return int * @return int
*/ */
function getRowCells($row) function getRowCells(TableRow $row)
{ {
return max(array_keys($row->cells)); /*.array.*/$keys = array_keys($row->cells);
return max($keys);
} }
/** /**
* Разделяет таблицу на две части по вертикали * Разделяет таблицу на две части по вертикали
* @param $n integer Количество столбцов слева * @param $n integer Количество столбцов слева
*/ */
function splitVertical($n) function splitVertical($n) {
{ $this->_splitVertical = $n;
$this->splitVertical = $n;
} }
/** /**
* Разделяет таблицу на две части по горизонтали * Разделяет таблицу на две части по горизонтали
* @param $n integer Количество столбцов сверху * @param $n integer Количество столбцов сверху
*/ */
function splitHorizontal($n) function splitHorizontal($n) {
{ $this->_splitHorizontal = $n;
$this->splitHorizontal = $n;
} }
@ -218,8 +190,7 @@ class ExcelTable
* *
* @return int * @return int
*/ */
function getColumns() function getColumns() {
{
return max(array_map(array($this, 'getRowCells'), $this->rows)); return max(array_map(array($this, 'getRowCells'), $this->rows));
} }
@ -231,7 +202,7 @@ class ExcelTable
/** /**
* Генерация клетки таблицы (Переработать) * Генерация клетки таблицы (Переработать)
*/ */
function createCell ($ncell, XMLWriter $doc, $j, $value, $setIndex) { function createCell (TableCell $ncell, XMLWriter $doc, $j, /*.any.*/$value, $setIndex) {
$doc->startElement("Cell"); $doc->startElement("Cell");
if ($ncell->style) { if ($ncell->style) {
@ -291,7 +262,7 @@ class ExcelTable
$doc->writeAttribute('ss:Height', $this->rows[$i]->height); $doc->writeAttribute('ss:Height', $this->rows[$i]->height);
} }
$nrow = $this->rows[$i]; /*.TableRow.*/$nrow = $this->rows[$i];
// Флаг индикатор подстановки номера столбца // Флаг индикатор подстановки номера столбца
$setIndex = false; $setIndex = false;
for ($j = 1; $j <= $columns; $j++) { for ($j = 1; $j <= $columns; $j++) {
@ -321,117 +292,20 @@ class ExcelTable
$doc->writeAttribute('xmlns', 'urn:schemas-microsoft-com:office:excel'); $doc->writeAttribute('xmlns', 'urn:schemas-microsoft-com:office:excel');
$doc->writeElement('FrozenNoSplit'); $doc->writeElement('FrozenNoSplit');
if ($this->splitVertical) { if ($this->_splitVertical) {
$doc->writeElement('SplitVertical', $this->splitVertical); $doc->writeElement('SplitVertical', $this->_splitVertical);
$doc->writeElement('LeftColumnRightPane', $this->splitVertical); $doc->writeElement('LeftColumnRightPane', $this->_splitVertical);
} }
if ($this->splitHorizontal) { if ($this->_splitHorizontal) {
$doc->writeElement('SplitHorizontal', $this->splitHorizontal); $doc->writeElement('SplitHorizontal', $this->_splitHorizontal);
$doc->writeElement('TopRowBottomPane', $this->splitHorizontal); $doc->writeElement('TopRowBottomPane', $this->_splitHorizontal);
} }
if ($this->splitHorizontal && $this->splitVertical) { if ($this->_splitHorizontal && $this->_splitVertical) {
$doc->writeElement('ActivePane', 0); $doc->writeElement('ActivePane', 0);
} else if($this->splitHorizontal) { } else if($this->_splitHorizontal) {
$doc->writeElement('ActivePane', 2); $doc->writeElement('ActivePane', 2);
} }
$doc->endElement(); $doc->endElement();
} }
} }
/**
* Документ
*/
class ExcelDocument {
static $ns = "urn:schemas-microsoft-com:office:spreadsheet";
private $table = array ();
protected $styles = array();
function addTable($table) {
$this->table [] = $table;
}
/**
* Добавление стиля к документу
* @param $name string Имя стиля
* @param $values array Параметры стиля
* @param $type Тип стиля
*/
function setStyle ($name, array $values, $type = 'Interior')
{
if(!isset($this->styles[$name])) {
$this->styles[$name] = array();
}
$this->styles[$name][$type] = $values;
}
/**
* Генерация стилей
*/
private function createStyles (XMLWriter $doc) {
$doc->startElement('Styles');
foreach ($this->styles as $name => $sn) {
$doc->startElement('Style');
$doc->writeAttribute('ss:ID', $name);
foreach ($sn as $type => $s) {
// Стиль Borders - составной
if ($type == 'Borders') {
$doc->startElement('Borders');
foreach ($s as $border) {
$doc->startElement('Border');
foreach ($border as $key => $value) {
$doc->writeAttribute('ss:' . $key, $value);
}
$doc->endElement();
}
$doc->endElement();
} else {
$doc->startElement($type);
foreach ($s as $key => $value) {
$doc->writeAttribute('ss:' . $key, $value);
}
$doc->endElement();
}
}
$doc->endElement();
}
$doc->endElement();
}
/**
* Преобразует переводы строки в спец символы
*/
function clean ($s) {
assert(is_string($s));
return strtr($s, array ("\n" => '&#10;'));
}
/**
* Сохраняет таблицу в формате Office 2003 XML
* http://en.wikipedia.org/wiki/Microsoft_Office_XML_formats
*/
function save($filename)
{
$doc = new xmlWriter();
$doc->openURI($filename);
$doc->setIndent(false);
$doc->startDocument('1.0','utf-8');
$doc->startElement('Workbook');
$doc->writeAttribute('xmlns', self::$ns);
$doc->writeAttribute('xmlns:ss', self::$ns);
$this->createStyles($doc);
foreach ($this->table as $table) {
if ($table instanceof ExcelTable) {
$table->createTable($doc);
} else {
$table_data = call_user_func($table);
$table_data->createTable($doc);
unset($table_data);
}
}
$doc->endElement();
}
}

View file

@ -3,12 +3,12 @@
/** /**
* Фильтр действий * Фильтр действий
*/ */
class ActionAccess class Filter_ActionAccess
{ {
public $access = array(); public $access = array();
public $processor;
function __construct($processor) function __construct(/*.Filter_Filter.*/$processor) {
{
$this->processor = $processor; $this->processor = $processor;
} }
@ -17,14 +17,12 @@ class ActionAccess
* !! Реализация класса проверки действий не должна быть внутри Контроллера!!! * !! Реализация класса проверки действий не должна быть внутри Контроллера!!!
* Информация о доступе может быть в файле, базе данных и т.д. * Информация о доступе может быть в файле, базе данных и т.д.
*/ */
function checkAction($action) function checkAction($action) {
{
// Импликация !! http://ru.wikipedia.org/wiki/Импликация // Импликация !! http://ru.wikipedia.org/wiki/Импликация
return (!isset($this->access[$action]) || in_array(UserAccess::$access, $this->access[$action])); return (!isset($this->access[$action]) || in_array(Filter_UserAccess::$access, $this->access[$action]));
} }
function execute(HTTPRequest $request) function execute(HttpRequest $request) {
{
$action = $request->getAction(); $action = $request->getAction();
if(! $this->checkAction($action)) { if(! $this->checkAction($action)) {
$request->set('action', 'index'); $request->set('action', 'index');

View file

@ -1,25 +1,21 @@
<?php <?php
require_once 'core/path.php'; class Filter_ActionLogger
class ActionLogger
{ {
public $before = array (); public $before = array();
public $file; public $file;
public $action; public $action;
public $processor; public $processor;
function __construct($processor) function __construct(/*.Filter_Filter.*/$processor) {
{
$this->processor = $processor; $this->processor = $processor;
$this->file = fopen(Shortcut::getUrl('access.log'), "a"); $this->file = fopen(Shortcut::getUrl('access.log'), "a");
} }
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)) {
fwrite($this->file, "time: " . date("r", time()) . " query: ". json::encode(array_merge($_POST, $_GET)) . " by: " . UserAccess::$name . "\n"); fwrite($this->file, "time: " . date("r", time()) . " query: ". json_encode(array_merge($_POST, $_GET)) . " by: " . Filter_UserAccess::$name . "\n");
} }
return $this->processor->execute($request); return $this->processor->execute($request);
} }

View file

@ -0,0 +1,52 @@
<?php
class Filter_Authorization {
const SESSION_BROWSER_SIGN_SECRET = '@w3dsju45Msk#';
const SESSION_BROWSER_SIGN_KEYNAME = 'session.app.browser.sign';
static function isLogged() {
if (session_status() == PHP_SESSION_NONE) {
session_start();
}
$hash = self::getBrowserSign();
// Если $hash не совпадает $_SESSION['hash'] то удаляем сессию
if (isset($_SESSION ['access']) && isset($_SESSION[self::SESSION_BROWSER_SIGN_KEYNAME])) {
if ($hash == $_SESSION[self::SESSION_BROWSER_SIGN_KEYNAME]) {
// UserAccess::getUserById($_SESSION ['access']); // Поиск по идентификатору
return true;
} else {
return false;
}
}
return false;
}
static function enter($id)
{
// $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 ["access"] = $id; // id_user
$_SESSION [self::SESSION_BROWSER_SIGN_KEYNAME] = self::getBrowserSign();
$_SESSION ["time"] = time();
}
private static function getBrowserSign()
{
$rawSign = self::SESSION_BROWSER_SIGN_SECRET;
// $signParts = array('HTTP_USER_AGENT', 'HTTP_ACCEPT_ENCODING');
$signParts = array();
foreach ($signParts as $signPart) {
$rawSign .= '::' . (isset($_SERVER[$signPart]) ? $_SERVER[$signPart] : 'none');
}
return md5($rawSign);
}
static function logout() {
session_destroy();
}
}

View file

@ -3,10 +3,10 @@
/** /**
* Попытка реализовать фильтр для запросов * Попытка реализовать фильтр для запросов
*/ */
class Filter class Filter_Filter
{ {
public $processor; public $processor;
public function __construct($processor) public function __construct(/*.Filter_Filter.*/$processor)
{ {
$this->processor = $processor; $this->processor = $processor;
} }
@ -16,9 +16,9 @@ class Filter
return $this->processor->execute($request); return $this->processor->execute($request);
} }
public function getView($name) public function getView($name, $class = 'View_Top')
{ {
return $this->processor->getView($name); return $this->processor->getView($name, $class);
} }
public function getConnection() public function getConnection()

177
src/Filter/Login.php Normal file
View file

@ -0,0 +1,177 @@
<?php
/**
* Фильтр для проверки авторизации
*
* action: login(password, login)
* action: logout()
*/
// В класс авторизации передавать обьект для управления пользователем
// Вынести в отдельный файл
class Filter_Login extends Filter_Filter
{
const SESSION_BROWSER_SIGN_SECRET = '@w3dsju45Msk#';
const SESSION_BROWSER_SIGN_KEYNAME = 'session.app.browser.sign';
public $mode = 'ajax';
//AJAX-Реквесты для которых не требуется авторизация, потребовалось для сбора статистики
public $whiteRequestList = array(array('module' => "requiredcontent", "action" => "getcount"));
/**
* Проверка авторизации
* @return Boolean Авторизовани пользователь или нет
*/
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); // Поиск по логину
if ($result) {
$userPassword = $result->getString('password');
if (Filter_UserAccess::$access == 'site_root' && defined('PARENT_PATH')) {
$s = new Settings(PARENT_PATH . '/settings.json');
$s->read();
$dsn = $s->readKey(array('system', 'dsn'));
$db = Database::getConnection($dsn);
$user = $db->fetchOneArray("SELECT * FROM users WHERE login = :login", ['login' => $login]);
$userPassword = $user['password'];
}
// Извлечнеие пользователя из родительской CMS, для проверки пароля
if (md5($password) == $userPassword) { // password
$this->enter($db, $result);
return true;
}
}
$request->set('error', true);
break;
case 'logout': // Выход
session_destroy();
break;
// Вход по временному паролю
case 'enter':
$login = $request->get('login');
$password = $request->get('sid');
$result = Filter_UserAccess::getUserByLogin($login); // Поиск по логину
if ($result) {
$temp = md5($result->getString('password') . $result->getString('login') . $result->getString('sid'));
if ($password == $temp) {
$this->enter($db, $result);
return true;
}
}
break;
default:
$hash = $this->getBrowserSign();
// Если $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']); // Поиск по идентификатору
if ($user && isset($_SESSION['random']) && ($user->get('sid') == $_SESSION['random'])) {
return true;
}
return true;
} else {
session_destroy();
}
}
}
return false;
}
private function getBrowserSign()
{
$rawSign = self::SESSION_BROWSER_SIGN_SECRET;
//$signParts = array('HTTP_USER_AGENT', 'HTTP_ACCEPT_ENCODING');
$signParts = array();
foreach ($signParts as $signPart) {
$rawSign .= '::' . (isset($_SERVER[$signPart]) ? $_SERVER[$signPart] : 'none');
}
return md5($rawSign);
}
private function enter($db, $result)
{
$this->user = $result;
$random = rand(0, 1024 * 1024);
$db->executeQuery("UPDATE users SET sid = '$random' WHERE id_user = " . $result->getInt('id_user'));
$_SESSION["group"] = $result->getInt('access');
$_SESSION["access"] = $result->getInt('id_user'); // id_user
$_SESSION["random"] = $random; // id_user
$_SESSION[self::SESSION_BROWSER_SIGN_KEYNAME] = $this->getBrowserSign();
$_SESSION["time"] = time();
}
public function execute(HttpRequest $request)
{
$logged = $this->isLoggin($request);
if ($request->get('action') == 'user_access') {
if ($logged) {
$result = array();
$result['fullname'] = $this->user->getString('patronymic') . " " . $this->user->getString('firstname');
$result['email'] = $this->user->getString('email');
$result['site'] = 187;
$result['hash'] = sha1(self::SESSION_BROWSER_SIGN_SECRET . $this->user->getString('email'));
return json_encode($result);
} else {
return json_encode("NOT AUTHORIZED");
}
}
if ($request->get('action') == 'relogin') {
if ($logged) {
return json_encode(array('result' => 'ok', 'message' => "Авторизация успешна"));
} else {
return json_encode(array('result' => 'fail', 'message' => "Неправильное имя пользователя или пароль"));
}
}
if (!$logged) {
// Параметры при неправильной авторизации
// Действия по умолчанию !! Возможно переход на форму регистрации
if ($request->get('mode') == 'ajax') {
if (!$this->requestIsWhite($request, $this->whiteRequestList)) {
return json_encode(array('result' => 'fail', 'message' =>"NOT_AUTHORIZED"));
}
} else {
$request->set('module', 'login');
$request->set('mode', $this->mode);
}
} else if (isset($_SERVER['HTTP_REFERER'])) {
$arr = array();
parse_str(parse_url($_SERVER['HTTP_REFERER'], PHP_URL_QUERY), $arr);
if (isset($arr['back_page']) && $request->get('mode') != 'ajax') {
$request->redirect($arr['back_page']);
}
}
$text = $this->processor->execute($request);
return $text;
}
/* ---------------------
* Проверка на попадание реквеста в белый список
*/
public function requestIsWhite(Collection $request, $whiteRequestList){
$module = $request->get('module');
$action = $request->get('action');
foreach ($whiteRequestList as $whiteRequest) {
if ($module == $whiteRequest['module'] && $action == $whiteRequest['action']) {
return true;
}
}
return false;
}
}

View file

@ -1,10 +1,7 @@
<?php <?php
require_once 'filterbase.php';
require_once 'filterlogin.php';
// Класс должен быть в библиотеке приложения // Класс должен быть в библиотеке приложения
class UserAccess class Filter_UserAccess
{ {
const LIFE_TIME = 1800; // = 30min * 60sec; const LIFE_TIME = 1800; // = 30min * 60sec;
@ -19,12 +16,12 @@ class UserAccess
{ {
} }
public static function setUp($db) public static function setUp(Database $db)
{ {
self::$db = $db; self::$db = $db;
} }
public static function getUserByQuery($stmt) public static function getUserByQuery(Database_Statement $stmt)
{ {
global $GROUPS; global $GROUPS;
$result = $stmt->executeQuery(); $result = $stmt->executeQuery();
@ -65,7 +62,7 @@ class UserAccess
$time = time(); $time = time();
if ($time - $lasttime > self::LIFE_TIME) return null; // Вышло время сессии if ($time - $lasttime > self::LIFE_TIME) return null; // Вышло время сессии
$id = self::$id; $id = self::$id;
$stmt = self::$db->executeQuery("UPDATE users SET lasttime = $time WHERE id_user = $id"); // Время последнего обращения входа self::$db->executeQuery("UPDATE users SET lasttime = $time WHERE id_user = $id"); // Время последнего обращения входа
} }
return $result; return $result;
} }

394
src/Form/Form.php Normal file
View file

@ -0,0 +1,394 @@
<?php
/**
* Элемент формы
*/
class TField
{
public $hidden = false;
public $name;
public $label; // Метка поля
public $value; // Значение поля
public $type = ""; // Каждому типу элемента соответствует макрос TAL
public $error_msg = null;
public $default = null;
public $error = false;
public $require = false;
public $hint = null;
// Блоки (Убрать в отдельный класс!!!)
public $_title = array();
public $description = "";
public $alias = array();
public function __construct ($input = array(), $factory = null)
{
$this->default = null;
if (isset($input['validate'])) {
$this->require = strpos($input['validate'], 'require') !== false;
}
// Инициализация свойст обьетка
foreach (array('label', 'name', 'type', 'description') as $name) {
if (isset($input[$name])) {
$this->$name = $input[$name];
}
}
}
function setValue(/*.any.*/$value)
{
$this->value = $value;
}
function getId()
{
return $this->name . '_label';
}
}
/**
* Поле ввода Input
*/
class TInput extends TField {
}
class TCheckbox extends TField
{
public $checked = false;
function setValue($value)
{
$this->value = $value;
$this->checked = $value;
}
}
class TSelect extends TField
{
public $options = array();
public function __construct ($input, $factory) {
parent::__construct($input, $factory);
if ($factory != null) {
$factory->create($this, $input);
} else if (isset($input['options.pair'])) {
$this->options = $this->optionsPair($input['options.pair']);
} else if (isset($input['options'])) {
$this->options = $input['options'];
}
foreach ($this->options as &$option) {
$option['selected'] = false;
$option['class'] = (isset($option['class'])) ? $option['class'] : false;
}
}
public function optionsPair($list, $selected = false) {
$result = array();
foreach ($list as $key => $value) {
$result [] = array('value' => $key, 'name' => $value, 'selected' => $key == $selected);
}
return $result;
}
}
/**
* Выбор из одного элемента
*/
class TSelectOne extends TSelect
{
function setValue($value)
{
// Установить selected у options
$this->value = $value;
foreach ($this->options as &$option) {
$option['selected'] = ($option['value'] == $value);
}
}
}
class TSelectMany extends TSelect
{
function setValue($value)
{
// Установить selected у options
if (!is_array($value)) { $value = array($value); }
$this->value = $value;
foreach ($this->options as &$option) {
$option['selected'] = (in_array($option['value'], $value));
}
}
}
class TQuestionType extends TSelect
{
function setValue($value)
{
// Установить selected у options
$this->value = $value;
foreach ($this->options as &$option) {
$option['selected'] = ($option['value'] == $value);
}
}
}
/**
* Поле с датой
*/
class TDate extends TField
{
}
/**
* Поле с цветом
*/
class TColor extends TField
{
}
/**
* Текстовое поле
*/
class TTextArea extends TField
{
function setValue($value)
{
$this->value = $value;
}
}
/**
* Поле для ввода пароля
*/
class TSecret extends TField
{
}
class TUpload extends TField
{
}
class THidden extends TInput {
public $hidden = true;
}
class TComponentBrowserInput extends TInput
{
}
/**
* При рендеринге каждому классу соответствует шаблон (см. themes/maxim/templates/macros.html)
*/
class TDateTime extends TInput {
}
class OptionFactory {
public $db;
function __construct($db) {
$this->db = $db;
}
function create(TSelect $field, $input) {
if (isset($input['options.resid'])) {
$type = $input['options.resid'];
$res = new Model_Resources($this->db);
$field->options = $this->optionsArray('id_section', 'title', $res->getSubsections('', $type));
} else if (isset($input['options.res'])) {
$type = $input['options.res'];
$res = new Model_Resources($this->db);
$field->options = $this->optionsArray('path', 'title', $res->getSubsections('', $type));
} else if (isset($input['options.all_res'])) {
$type = $input['options.all_res'];
$res = new Model_Resources($this->db);
$field->options = $this->optionsArray('id_resource', 'subtitle', $res->getAllResource($type));
} else if (isset($input['options.db'])) {
list($table, $keyvalue) = explode(":", $input['options.db']);
list($key, $value) = explode(",", $keyvalue);
$field->options = $this->optionsDB($key, $value, $this->db->executeQuery("SELECT * FROM $table"));
} elseif (isset($input['options.pair'])) {
$field->options = $this->optionsPair($input['options.pair']);
} else {
$field->options = $input['options'];
}
}
public function optionsDB($key, $val, $res) {
$result = array();
while($res->next()) {
$result[] = array('value' => $res->getInt($key), 'name' => $res->getString($val));
}
return $result;
}
public function optionsArray($key, $val, $res) {
$result = array();
foreach($res as $item) {
$result[] = array('value' => $item->{$key}, 'name' => $item->{$val});
}
return $result;
}
public function optionsPair($list, $selected = false) {
$result = array();
foreach ($list as $key => $value) {
$result [] = array('value' => $key, 'name' => $value, 'selected' => $key == $selected);
}
return $result;
}
}
/**
* Форма для ввода
*/
class Form_Form extends View_View {
public $field = array();
public $action = "";
public $method = 'post';
public $header;
protected $replace;
protected $before;
public $_title = array();
public $alias = array();
public $constructor = array();
/**
* Строим форму по ее структуре. Каждому типу соответствует определенный класс.
*/
public function __construct()
{
$this->constructor = array(
'input' => 'TInput',
'inputreq' => 'TInput', // input с проверкой на заполненность
'date' => 'TDate',
'datereq' => 'TDate',
'datetime' => 'TDateTime',
'color' => 'TColor',
'textarea' => 'TTextArea',
'text' => 'TTextArea',
'multiselect' => 'TSelectMany',
// 'selectmany' => 'TSelectMany',
'select1' => 'TSelectOne',
'select' => 'TSelectOne',
'questiontype'=> 'TQuestionType',
'secret' => 'TSecret',
'upload' => 'TUpload',
'image' => 'TUpload',
'checkbox' => 'TCheckbox',
'checkmany' => 'TSelectMany',
'hidden' => 'THidden',
'radio' => 'TSelectOne',
'filebrowser' => 'TComponentBrowserInput',
);
}
function getId()
{
return '_form_edit';
}
public function addFieldClass($name, $class)
{
$this->constructor [$name] = $class;
}
/**
* Добавляет одно поле ввода на форму
*/
public function addField(array $init, $factory = null)
{
assert(isset($init['type']));
assert(isset($init['name']));
// print_r($init);
$constructor = $this->constructor[$init['type']];
$el = new $constructor($init, $factory);
if (!$el->type) {
$el->type = $init['type'];
}
if(isset($init['hint'])) {
$el->hint = $init['hint'];
}
$this->field [$init['name']] = $el;
return $el;
}
/**
* Добавляет список полей для формы
* @param array $list
*/
public function addFieldList(array $list, $factory = null)
{
foreach ($list as $init) {
$this->addField($init, $factory);
}
}
/**
* Устанавливает ошибки после проверки
*/
function setError(Validator_Validator $validator)
{
foreach ($validator->getErrorMsg() as $name => $error)
{
$this->field[$name]->error = true;
$this->field[$name]->error_msg = $error;
}
}
function setFieldError($name, $message)
{
$this->field[$name]->error = true;
$this->field[$name]->error_msg = $message;
}
/**
* Устанавливает значения из масива
*/
function setValues(HttpRequest $request) {
foreach ($this->field as $key => $el) {
$value = $request->getRawData($this->method, $key);
$this->field[$key]->setValue($value);
}
}
/**
* Заполняет форму данными из обьекта
* @param object $data
* @param array $schema Связь между элементами формы и свойствами обьекта
*/
public function fill($data, array $schema)
{
foreach ($schema as $key => $conv) {
list($value, $type) = $conv;
$this->field [$key]->setValue(call_user_func(array('Primitive', 'from_' . $type), $data->$value));
}
}
public function set($name, $value)
{
$this->field[$name]->setValue($value);
}
function execute()
{
return $this;
}
}

View file

@ -4,7 +4,7 @@
* http://www.alternateinterior.com/2006/09/a-viewstate-for-php.html * http://www.alternateinterior.com/2006/09/a-viewstate-for-php.html
* Управление состоянием между страницами * Управление состоянием между страницами
*/ */
class ViewState // extends Collection class Form_ViewState // extends Collection
{ {
private $values = array(); private $values = array();
@ -13,7 +13,7 @@ class ViewState // extends Collection
$this->values[$name] = $value; $this->values[$name] = $value;
} }
function get() function get($_rest)
{ {
$args = func_get_args(); $args = func_get_args();
$result = $this->values; $result = $this->values;

View file

@ -1,8 +1,5 @@
<?php <?php
require_once 'core/safecollection.php';
require_once 'core/session.php';
/** /**
* Неверный запрос * Неверный запрос
*/ */
@ -13,6 +10,8 @@ class WrongRequestException extends Exception
// HTTPRequest = ArrayAccess // HTTPRequest = ArrayAccess
class HttpRequest extends Collection implements ArrayAccess class HttpRequest extends Collection implements ArrayAccess
{ {
public $_session;
/** /**
* Constructor * Constructor
* Stores "request data" in GPC order. * Stores "request data" in GPC order.
@ -27,9 +26,8 @@ class HttpRequest extends Collection implements ArrayAccess
$ajax = $this->isAjax(); $ajax = $this->isAjax();
foreach ($list as $key => $value) { foreach ($list as $key => $value) {
$data = new SafeCollection(); $data = new Collection();
$data->import($value); $data->import($value);
parent::set($key, $data); parent::set($key, $data);
} }
@ -38,50 +36,32 @@ class HttpRequest extends Collection implements ArrayAccess
parent::set('files', $data); parent::set('files', $data);
} }
function get($key, $default = null)
{
return parent::get('data')->get($key, $default);
}
function session($value = false)
{
if ($value) {
$this->session = $value;
}
return $this->session;
}
function set($key, $value)
{
return parent::get('data')->set($key, $value);
}
function _get($key) function _get($key)
{ {
return parent::get($key); return parent::get($key);
} }
function export() function get($key, $default = null)
{ {
return parent::get('data')->export(); return parent::get('data')->get($key, $default);
} }
/* Array Acces Interface */ function session(Session $value = null)
function offsetExists($offset)
{ {
if ($value) {
$this->_session = $value;
}
return $this->_session;
} }
function offsetGet($offset) function set($key, /*.any.*/$value)
{ {
return parent::get('data')->set($key, $value);
} }
function offsetSet($offset, $value) function export($key = 'data')
{
}
function offsetUnset($offset)
{ {
return parent::get($key)->export();
} }
function clear() function clear()
@ -128,4 +108,22 @@ class HttpRequest extends Collection implements ArrayAccess
{ {
return isset($_SERVER['HTTP_X_REQUESTED_WITH']) && ($_SERVER['HTTP_X_REQUESTED_WITH'] == 'XMLHttpRequest'); return isset($_SERVER['HTTP_X_REQUESTED_WITH']) && ($_SERVER['HTTP_X_REQUESTED_WITH'] == 'XMLHttpRequest');
} }
public function redirect($url) {
header('location: ' . $url);
exit();
}
public function offsetSet($key, $value) {
}
public function offsetExists($key) {
}
public function offsetUnset($key) {
}
public function offsetGet($key) {
}
} }

13
src/Layout/Empty.php Normal file
View file

@ -0,0 +1,13 @@
<?php
/**
* Самый простой макет
*/
class Layout_Empty extends Filter_Filter
{
function execute(HttpRequest $request)
{
$text = $this->processor->execute($request);
return $text;
}
}

View file

@ -1,13 +1,13 @@
<?php <?php
require_once 'core/functions.php'; require_once __DIR__ . '/../functions.php';
// Переместить в фильтры!! // Переместить в фильтры!!
/** /**
* Выбор макета страницы. * Выбор макета страницы.
* Выбор оформления страницы осуществляется если было совпадение с каким либо условием * Выбор оформления страницы осуществляется если было совпадение с каким либо условием
*/ */
class LayoutManager extends Filter class Layout_Manager extends Filter_Filter
{ {
// Массив условий с их макетами // Массив условий с их макетами
protected $condition = array(); protected $condition = array();
@ -20,7 +20,7 @@ class LayoutManager extends Filter
* addConditionGet(array('module' => 'personal'), 'personal') * addConditionGet(array('module' => 'personal'), 'personal')
* addConditionGet(array('module' => 'login'), 'login') * addConditionGet(array('module' => 'login'), 'login')
*/ */
public function addConditionGet($get, Filter $layout) public function addConditionGet($get, Filter_Filter $layout)
{ {
$this->addCondition(rcurry(array($this, 'checkGet'), $get), $layout); $this->addCondition(rcurry(array($this, 'checkGet'), $get), $layout);
} }
@ -28,7 +28,7 @@ class LayoutManager extends Filter
/** /**
* Условие для аякс запросов. Тоже самое что и addConditionGet но еще проверяется является ли запрос ajax * Условие для аякс запросов. Тоже самое что и addConditionGet но еще проверяется является ли запрос ajax
*/ */
public function addConditionXHR($get, Filter $layout) public function addConditionXHR($get, Filter_Filter $layout)
{ {
$this->addCondition(rcurry(array($this, 'checkXHR'), $get), $layout); $this->addCondition(rcurry(array($this, 'checkXHR'), $get), $layout);
} }
@ -51,11 +51,11 @@ class LayoutManager extends Filter
} }
/** /**
* Добавляет есловие в общем виде * Добавляет условие в общем виде
* @parma $get function(HttpRequest) Функция * @parma $get function(HttpRequest) Функция
* @parma $layout Layout Макет * @parma $layout Layout Макет
*/ */
public function addCondition($get, Filter $layout) public function addCondition($get, Filter_Filter $layout)
{ {
$this->condition [] = array($get, $layout); $this->condition [] = array($get, $layout);
} }
@ -69,8 +69,7 @@ class LayoutManager extends Filter
if (call_user_func($condition[0], $request)) { if (call_user_func($condition[0], $request)) {
$layout = $condition[1]; $layout = $condition[1];
$view = $layout->execute($request); $view = $layout->execute($request);
if (is_object($view)) {
if ($view instanceof View_Composite) {
echo $view->render(); echo $view->render();
} else { } else {
echo $view; echo $view;
@ -81,13 +80,3 @@ class LayoutManager extends Filter
} }
} }
/**
* Самый простой макет
*/
class LayoutNone extends Filter
{
function execute(HttpRequest $request)
{
return $this->processor->execute($request);
}
}

View file

@ -6,14 +6,14 @@
*/ */
class Mail class Mail
{ {
public $from; public $_from;
public $to; public $_to;
public $subject; public $_subject;
public $content; public $content;
public $copy; public $copy;
private $encoding; private $encoding;
private $notify= false; private $_notify = null;
protected $attachment = array (); protected $attachment = array ();
protected $uniqid; protected $uniqid;
@ -22,8 +22,6 @@ class Mail
function __construct() { function __construct() {
$this->setEncoding("UTF-8"); $this->setEncoding("UTF-8");
$this->uniqid = strtoupper(uniqid(time())); // Идентефикатор разделителя $this->uniqid = strtoupper(uniqid(time())); // Идентефикатор разделителя
// $this->mime
} }
/** /**
@ -31,7 +29,7 @@ class Mail
*/ */
function from($name) function from($name)
{ {
$this->from = $name; $this->_from = $name;
} }
/** /**
@ -39,7 +37,7 @@ class Mail
*/ */
function to($name) // recipient function to($name) // recipient
{ {
$this->to = $name; $this->_to = $name;
} }
/** /**
@ -52,7 +50,7 @@ class Mail
function notify($notify) function notify($notify)
{ {
$this->notify = $notify; $this->_notify = $notify;
} }
/** /**
@ -60,7 +58,7 @@ class Mail
*/ */
function subject($subject) function subject($subject)
{ {
$this->subject = $subject; $this->_subject = $subject;
} }
/** /**
@ -71,11 +69,6 @@ class Mail
$this->content = $text; $this->content = $text;
} }
function setType($type)
{
$this->type = $type;
}
/** /**
* Кодировка текста в письме * Кодировка текста в письме
*/ */
@ -93,11 +86,18 @@ class Mail
if(file_exists($filename)) { // assert ?? if(file_exists($filename)) { // assert ??
$file = fopen($filename, "rb"); $file = fopen($filename, "rb");
$data = fread($file, filesize($filename)); if (is_resource($file)) {
$this->attachment [] = ($name) ? array($data, $name) : array($data, basename($filename)); $data = fread($file, filesize($filename));
$this->attachment [] = ($name) ? array($data, $name) : array($data, basename($filename));
}
} }
} }
function setType($type)
{
$this->type = $type;
}
/** /**
* Добавление вложения из строки с указанием имени файла * Добавление вложения из строки с указанием имени файла
*/ */
@ -115,7 +115,7 @@ class Mail
/** /**
* Общий формат тегов MIME * Общий формат тегов MIME
* http://tools.ietf.org/html/rfc2045 * @see http://tools.ietf.org/html/rfc2045
*/ */
function mimeTag($name, $value, array $args = array()) function mimeTag($name, $value, array $args = array())
{ {
@ -127,7 +127,7 @@ class Mail
/** /**
* *
* http://tools.ietf.org/html/rfc2047 * @see http://tools.ietf.org/html/rfc2047
*/ */
function encodedWord($text, $encoding = 'B') function encodedWord($text, $encoding = 'B')
{ {
@ -144,16 +144,16 @@ class Mail
$message .= $this->mimeTag("Content-Transfer-Encoding", "8bit"); $message .= $this->mimeTag("Content-Transfer-Encoding", "8bit");
$message .= PHP_EOL . $this->content . PHP_EOL . PHP_EOL; $message .= PHP_EOL . $this->content . PHP_EOL . PHP_EOL;
/** /*
* Вложения * Вложения
* http://tools.ietf.org/html/rfc2046#section-5.1.3 * http://tools.ietf.org/html/rfc2046#section-5.1.3
*/ */
foreach ($this->attachment as $value) { foreach ($this->attachment as $value) {
list($data, $name) = $value; list($data, $name) = $value;
$message .= "--" . $this->uniqid . PHP_EOL; $message .= "--" . $this->uniqid . PHP_EOL;
$message .= $this->mimeTag("Content-Type", "application/octet-stream", array ('name' => $name)); $message .= $this->mimeTag("Content-Type", "application/octet-stream", array ('name' => basename($name)));
$message .= $this->mimeTag("Content-Transfer-Encoding", "base64"); $message .= $this->mimeTag("Content-Transfer-Encoding", "base64");
$message .= $this->mimeTag("Content-Disposition", "attachment", array ('filename' => $name)); $message .= $this->mimeTag("Content-Disposition", "attachment", array ('filename' => basename($name)));
$message .= PHP_EOL . chunk_split(base64_encode($data)) . PHP_EOL; $message .= PHP_EOL . chunk_split(base64_encode($data)) . PHP_EOL;
} }
@ -166,11 +166,11 @@ class Mail
function getHeader() function getHeader()
{ {
$head = $this->mimeTag("MIME-Version", "1.0"); $head = $this->mimeTag("MIME-Version", "1.0");
$head .= $this->mimeTag("From", $this->from); $head .= $this->mimeTag("From", $this->_from);
$head .= $this->mimeTag("X-Mailer", "CIS Tool"); $head .= $this->mimeTag("X-Mailer", "CMS Tool");
$head .= $this->mimeTag("Reply-To", $this->from); $head .= $this->mimeTag("Reply-To", $this->_from);
if ($this->notify) { if (is_string($this->_notify)) {
$head .= $this->mimeTag("Disposition-Notification-To", "\"" . $this->notify . "\" <" . $this->from . ">"); $head .= $this->mimeTag("Disposition-Notification-To", "\"" . $this->_notify . "\" <" . $this->_from . ">");
} }
$head .= $this->mimeTag("Content-Type", "multipart/mixed", array ("boundary" => $this->uniqid)); $head .= $this->mimeTag("Content-Type", "multipart/mixed", array ("boundary" => $this->uniqid));
if ($this->copy) { if ($this->copy) {
@ -182,7 +182,7 @@ class Mail
function getSubject() function getSubject()
{ {
return $this->encodedWord($this->subject); return $this->encodedWord($this->_subject);
} }
/** /**
@ -190,7 +190,7 @@ class Mail
*/ */
function eml() function eml()
{ {
return "To: " . $this->to . PHP_EOL . "Subject: {$this->getSubject()}" . PHP_EOL . $this->getHeader() . $this->getMessage(); return "To: " . $this->_to . PHP_EOL . "Subject: {$this->getSubject()}" . PHP_EOL . $this->getHeader() . $this->getMessage();
} }
/** /**
@ -198,11 +198,10 @@ class Mail
*/ */
function send() function send()
{ {
$result = mail($this->to, $this->getSubject(), $this->getMessage(), $this->getHeader()); $result = mail($this->_to, $this->getSubject(), $this->getMessage(), $this->getHeader());
if(! $result) { if(! $result) {
throw new Exception('Невозможно отправить почту'); file_put_contents(Path::resolveFile("send.eml"), $this->eml());
// require_once "core/path.php"; throw new Exception('Невозможно отправить почту');
// file_put_contents(Path::resolveFile("data/email/send.eml"), $this->eml());
} }
return $result; return $result;
} }

View file

@ -12,7 +12,7 @@ class Numbers
return $i; return $i;
} }
static function prefix($prefix, array $array) static function prefix($prefix, array $array, $key = false)
{ {
$result = array(); $result = array();
for ($i = 0; $i < count($array); $i++) { for ($i = 0; $i < count($array); $i++) {

430
src/Path.php Normal file
View file

@ -0,0 +1,430 @@
<?php
/**
* Класс для работы с папками и путями
* Для итерации над файлами возможно лучше использовать SPL
*
*/
class Path
{
const SEPARATOR = "/";
protected $path = array();
protected $url = array();
protected $absolute = false;
public function __construct($path)
{
// assert(is_string($path));
$this->url = parse_url($path);
if (isset($this->url['path'])) {
$path = $this->url['path'];
// $path = preg_replace('/\/{2,}/', '/', $path);
$this->path = self::optimize($this->fromString($path));
}
}
static function factory($path) {
return new Path($path);
}
public function getParts()
{
return $this->path;
}
public static function normalize($pathName)
{
$path = new Path($pathName);
return $path->__toString();
}
/**
* Базовое имя
* @param $path
* @return mixed
*/
public static function basename($path)
{
$list = preg_split('#\\\\|/#s', $path);
return end($list);
}
/**
* Возвращает расширение файла
*
* @param string $fileName Полное имя файла
*
* @return string
*/
static function getExtension($fileName)
{
assert(is_string($fileName) || is_null($fileName));
return pathinfo($fileName, PATHINFO_EXTENSION);
}
static function isType($fileName, $extension)
{
if (is_array($extension)) {
return in_array(pathinfo($fileName, PATHINFO_EXTENSION), $extension);
} else {
return (pathinfo($fileName, PATHINFO_EXTENSION) == $extension);
}
}
/**
* Полное имя файла без расширения
*
* @param string $fileName Имя файла
*
* @return string
*/
static function skipExtension($fileName)
{
assert(is_string($fileName));
$path = pathinfo($fileName);
if ($path['dirname'] == ".") {
return $path['filename'];
} else {
return self::join($path['dirname'], $path['filename']);
}
}
/**
* Возвращает имя файла без расширения
*
* @param string $fileName Полное имя файла
*
* @return string
*/
static function getFileName($fileName)
{
assert(is_string($fileName));
return pathinfo($fileName, PATHINFO_FILENAME);
}
/**
* Преобразует строку путя в массив
*
* @param string $path Путь
*
* @return array
*/
public function fromString ($path)
{
assert(is_string($path));
$list = preg_split('#\\\\|/#s', $path);
if (isset($this->url['scheme']) && !isset($this->url['host'])) {
$this->absolute = false;
} else if ($list[0] == '' && count($list) > 1) {
$this->absolute = true;
}
return $list;
}
/**
* Преобразует относительный путь в абсолютный
*/
public static function optimize($path) //
{
$result = array();
foreach ($path as $n) {
switch ($n) {
// Может быть относительным или абсолютным путем
case "": break;
case ".": break;
case "..":
if (count($result) > 0) { array_pop($result); break; }
default:
array_push($result, $n);
}
}
return $result;
}
// Сравнение двух путей на равентство
public function equal(/*.Path.*/ $path)
{
if (count($this->path) == count($path->path)) {
for ($i = 0; $i < count($this->path); $i++) {
if ($this->path[$i] != $path->path[$i]) {
return false;
}
}
return true;
}
return false;
}
public static function makeUrl($path)
{
return (isset($path['scheme']) ? $path['scheme'] . ':/' : '')
. (isset($path['host']) ? ('/'
. (isset($path['user']) ? $path['user'] . (isset($path['pass']) ? ':' . $path['pass'] : '') . '@' : '')
. $path['host']
. (isset($path['port']) ? ':' . $path['port'] : '')) : '')
. $path['path']
. (isset($path['query']) ? '?' . $path['query'] : '')
. (isset($path['fragment']) ? '#' . $path['fragment'] : '');
}
/**
* Преобразует путь в строку
*
* @return string
*/
public function __toString()
{
$result = (($this->absolute) ? '/' : '') . implode(self::SEPARATOR, $this->path);
$this->url['path'] = $result;
return self::makeUrl($this->url);
}
/**
* Проверяет является ли папка родительской для другой папки
*
* @parma Path $path
*
* @return boolean
*/
public function isParent(/*.Path.*/ $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++) {
if ($path->path[$i] != $this->path[$i]) {
return false;
}
}
return true;
}
return false;
}
public static function _isParent($path1, $path2)
{
$path = new Path($path1);
return $path->isParent(new Path($path2));
}
/**
* Находит путь относительно текущего путя
*
* @param string $name Полный путь к файлу
*
* @return string Относительный путь к файлу
*/
public function relPath($name)
{
$path = new Path($name);
unset($path->url['scheme']);
// $this->absolute = false;
$path->absolute = false;
foreach ($this->path as $n) {
array_shift($path->path);
}
return $path->__toString();
}
// Вычисляет относительный путь в виде строки
static function relative($rpath, $lpath) {
// Нужно проверять диск!!
$self = new Path($rpath);
$list = new Path($lpath);
$self_path = $self->getParts();
$list_path = $list->getParts();
$result = array();
for ($i = 0; $i < count($list_path); $i++) {
if (($i >= count($self_path)) || $list_path[$i] != $self_path[$i]) {
break;
}
}
for($j = $i; $j < count($list_path); $j++) {
array_push($result, '..');
}
for($j = $i; $j < count($self_path); $j++) {
array_push($result, $self_path[$j]);
}
return implode("/", $result);
}
public function append($path)
{
$base = $this->__toString();
return self::join($base, $path);
}
/**
* Обьединяет строки в путь соединяя необходимым разделителем
* fixme не обрабатывает параметры урла, решение Path::join(SITE_WWW_PATH) . '?param=pampam'
* @return string
*/
static function join($_rest)
{
$args = func_get_args();
$result = array();
$parts0 = new Path(array_shift($args));
$result [] = $parts0->getParts();
foreach ($args as $file) {
$parts = new Path($file);
$result [] = $parts->getParts();
}
// При обьединении ссылок можно обьеденить path, query, fragment
$path = implode(self::SEPARATOR, call_user_func_array('array_merge', $result));
$parts0->url['path'] = ($parts0->isAbsolute()) ? '/' . $path : $path;
return self::makeUrl($parts0->url);
}
// Проверка структуры имени файла
static function checkName($name, $extension)
{
return (strlen(pathinfo($name, PATHINFO_FILENAME)) > 0) && (pathinfo($name, PATHINFO_EXTENSION) == $extension);
}
static function isCharName($char)
{
$ch = ord($char);
return ((($ch >= ord('a')) && ($ch <= ord('z'))) || (strpos('-._', $char) !== false) || (($ch >= ord('0')) && ($ch <= ord('9'))));
}
// Проверка имени файла
static function isName($name) {
if (strlen(trim($name)) == 0) {
return false;
}
for ($i = 0; $i < strlen($name); $i++) {
if (!self::isCharName($name[$i])) {
return false;
}
}
return true;
}
public function isAbsolute()
{
return $this->absolute;
}
/**
* Подбирает новое временное имя для файла
*
* @param string $dst Предпологаемое имя файла
*
* @return string Новое имя файла
*/
static function resolveFile($dst)
{
$i = 0;
$file = self::skipExtension($dst);
$suffix = self::getExtension($dst);
$temp = $dst;
while (file_exists($temp)) {
$i ++;
$temp = $file . "." . $i . "." . $suffix;
}
return $temp;
}
/**
* Список файлов в директории
*
* @param array $allow массив расширений для файлов
* @param array $ignore массив имен пааок которые не нужно обрабатывать
*
* @returnarray
*/
public function getContent($allow = null, $ignore = array())
{
$ignore = array_merge(array(".", ".."), $ignore);
return self::fileList($this->__toString(), $allow, $ignore);
}
/**
* Обьединяет строки в путь соединяя необходимым разделителем
*
* @param array $allow массив расширений разрешеных для файлов
* @param array $ignore массив имен пааок которые не нужно обрабатывать
*
* @return array
*/
function getContentRec($allow = null, $ignore = array())
{
$result = array ();
$ignore = array_merge(array (".", ".."), $ignore);
self::fileListAll($result, $this->__toString(), $allow, $ignore);
return $result;
}
// Использовать SPL ???
protected static function fileList($base, &$allow, &$ignore)
{
if ($base == '') $base = '.';
$result = array ();
$handle = opendir($base);
if (is_resource($handle)) {
while (true) {
$file = readdir($handle);
if (is_string($file)) {
if (! in_array($file, $ignore)) {
$isDir = is_dir(Path::join($base, $file));
if ($isDir || ($allow == null) || in_array(self::getExtension($file), $allow)) {
$result[] = $file;
}
}
continue;
}
break;
}
closedir($handle);
}
// При обьединении ссылок можно обьеденить path, query, fragment
return $result;
}
protected static function fileListAll(&$result, $base, &$allow, &$ignore)
{
$files = self::fileList($base, $allow, $ignore);
foreach ($files as $name) {
$fullname = self::join($base, $name);
if (is_dir($fullname)) {
self::fileListAll($result, $fullname, $allow, $ignore);
} else {
array_push($result, $fullname);
}
}
}
/**
* Создает недастающие папки для записи файла
*
* @param string $dst Полное имя файла
*
* @return void
*/
static function prepare($dst, $filename = true)
{
if ($filename) {
$path_dst = pathinfo($dst, PATHINFO_DIRNAME);
} else {
$path_dst = $dst;
}
if (! file_exists($path_dst)) {
mkdir($path_dst, 0777, true);
}
}
}

119
src/Primitive.php Normal file
View file

@ -0,0 +1,119 @@
<?php
/**
* Преобразование типов !!! Пересмотреть использование классов!!
* Класс преобразования типа значения поля класса в тип поля таблицы
* @package system
*/
class Primitive {
// varchar
public static function to_varchar($value)
{
return ((string) $value);
}
public static function from_varchar($value)
{
return $value;
}
// int
public static function to_bool($value)
{
return filter_var($value, FILTER_VALIDATE_BOOLEAN);//(int)((bool) $value);
}
public static function from_bool($value)
{
return ((bool) $value);
}
// int
public static function to_int($value)
{
return ((int) $value);
}
public static function from_int($value)
{
return ((string) $value);
}
// date
public static function to_date($value)
{
$result = 0;
$tmp = explode("/", $value, 3);
if (!empty($tmp)) {
if (count($tmp) != 3) return $result;
$year = intval($tmp[2]);
$month = intval($tmp[1]);
$day = intval($tmp[0]);
if ($month != 0 && $day != 0 && $year != 0) {
if (checkdate($month, $day, $year)) {
return mktime(0, 0, 0, $month, $day, $year);
} else {
return 0;
}
}
}
return $result;
}
public static function to_datetime($value)
{
$result = 0;
$tmp = array();
if (preg_match('/(\d+)-(\d+)-(\d+)T(\d+):(\d+)Z/', $value, $tmp)) {
if (checkdate($tmp[2], $tmp[3], $tmp[1])) {
$result = mktime($tmp[4], $tmp[5], 0, $tmp[2], $tmp[3], $tmp[1]);
}
}
return $result;
}
public static function from_date($value)
{
if ($value > 0) {
return date("d/m/Y", $value);
}
return '';
}
public static function from_datetime($value)
{
if ($value > 0) {
return date("Y-m-d\TH:i\Z", $value);
}
return '';
}
// secure
public static function to_secure($value)
{
// Значение приабразуется во время сохранения в базе данных
return $value;
}
public static function from_secure($value)
{
return $value;
}
// array
public static function to_array($value)
{
return (is_array($value)) ? $value : array();
}
public static function from_array($value)
{
return $value;
}
}

View file

@ -1,11 +1,12 @@
<?php <?php
///<reference path="settings.php" />
/** /**
* http://www.patternsforphp.com/wiki/Registry * http://www.patternsforphp.com/wiki/Registry
* http://www.patternsforphp.com/wiki/Singleton * http://www.patternsforphp.com/wiki/Singleton
* http://www.phppatterns.com/docs/design/the_registry?s=registry * http://www.phppatterns.com/docs/design/the_registry?s=registry
*/ */
require_once 'core/settings.php';
class Registry extends Settings class Registry extends Settings
{ {

View file

@ -26,7 +26,7 @@ class Session
function start() function start()
{ {
session_start(); @session_start();
} }
function stop() function stop()

View file

@ -1,7 +1,5 @@
<?php <?php
require_once 'core/collection.php';
/** /**
* Класс реестра * Класс реестра
* Реестр организован как ассоциативный многомерный массив * Реестр организован как ассоциативный многомерный массив
@ -14,23 +12,31 @@ require_once 'core/collection.php';
class Settings extends Collection class Settings extends Collection
{ {
protected $file; protected $file;
protected $format = 'php';
public function __construct ($file = null) public function __construct ($file = null)
{ {
$this->format = pathinfo($file, PATHINFO_EXTENSION);
$this->file = $file; $this->file = $file;
} }
/** /**
* Чтение настроек из файла * Чтение настроек из файла
*
* @param File $file
*
* @return Boolean * @return Boolean
*/ */
public function read() public function read()
{ {
if ( !file_exists ($this->file)) return false; if (!file_exists ($this->file)) {
return false;
}
// Не include_once т.к читать настройки можно несколько раз // Не include_once т.к читать настройки можно несколько раз
include($this->file); $settings = array();
if ($this->format == 'json') {
$settings = json_decode(file_get_contents($this->file), true);
} else {
include ($this->file);
}
if (!is_array($settings)) { if (!is_array($settings)) {
throw new Exception($this->file); throw new Exception($this->file);
} }
@ -53,7 +59,9 @@ class Settings extends Collection
// assert(count($key) == 1); // assert(count($key) == 1);
$name = array_shift($key); $name = array_shift($key);
if (is_array($value)) { if (is_array($value)) {
if (! isset($data[$name])) $data[$name] = array(); if (!isset($data[$name])) {
$data[$name] = array();
}
$this->merge($data[$name], $value); $this->merge($data[$name], $value);
} else { } else {
$data[$name] = $value; $data[$name] = $value;
@ -109,7 +117,7 @@ class Settings extends Collection
* Чтение ключа из реестра (Собирает все ключи с определенным значением во всех модулях) * Чтение ключа из реестра (Собирает все ключи с определенным значением во всех модулях)
* @param $key Путь к значению ключа внутри модуля * @param $key Путь к значению ключа внутри модуля
*/ */
public function readKeyList() public function readKeyList($_rest)
{ {
$key = func_get_args(); $key = func_get_args();
$result = array(); $result = array();
@ -151,10 +159,15 @@ class Settings extends Collection
* *
* @return void * @return void
*/ */
public function write($file = false) public function write($file = null)
{ {
$result = var_export ($this->data, true); if ($this->format == 'json') {
file_put_contents (($file) ? $file : $this->file, "<?php\n\$settings = ".$result.";\n?>"); $result = json_encode($this->data, JSON_PRETTY_PRINT | JSON_UNESCAPED_UNICODE);
} else {
$result = var_export($this->data, true);
$result = "<?php\n\$settings = ".$result.";\n?>";
}
file_put_contents (($file) ? $file : $this->file, $result);
} }
/** /**

212
src/Setup.php Normal file
View file

@ -0,0 +1,212 @@
<?php
/**
* <code>
* $setup = new Setup('test.xml');
* $setup->set('target', 'dst');
* $setup->executeActions('install');
* </code>
*/
class Setup
{
protected $actions = array();
public $context = array();
protected $file;
protected $action;
protected $node;
protected $stack = array();
public $zip;
public $target;
public function __construct($file)
{
$this->file = $file;
$this->node = simplexml_load_file($file);
$this->target = '';
$this->zip = new ZipArchive();
$this->zip->open(strtr($file, array('.xml' => '.zip')));
array_push($this->stack, $this->node);
$this->registerAction('copy', array($this, 'copyFile'));
$this->registerAction('make-directory', array($this, 'makeDirectory'));
$this->registerAction('make-link', array($this, 'makeLink'));
$this->registerAction('include', array($this, 'includeFile'));
$this->registerAction('when', array($this, 'testWhen'));
}
/**
* Регистрация новых действия для установки
*/
public function registerAction($name, $action)
{
$this->actions[$name] = $action;
}
/**
* Установка переменных для шаблона
*/
public function set($name, $value)
{
$this->context[$name] = $value;
}
function replaceFn($matches) {
if (isset($this->context[$matches[2]])) {
$v = $this->context[$matches[2]];
} else {
$v = $matches[2];
}
if ($matches[1] == '*') {
return addslashes($v);
}
return $v;
}
public function fileContent($file, array $tpl)
{
$result = $this->zip->getFromName($file);
$result = preg_replace_callback('/\{\{\s*(\*?)(\w+)\s*\}\}/', array($this, 'replaceFn'), $result);
return $result;
}
function callAction($name, array $attributes)
{
if(isset($this->actions[$name])) {
call_user_func_array($this->actions[$name], $attributes);
}
}
/**
* Заменяет переменные на их значения в строке
*/
function replaceVariable(array $match)
{
if (isset($this->context[$match[1]])) {
return $this->context[$match[1]];
}
return $match[0];
}
/**
* Для всех аттрибутов заменяет переменные на их значения
*/
function resolve($attributes)
{
$result = array();
foreach ($attributes as $key => $value) {
$result [$key] = preg_replace_callback("/\\\${(\w+)}/", array($this, 'replaceVariable'), $value);
}
return $result;
}
/**
* Выполняет список действий если для действия не указан аттрибут when то оно выполняется всегда
*
* @param $action специальное действие
*/
function executeActions($action = "install")
{
$this->action = $action;
if ($this->stack[count($this->stack) - 1] === false) {
return;
}
/*.SimpleXMLElement.*/$item = $this->stack[count($this->stack) - 1];
$root = $item->children();
foreach ($root as $node)
{
$attributes = $node->attributes();
array_push($this->stack, $node);
$this->callAction($node->getName(), array($this->resolve($attributes)));
array_pop($this->stack);
}
}
/**
* Копирования файла
* @param preserve Не переписывать файл если он существует
* @param template Файл является шаблоном подставить параметры до копирования
* @param src Исходный файл
* @param dst Новый файл
*/
public function copyFile(array $attributes)
{
$path = $this->targetPath($attributes['dst']);
if (!(file_exists($path) && isset($attributes['preserve']))) {
file_put_contents($path, $this->fileContent($attributes['src'], $this->context));
}
}
/**
* Создает символическую ссылку на папку/файл
* @param dst Имя папки
*/
public function makeLink(array $attributes)
{
if (function_exists('symlink')) {
symlink($attributes['target'], $attributes['link']);
}
}
/**
* Подключение файла установки
* @param file Имя подключаемого файла
*/
public function includeFile(array $attributes)
{
$file = basename($this->file) . "/" . $attributes['file'];
$setup = new Setup($file);
$setup->context = $this->context;
$setup->executeActions();
}
function targetPath($s) {
return $this->target . '/' . $s;
}
/**
* Создает новую папку
* @param dst Имя папки
*/
public function makeDirectory(array $attributes)
{
$path = $this->targetPath($attributes['dst']);
if (!file_exists($path)) {
mkdir($path);
}
}
function testWhen(array $attributes)
{
if (!isset($attributes['test']) || $attributes['test'] == $this->action) {
$this->executeActions($this->action);
}
}
/**
* Выполнение Списка SQL команд
*/
function batchSQLZip(/*.Database.*/ $conn, $file)
{
$stmtList = Tools_SQLStatementExtractor::extract($this->zip->getFromName($file));
foreach ($stmtList as $stmt) {
$conn->executeQuery ($stmt);
}
}
static function batchSQL(/*.Database.*/ $conn, $file)
{
$stmtList = Utils_SQLStatementExtractor::extractFile($file);
foreach ($stmtList as $stmt) {
$conn->executeQuery ($stmt);
}
}
}

Some files were not shown because too many files have changed in this diff Show more