_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) { } }