492 lines
15 KiB
PHP
Raw Normal View History

2014-05-14 23:24:20 +10:00
<?php namespace Cms\Controllers;
use URL;
use Lang;
use Flash;
use Event;
use Config;
2014-05-14 23:24:20 +10:00
use Request;
use Response;
use Exception;
use BackendMenu;
use Backend\Classes\Controller;
use Backend\Classes\WidgetManager;
use Cms\Widgets\AssetList;
2014-05-14 23:24:20 +10:00
use Cms\Widgets\TemplateList;
use Cms\Widgets\ComponentList;
use Cms\Classes\Page;
use Cms\Classes\Theme;
use Cms\Classes\Router;
2014-05-14 23:24:20 +10:00
use Cms\Classes\Layout;
use Cms\Classes\Partial;
2014-05-14 23:24:20 +10:00
use Cms\Classes\Content;
use Cms\Classes\CmsCompoundObject;
use Cms\Classes\ComponentManager;
use Cms\Classes\ComponentPartial;
2015-01-28 18:03:35 +11:00
use ApplicationException;
2014-05-14 23:24:20 +10:00
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);
2014-05-14 23:24:20 +10:00
try {
2014-10-11 01:27:52 +02:00
if (!($theme = Theme::getEditTheme())) {
2014-05-14 23:24:20 +10:00
throw new ApplicationException(Lang::get('cms::lang.theme.edit.not_found'));
2014-10-11 01:27:52 +02:00
}
2014-05-14 23:24:20 +10:00
$this->theme = $theme;
2014-10-11 01:27:52 +02:00
new TemplateList($this, 'pageList', function () use ($theme) {
2014-05-14 23:24:20 +10:00
return Page::listInTheme($theme, true);
});
2014-10-11 01:27:52 +02:00
new TemplateList($this, 'partialList', function () use ($theme) {
2014-05-14 23:24:20 +10:00
return Partial::listInTheme($theme, true);
});
2014-10-11 01:27:52 +02:00
new TemplateList($this, 'layoutList', function () use ($theme) {
2014-05-14 23:24:20 +10:00
return Layout::listInTheme($theme, true);
});
2014-10-11 01:27:52 +02:00
new TemplateList($this, 'contentList', function () use ($theme) {
2014-05-14 23:24:20 +10:00
return Content::listInTheme($theme, true);
});
new ComponentList($this, 'componentList');
new AssetList($this, 'assetList');
}
catch (Exception $ex) {
2014-05-14 23:24:20 +10:00
$this->handleError($ex);
}
}
//
// Pages
//
2014-05-14 23:24:20 +10:00
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->addCss('/modules/cms/assets/css/october.components.css', 'core');
2014-05-14 23:24:20 +10:00
// Preload the code editor class as it could be needed
// before it loads dynamically.
$this->addJs('/modules/backend/formwidgets/codeeditor/assets/js/build-min.js', 'core');
2014-05-14 23:24:20 +10:00
$this->bodyClass = 'compact-container side-panel-not-fixed';
$this->pageTitle = 'cms::lang.cms.menu_label';
$this->pageTitleTemplate = '%s '.trans($this->pageTitle);
if (Request::ajax() && Request::input('formWidgetAlias')) {
$this->bindFormWidgetToController();
}
2014-05-14 23:24:20 +10:00
}
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),
2014-10-18 15:52:44 +11:00
'tab' => $this->makePartial('form_page', [
2014-05-14 23:24:20 +10:00
'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);
2014-05-14 23:24:20 +10:00
$templateData = [];
2014-10-11 01:27:52 +02:00
if ($settings) {
2014-05-14 23:24:20 +10:00
$templateData['settings'] = $settings;
2014-10-11 01:27:52 +02:00
}
2014-05-14 23:24:20 +10:00
$fields = ['markup', 'code', 'fileName', 'content'];
foreach ($fields as $field) {
2014-10-11 01:27:52 +02:00
if (array_key_exists($field, $_POST)) {
2014-05-14 23:24:20 +10:00
$templateData[$field] = Request::input($field);
2014-10-11 01:27:52 +02:00
}
2014-05-14 23:24:20 +10:00
}
if (!empty($templateData['markup']) && Config::get('cms.convertLineEndings', false) === true) {
2014-05-19 12:58:35 -05:00
$templateData['markup'] = $this->convertLineEndings($templateData['markup']);
}
2014-05-14 23:24:20 +10:00
if (!Request::input('templateForceSave') && $template->mtime) {
2014-10-11 01:27:52 +02:00
if (Request::input('templateMtime') != $template->mtime) {
2014-05-14 23:24:20 +10:00
throw new ApplicationException('mtime-mismatch');
2014-10-11 01:27:52 +02:00
}
2014-05-14 23:24:20 +10:00
}
$template->attributes = [];
2014-05-14 23:24:20 +10:00
$template->fill($templateData);
$template->save();
/*
* Extensibility
*/
Event::fire('cms.template.save', [$this, $template, $type]);
2014-08-19 21:34:59 +10:00
$this->fireEvent('template.save', [$template, $type]);
2014-05-14 23:24:20 +10:00
Flash::success(Lang::get('cms::lang.template.saved'));
$result = [
'templatePath' => $template->fileName,
2014-05-14 23:24:20 +10:00
'templateMtime' => $template->mtime,
'tabTitle' => $this->getTabTitle($type, $template)
2014-05-14 23:24:20 +10:00
];
if ($type == 'page') {
$result['pageUrl'] = URL::to($template->url);
$router = new Router($this->theme);
$router->clearCache();
CmsCompoundObject::clearCache($this->theme);
2014-05-14 23:24:20 +10:00
}
return $result;
}
public function onOpenConcurrencyResolveForm()
{
return $this->makePartial('concurrency_resolve_form');
}
public function onCreateTemplate()
{
$type = Request::input('type');
$template = $this->createTemplate($type);
2014-10-11 01:27:52 +02:00
if ($type == 'asset') {
$template->fileName = $this->widget->assetList->getCurrentRelativePath();
2014-10-11 01:27:52 +02:00
}
2014-05-14 23:24:20 +10:00
$widget = $this->makeTemplateFormWidget($type, $template);
$this->vars['templatePath'] = '';
return [
'tabTitle' => $this->getTabTitle($type, $template),
2014-05-14 23:24:20 +10:00
'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 {
2014-10-11 01:27:52 +02:00
foreach ($templates as $path => $selected) {
2014-05-14 23:24:20 +10:00
if ($selected) {
$this->loadTemplate($type, $path)->delete();
$deleted[] = $path;
}
}
}
catch (Exception $ex) {
2014-05-14 23:24:20 +10:00
$error = $ex->getMessage();
}
/*
* Extensibility
*/
Event::fire('cms.template.delete', [$this, $type]);
2014-08-19 21:34:59 +10:00
$this->fireEvent('template.delete', [$type]);
2014-05-14 23:24:20 +10:00
return [
'deleted' => $deleted,
'error' => $error,
'theme' => Request::input('theme')
];
}
public function onDelete()
{
$this->validateRequestTheme();
2014-07-25 18:11:16 +10:00
$type = Request::input('templateType');
$this->loadTemplate($type, trim(Request::input('templatePath')))->delete();
2014-07-14 02:38:52 +00:00
/*
* Extensibility
*/
Event::fire('cms.template.delete', [$this, $type]);
2014-08-19 21:34:59 +10:00
$this->fireEvent('template.delete', [$type]);
2014-05-14 23:24:20 +10:00
}
public function onGetTemplateList()
{
$this->validateRequestTheme();
$page = Page::inTheme($this->theme);
2014-05-14 23:24:20 +10:00
return [
'layouts' => $page->getLayoutOptions()
];
}
public function onExpandMarkupToken()
{
2014-10-11 01:27:52 +02:00
if (!$alias = post('tokenName')) {
throw new ApplicationException(trans('cms::lang.component.no_records'));
2014-10-11 01:27:52 +02:00
}
// Can only expand components at this stage
2014-10-11 01:27:52 +02:00
if ((!$type = post('tokenType')) && $type != 'component') {
return;
2014-10-11 01:27:52 +02:00
}
2014-10-11 01:27:52 +02:00
if (!($names = (array) post('component_names')) || !($aliases = (array) post('component_aliases'))) {
throw new ApplicationException(trans('cms::lang.component.not_found', ['name' => $alias]));
2014-10-11 01:27:52 +02:00
}
2014-10-11 01:27:52 +02:00
if (($index = array_get(array_flip($aliases), $alias, false)) === false) {
throw new ApplicationException(trans('cms::lang.component.not_found', ['name' => $alias]));
2014-10-11 01:27:52 +02:00
}
2014-10-11 01:27:52 +02:00
if (!$componentName = array_get($names, $index)) {
throw new ApplicationException(trans('cms::lang.component.not_found', ['name' => $alias]));
2014-10-11 01:27:52 +02:00
}
$manager = ComponentManager::instance();
$componentObj = $manager->makeComponent($componentName);
$partial = ComponentPartial::load($componentObj, 'default');
$content = $partial->getContent();
$content = str_replace('__SELF__', $alias, $content);
return $content;
}
2014-05-14 23:24:20 +10:00
//
// Methods for the internal use
//
protected function validateRequestTheme()
{
2014-10-11 01:27:52 +02:00
if ($this->theme->getDirName() != Request::input('theme')) {
2014-05-14 23:24:20 +10:00
throw new ApplicationException(trans('cms::lang.theme.edit.not_match'));
2014-10-11 01:27:52 +02:00
}
2014-05-14 23:24:20 +10:00
}
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'
2014-05-14 23:24:20 +10:00
];
2014-10-11 01:27:52 +02:00
if (!array_key_exists($type, $types)) {
2014-05-14 23:24:20 +10:00
throw new ApplicationException(trans('cms::lang.template.invalid_type'));
2014-10-11 01:27:52 +02:00
}
2014-05-14 23:24:20 +10:00
return $types[$type];
}
protected function loadTemplate($type, $path)
{
$class = $this->resolveTypeClassName($type);
2016-03-29 14:55:25 +02:00
if (!($template = call_user_func([$class, 'load'], $this->theme, $path))) {
2014-05-14 23:24:20 +10:00
throw new ApplicationException(trans('cms::lang.template.not_found'));
2014-10-11 01:27:52 +02:00
}
2014-05-14 23:24:20 +10:00
Event::fire('cms.template.processSettingsAfterLoad', [$this, $template]);
2014-05-14 23:24:20 +10:00
return $template;
}
protected function createTemplate($type)
{
$class = $this->resolveTypeClassName($type);
if (!($template = $class::inTheme($this->theme))) {
2014-05-14 23:24:20 +10:00
throw new ApplicationException(trans('cms::lang.template.not_found'));
2014-10-11 01:27:52 +02:00
}
2014-05-14 23:24:20 +10:00
return $template;
}
protected function getTabTitle($type, $template)
{
if ($type == 'page') {
$result = $template->title ?: $template->getFileName();
2014-10-11 01:27:52 +02:00
if (!$result) {
2014-05-14 23:24:20 +10:00
$result = trans('cms::lang.page.new');
2014-10-11 01:27:52 +02:00
}
2014-05-14 23:24:20 +10:00
return $result;
}
if ($type == 'partial' || $type == 'layout' || $type == 'content' || $type == 'asset') {
$result = in_array($type, ['asset', 'content']) ? $template->getFileName() : $template->getBaseFileName();
2014-10-11 01:27:52 +02:00
if (!$result) {
2014-05-14 23:24:20 +10:00
$result = trans('cms::lang.'.$type.'.new');
2014-10-11 01:27:52 +02:00
}
2014-05-14 23:24:20 +10:00
return $result;
}
return $template->getFileName();
}
protected function makeTemplateFormWidget($type, $template, $alias = null)
2014-05-14 23:24:20 +10:00
{
$formConfigs = [
2015-02-07 16:20:34 +11:00
'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'
2014-05-14 23:24:20 +10:00
];
2014-10-11 01:27:52 +02:00
if (!array_key_exists($type, $formConfigs)) {
2014-05-14 23:24:20 +10:00
throw new ApplicationException(trans('cms::lang.template.not_found'));
2014-10-11 01:27:52 +02:00
}
2014-05-14 23:24:20 +10:00
$widgetConfig = $this->makeConfig($formConfigs[$type]);
$widgetConfig->model = $template;
$widgetConfig->alias = $alias ?: 'form'.studly_case($type).md5($template->getFileName()).uniqid();
2014-05-14 23:24:20 +10:00
$widget = $this->makeWidget('Backend\Widgets\Form', $widgetConfig);
return $widget;
}
protected function upgradeSettings($settings)
{
/*
* Handle component usage
*/
$componentProperties = post('component_properties');
$componentNames = post('component_names');
$componentAliases = post('component_aliases');
2014-05-14 23:24:20 +10:00
if ($componentProperties !== null) {
if ($componentNames === null || $componentAliases === null) {
throw new ApplicationException(trans('cms::lang.component.invalid_request'));
}
2014-05-14 23:24:20 +10:00
$count = count($componentProperties);
if (count($componentNames) != $count || count($componentAliases) != $count) {
throw new ApplicationException(trans('cms::lang.component.invalid_request'));
}
2014-05-14 23:24:20 +10:00
for ($index = 0; $index < $count; $index++) {
$componentName = $componentNames[$index];
$componentAlias = $componentAliases[$index];
2014-05-14 23:24:20 +10:00
$section = $componentName;
if ($componentAlias != $componentName) {
$section .= ' '.$componentAlias;
}
2014-05-14 23:24:20 +10:00
$properties = json_decode($componentProperties[$index], true);
2015-09-26 08:01:08 +10:00
unset($properties['oc.alias']);
unset($properties['inspectorProperty']);
unset($properties['inspectorClassName']);
$settings[$section] = $properties;
}
2014-05-14 23:24:20 +10:00
}
/*
* Handle view bag
*/
$viewBag = post('viewBag');
if ($viewBag !== null) {
$settings['viewBag'] = $viewBag;
}
/*
* Extensibility
*/
$dataHolder = (object)[
'settings' => $settings
];
Event::fire('cms.template.processSettingsBeforeSave', [$this, $dataHolder]);
return $dataHolder->settings;
2014-05-14 23:24:20 +10:00
}
protected function bindFormWidgetToController()
{
$alias = Request::input('formWidgetAlias');
$type = Request::input('templateType');
$object = $this->loadTemplate($type, Request::input('templatePath'));
$widget = $this->makeTemplateFormWidget($type, $object, $alias);
$widget->bindToController();
}
2014-05-19 12:58:35 -05:00
/**
2014-05-20 10:25:04 +10:00
* Replaces Windows style (/r/n) line endings with unix style (/n)
2014-05-19 12:58:35 -05:00
* line endings.
* @param string $markup The markup to convert to unix style endings
2014-05-20 10:25:04 +10:00
* @return string
2014-05-19 12:58:35 -05:00
*/
2014-08-01 18:18:09 +10:00
protected function convertLineEndings($markup)
2014-05-19 12:58:35 -05:00
{
$markup = str_replace("\r\n", "\n", $markup);
$markup = str_replace("\r", "\n", $markup);
return $markup;
}
}