/modules/cms/controllers/Index.php
PHP | 458 lines | 336 code | 89 blank | 33 comment | 52 complexity | ff33fb412a9b77022c55e67369ff3939 MD5 | raw file
- <?php namespace Cms\Controllers;
- use URL;
- use Lang;
- use Flash;
- use Event;
- use Config;
- use Request;
- use Response;
- use Exception;
- use BackendMenu;
- use Backend\Classes\Controller;
- use Backend\Classes\WidgetManager;
- use Cms\Widgets\AssetList;
- use Cms\Widgets\TemplateList;
- use Cms\Widgets\ComponentList;
- use Cms\Classes\Page;
- use Cms\Classes\Theme;
- use Cms\Classes\Router;
- use Cms\Classes\Layout;
- use Cms\Classes\Partial;
- use Cms\Classes\Content;
- use Cms\Classes\CmsCompoundObject;
- use Cms\Classes\ComponentManager;
- use Cms\Classes\ComponentPartial;
- use System\Classes\ApplicationException;
- use Backend\Traits\InspectableContainer;
- use October\Rain\Router\Router as RainRouter;
- /**
- * CMS index
- *
- * @package october\cms
- * @author Alexey Bobkov, Samuel Georges
- */
- class Index extends Controller
- {
- use InspectableContainer;
- protected $theme;
- public $requiredPermissions = ['cms.*'];
- /**
- * Constructor.
- */
- public function __construct()
- {
- parent::__construct();
- BackendMenu::setContext('October.Cms', 'cms', true);
- try {
- if (!($theme = Theme::getEditTheme())) {
- throw new ApplicationException(Lang::get('cms::lang.theme.edit.not_found'));
- }
- $this->theme = $theme;
- new TemplateList($this, 'pageList', function () use ($theme) {
- return Page::listInTheme($theme, true);
- });
- new TemplateList($this, 'partialList', function () use ($theme) {
- return Partial::listInTheme($theme, true);
- });
- new TemplateList($this, 'layoutList', function () use ($theme) {
- return Layout::listInTheme($theme, true);
- });
- new TemplateList($this, 'contentList', function () use ($theme) {
- return Content::listInTheme($theme, true);
- });
- new ComponentList($this, 'componentList');
- new AssetList($this, 'assetList');
- }
- catch (Exception $ex) {
- $this->handleError($ex);
- }
- }
- //
- // Pages
- //
- public function index()
- {
- $this->addJs('/modules/cms/assets/js/october.cmspage.js', 'core');
- $this->addJs('/modules/cms/assets/js/october.dragcomponents.js', 'core');
- $this->addJs('/modules/cms/assets/js/october.tokenexpander.js', 'core');
- $this->addJs('/modules/backend/formwidgets/codeeditor/assets/js/codeeditor.js', 'core');
- $this->addCss('/modules/cms/assets/css/october.components.css', 'core');
- // Preload Ace editor modes explicitly, because they could be changed dynamically
- // depending on a content block type
- $this->addJs('/modules/backend/formwidgets/codeeditor/assets/vendor/ace/ace.js', 'core');
- $aceModes = ['markdown', 'plain_text', 'html', 'less', 'css', 'scss', 'sass', 'javascript'];
- foreach ($aceModes as $mode) {
- $this->addJs('/modules/backend/formwidgets/codeeditor/assets/vendor/ace/mode-'.$mode.'.js', 'core');
- }
- $this->bodyClass = 'compact-container side-panel-not-fixed';
- $this->pageTitle = 'cms::lang.cms.menu_label';
- $this->pageTitleTemplate = '%s CMS';
- }
- public function index_onOpenTemplate()
- {
- $this->validateRequestTheme();
- $type = Request::input('type');
- $template = $this->loadTemplate($type, Request::input('path'));
- $widget = $this->makeTemplateFormWidget($type, $template);
- $this->vars['templatePath'] = Request::input('path');
- if ($type == 'page') {
- $router = new RainRouter;
- $this->vars['pageUrl'] = $router->urlFromPattern($template->url);
- }
- return [
- 'tabTitle' => $this->getTabTitle($type, $template),
- 'tab' => $this->makePartial('form_page', [
- 'form' => $widget,
- 'templateType' => $type,
- 'templateTheme' => $this->theme->getDirName(),
- 'templateMtime' => $template->mtime
- ])
- ];
- }
- public function onSave()
- {
- $this->validateRequestTheme();
- $type = Request::input('templateType');
- $templatePath = trim(Request::input('templatePath'));
- $template = $templatePath ? $this->loadTemplate($type, $templatePath) : $this->createTemplate($type);
- $settings = Request::input('settings') ?: [];
- $settings = $this->upgradeSettings($settings);
- $templateData = [];
- if ($settings) {
- $templateData['settings'] = $settings;
- }
- $fields = ['markup', 'code', 'fileName', 'content'];
- foreach ($fields as $field) {
- if (array_key_exists($field, $_POST)) {
- $templateData[$field] = Request::input($field);
- }
- }
- if (!empty($templateData['markup']) && Config::get('cms.convertLineEndings', false) === true) {
- $templateData['markup'] = $this->convertLineEndings($templateData['markup']);
- }
- if (!Request::input('templateForceSave') && $template->mtime) {
- if (Request::input('templateMtime') != $template->mtime) {
- throw new ApplicationException('mtime-mismatch');
- }
- }
- $template->fill($templateData);
- $template->save();
- /*
- * Extensibility
- */
- Event::fire('cms.template.save', [$this, $template, $type]);
- $this->fireEvent('template.save', [$template, $type]);
- Flash::success(Lang::get('cms::lang.template.saved'));
- $result = [
- 'templatePath' => $template->fileName,
- 'templateMtime' => $template->mtime,
- 'tabTitle' => $this->getTabTitle($type, $template)
- ];
- if ($type == 'page') {
- $result['pageUrl'] = URL::to($template->url);
- $router = new Router($this->theme);
- $router->clearCache();
- CmsCompoundObject::clearCache($this->theme);
- }
- return $result;
- }
- public function onOpenConcurrencyResolveForm()
- {
- return $this->makePartial('concurrency_resolve_form');
- }
- public function onCreateTemplate()
- {
- $type = Request::input('type');
- $template = $this->createTemplate($type);
- if ($type == 'asset') {
- $template->setInitialPath($this->widget->assetList->getCurrentRelativePath());
- }
- $widget = $this->makeTemplateFormWidget($type, $template);
- $this->vars['templatePath'] = '';
- return [
- 'tabTitle' => $this->getTabTitle($type, $template),
- 'tab' => $this->makePartial('form_page', [
- 'form' => $widget,
- 'templateType' => $type,
- 'templateTheme' => $this->theme->getDirName(),
- 'templateMtime' => null
- ])
- ];
- }
- public function onDeleteTemplates()
- {
- $this->validateRequestTheme();
- $type = Request::input('type');
- $templates = Request::input('template');
- $error = null;
- $deleted = [];
- try {
- foreach ($templates as $path => $selected) {
- if ($selected) {
- $this->loadTemplate($type, $path)->delete();
- $deleted[] = $path;
- }
- }
- }
- catch (Exception $ex) {
- $error = $ex->getMessage();
- }
- /*
- * Extensibility
- */
- Event::fire('cms.template.delete', [$this, $type]);
- $this->fireEvent('template.delete', [$type]);
- return [
- 'deleted' => $deleted,
- 'error' => $error,
- 'theme' => Request::input('theme')
- ];
- }
- public function onDelete()
- {
- $this->validateRequestTheme();
- $type = Request::input('templateType');
- $this->loadTemplate($type, trim(Request::input('templatePath')))->delete();
- /*
- * Extensibility
- */
- Event::fire('cms.template.delete', [$this, $type]);
- $this->fireEvent('template.delete', [$type]);
- }
- public function onGetTemplateList()
- {
- $this->validateRequestTheme();
- $page = new Page($this->theme);
- return [
- 'layouts' => $page->getLayoutOptions()
- ];
- }
- public function onExpandMarkupToken()
- {
- if (!$alias = post('tokenName')) {
- throw new ApplicationException(trans('cms::lang.component.no_records'));
- }
- // Can only expand components at this stage
- if ((!$type = post('tokenType')) && $type != 'component') {
- return;
- }
- if (!($names = (array) post('component_names')) || !($aliases = (array) post('component_aliases'))) {
- throw new ApplicationException(trans('cms::lang.component.not_found', ['name' => $alias]));
- }
- if (($index = array_get(array_flip($aliases), $alias, false)) === false) {
- throw new ApplicationException(trans('cms::lang.component.not_found', ['name' => $alias]));
- }
- if (!$componentName = array_get($names, $index)) {
- throw new ApplicationException(trans('cms::lang.component.not_found', ['name' => $alias]));
- }
- $manager = ComponentManager::instance();
- $componentObj = $manager->makeComponent($componentName);
- $partial = ComponentPartial::load($componentObj, 'default');
- $content = $partial->getContent();
- $content = str_replace('__SELF__', $alias, $content);
- return $content;
- }
- //
- // Methods for the internal use
- //
- protected function validateRequestTheme()
- {
- if ($this->theme->getDirName() != Request::input('theme')) {
- throw new ApplicationException(trans('cms::lang.theme.edit.not_match'));
- }
- }
- protected function resolveTypeClassName($type)
- {
- $types = [
- 'page' => '\Cms\Classes\Page',
- 'partial' => '\Cms\Classes\Partial',
- 'layout' => '\Cms\Classes\Layout',
- 'content' => '\Cms\Classes\Content',
- 'asset' => '\Cms\Classes\Asset',
- ];
- if (!array_key_exists($type, $types)) {
- throw new ApplicationException(trans('cms::lang.template.invalid_type'));
- }
- return $types[$type];
- }
- protected function loadTemplate($type, $path)
- {
- $class = $this->resolveTypeClassName($type);
- if (!($template = call_user_func(array($class, 'load'), $this->theme, $path))) {
- throw new ApplicationException(trans('cms::lang.template.not_found'));
- }
- return $template;
- }
- protected function createTemplate($type)
- {
- $class = $this->resolveTypeClassName($type);
- if (!($template = new $class($this->theme))) {
- throw new ApplicationException(trans('cms::lang.template.not_found'));
- }
- return $template;
- }
- protected function getTabTitle($type, $template)
- {
- if ($type == 'page') {
- $result = $template->title ?: $template->getFileName();
- if (!$result) {
- $result = trans('cms::lang.page.new');
- }
- return $result;
- }
- if ($type == 'partial' || $type == 'layout' || $type == 'content' || $type == 'asset') {
- $result = in_array($type, ['asset', 'content']) ? $template->getFileName() : $template->getBaseFileName();
- if (!$result) {
- $result = trans('cms::lang.'.$type.'.new');
- }
- return $result;
- }
- return $template->getFileName();
- }
- protected function makeTemplateFormWidget($type, $template)
- {
- $formConfigs = [
- 'page' => '@/modules/cms/classes/page/fields.yaml',
- 'partial' => '@/modules/cms/classes/partial/fields.yaml',
- 'layout' => '@/modules/cms/classes/layout/fields.yaml',
- 'content' => '@/modules/cms/classes/content/fields.yaml',
- 'asset' => '@/modules/cms/classes/asset/fields.yaml',
- ];
- if (!array_key_exists($type, $formConfigs)) {
- throw new ApplicationException(trans('cms::lang.template.not_found'));
- }
- $widgetConfig = $this->makeConfig($formConfigs[$type]);
- $widgetConfig->model = $template;
- $widgetConfig->alias = 'form'.studly_case($type).md5($template->getFileName()).uniqid();
- $widget = $this->makeWidget('Backend\Widgets\Form', $widgetConfig);
- return $widget;
- }
- protected function upgradeSettings($settings)
- {
- if (!array_key_exists('component_properties', $_POST)) {
- return $settings;
- }
- if (!array_key_exists('component_names', $_POST) || !array_key_exists('component_aliases', $_POST)) {
- throw new ApplicationException(trans('cms::lang.component.invalid_request'));
- }
- $count = count($_POST['component_properties']);
- if (count($_POST['component_names']) != $count || count($_POST['component_aliases']) != $count) {
- throw new ApplicationException(trans('cms::lang.component.invalid_request'));
- }
- for ($index = 0; $index < $count; $index ++) {
- $componentName = $_POST['component_names'][$index];
- $componentAlias = $_POST['component_aliases'][$index];
- $section = $componentName;
- if ($componentAlias != $componentName) {
- $section .= ' '.$componentAlias;
- }
- $properties = json_decode($_POST['component_properties'][$index], true);
- unset($properties['oc.alias']);
- unset($properties['inspectorProperty']);
- unset($properties['inspectorClassName']);
- $settings[$section] = $properties;
- }
- return $settings;
- }
- /**
- * Replaces Windows style (/r/n) line endings with unix style (/n)
- * line endings.
- * @param string $markup The markup to convert to unix style endings
- * @return string
- */
- protected function convertLineEndings($markup)
- {
- $markup = str_replace("\r\n", "\n", $markup);
- $markup = str_replace("\r", "\n", $markup);
- return $markup;
- }
- }