phplibrary/src/Controller/Component.php

378 lines
12 KiB
PHP

<?php
namespace ctiso\Controller;
use ctiso\HttpRequest,
ctiso\ComponentRequest,
ctiso\Arr,
ctiso\Path,
ctiso\File,
ctiso\Form\Form,
ctiso\View\Composite,
ctiso\Database,
ctiso\Database\PDOStatement,
ctiso\Collection,
ctiso\Registry,
ctiso\Controller\SiteInterface,
PHPTAL,
PHPTAL_PreFilter_Normalize;
class FakeTemplate {
public $_data = [];
public $_name = '';
function __construct($name) {
$this->_name = $name;
}
function __set($key, $value) {
$this->_data[$key] = $value;
}
function execute() {
return json_encode($this->_data);
}
}
/**
* Класс компонента
*/
class Component
{
public $viewPath = array();
public $webPath = array();
public $template = null;
public $templatePath;
public $component_id;
public $component_title;
public $COMPONENTS_WEB;
public $config/*: Registry*/;
public $db/*: Database*/;
public $parameter/*: Collection*/;
public $output = 'html';
public $module;
public $item_module;
public $site;
function before() {
}
static function replaceContent($match) {
return \ctiso\Tales::phptal_component(htmlspecialchars_decode($match[3]));
}
static function applyComponents($text) {
return preg_replace_callback('/<(\w+)(\s+[a-zA-Z\-]+=\"[^\"]*\")*\s+tal:replace="structure\s+component:([^\"]*)"[^>]*>/u', 'ctiso\\Controller\\Component::replaceContent', $text);
}
function execute(HttpRequest $request, $has_id = true) {
$crequest = new ComponentRequest($this->component_id, $request);
$_action = $request->get('action', 'index');
if (is_array($_action)) {
$action = 'action' . ucfirst(Arr::get($_action, $this->component_id, 'index'));
} else {
$action = 'action' . ucfirst($_action);
}
$this->before();
if (method_exists($this, $action)) {
return call_user_func(array($this, $action), $crequest);
} else {
return $this->actionIndex($crequest);
}
}
public function getTemplateName($_registry/*: \ctiso\Settings*/) {
return (isset($_COOKIE['with_template']) && preg_match('/^[\w\d-]{3,20}$/', $_COOKIE['with_template']))
? $_COOKIE['with_template'] : ($_registry ? $_registry->get('site', 'template') : 'modern');
}
public function getView($name)
{
if ($this->output == 'json') {
return new FakeTemplate($name);
}
$config/*: Registry*/ = $this->config;
$default = $config->get('site', 'template');
$template = ($this->template) ? $this->template : $this->getTemplateName($config);
$selected = null;
foreach ($this->viewPath as $index => $viewPath) {
// Загружать шаблон по умолчанию если не найден текущий
$dir = Path::join($this->viewPath[$index], 'templates', $template);
if(is_dir($dir)) {
$tpl = new PHPTAL(Path::join($this->viewPath[$index], 'templates', $template, $name));
$tpl->setPhpCodeDestination(PHPTAL_PHP_CODE_DESTINATION);
$selected = $index;
break;
}
}
if ($selected === null) {
// Последний вариант viewPath, путь к папке компонента
$selected = count($this->viewPath) - 1;
$tpl = new PHPTAL(Path::join($this->viewPath[$selected], 'templates', 'modern', $name));
$tpl->setPhpCodeDestination(PHPTAL_PHP_CODE_DESTINATION);
$template = 'modern';
}
$tpl->stripComments(true);
$tpl->addPreFilter(new PHPTAL_PreFilter_Normalize());
$tpl->set('common', Path::join($this->config->get('system', 'web'), '../', 'common'));
$tpl->set('script', Path::join($this->config->get('system', 'web'), 'js'));
$tpl->set('media', Path::join($this->config->get('system', 'web'), 'templates', $template));
if ($default) {
$tpl->set('site_template', $this->config->get('site', 'web') . '/templates/' . $default);
}
$tpl->set('base', $this->config->get('site', 'web'));
$tpl->set('component_base', $this->webPath[$selected]);
$tpl->set('component', Path::join($this->webPath[$selected], 'templates', $template));
$tpl->set('component_id', $this->component_id);
return $tpl;
}
function _getDefaultPath() {
return $this->viewPath[count($this->viewPath) - 1];
}
public function getTemplatePath($name) {
$registry/*: \ctiso\Settings*/ = $this->config;
// Брать настройки из куков если есть
$template = ($this->template) ? $this->template : $this->getTemplateName($registry);
foreach ($this->viewPath as $index => $viewPath) {
if(is_dir(Path::join($this->viewPath[$index], 'templates', $template))) {
return Path::join($this->viewPath[$index], 'templates', $template, $name);
}
}
return Path::join($this->viewPath[count($this->viewPath) - 1], 'templates', 'modern', $name);
}
public function getTemplateWebPath()
{
return Path::join($this->webPath[count($this->webPath) - 1], 'templates', 'modern');
}
/**
* Создает модель
* @param string $name
* @return model
*/
public function getModel($name)
{
$modelName = "App\\Mapper\\" . $name;
$model = new $modelName();
$model->config = $this->config;
$model->db = $this->db;
return $model;
}
public function options($key, $val, $res/*: PDOStatement*/) {
$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 findFile($pathList, $name) {
foreach($pathList as $item) {
$filename = Path::join($item, $name);
if (file_exists($filename)) {
return $filename;
}
}
return null;
}
function getInfo() {
$filename = Path::join($this->viewPath[count($this->viewPath) - 1], 'install.json');
if (file_exists($filename)) {
$settings = json_decode(File::getContents($filename), true);
return $settings;
}
return array();
}
/**
* Генерация интерфейса для выбора галлереи фотографии
*/
public function setParameters($view/*: Composite*/, $options = null)
{
$form = new Form();
$settings = $this->getInfo();
$form->addFieldList($settings['parameter'], $options);
$view->form = $form;
$view->component = $settings['component'];
$view->component_title = $settings['title'];
}
static function loadComponent($expression, $site/*: SiteInterface*/)
{
$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 ($site->config->get('site', 'components'), $name, $name . '.php');
$className = 'Components\\'. ucfirst($name). '\\' . $name;
$component/*: Component*/ = null;
if (file_exists($path)) {
// require_once ($path);
$component = new $className();
$component->viewPath = array($site->config->get('site', 'path') . '/components/' . $name . '/');
$component->webPath = array($site->config->get('site', 'web') . '/components/' . $name);
$component->COMPONENTS_WEB = $site->config->get('site', 'web') . '/components/';
} else {
$component = new $className();
$template = $component->getTemplateName($site->config);
$component->viewPath = array(
// Сначало ищем локально
$site->config->get('site', 'path') . '/templates/' . $template . '/_components/' . $name . '/',
$site->config->get('site', 'path') . '/components/' . $name . '/',
// Потом в общем хранилище
CMS_PATH . '/../templates/' . $template . '/_components/' . $name . '/',
$site->config->get('system', 'components') . '/' . $name . '/',
);
if (defined('COMPONENTS_WEB')) {
$component->webPath = array(
// Сначало локально
$site->config->get('site', 'web') . '/templates/' . $template . '/_components/' . $name,
$site->config->get('site', 'web') . '/components/' . $name,
// Потом в общем хранилище
TEMPLATE_WEB . '/' . $template . '/_components/' . $name,
COMPONENTS_WEB . '/' . $name,
);
$component->COMPONENTS_WEB = COMPONENTS_WEB;
} else {
$component->webPath = array('', $site->config->get('site', 'web') . '/components/' . $name, '');
}
}
$db = $site->getDatabase();
$component->db = $db;
$component->config = $site->config;
$component->site = $site;
$stmt = $db->prepareStatement("SELECT * FROM component WHERE code = ?");
$stmt->setString(1, $expression);
$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($arguments);
$component->parameter = $params;
$component->template = $params->get('template', false);
$editor = $component->getEditUrl();
if ($editor) {
$site->componentsConfig[] = $editor;
}
return $component;
}
function getEditUrl() {
return null;
}
function raw_query($request/*: ComponentRequest*/)
{
$arr = $request->r->export('get');
$param = array();
$parameter/*: Collection*/ = $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($request/*: ComponentRequest*/, $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) {
$this->site->addRequireJsPath($name, $path, $shim);
}
function actionIndex($request/*: ComponentRequest*/) {
}
}