Синхронизировал частично с CMS2

This commit is contained in:
origami11 2017-02-09 17:14:11 +03:00
parent 6b412f5d6f
commit f2938b1353
30 changed files with 1447 additions and 1099 deletions

1
.gitignore vendored Normal file
View file

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

View file

@ -1,8 +1,7 @@
<?php
/**
* Коллекция
*
* package core
*
*/
class Collection implements ArrayAccess
{
@ -40,7 +39,7 @@ class Collection implements ArrayAccess
*
* @return void
*/
public function set($key, $value)
public function set(/*.string.*/$key, /*.any.*/$value)
{
$this->data[$key] = $value;
}
@ -54,7 +53,7 @@ class Collection implements ArrayAccess
*/
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)

View file

@ -1,423 +1,339 @@
<?php
/**
*
* @package Core
*/
/**
* Переименовать контроллер !! (StubController, CrudController, PageController, BaseController) ModelController
* Возможно нужен еще класс с мета действиями как для actionIndex <= metaActionIndex либо с классам для этих действий
* Есть класс для управлениями действиями а есть сами действия в виде классов или функций !!
*/
class Controller_Model extends Controller_Action
require_once __DIR__ . '/../functions.php';
function forceUrl($name)
{
public $schema = array();
public $schemaSearch = array();
if (is_callable($name)) {
return call_user_func($name);
}
return $name;
}
/**
* FIXME: Лучше $this->table->setHeader
*/
public $tableSchema = null;
public $formSchema = array();
/**
* Контроллер страниц
*/
class Controller_Action
{
public $menu;
const TEMPLATE_EXTENSION = ".html"; // Расширение для шаблонов
const ACTION_PREFIX = "action"; // Префикс для функций действий
public $jsPath; // Глобальный путь к скриптам
public $themePath; // Глобальный путь к текущей теме
// Параметры устанавливаются при создании контроллера
public $name; // Имя модуля
public $viewPath = null; // Путь к шаблонам контроллера
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 $table;
public function __construct()
public function __construct ()
{
$this->path = new PathMenu();
$this->menu = new PageMenu();
$this->table = new ListTable();
//
}
/**
*/
function setUp()
public function setUp ()
{
$this->table->addMenuItem($this->aUrl('delete'), 'удалить', false, 'all', 'warning');
//$this->table->addMenuItem($this->nUrl('form'), 'редактировать', 'edit-24.png');
// override this
}
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);
public function loadConfig($name) {
$filename = Shortcut::getUrl('config', $name);
if (file_exists($filename)) {
include($filename);
} else {
$form->addFieldList($this->schema);
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");
}
}
/**
* Добавление пользователя
*/
public function actionAdd(HttpRequest $request)
function findIcon($icon, $size)
{
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);
return Path::join($this->iconPath, $size . 'x' . $size, $icon . '.png');
}
// Действия до проверки формы
$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);
}
/**
* Заголовок
* Создает представление
* @param string $file
* @return template
*/
private function setTitlePath($ref)
public function getView($name)
{
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) {
// Не найден заголовок потому что неправильно определен родительский элемент
}
}
$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; }
}
}
/**
* Форма для редактирования
*/
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')); // Инициализация формы
$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));
$list = $request->get('table_item');
$id = ($list[0]) ? $list[0] : $request->get('id');
$tpl->loadImports(Path::skipExtension($template) . ".import");
$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);
///
}
$this->addSuggest($tpl, $name);
return $tpl;
}
/**
*/
function tableSetup($table, $id = null, $ref = null)
public function getModel($name)
{
// 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);
if (!$this->factory) {
$this->factory = new ModelFactory($this->db, $this->_registry, $this->_shortcut);
}
return $this->factory->getModel($name);
}
/**
* Выбор действия
* Т.к действия являются методами класса то
* 1. Можно переопределить действия
* 2. Использовать наследование чтобы добавить к старому обработчику новое поведение
* @param $request Обьект запроса
*/
public function actionIndex(HttpRequest $request)
public function execute1(HTTPRequest $request)
{
$this->getActionPath($request, 'index');
// Такое мета действие наверное можно вынести в отдельный класс
return $this->metaActionIndex($request, array($this, 'tableSetup'), $this->aUrl('list'));
$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 metaActionIndex(HttpRequest $request, $setup, $list)
public function actionIndex(HttpRequest $request)
{
// может быть одно ref или несколько
// {{{ история переходов
$ref = null;
if ($request->get('ref')) {
$ref = $request->get('ref');
} else if ($request->session()->get('ref')) {
$ref = $request->session()->get('ref');
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;
}
$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 fUrl($name, array $param = array())
{
return forceUrl($this->nUrl($name, $param));
}
/**
* Добавляет параметр для всех ссылок создаваемых функцией nUrl, aUrl
*/
public function actionSetup($request)
public function addParameter($name, $value)
{
$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);
if ($value) {
$this->param [$name] = $value;
}
}
/**
* Генерация ссылки на действие контроллера
* Ajax определяется автоматически mode = ajax используется для смены layout
*/
private function formPage($form, $request)
public function aUrl($name, array $param = array())
{
$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;
return $this->nUrl($name, array_merge(array('mode' => 'ajax'), $param)); // FIXME
}
// Тоже убрать в метод Controller_Model
function getActionPath(HttpRequest $request/*, $action = false*/)
/**
* Добавление помошника контроллера
*/
public function addHelper($class)
{
require_once 'state.php';
$this->_getActionPath()->getPath($this, ($action) ? $action : $request->getAction());
}
$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();
}
}

