2014-05-14 23:24:20 +10:00
|
|
|
<?php namespace Cms\Classes;
|
|
|
|
|
2015-06-25 19:26:47 +10:00
|
|
|
use Lang;
|
2020-10-12 13:35:33 -04:00
|
|
|
use BackendAuth;
|
2015-06-25 19:26:47 +10:00
|
|
|
use ApplicationException;
|
2017-05-04 14:53:19 +02:00
|
|
|
use October\Rain\Filesystem\Definitions as FileDefinitions;
|
2014-05-14 23:24:20 +10:00
|
|
|
|
|
|
|
/**
|
|
|
|
* The CMS page class.
|
|
|
|
*
|
|
|
|
* @package october\cms
|
|
|
|
* @author Alexey Bobkov, Samuel Georges
|
|
|
|
*/
|
|
|
|
class Page extends CmsCompoundObject
|
|
|
|
{
|
2016-03-12 15:32:16 +11:00
|
|
|
/**
|
|
|
|
* @var string The container name associated with the model, eg: pages.
|
|
|
|
*/
|
|
|
|
protected $dirName = 'pages';
|
|
|
|
|
|
|
|
/**
|
|
|
|
* @var array The attributes that are mass assignable.
|
|
|
|
*/
|
|
|
|
protected $fillable = [
|
|
|
|
'url',
|
2016-03-17 19:25:50 +11:00
|
|
|
'layout',
|
2016-03-12 15:32:16 +11:00
|
|
|
'title',
|
|
|
|
'description',
|
2016-03-17 19:25:50 +11:00
|
|
|
'is_hidden',
|
2016-03-12 15:32:16 +11:00
|
|
|
'meta_title',
|
|
|
|
'meta_description',
|
|
|
|
'markup',
|
|
|
|
'settings',
|
|
|
|
'code'
|
|
|
|
];
|
|
|
|
|
2014-10-16 20:47:23 -07:00
|
|
|
/**
|
2015-06-05 18:07:10 +10:00
|
|
|
* @var array The API bag allows the API handler code to bind arbitrary
|
|
|
|
* data to the page object.
|
2014-10-16 20:47:23 -07:00
|
|
|
*/
|
|
|
|
public $apiBag = [];
|
|
|
|
|
2016-03-17 19:25:50 +11:00
|
|
|
/**
|
|
|
|
* @var array The rules to be applied to the data.
|
|
|
|
*/
|
|
|
|
public $rules = [
|
2014-05-14 23:24:20 +10:00
|
|
|
'title' => 'required',
|
2015-09-22 10:38:35 +10:00
|
|
|
'url' => ['required', 'regex:/^\/[a-z0-9\/\:_\-\*\[\]\+\?\|\.\^\\\$]*$/i']
|
2014-05-14 23:24:20 +10:00
|
|
|
];
|
|
|
|
|
|
|
|
/**
|
|
|
|
* Creates an instance of the object and associates it with a CMS theme.
|
2016-03-17 19:25:50 +11:00
|
|
|
* @param array $attributes
|
2014-05-14 23:24:20 +10:00
|
|
|
*/
|
2016-03-12 15:32:16 +11:00
|
|
|
public function __construct(array $attributes = [])
|
2014-05-14 23:24:20 +10:00
|
|
|
{
|
2016-03-12 15:32:16 +11:00
|
|
|
parent::__construct($attributes);
|
2014-05-14 23:24:20 +10:00
|
|
|
|
2016-03-17 19:25:50 +11:00
|
|
|
$this->customMessages = [
|
2020-03-03 10:38:03 -06:00
|
|
|
'url.regex' => 'cms::lang.page.invalid_url',
|
2014-05-14 23:24:20 +10:00
|
|
|
];
|
|
|
|
}
|
|
|
|
|
|
|
|
/**
|
|
|
|
* Returns name of a PHP class to us a parent for the PHP class created for the object's PHP section.
|
|
|
|
* @return mixed Returns the class name or null.
|
|
|
|
*/
|
2018-10-01 10:29:03 +10:00
|
|
|
public function getCodeClassParent()
|
2014-05-14 23:24:20 +10:00
|
|
|
{
|
2018-03-22 19:55:13 +03:00
|
|
|
return PageCode::class;
|
2014-05-14 23:24:20 +10:00
|
|
|
}
|
|
|
|
|
|
|
|
/**
|
2016-03-20 16:04:27 +11:00
|
|
|
* Returns a list of layouts available in the theme.
|
2014-05-14 23:24:20 +10:00
|
|
|
* This method is used by the form widget.
|
|
|
|
* @return array Returns an array of strings.
|
|
|
|
*/
|
2018-10-01 10:29:03 +10:00
|
|
|
public function getLayoutOptions()
|
2014-05-14 23:24:20 +10:00
|
|
|
{
|
2014-10-11 01:22:03 +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:22:03 +02:00
|
|
|
}
|
2014-05-14 23:24:20 +10:00
|
|
|
|
|
|
|
$layouts = Layout::listInTheme($theme, true);
|
|
|
|
$result = [];
|
|
|
|
$result[null] = Lang::get('cms::lang.page.no_layout');
|
2017-05-04 14:53:19 +02:00
|
|
|
|
2014-05-14 23:24:20 +10:00
|
|
|
foreach ($layouts as $layout) {
|
|
|
|
$baseName = $layout->getBaseFileName();
|
2017-05-04 14:53:19 +02:00
|
|
|
|
2017-05-16 07:38:38 +10:00
|
|
|
if (FileDefinitions::isPathIgnored($baseName)) {
|
2017-05-04 14:53:19 +02:00
|
|
|
continue;
|
|
|
|
}
|
|
|
|
|
2014-05-14 23:24:20 +10:00
|
|
|
$result[$baseName] = strlen($layout->name) ? $layout->name : $baseName;
|
|
|
|
}
|
|
|
|
|
|
|
|
return $result;
|
|
|
|
}
|
2014-07-11 18:50:29 +10:00
|
|
|
|
|
|
|
/**
|
|
|
|
* Helper that returns a nicer list of pages for use in dropdowns.
|
|
|
|
* @return array
|
|
|
|
*/
|
2018-10-01 10:29:03 +10:00
|
|
|
public static function getNameList()
|
2014-07-11 18:50:29 +10:00
|
|
|
{
|
|
|
|
$result = [];
|
|
|
|
$pages = self::sortBy('baseFileName')->all();
|
|
|
|
foreach ($pages as $page) {
|
2018-01-12 09:23:20 +03:00
|
|
|
$result[$page->baseFileName] = $page->title . ' (' . $page->baseFileName . ')';
|
2014-07-11 18:50:29 +10:00
|
|
|
}
|
|
|
|
|
|
|
|
return $result;
|
|
|
|
}
|
|
|
|
|
|
|
|
/**
|
|
|
|
* Helper that makes a URL for a page in the active theme.
|
2014-10-02 15:55:55 -07:00
|
|
|
* @param mixed $page Specifies the Cms Page file name.
|
2015-03-11 19:15:54 +11:00
|
|
|
* @param array $params Route parameters to consider in the URL.
|
2014-07-11 18:50:29 +10:00
|
|
|
* @return string
|
|
|
|
*/
|
2018-10-01 10:29:03 +10:00
|
|
|
public static function url($page, array $params = [])
|
2014-07-11 18:50:29 +10:00
|
|
|
{
|
2014-09-27 23:28:38 -07:00
|
|
|
/*
|
2014-11-19 17:46:26 +11:00
|
|
|
* Reuse existing controller or create a new one,
|
2014-09-27 23:28:38 -07:00
|
|
|
* assuming that the method is called not during the front-end
|
|
|
|
* request processing.
|
|
|
|
*/
|
2015-03-25 19:34:09 +11:00
|
|
|
$controller = Controller::getController() ?: new Controller;
|
2014-09-27 23:28:38 -07:00
|
|
|
|
2015-03-11 19:15:54 +11:00
|
|
|
return $controller->pageUrl($page, $params, true);
|
2014-07-11 18:50:29 +10:00
|
|
|
}
|
2014-10-02 15:55:55 -07:00
|
|
|
|
|
|
|
/**
|
|
|
|
* Handler for the pages.menuitem.getTypeInfo event.
|
|
|
|
* Returns a menu item type information. The type information is returned as array
|
|
|
|
* with the following elements:
|
|
|
|
* - references - a list of the item type reference options. The options are returned in the
|
|
|
|
* ["key"] => "title" format for options that don't have sub-options, and in the format
|
|
|
|
* ["key"] => ["title"=>"Option title", "items"=>[...]] for options that have sub-options. Optional,
|
|
|
|
* required only if the menu item type requires references.
|
|
|
|
* - nesting - Boolean value indicating whether the item type supports nested items. Optional,
|
|
|
|
* false if omitted.
|
|
|
|
* - dynamicItems - Boolean value indicating whether the item type could generate new menu items.
|
|
|
|
* Optional, false if omitted.
|
2014-10-11 01:22:03 +02:00
|
|
|
* - cmsPages - a list of CMS pages (objects of the Cms\Classes\Page class), if the item type requires
|
|
|
|
* a CMS page reference to resolve the item URL.
|
2014-10-02 15:55:55 -07:00
|
|
|
* @param string $type Specifies the menu item type
|
|
|
|
* @return array Returns an array
|
|
|
|
*/
|
2018-10-01 10:29:03 +10:00
|
|
|
public static function getMenuTypeInfo(string $type)
|
2014-10-02 15:55:55 -07:00
|
|
|
{
|
|
|
|
$result = [];
|
|
|
|
|
2018-01-12 09:23:20 +03:00
|
|
|
if ($type === 'cms-page') {
|
2014-10-02 15:55:55 -07:00
|
|
|
$theme = Theme::getActiveTheme();
|
|
|
|
$pages = self::listInTheme($theme, true);
|
2017-12-22 00:06:56 +02:00
|
|
|
$references = [];
|
2014-10-02 15:55:55 -07:00
|
|
|
|
2014-10-11 01:22:03 +02:00
|
|
|
foreach ($pages as $page) {
|
2018-01-12 09:23:20 +03:00
|
|
|
$references[$page->getBaseFileName()] = $page->title . ' [' . $page->getBaseFileName() . ']';
|
2014-10-11 01:22:03 +02:00
|
|
|
}
|
2014-10-02 15:55:55 -07:00
|
|
|
|
|
|
|
$result = [
|
2014-10-18 14:32:06 +11:00
|
|
|
'references' => $references,
|
|
|
|
'nesting' => false,
|
2014-10-02 15:55:55 -07:00
|
|
|
'dynamicItems' => false
|
|
|
|
];
|
|
|
|
}
|
|
|
|
|
|
|
|
return $result;
|
|
|
|
}
|
|
|
|
|
|
|
|
/**
|
|
|
|
* Handler for the pages.menuitem.resolveItem event.
|
|
|
|
* Returns information about a menu item. The result is an array
|
|
|
|
* with the following keys:
|
|
|
|
* - url - the menu item URL. Not required for menu item types that return all available records.
|
|
|
|
* The URL should be returned relative to the website root and include the subdirectory, if any.
|
2017-06-02 23:34:50 +10:00
|
|
|
* Use the Url::to() helper to generate the URLs.
|
2017-04-24 13:38:19 +02:00
|
|
|
* - isActive - determines whether the menu item is active. Not required for menu item types that
|
2014-10-02 15:55:55 -07:00
|
|
|
* return all available records.
|
2017-04-24 13:38:19 +02:00
|
|
|
* - items - an array of arrays with the same keys (url, isActive, items) + the title key.
|
2014-10-02 15:55:55 -07:00
|
|
|
* The items array should be added only if the $item's $nesting property value is TRUE.
|
|
|
|
* @param \RainLab\Pages\Classes\MenuItem $item Specifies the menu item.
|
|
|
|
* @param string $url Specifies the current page URL, normalized, in lower case
|
2015-10-16 16:30:26 +02:00
|
|
|
* @param \Cms\Classes\Theme $theme Specifies the current theme.
|
2014-10-02 15:55:55 -07:00
|
|
|
* The URL is specified relative to the website root, it includes the subdirectory name, if any.
|
|
|
|
* @return mixed Returns an array. Returns null if the item cannot be resolved.
|
|
|
|
*/
|
2018-01-12 09:23:20 +03:00
|
|
|
public static function resolveMenuItem($item, string $url, Theme $theme)
|
2014-10-02 15:55:55 -07:00
|
|
|
{
|
|
|
|
$result = null;
|
|
|
|
|
2018-01-12 09:23:20 +03:00
|
|
|
if ($item->type === 'cms-page') {
|
2014-10-11 01:22:03 +02:00
|
|
|
if (!$item->reference) {
|
2014-10-02 15:55:55 -07:00
|
|
|
return;
|
2014-10-11 01:22:03 +02:00
|
|
|
}
|
2014-10-02 15:55:55 -07:00
|
|
|
|
2014-11-19 17:46:26 +11:00
|
|
|
$page = self::loadCached($theme, $item->reference);
|
2020-10-12 13:35:33 -04:00
|
|
|
|
|
|
|
// Remove hidden CMS pages from menus when backend user is logged out
|
|
|
|
if ($page && $page->is_hidden && !BackendAuth::getUser()) {
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
2015-03-25 19:34:09 +11:00
|
|
|
$controller = Controller::getController() ?: new Controller;
|
|
|
|
$pageUrl = $controller->pageUrl($item->reference, [], false);
|
2014-10-02 15:55:55 -07:00
|
|
|
|
|
|
|
$result = [];
|
|
|
|
$result['url'] = $pageUrl;
|
|
|
|
$result['isActive'] = $pageUrl == $url;
|
2014-11-19 17:46:26 +11:00
|
|
|
$result['mtime'] = $page ? $page->mtime : null;
|
2014-10-02 15:55:55 -07:00
|
|
|
}
|
|
|
|
|
|
|
|
return $result;
|
|
|
|
}
|
2015-06-25 19:26:47 +10:00
|
|
|
|
|
|
|
/**
|
|
|
|
* Handler for the backend.richeditor.getTypeInfo event.
|
|
|
|
* Returns a menu item type information. The type information is returned as array
|
|
|
|
* @param string $type Specifies the page link type
|
|
|
|
* @return array
|
|
|
|
*/
|
2018-10-01 10:29:03 +10:00
|
|
|
public static function getRichEditorTypeInfo(string $type)
|
2015-06-25 19:26:47 +10:00
|
|
|
{
|
|
|
|
$result = [];
|
|
|
|
|
2018-01-12 09:23:20 +03:00
|
|
|
if ($type === 'cms-page') {
|
2015-06-25 19:26:47 +10:00
|
|
|
$theme = Theme::getActiveTheme();
|
|
|
|
$pages = self::listInTheme($theme, true);
|
|
|
|
|
|
|
|
foreach ($pages as $page) {
|
|
|
|
$url = self::url($page->getBaseFileName());
|
|
|
|
$result[$url] = $page->title;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
return $result;
|
|
|
|
}
|
2014-05-14 23:24:20 +10:00
|
|
|
}
|