phplibrary/src/Controller/Component.php

428 lines
13 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
namespace ctiso\Controller;
use ctiso\HttpRequest;
use ctiso\ComponentRequest;
use ctiso\Arr;
use ctiso\Path;
use ctiso\File;
use ctiso\Form\Form;
use ctiso\View\Composite;
use ctiso\Database;
use ctiso\Collection;
use ctiso\Registry;
use ctiso\Controller\SiteInterface;
use PHPTAL;
use 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 = [];
public $webPath = [];
public $template = null;
public string $templatePath;
public $component_id;
public $component_title;
public $COMPONENTS_WEB;
public Registry $config;
public Database $db;
public Collection $parameter;
public $output = 'html';
public $module;
public $item_module;
/**
* @var SiteInterface $site
*/
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([$this, $action], $crequest);
} else {
return $this->actionIndex($crequest);
}
}
/**
* Получить имя шаблона
* @param Registry $_registry
*/
public function getTemplateName($_registry) {
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);
}
/* @var Registry $config */
$config = $this->config;
$default = $config->get('site', 'template');
$template = ($this->template) ? $this->template : $this->getTemplateName($config);
$selected = null;
$tpl = 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', 'templates.web'), $template));
if ($default) {
$tpl->set('site_template', Path::join($this->config->get('site', 'templates.web'), $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 = $this->config;
// Брать настройки из куков если есть
$template = ($this->template) ? $this->template : $this->getTemplateName($registry);
foreach ($this->viewPath as $index => $_) {
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 mixed
*/
public function getModel($name)
{
$modelName = "App\\Mapper\\" . $name;
$model = new $modelName();
$model->config = $this->config;
$model->db = $this->db;
return $model;
}
/**
* @param string $key
* @param string $val
* @param $res
*/
public function options(string $key, string $val, $res) {
$result = [];
while($res->next()) {
$result[] = ['value' => $res->getString($key), 'name' => $res->getString($val)];
}
return $result;
}
public function optionsPair(array $list, $selected = false) {
$result = [];
foreach ($list as $key => $value) {
$result [] = ['value' => $key, 'name' => $value, 'selected' => $key == $selected];
}
return $result;
}
/**
* Найти файл по пути
* @param string[] $pathList
* @param string $name
* @return string|null
*/
function findFile(array $pathList, string $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);
if ($settings) {
return $settings;
}
}
return ['parameter' => []];
}
/**
* Генерация интерфейса для выбора галлереи фотографии
* @param Composite $view
* @param \ctiso\Form\OptionsFactory $options
*/
public function setParameters(Composite $view, $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'];
}
public function getFields($options = null) {
$form = new Form();
$form->addFieldList($this->getInfo()['parameter'], $options);
return $form->field;
}
/**
* Обьеденить с ComponentFactory
* @param string $expression
* @param SiteInterface $site
* @return Component
*/
static function loadComponent(string $expression, $site)
{
$expression = htmlspecialchars_decode($expression);
$offset = strpos($expression, '?');
$url = parse_url($expression);
$arguments = [];
$path = $expression;
if (is_int($offset)) {
$path = substr($expression, 0, $offset);
$query = substr($expression, $offset + 1);
parse_str($query, $arguments);
}
$name = $path;
$config = $site->getConfig();
$filename = ucfirst($name);
$path = Path::join ($config->get('site', 'components'), $name, $filename . '.php');
$className = implode("\\", ['Components', ucfirst($name), $filename]);
/**
* @var ?Component $component
*/
$component = null;
if (file_exists($path)) {
$component = new $className();
$component->viewPath = [$config->get('site', 'components') . '/' . $name . '/'];
$component->webPath = [$config->get('site', 'components.web') . '/' . $name];
$component->COMPONENTS_WEB = $config->get('site', 'web') . '/components/';
} else {
$component = new $className();
$template = $component->getTemplateName($site->getConfig());
$component->viewPath = [
// Сначало ищем локально
$config->get('site', 'templates') . '/'. $template . '/_components/' . $name . '/',
$config->get('site', 'components') . '/' . $name . '/',
// Потом в общем хранилище
$config->get('system', 'templates'). '/' . $template . '/_components/' . $name . '/',
$config->get('system', 'components') . '/' . $name . '/',
];
if (defined('COMPONENTS_WEB')) {
$component->webPath = [
// Сначало локально
$config->get('site', 'templates.web') . '/' . $template . '/_components/' . $name,
$config->get('site', 'components.web') . '/' . $name,
// Потом в общем хранилище
$config->get('system', 'templates.web') . '/' . $template . '/_components/' . $name,
$config->get('system', 'components.web') . '/' . $name,
];
$component->COMPONENTS_WEB = $config->get('system', 'components.web');
} else {
$component->webPath = ['', $config->get('site', 'components.web') . '/' . $name, '', ''];
}
}
// Вынести в отдельную функцию
$db = $site->getDatabase();
$component->db = $db;
$component->config = $site->getConfig();
$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();
$result = null;
if ($last->isBeforeInsert()) {
$result = $last->getId('component_id_component_seq');
$stmt = $db->prepareStatement("INSERT INTO component (id_component, code) VALUES ($result, ?)");
$stmt->setString(1, $expression);
$stmt->executeQuery();
}
if ($last->isAfterInsert()) {
$stmt = $db->prepareStatement("INSERT INTO component (code) VALUES (?)");
$stmt->setString(1, $expression);
$stmt->executeQuery();
$result = $last->getId('component_id_component_seq');
}
$component->component_id = $result;
}
$params = new Collection();
$params->import(array_merge($_GET, $arguments));
$component->parameter = $params;
$component->template = $params->get('template', false);
$editor = $component->getEditUrl();
if ($editor) {
$site->addComponentConfig($editor);
}
return $component;
}
function getEditUrl() {
return null;
}
/**
* @param ComponentRequest $request
*/
function raw_query($request)
{
$arr = $request->r->export('get');
$param = [];
$parameter = $this->parameter;
foreach($parameter->export() as $key => $value) {
$param[$key] = $value;
}
$data = [];
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;
}
/**
* @param ComponentRequest $request
*/
function query($request, $list)
{
$arr = $request->r->export('get');
foreach($list as $key => $val) {
$arr[$key] [$this->component_id] = $val;
}
unset($arr['active_page']);
return '?' . http_build_query($arr);
}
function addRequireJsPath($name, $path, $shim = null) {
$this->site->addRequireJsPath($name, $path, $shim);
}
/**
* @param ComponentRequest $request
*/
function actionIndex($request) {
}
}