View file

@ -1,341 +0,0 @@
<?php
require_once 'core/functions.php';
function forceUrl($name)
{
if (is_callable($name)) {
return call_user_func($name);
}
return $name;
}
/**
* Контроллер страниц
* @package core
*/
class Controller_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,30 +1,24 @@
<?php
require_once 'core/controller/controller.php';
require_once 'core/controller/installer.php';
/**
* Первичный контроллер контроллер страниц
* @package core
*/
class Controller_Front extends Controller
class Controller_Front extends Controller_Action
{
protected $shortcut; // Ярлык к модулю
protected $_param; // Параметр по которому выбирается модуль
protected $default; // Значение параметра по умолчанию
protected $installer;
public function __construct(Settings $_registry, $_shortcut)
{
require_once 'core/database_pdo.php';
parent::__construct();
$registry = $_registry;
$this->_registry = $_registry;
$this->_shortcut = $_shortcut;
$this->db = Database::getConnection($registry->readKey(array('system', 'dsn')));
$this->installer = new Installer($_registry);
}
@ -36,8 +30,6 @@ class Controller_Front extends Controller
*/
public function loadModule($name, Collection $request)
{
$this->installer->setUp($this->db, array($this, 'installPath'));
$this->installer->doUpdates($name); // ModuleLoader (1)
$moduleFile = Shortcut::getUrl($this->shortcut, $name); // ModuleLoader (2)
$module = $this->loadClass($moduleFile);
@ -59,10 +51,10 @@ class Controller_Front extends Controller
$module->db = $this->db;
// Не для всех приложений нужно вести лог действий
// Ведение лога
$logger = $this->loadClass(FRAMEWORK_PATH . '/core/filter/actionlogger.php', $module);
$logger = $this->loadClass(FRAMEWORK_PATH . '/src/filter/actionlogger.php', $module);
$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 . '/src/filter/actionaccess.php', $logger);
$module->access->access = $this->loadSettings(Shortcut::getUrl('access', $name));
$module->setUp();

426
src/controller/model.php Normal file
View file

@ -0,0 +1,426 @@
<?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()
{
$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

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

View file

@ -1,7 +1,5 @@
<?php
require_once 'core/path.php';
class ActionLogger
{
public $before = array ();

View file

@ -8,7 +8,7 @@
*/
// В класс авторизации передавать обьект для управления пользователем
// Вынести в отдельный файл
class Filter_LoginFilter extends Filter_Filter
class Filter_Login extends Filter_Filter
{
const SESSION_BROWSER_SIGN_SECRET = '@w3dsju45Msk#';
const SESSION_BROWSER_SIGN_KEYNAME = 'session.app.browser.sign';
@ -20,16 +20,16 @@ class Filter_LoginFilter extends Filter_Filter
public function isLoggin(HttpRequest $request)
{
// Авторизация
session_start();
// session_start();
$db = $this->getConnection();
UserAccess::setUp($db); // Соединение
Filter_UserAccess::setUp($db); // Соединение
switch ($request->getAction()) {
// Авторизация по постоянному паролю
case 'login':
$login = $request->get('login');
$password = $request->get('password');
$result = UserAccess::getUserByLogin($login); // Поиск по логину
$result = Filter_UserAccess::getUserByLogin($login); // Поиск по логину
if ($result) {
if (md5($password) == $result->getString('password')) { // password
$this->enter($db, $result);

View file

@ -1,10 +1,7 @@
<?php
require_once 'filterbase.php';
require_once 'filterlogin.php';
// Класс должен быть в библиотеке приложения
class UserAccess
class Filter_UserAccess
{
const LIFE_TIME = 1800; // = 30min * 60sec;

View file

@ -2,17 +2,23 @@
/**
* Элемент формы
* @package core
*/
class TField
{
public $hidden = false;
public $name;
public $label; // Метка поля
public $value; // Значение поля
public $type; // Каждому типу элемента соответствует макрос TAL
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)
{

View file

@ -107,7 +107,7 @@ function compose() {
*
* @return array[int]mixed
*/
function rcurry() {
function rcurry($_rest) {
$closure = new __right(func_get_args ());
return array($closure, 'apply');
}
@ -117,7 +117,7 @@ function rcurry() {
*
* @return array[int]mixed
*/
function lcurry() {
function lcurry($_rest) {
$closure = new __left(func_get_args ());
return array($closure, 'apply');
}
@ -192,7 +192,7 @@ function __self($name, $o) {
function concat(/* $args ...*/) {
$args = func_get_args();
return implode($args);
return implode("", $args);
}
function __empty($x) {
@ -229,6 +229,15 @@ function key_values($key, /*array|ArrayIterator*/ $array) {
return $result;
}
function key_values_object($key, /*array|ArrayIterator*/ $array) {
$result = array();
foreach($array as $item) {
$result[] = $item->{$key};
}
return $result;
}
function assoc_key_values($key, $value, $array) {
$result = array();
foreach ($array as $item) {
@ -245,7 +254,7 @@ function assoc_key($key, $array) {
return $result;
}
function _get($key, $value, $array) {
function _get($key, /*.any.*/$value, /*.array.*/$array) {
foreach ($array as $item) {
if ($item[$key] == $value) return $item;
}
@ -265,7 +274,7 @@ function _get_key($key, $value, $array) {
* @return bool
*/
function every(array $array, $callback) {
foreach ($array as $key => $value) {
foreach ($array as $value) {
if (call_user_func($callback, $value) === false) {
return false;
}
@ -337,10 +346,33 @@ if (!function_exists('hash_key')) {
};
}
function array_merge1($x, $y) {
$result = $x;
foreach ($y as $k => $v) {
$result [$k] = $v;
/**
* Выбирает все сроки из таблицы с уникальными значениями ключа
* @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 $result;
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;
}

View file

@ -10,6 +10,8 @@ class WrongRequestException extends Exception
// HTTPRequest = ArrayAccess
class HttpRequest extends Collection implements ArrayAccess
{
public $_session;
/**
* Constructor
* Stores "request data" in GPC order.
@ -24,9 +26,8 @@ class HttpRequest extends Collection implements ArrayAccess
$ajax = $this->isAjax();
foreach ($list as $key => $value) {
$data = new SafeCollection();
$data = new Collection();
$data->import($value);
parent::set($key, $data);
}
@ -35,50 +36,32 @@ class HttpRequest extends Collection implements ArrayAccess
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)
{
return parent::get($key);
}
function export()
function get($key, $default = null)
{
return parent::get('data')->export();
return parent::get('data')->get($key, $default);
}
function session(Session $value = null)
{
if ($value) {
$this->_session = $value;
}
return $this->_session;
}
/* Array Acces Interface */
function offsetExists($offset)
function set($key, /*.any.*/$value)
{
return parent::get('data')->set($key, $value);
}
function offsetGet($offset)
{
}
function offsetSet($offset, $value)
{
}
function offsetUnset($offset)
function export($key = 'data')
{
return parent::get($key)->export();
}
function clear()
@ -125,4 +108,22 @@ class HttpRequest extends Collection implements ArrayAccess
{
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) {
}
}

View file

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

11
src/layout/none.php Normal file
View file

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

View file

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

View file

@ -20,7 +20,7 @@ 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{
class Markup_SimpleBBCode{
//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
@ -38,7 +38,7 @@ class Simple_BB_Code{
var $auto_links = true;
//Internal Storage
var $_code = '';
function Simple_BB_Code($new=true,$parse=true,$links=true){
function __construct($new=true,$parse=true,$links=true){
$this->convert_newlines = $new;
$this->parse_smilies = $parse;
$this->auto_links = $links;

View file

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

View file

@ -1,33 +1,58 @@
<?php
/*.
require_module 'standard';
.*/
/**
* Класс для работы с папками и путями
* Для итерации над файлами возможно лучше использовать SPL
*
* @package utils
*/
class Path
class Path
{
const SEPARATOR = "/";
protected $path;
protected $path = array();
protected $url = array();
protected $absolute = false;
public function __construct ($path)
public function __construct($path)
{
assert(is_string($path));
// assert(is_string($path));
$this->path = $this->fromString($path);
$this->optimize();
}
$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);
}
/**
* Возвращает расширение файла
*
@ -35,13 +60,22 @@ class Path
*
* @return string
*/
static function getExtension ($fileName)
static function getExtension($fileName)
{
assert(is_string($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);
}
}
/**
* Полное имя файла без расширения
*
@ -49,7 +83,7 @@ class Path
*
* @return string
*/
static function skipExtension ($fileName)
static function skipExtension($fileName)
{
assert(is_string($fileName));
@ -68,118 +102,13 @@ class Path
*
* @return string
*/
static function getFileName ($fileName)
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);
}
}
/**
* Преобразует строку путя в массив
@ -192,28 +121,60 @@ class Path
{
assert(is_string($path));
$list = preg_split("/[\/\\\\]/", $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 function optimize ()
public static function optimize($path) //
{
$result = array(current($this->path));
while (next($this->path) !== false) {
$n = current ($this->path);
$result = array();
foreach ($path as $n) {
switch ($n) {
// Может быть относительным или абсолютным путем
case "": break;
case ".": break;
case "..": if (count($result) > 0) array_pop($result); break;
case "..":
if (count($result) > 0) { array_pop($result); break; }
default:
array_push($result, $n);
}
}
reset($this->path);
$this->path = $result;
}
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'] : '');
}
/**
@ -221,10 +182,11 @@ class Path
*
* @return string
*/
public function __toString ()
public function __toString()
{
$result = implode($this->path, self::SEPARATOR);
return $result;
$result = (($this->absolute) ? '/' : '') . implode(self::SEPARATOR, $this->path);
$this->url['path'] = $result;
return self::makeUrl($this->url);
}
/**
@ -234,8 +196,11 @@ class Path
*
* @return boolean
*/
public function isParent ($path)
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]) {
@ -246,6 +211,12 @@ class Path
}
return false;
}
public static function _isParent($path1, $path2)
{
$path = new Path($path1);
return $path->isParent(new Path($path2));
}
/**
* Находит путь относительно текущего путя
@ -254,34 +225,97 @@ class Path
*
* @return string Относительный путь к файлу
*/
public function relPath ($name)
public function relPath($name)
{
$path = new Path ($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();
}
public function append ($path)
// Вычисляет относительный путь в виде строки
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);
}
}
/**
* Создает недастающие папки для записи файла
*
* @param string $dst Полное имя файла
*
* @return void
* Обьединяет строки в путь соединяя необходимым разделителем
* fixme не обрабатывает параметры урла, решение Path::join(SITE_WWW_PATH) . '?param=pampam'
* @return string
*/
static function prepare ($dst)
static function join($_rest)
{
$path_dst = pathinfo($dst, PATHINFO_DIRNAME);
if (! file_exists($path_dst)) {
mkdir($path_dst, 0700, true);
$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;
}
/**
@ -291,7 +325,7 @@ class Path
*
* @return string Новое имя файла
*/
static function resolveFile ($dst)
static function resolveFile($dst)
{
$i = 0;
$file = self::skipExtension($dst);
@ -304,14 +338,93 @@ class Path
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);
}
/**
* Обьединяет строки в путь соединяя необходимым разделителем
*
* @return string
*/
static function join ()
* @param array $allow массив расширений разрешеных для файлов
* @param array $ignore массив имен пааок которые не нужно обрабатывать
*
* @return array
*/
function getContentRec($allow = null, $ignore = array())
{
$args = func_get_args();
return implode(self::SEPARATOR, $args);
$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);
}
}
}

View file

@ -1,5 +1,7 @@
<?php
///<reference path="settings.php" />
/**
* http://www.patternsforphp.com/wiki/Registry
* http://www.patternsforphp.com/wiki/Singleton

View file

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

View file

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

View file

@ -1,54 +1,212 @@
<?php
/**
* Обработка файлов для установки
*/
* <code>
* $setup = new Setup('test.xml');
* $setup->set('target', 'dst');
* $setup->executeActions('install');
* </code>
*/
class Setup
{
/**
* Содержимое PHP файла
*/
static function fileContent($file, array $tpl)
protected $actions = array();
public $context = array();
protected $file;
protected $action;
protected $node;
protected $stack = array();
public $zip;
public $target;
public function __construct($file)
{
ob_start();
include $file;
$result = ob_get_contents();
ob_clean();
return $result;
$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'));
}
/**
* Копирует файлы шаблонной директории
* Регистрация новых действия для установки
*/
static function copyTemplatePath($srcPath, $dstPath, array $tpl, $tplFile = 'tpl')
public function registerAction($name, $action)
{
$out = new Path($srcPath);
$path = new Path($dstPath);
$files = $path->getContentRec(null, array(".svn"));
$this->actions[$name] = $action;
}
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);
}
/**
* Установка переменных для шаблона
*/
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 команд
*/
static function batchSQL(Connection $conn, $file)
function batchSQLZip(/*.Database.*/ $conn, $file)
{
$stmtList = SQLStatementExtractor::extractFile ($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);
}
}
}

View file

@ -10,7 +10,7 @@ class Shortcut
public $list = array();
// Singleton pattern
static public function getInstance ()
static public function getInstance()
{
if (self::$instance == null) {
self::$instance = new Shortcut();
@ -24,7 +24,7 @@ class Shortcut
*/
public function addUrl($prefix, $path)
{
$this->list [$prefix] = $path;
$this->list[$prefix] = $path;
}
/**
@ -38,9 +38,10 @@ class Shortcut
/**
* Возвращает путь по имени ярлыка
*/
static function getUrl ($prefix, $name = null, $name1 = false)
static function getUrl($prefix, $name = null, $name1 = null)
{
$shortcut = self::getInstance();
$names = $shortcut->variables;
if ($name) {
$names['$name'] = $name;
@ -48,10 +49,18 @@ class Shortcut
if ($name1) {
$names['$name1'] = $name1;
}
if (isset($shortcut->list[$prefix])) {
return strtr($shortcut->list[$prefix], $names);
}
return false;
return null;
}
}
static function expand($path)
{
$shortcut = self::getInstance();
$names = $shortcut->variables;
return strtr($path, $names);
}
}

View file

@ -2,33 +2,61 @@
/**
* Расширения для PHPTAL для отображения времени и даты
* package utils
*/
class DateTime_Tales implements PHPTAL_Tales
{
static public function date ($expression, $nothrow = false)
static public function date($expression, $nothrow = false)
{
return "phptal_date(".PHPTAL_TalesInternal::path ($expression).")";
return "phptal_date(".PHPTAL_Php_TalesInternal::path ($expression).")";
}
static public function time ($expression, $nothrow = false)
static public function time($expression, $nothrow = false)
{
return "phptal_time(".PHPTAL_TalesInternal::path ($expression).")";
return "phptal_time(".PHPTAL_Php_TalesInternal::path ($expression).")";
}
}
/* Регистрация нового префикса для подключения компонента */
$registry = PHPTAL_TalesRegistry::getInstance();
$registry->registerPrefix('date', array('DateTime_Tales', 'date'));
$registry->registerPrefix('time', array('DateTime_Tales', 'time'));
/**
* TALES для подключения компонентов
* component:name?param1=value1&param2=value2
*/
class Component_Tales implements PHPTAL_Tales
{
static public function component($expression, $nothrow = false)
{
$s = PHPTAL_Php_TalesInternal::string($expression);
return "phptal_component(" . $s . ")";
}
}
function phptal_date ($e)
{
return date ("d.m.Y", $e);
return date("d.m.Y", $e);
}
function phptal_time ($e)
{
return date ("H:i", $e);
return date("H:i", $e);
}
/**
* Функция подключения компонента
*/
function phptal_component ($expression) {
global $db, $registry; // Нужно как-то передавать параметры
$component = Controller_Component::loadComponent($expression, $db, $registry);
$req = new HttpRequest();
return $component->execute($req);
}
/* Регистрация нового префикса для подключения компонента */
$tales = PHPTAL_TalesRegistry::getInstance();
$tales->registerPrefix('component', array('Component_Tales', 'component'));
$tales->registerPrefix('date', array('DateTime_Tales', 'date'));
$tales->registerPrefix('time', array('DateTime_Tales', 'time'));

View file

@ -2,7 +2,6 @@
class Drawing
{
const ALIGN_LEFT = "left";
const ALIGN_TOP = "top";
const ALIGN_BOTTOM = "bottom";
@ -26,7 +25,6 @@ class Drawing
static function imagettftextbox(&$image, $size, $angle, $left, $top, $color, $font, $text,
$max_width, $max_height, $align, $valign)
{
// echo var_dump($font);
// echo $left,"\n", $top, "\n";
// echo $max_width,"\n", $max_height, "\n";
// self::drawrectnagle($image, $left, $top, $max_width, $max_height, array(0xFF,0,0));
@ -44,7 +42,6 @@ class Drawing
$last_width = 0;
for ($i = 0; $i < count($words); $i++) {
$item = $words[$i];
// echo "->", $font, "\n";
$dimensions = imagettfbbox($size, $angle, $font, $current_line . ($first_word ? '' : ' ') . $item);
$line_width = $dimensions[2] - $dimensions[0];
$line_height = $dimensions[1] - $dimensions[7];
@ -75,6 +72,7 @@ class Drawing
}
// vertical align
$top_offset = 0;
if ($valign == self::ALIGN_CENTER) {
$top_offset = ($max_height - $largest_line_height * count($lines)) / 2;
} elseif ($valign == self::ALIGN_BOTTOM) {
@ -84,17 +82,15 @@ class Drawing
$top += $largest_line_height + $top_offset;
$i = 0;
fb($lines);
fb($line_widths);
foreach ($lines as $line) {
// horizontal align
$left_offset = 0;
if ($align == self::ALIGN_CENTER) {
$left_offset = ($max_width - $line_widths[$i]) / 2;
} elseif ($align == self::ALIGN_RIGHT) {
$left_offset = ($max_width - $line_widths[$i]);
}
// echo $font, "\n";
imagettftext($image, $size, $angle, $left + $left_offset, $top + ($largest_line_height * $i), $color, $font, $line);
$i++;
}

40
src/view/composite.php Normal file
View file

@ -0,0 +1,40 @@
<?php
// CompositeView+PHPTAL
class View_Composite extends View_Top
{
private $tal;
function __construct($file)
{
parent::__construct($file);
$this->tal = new PHPTAL($file);
$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,6 +1,6 @@
<?php
class _View_Composite // AbstractCompositeView
class View_Top // AbstractCompositeView
{
protected $_section = array(); // Вложенные шаблоны
// Блоки
@ -257,42 +257,3 @@ class _View_Composite // AbstractCompositeView
}
}
// 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

@ -5,21 +5,28 @@
*/
class ZipFile extends ZipArchive
{
private $ignore = array('.', '..');
public function addIgnore($name)
{
$this->ignore [] = $name;
}
private function addDirDo($location, $name)
{
assert(is_string($location) && is_string($name));
$name .= '/';
$location .= '/';
$file = null;
// Read all Files in Dir
$dir = opendir($location);
while (($file = readdir($dir)) !== false)
{
if ($file === '.' || $file === '..') continue;
if (in_array($file, $this->ignore)) continue;
// Rekursiv, If dir: FlxZipArchive::addDir(), else ::File();
$call = (is_dir($file)) ? 'addDir' : 'addFile';
$call = (is_dir($location . $file)) ? 'addDir' : 'addFile';
call_user_func(array($this, $call), $location . $file, $name . $file);
}
}