phplibrary/src/Controller/Action.php
2017-05-04 15:51:19 +03:00

380 lines
11 KiB
PHP
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

<?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 = '';
// Для Widgets
public $view = null;
public $childNodes = array();
public $ctrlValues = array();
public $childViews = array();
function __construct() {
}
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);
$assets = Path::join(WWW_PATH, "assets", "css");
$tpl->set('icons', $this->iconPath); // Путь к файлам текущей темы
$tpl->set('media', $this->themePath); // Путь к файлам текущей темы
$tpl->set('assets', $assets);
$tpl->set('script', $this->jsPath); // Путь к файлам скриптов
$tpl->set('template', $path); // Путь к файлам текущего шаблона
$tpl->setAlias(array(
'assets' => $assets,
'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 preprocess(HttpRequest $request)
{
$action = self::ACTION_PREFIX . ucfirst($request->getAction());
if (!method_exists($this, $action)) {
$action = "actionIndex";
}
$view = $this->forward($action, $request);
if ($view instanceof View_View) {
$view->active_module = get_class($this);
$view->module_action = $action;
}
return $view;
}
public function execute(HttpRequest $request)
{
$result = $this->preprocess($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();
}
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 redirect($action) {
header('location: ' . $this->fUrl($action));
exit();
}
}