mirror of
https://github.com/silverstripe/silverstripe-cms
synced 2024-10-22 08:05:56 +02:00
Compare commits
2 Commits
7221223567
...
cfc479acc0
Author | SHA1 | Date | |
---|---|---|---|
|
cfc479acc0 | ||
|
47dbda8381 |
@ -2,7 +2,6 @@
|
|||||||
|
|
||||||
use SilverStripe\Admin\CMSMenu;
|
use SilverStripe\Admin\CMSMenu;
|
||||||
use SilverStripe\CMS\Controllers\CMSMain;
|
use SilverStripe\CMS\Controllers\CMSMain;
|
||||||
use SilverStripe\CMS\Controllers\CMSPageAddController;
|
|
||||||
use SilverStripe\CMS\Controllers\CMSPageEditController;
|
use SilverStripe\CMS\Controllers\CMSPageEditController;
|
||||||
use SilverStripe\CMS\Controllers\CMSPageSettingsController;
|
use SilverStripe\CMS\Controllers\CMSPageSettingsController;
|
||||||
use SilverStripe\CMS\Model\SiteTree;
|
use SilverStripe\CMS\Model\SiteTree;
|
||||||
@ -35,4 +34,3 @@ ShortcodeParser::get('default')->register(
|
|||||||
CMSMenu::remove_menu_class(CMSMain::class);
|
CMSMenu::remove_menu_class(CMSMain::class);
|
||||||
CMSMenu::remove_menu_class(CMSPageEditController::class);
|
CMSMenu::remove_menu_class(CMSPageEditController::class);
|
||||||
CMSMenu::remove_menu_class(CMSPageSettingsController::class);
|
CMSMenu::remove_menu_class(CMSPageSettingsController::class);
|
||||||
CMSMenu::remove_menu_class(CMSPageAddController::class);
|
|
||||||
|
@ -4,10 +4,10 @@ After:
|
|||||||
- '#corecache'
|
- '#corecache'
|
||||||
---
|
---
|
||||||
SilverStripe\Core\Injector\Injector:
|
SilverStripe\Core\Injector\Injector:
|
||||||
Psr\SimpleCache\CacheInterface.CMSMain_SiteTreeHints:
|
Psr\SimpleCache\CacheInterface.CMSMain_TreeHints:
|
||||||
factory: SilverStripe\Core\Cache\CacheFactory
|
factory: SilverStripe\Core\Cache\CacheFactory
|
||||||
constructor:
|
constructor:
|
||||||
namespace: "CMSMain_SiteTreeHints"
|
namespace: "CMSMain_TreeHints"
|
||||||
Psr\SimpleCache\CacheInterface.SiteTree_CreatableChildren:
|
Psr\SimpleCache\CacheInterface.SiteTree_CreatableChildren:
|
||||||
factory: SilverStripe\Core\Cache\CacheFactory
|
factory: SilverStripe\Core\Cache\CacheFactory
|
||||||
constructor:
|
constructor:
|
||||||
|
@ -13,10 +13,12 @@ use SilverStripe\CMS\BatchActions\CMSBatchAction_Archive;
|
|||||||
use SilverStripe\CMS\BatchActions\CMSBatchAction_Publish;
|
use SilverStripe\CMS\BatchActions\CMSBatchAction_Publish;
|
||||||
use SilverStripe\CMS\BatchActions\CMSBatchAction_Unpublish;
|
use SilverStripe\CMS\BatchActions\CMSBatchAction_Unpublish;
|
||||||
use SilverStripe\CMS\Controllers\CMSSiteTreeFilter_Search;
|
use SilverStripe\CMS\Controllers\CMSSiteTreeFilter_Search;
|
||||||
use SilverStripe\CMS\Model\CurrentPageIdentifier;
|
use SilverStripe\CMS\Forms\CMSMainAddForm;
|
||||||
|
use SilverStripe\CMS\Model\CurrentRecordIdentifier;
|
||||||
use SilverStripe\CMS\Model\RedirectorPage;
|
use SilverStripe\CMS\Model\RedirectorPage;
|
||||||
use SilverStripe\CMS\Model\SiteTree;
|
use SilverStripe\CMS\Model\SiteTree;
|
||||||
use SilverStripe\CMS\Model\VirtualPage;
|
use SilverStripe\CMS\Model\VirtualPage;
|
||||||
|
use SilverStripe\CMS\Search\SearchForm;
|
||||||
use SilverStripe\Control\Controller;
|
use SilverStripe\Control\Controller;
|
||||||
use SilverStripe\Control\Director;
|
use SilverStripe\Control\Director;
|
||||||
use SilverStripe\Control\HTTPRequest;
|
use SilverStripe\Control\HTTPRequest;
|
||||||
@ -25,7 +27,6 @@ use SilverStripe\Control\HTTPResponse_Exception;
|
|||||||
use SilverStripe\Control\PjaxResponseNegotiator;
|
use SilverStripe\Control\PjaxResponseNegotiator;
|
||||||
use SilverStripe\Core\Cache\MemberCacheFlusher;
|
use SilverStripe\Core\Cache\MemberCacheFlusher;
|
||||||
use SilverStripe\Core\Config\Config;
|
use SilverStripe\Core\Config\Config;
|
||||||
use SilverStripe\Core\Convert;
|
|
||||||
use SilverStripe\Core\Environment;
|
use SilverStripe\Core\Environment;
|
||||||
use SilverStripe\Core\Flushable;
|
use SilverStripe\Core\Flushable;
|
||||||
use SilverStripe\Core\Injector\Injector;
|
use SilverStripe\Core\Injector\Injector;
|
||||||
@ -47,10 +48,8 @@ use SilverStripe\Forms\LabelField;
|
|||||||
use SilverStripe\Forms\LiteralField;
|
use SilverStripe\Forms\LiteralField;
|
||||||
use SilverStripe\Forms\Tab;
|
use SilverStripe\Forms\Tab;
|
||||||
use SilverStripe\Forms\TabSet;
|
use SilverStripe\Forms\TabSet;
|
||||||
use SilverStripe\Forms\TextField;
|
|
||||||
use SilverStripe\Model\List\ArrayList;
|
use SilverStripe\Model\List\ArrayList;
|
||||||
use SilverStripe\ORM\CMSPreviewable;
|
use SilverStripe\ORM\CMSPreviewable;
|
||||||
use SilverStripe\ORM\DataList;
|
|
||||||
use SilverStripe\ORM\DataObject;
|
use SilverStripe\ORM\DataObject;
|
||||||
use SilverStripe\ORM\DB;
|
use SilverStripe\ORM\DB;
|
||||||
use SilverStripe\ORM\FieldType\DBHTMLText;
|
use SilverStripe\ORM\FieldType\DBHTMLText;
|
||||||
@ -60,7 +59,6 @@ use SilverStripe\ORM\Hierarchy\MarkedSet;
|
|||||||
use SilverStripe\Model\List\SS_List;
|
use SilverStripe\Model\List\SS_List;
|
||||||
use SilverStripe\Core\Validation\ValidationResult;
|
use SilverStripe\Core\Validation\ValidationResult;
|
||||||
use SilverStripe\Security\InheritedPermissions;
|
use SilverStripe\Security\InheritedPermissions;
|
||||||
use SilverStripe\Security\Member;
|
|
||||||
use SilverStripe\Security\Permission;
|
use SilverStripe\Security\Permission;
|
||||||
use SilverStripe\Security\PermissionProvider;
|
use SilverStripe\Security\PermissionProvider;
|
||||||
use SilverStripe\Security\Security;
|
use SilverStripe\Security\Security;
|
||||||
@ -71,6 +69,7 @@ use SilverStripe\Versioned\ChangeSetItem;
|
|||||||
use SilverStripe\Versioned\Versioned;
|
use SilverStripe\Versioned\Versioned;
|
||||||
use SilverStripe\VersionedAdmin\Controllers\CMSPageHistoryViewerController;
|
use SilverStripe\VersionedAdmin\Controllers\CMSPageHistoryViewerController;
|
||||||
use SilverStripe\Model\ArrayData;
|
use SilverStripe\Model\ArrayData;
|
||||||
|
use SilverStripe\Versioned\RecursivePublishable;
|
||||||
use SilverStripe\View\Requirements;
|
use SilverStripe\View\Requirements;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -78,53 +77,47 @@ use SilverStripe\View\Requirements;
|
|||||||
*
|
*
|
||||||
* This class creates a 2-frame layout - left-tree and right-form - to sit beneath the main
|
* This class creates a 2-frame layout - left-tree and right-form - to sit beneath the main
|
||||||
* admin menu.
|
* admin menu.
|
||||||
*
|
|
||||||
* @mixin LeftAndMainPageIconsExtension
|
|
||||||
*/
|
*/
|
||||||
class CMSMain extends LeftAndMain implements CurrentPageIdentifier, PermissionProvider, Flushable, MemberCacheFlusher
|
class CMSMain extends LeftAndMain implements CurrentRecordIdentifier, PermissionProvider, Flushable, MemberCacheFlusher
|
||||||
{
|
{
|
||||||
/**
|
/**
|
||||||
* Unique ID for page icons CSS block
|
* Unique ID for page icons CSS block
|
||||||
*/
|
*/
|
||||||
const PAGE_ICONS_ID = 'PageIcons';
|
public const PAGE_ICONS_ID = 'PageIcons'; // @TODO AHHHH!!!
|
||||||
|
|
||||||
private static $url_segment = 'pages';
|
private static string $url_segment = 'pages';
|
||||||
|
|
||||||
private static $url_rule = '/$Action/$ID/$OtherID';
|
private static string $url_rule = '/$Action/$ID/$OtherID';
|
||||||
|
|
||||||
// Maintain a lower priority than other administration sections
|
// Maintain a lower priority than other administration sections
|
||||||
// so that Director does not think they are actions of CMSMain
|
// so that Director does not think they are actions of CMSMain
|
||||||
private static $url_priority = 39;
|
private static int $url_priority = 39;
|
||||||
|
|
||||||
private static $menu_title = 'Edit Page';
|
private static $menu_title = 'Pages';
|
||||||
|
|
||||||
private static $menu_icon_class = 'font-icon-sitemap';
|
private static string $menu_icon_class = 'font-icon-sitemap';
|
||||||
|
|
||||||
private static $menu_priority = 10;
|
private static int $menu_priority = 10;
|
||||||
|
|
||||||
private static $tree_class = SiteTree::class;
|
private static string $tree_class = SiteTree::class;
|
||||||
|
|
||||||
private static $session_namespace = CMSMain::class;
|
private static string $session_namespace = CMSMain::class;
|
||||||
|
|
||||||
private static $required_permission_codes = 'CMS_ACCESS_CMSMain';
|
private static string|array $required_permission_codes = 'CMS_ACCESS_CMSMain';
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Should the archive warning message be dynamic based on the specific content? This is slow on larger sites and can be disabled.
|
* Should the archive warning message be dynamic based on the specific content? This is slow on larger sites and can be disabled.
|
||||||
*
|
|
||||||
* @config
|
|
||||||
* @var bool
|
|
||||||
*/
|
*/
|
||||||
private static $enable_dynamic_archive_warning_message = true;
|
private static bool $enable_dynamic_archive_warning_message = true;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Amount of results showing on a single page.
|
* Amount of results showing on a single page.
|
||||||
*
|
|
||||||
* @config
|
|
||||||
* @var int
|
|
||||||
*/
|
*/
|
||||||
private static $page_length = 15;
|
private static int $page_length = 15;
|
||||||
|
|
||||||
private static $allowed_actions = [
|
private static array $allowed_actions = [
|
||||||
|
'add',
|
||||||
|
'AddForm',
|
||||||
'archive',
|
'archive',
|
||||||
'deleteitems',
|
'deleteitems',
|
||||||
'DeleteItemsForm',
|
'DeleteItemsForm',
|
||||||
@ -138,7 +131,7 @@ class CMSMain extends LeftAndMain implements CurrentPageIdentifier, PermissionPr
|
|||||||
'EditForm',
|
'EditForm',
|
||||||
'schema',
|
'schema',
|
||||||
'SearchForm',
|
'SearchForm',
|
||||||
'SiteTreeAsUL',
|
'TreeAsUL',
|
||||||
'getshowdeletedsubtree',
|
'getshowdeletedsubtree',
|
||||||
'savetreenode',
|
'savetreenode',
|
||||||
'getsubtree',
|
'getsubtree',
|
||||||
@ -150,26 +143,26 @@ class CMSMain extends LeftAndMain implements CurrentPageIdentifier, PermissionPr
|
|||||||
'childfilter',
|
'childfilter',
|
||||||
];
|
];
|
||||||
|
|
||||||
private static $url_handlers = [
|
private static array $url_handlers = [
|
||||||
'EditForm/$ID' => 'EditForm',
|
'EditForm/$ID' => 'EditForm',
|
||||||
];
|
];
|
||||||
|
|
||||||
private static $casting = [
|
private static array $casting = [
|
||||||
'TreeIsFiltered' => 'Boolean',
|
'TreeIsFiltered' => 'Boolean',
|
||||||
'AddForm' => 'HTMLFragment',
|
'AddForm' => 'HTMLFragment',
|
||||||
'LinkPages' => 'Text',
|
'LinkRecords' => 'Text',
|
||||||
'Link' => 'Text',
|
'Link' => 'Text',
|
||||||
'ListViewForm' => 'HTMLFragment',
|
'ListViewForm' => 'HTMLFragment',
|
||||||
'ExtraTreeTools' => 'HTMLFragment',
|
'ExtraTreeTools' => 'HTMLFragment',
|
||||||
'PageList' => 'HTMLFragment',
|
'RecordList' => 'HTMLFragment',
|
||||||
'PageListSidebar' => 'HTMLFragment',
|
'RecordListSidebar' => 'HTMLFragment',
|
||||||
'SiteTreeHints' => 'HTMLFragment',
|
'TreeHints' => 'HTMLFragment',
|
||||||
'SecurityID' => 'Text',
|
'SecurityID' => 'Text',
|
||||||
'SiteTreeAsUL' => 'HTMLFragment',
|
'TreeAsUL' => 'HTMLFragment',
|
||||||
];
|
];
|
||||||
|
|
||||||
private static $dependencies = [
|
private static array $dependencies = [
|
||||||
'HintsCache' => '%$' . CacheInterface::class . '.CMSMain_SiteTreeHints',
|
'HintsCache' => '%$' . CacheInterface::class . '.CMSMain_TreeHints',
|
||||||
];
|
];
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -197,7 +190,7 @@ class CMSMain extends LeftAndMain implements CurrentPageIdentifier, PermissionPr
|
|||||||
// In case we're not showing a specific record, explicitly remove any session state,
|
// In case we're not showing a specific record, explicitly remove any session state,
|
||||||
// to avoid it being highlighted in the tree, and causing an edit form to show.
|
// to avoid it being highlighted in the tree, and causing an edit form to show.
|
||||||
if (!$request->param('Action')) {
|
if (!$request->param('Action')) {
|
||||||
$this->setCurrentPageID(null);
|
$this->setCurrentRecordID(null);
|
||||||
}
|
}
|
||||||
|
|
||||||
return parent::index($request);
|
return parent::index($request);
|
||||||
@ -216,51 +209,42 @@ class CMSMain extends LeftAndMain implements CurrentPageIdentifier, PermissionPr
|
|||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Get pages listing area
|
* Get record listing area
|
||||||
*
|
|
||||||
* @return DBHTMLText
|
|
||||||
*/
|
*/
|
||||||
public function PageList()
|
public function RecordList(): DBHTMLText
|
||||||
{
|
{
|
||||||
return $this->renderWith($this->getTemplatesWithSuffix('_PageList'));
|
return $this->renderWith($this->getTemplatesWithSuffix('_RecordList'));
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Page list view for edit-form
|
* Record list view for edit-form
|
||||||
*
|
|
||||||
* @return DBHTMLText
|
|
||||||
*/
|
*/
|
||||||
public function PageListSidebar()
|
public function RecordListSidebar(): DBHTMLText
|
||||||
{
|
{
|
||||||
return $this->renderWith($this->getTemplatesWithSuffix('_PageList_Sidebar'));
|
return $this->renderWith($this->getTemplatesWithSuffix('_RecordList_Sidebar'));
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* If this is set to true, the "switchView" context in the
|
* If this is set to true, the "switchView" context in the
|
||||||
* template is shown, with links to the staging and publish site.
|
* template is shown, with links to the staging and publish site.
|
||||||
*
|
|
||||||
* @return boolean
|
|
||||||
*/
|
*/
|
||||||
public function ShowSwitchView()
|
public function ShowSwitchView(): bool
|
||||||
{
|
{
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Overloads the LeftAndMain::ShowView. Allows to pass a page as a parameter, so we are able
|
* Overloads the LeftAndMain::ShowView. Allows to pass a record as a parameter, so we are able
|
||||||
* to switch view also for archived versions.
|
* to switch view also for archived versions.
|
||||||
*
|
|
||||||
* @param SiteTree $page
|
|
||||||
* @return array
|
|
||||||
*/
|
*/
|
||||||
public function SwitchView($page = null)
|
public function SwitchView(?DataObject $record = null): array
|
||||||
{
|
{
|
||||||
if (!$page) {
|
if (!$record) {
|
||||||
$page = $this->currentPage();
|
$record = $this->currentRecord();
|
||||||
}
|
}
|
||||||
|
|
||||||
if ($page) {
|
if ($record) {
|
||||||
$nav = SilverStripeNavigator::get_for_record($page);
|
$nav = SilverStripeNavigator::get_for_record($record);
|
||||||
return $nav['items'];
|
return $nav['items'];
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -289,14 +273,14 @@ class CMSMain extends LeftAndMain implements CurrentPageIdentifier, PermissionPr
|
|||||||
return $link;
|
return $link;
|
||||||
}
|
}
|
||||||
|
|
||||||
public function LinkPages()
|
public function LinkRecords()
|
||||||
{
|
{
|
||||||
return CMSPagesController::singleton()->Link();
|
return CMSPagesController::singleton()->Link();
|
||||||
}
|
}
|
||||||
|
|
||||||
public function LinkPagesWithSearch()
|
public function LinkRecordsWithSearch()
|
||||||
{
|
{
|
||||||
return $this->LinkWithSearch($this->LinkPages());
|
return $this->LinkWithSearch($this->LinkRecords());
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -306,7 +290,7 @@ class CMSMain extends LeftAndMain implements CurrentPageIdentifier, PermissionPr
|
|||||||
*/
|
*/
|
||||||
public function LinkTreeView()
|
public function LinkTreeView()
|
||||||
{
|
{
|
||||||
// Tree view is just default link to main pages section (no /treeview suffix)
|
// Tree view is just default link to main section (no /treeview suffix)
|
||||||
return CMSMain::singleton()->Link();
|
return CMSMain::singleton()->Link();
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -317,12 +301,12 @@ class CMSMain extends LeftAndMain implements CurrentPageIdentifier, PermissionPr
|
|||||||
*/
|
*/
|
||||||
public function LinkListView()
|
public function LinkListView()
|
||||||
{
|
{
|
||||||
// Note : Force redirect to top level page controller (no parentid)
|
// Note : Force redirect to top level record controller (no parentid)
|
||||||
return $this->LinkWithSearch(CMSMain::singleton()->Link('listview'));
|
return $this->LinkWithSearch(CMSMain::singleton()->Link('listview'));
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Link to list view for children of a parent page
|
* Link to list view for children of a parent record
|
||||||
*
|
*
|
||||||
* @param int|string $parentID Literal parentID, or placeholder (e.g. '%d') for
|
* @param int|string $parentID Literal parentID, or placeholder (e.g. '%d') for
|
||||||
* client side substitution
|
* client side substitution
|
||||||
@ -366,28 +350,31 @@ class CMSMain extends LeftAndMain implements CurrentPageIdentifier, PermissionPr
|
|||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Get the link for editing a page.
|
* Get the link for editing a record.
|
||||||
*
|
*
|
||||||
* @see CMSEditLinkExtension::getCMSEditLinkForManagedDataObject()
|
* @see CMSEditLinkExtension::getCMSEditLinkForManagedDataObject()
|
||||||
*/
|
*/
|
||||||
public function getCMSEditLinkForManagedDataObject(SiteTree $obj): string
|
public function getCMSEditLinkForManagedDataObject(DataObject $obj): string
|
||||||
{
|
{
|
||||||
return Controller::join_links(CMSPageEditController::singleton()->Link('show'), $obj->ID);
|
return Controller::join_links(CMSPageEditController::singleton()->Link('show'), $obj->ID);
|
||||||
}
|
}
|
||||||
|
|
||||||
public function LinkPageEdit($id = null)
|
public function LinkRecordEdit($id = null)
|
||||||
{
|
{
|
||||||
if (!$id) {
|
if (!$id) {
|
||||||
$id = $this->currentPageID();
|
$id = $this->currentRecordID();
|
||||||
}
|
}
|
||||||
return $this->LinkWithSearch(
|
return $this->LinkWithSearch(
|
||||||
Controller::join_links(CMSPageEditController::singleton()->Link('show'), $id)
|
Controller::join_links(CMSPageEditController::singleton()->Link('show'), $id)
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
public function LinkPageSettings()
|
public function LinkRecordSettings()
|
||||||
{
|
{
|
||||||
if ($id = $this->currentPageID()) {
|
if (!DataObject::singleton($this->getModelClass())->hasMethod('getSettingsFields')) { // @TODO This is awful, I'd much rather it just be part of the main form.
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
if ($id = $this->currentRecordID()) {
|
||||||
return $this->LinkWithSearch(
|
return $this->LinkWithSearch(
|
||||||
Controller::join_links(CMSPageSettingsController::singleton()->Link('show'), $id)
|
Controller::join_links(CMSPageSettingsController::singleton()->Link('show'), $id)
|
||||||
);
|
);
|
||||||
@ -396,10 +383,10 @@ class CMSMain extends LeftAndMain implements CurrentPageIdentifier, PermissionPr
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public function LinkPageHistory()
|
public function LinkRecordHistory()
|
||||||
{
|
{
|
||||||
$controller = Injector::inst()->get(CMSPageHistoryViewerController::class);
|
$controller = Injector::inst()->get(CMSPageHistoryViewerController::class);
|
||||||
if (($id = $this->currentPageID()) && $controller) {
|
if (($id = $this->currentRecordID()) && $controller) {
|
||||||
if ($controller) {
|
if ($controller) {
|
||||||
return $this->LinkWithSearch(
|
return $this->LinkWithSearch(
|
||||||
Controller::join_links($controller->Link('show'), $id)
|
Controller::join_links($controller->Link('show'), $id)
|
||||||
@ -463,10 +450,10 @@ class CMSMain extends LeftAndMain implements CurrentPageIdentifier, PermissionPr
|
|||||||
return $link;
|
return $link;
|
||||||
}
|
}
|
||||||
|
|
||||||
public function LinkPageAdd($extra = null, $placeholders = null)
|
public function LinkRecordAdd($extra = null, $placeholders = null)
|
||||||
{
|
{
|
||||||
$link = CMSPageAddController::singleton()->Link();
|
$link = $this->Link('add');
|
||||||
$this->extend('updateLinkPageAdd', $link);
|
$this->extend('updateLinkRecordAdd', $link);
|
||||||
|
|
||||||
if ($extra) {
|
if ($extra) {
|
||||||
$link = Controller::join_links($link, $extra);
|
$link = Controller::join_links($link, $extra);
|
||||||
@ -484,10 +471,10 @@ class CMSMain extends LeftAndMain implements CurrentPageIdentifier, PermissionPr
|
|||||||
*/
|
*/
|
||||||
public function LinkPreview()
|
public function LinkPreview()
|
||||||
{
|
{
|
||||||
$record = $this->getRecord($this->currentPageID());
|
$record = $this->getRecord($this->currentRecordID());
|
||||||
$baseLink = Director::absoluteBaseURL();
|
$baseLink = Director::absoluteBaseURL();
|
||||||
if ($record && $record instanceof SiteTree) {
|
if ($record && $record->hasMethod('Link')) {
|
||||||
// if we are an external redirector don't show a link
|
// if we are an external redirector don't show a link //@TODO generalise this!!!!!
|
||||||
if ($record instanceof RedirectorPage && $record->RedirectionType == 'External') {
|
if ($record instanceof RedirectorPage && $record->RedirectionType == 'External') {
|
||||||
$baseLink = false;
|
$baseLink = false;
|
||||||
} else {
|
} else {
|
||||||
@ -497,12 +484,27 @@ class CMSMain extends LeftAndMain implements CurrentPageIdentifier, PermissionPr
|
|||||||
return $baseLink;
|
return $baseLink;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public function add()
|
||||||
|
{
|
||||||
|
if ($this->getRequest()->isAjax()) {
|
||||||
|
return $this->AddForm()->forTemplate();
|
||||||
|
}
|
||||||
|
return $this->render([
|
||||||
|
'Content' => DBHTMLText::create()->setValue($this->AddForm()->forTemplate()),
|
||||||
|
]);
|
||||||
|
}
|
||||||
|
|
||||||
|
public function AddForm(): Form
|
||||||
|
{
|
||||||
|
return CMSMainAddForm::create($this);
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Return the entire site tree as a nested set of ULs
|
* Return the entire site tree as a nested set of ULs
|
||||||
*/
|
*/
|
||||||
public function SiteTreeAsUL()
|
public function TreeAsUL()
|
||||||
{
|
{
|
||||||
$treeClass = $this->config()->get('tree_class');
|
$treeClass = $this->getModelClass();
|
||||||
$filter = $this->getSearchFilter();
|
$filter = $this->getSearchFilter();
|
||||||
|
|
||||||
DataObject::singleton($treeClass)->prepopulateTreeDataCache(null, [
|
DataObject::singleton($treeClass)->prepopulateTreeDataCache(null, [
|
||||||
@ -510,9 +512,9 @@ class CMSMain extends LeftAndMain implements CurrentPageIdentifier, PermissionPr
|
|||||||
'numChildrenMethod' => $filter ? $filter->getNumChildrenMethod() : 'numChildren',
|
'numChildrenMethod' => $filter ? $filter->getNumChildrenMethod() : 'numChildren',
|
||||||
]);
|
]);
|
||||||
|
|
||||||
$html = $this->getSiteTreeFor($treeClass);
|
$html = $this->getTreeFor($treeClass);
|
||||||
|
|
||||||
$this->extend('updateSiteTreeAsUL', $html);
|
$this->extend('updateTreeAsUL', $html);
|
||||||
|
|
||||||
return $html;
|
return $html;
|
||||||
}
|
}
|
||||||
@ -528,9 +530,9 @@ class CMSMain extends LeftAndMain implements CurrentPageIdentifier, PermissionPr
|
|||||||
* @param string $numChildrenMethod
|
* @param string $numChildrenMethod
|
||||||
* @param callable $filterFunction
|
* @param callable $filterFunction
|
||||||
* @param int $nodeCountThreshold
|
* @param int $nodeCountThreshold
|
||||||
* @return string Nested unordered list with links to each page
|
* @return string Nested unordered list with links to each record
|
||||||
*/
|
*/
|
||||||
public function getSiteTreeFor(
|
public function getTreeFor(
|
||||||
$className,
|
$className,
|
||||||
$rootID = null,
|
$rootID = null,
|
||||||
$childrenMethod = null,
|
$childrenMethod = null,
|
||||||
@ -550,7 +552,7 @@ class CMSMain extends LeftAndMain implements CurrentPageIdentifier, PermissionPr
|
|||||||
}
|
}
|
||||||
if (!$filterFunction) {
|
if (!$filterFunction) {
|
||||||
$filterFunction = function ($node) use ($filter) {
|
$filterFunction = function ($node) use ($filter) {
|
||||||
return $filter->isPageIncluded($node);
|
return $filter->isRecordIncluded($node);
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -568,20 +570,23 @@ class CMSMain extends LeftAndMain implements CurrentPageIdentifier, PermissionPr
|
|||||||
// Mark tree from this node
|
// Mark tree from this node
|
||||||
$markingSet->markPartialTree();
|
$markingSet->markPartialTree();
|
||||||
|
|
||||||
// Ensure current page is exposed
|
// Ensure current record is exposed
|
||||||
$currentPage = $this->currentPage();
|
$currentRecord = $this->currentRecord();
|
||||||
if ($currentPage) {
|
if ($currentRecord) {
|
||||||
$markingSet->markToExpose($currentPage);
|
$markingSet->markToExpose($currentRecord);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Pre-cache permissions
|
// Pre-cache permissions
|
||||||
$checker = SiteTree::getPermissionChecker();
|
$modelClass = $this->getModelClass();
|
||||||
|
$singleton = DataObject::singleton($modelClass);
|
||||||
|
$checker = $singleton->hasMethod('getPermissionChecker') ? $modelClass::getPermissionChecker() : null; // @TODO eww why is it static?
|
||||||
if ($checker instanceof InheritedPermissions) {
|
if ($checker instanceof InheritedPermissions) {
|
||||||
$checker->prePopulatePermissionCache(
|
$checker->prePopulatePermissionCache(
|
||||||
InheritedPermissions::EDIT,
|
InheritedPermissions::EDIT,
|
||||||
$markingSet->markedNodeIDs()
|
$markingSet->markedNodeIDs()
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
// @TODO if we don't have inherited permissions, make sure we still DO do permission checks where needed!!
|
||||||
|
|
||||||
// Render using full-subtree template
|
// Render using full-subtree template
|
||||||
return $markingSet->renderChildren(
|
return $markingSet->renderChildren(
|
||||||
@ -590,7 +595,6 @@ class CMSMain extends LeftAndMain implements CurrentPageIdentifier, PermissionPr
|
|||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Get callback to determine template customisations for nodes
|
* Get callback to determine template customisations for nodes
|
||||||
*
|
*
|
||||||
@ -599,14 +603,14 @@ class CMSMain extends LeftAndMain implements CurrentPageIdentifier, PermissionPr
|
|||||||
protected function getTreeNodeCustomisations()
|
protected function getTreeNodeCustomisations()
|
||||||
{
|
{
|
||||||
$rootTitle = $this->getCMSTreeTitle();
|
$rootTitle = $this->getCMSTreeTitle();
|
||||||
return function (SiteTree $node) use ($rootTitle) {
|
return function (DataObject $node) use ($rootTitle) {
|
||||||
return [
|
return [
|
||||||
'listViewLink' => $this->LinkListViewChildren($node->ID),
|
'listViewLink' => $this->LinkListViewChildren($node->ID),
|
||||||
'rootTitle' => $rootTitle,
|
'rootTitle' => $rootTitle,
|
||||||
'extraClass' => $this->getTreeNodeClasses($node),
|
'extraClass' => $this->getTreeNodeClasses($node),
|
||||||
'Title' => _t(
|
'Title' => _t(
|
||||||
CMSMain::class . '.PAGETYPE_TITLE',
|
CMSMain::class . '.RECORD_TYPE_TITLE',
|
||||||
'(Page type: {type}) {title}',
|
'(Record type: {type}) {title}',
|
||||||
[
|
[
|
||||||
'type' => $node->i18n_singular_name(),
|
'type' => $node->i18n_singular_name(),
|
||||||
'title' => $node->Title,
|
'title' => $node->Title,
|
||||||
@ -617,15 +621,12 @@ class CMSMain extends LeftAndMain implements CurrentPageIdentifier, PermissionPr
|
|||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Get extra CSS classes for a page's tree node
|
* Get extra CSS classes for a record's tree node
|
||||||
*
|
|
||||||
* @param SiteTree $node
|
|
||||||
* @return string
|
|
||||||
*/
|
*/
|
||||||
public function getTreeNodeClasses(SiteTree $node)
|
public function getTreeNodeClasses(DataObject $node): string
|
||||||
{
|
{
|
||||||
// Get classes from object
|
// Get classes from object
|
||||||
$classes = $node->CMSTreeClasses();
|
$classes = $node->CMSTreeClasses(); // @TODO that's obviously not a thing.
|
||||||
|
|
||||||
// Get status flag classes
|
// Get status flag classes
|
||||||
$flags = $node->getStatusFlags();
|
$flags = $node->getStatusFlags();
|
||||||
@ -638,7 +639,7 @@ class CMSMain extends LeftAndMain implements CurrentPageIdentifier, PermissionPr
|
|||||||
|
|
||||||
// Get additional filter classes
|
// Get additional filter classes
|
||||||
$filter = $this->getSearchFilter();
|
$filter = $this->getSearchFilter();
|
||||||
if ($filter && ($filterClasses = $filter->getPageClasses($node))) {
|
if ($filter && ($filterClasses = $filter->getRecordClasses($node))) { // @TODO rename getRecordClasses or similar (though this is probably part of https://github.com/silverstripe/silverstripe-cms/issues/2949)
|
||||||
if (is_array($filterClasses)) {
|
if (is_array($filterClasses)) {
|
||||||
$filterClasses = implode(' ', $filterClasses);
|
$filterClasses = implode(' ', $filterClasses);
|
||||||
}
|
}
|
||||||
@ -654,8 +655,8 @@ class CMSMain extends LeftAndMain implements CurrentPageIdentifier, PermissionPr
|
|||||||
*/
|
*/
|
||||||
public function getsubtree(HTTPRequest $request): HTTPResponse
|
public function getsubtree(HTTPRequest $request): HTTPResponse
|
||||||
{
|
{
|
||||||
$html = $this->getSiteTreeFor(
|
$html = $this->getTreeFor(
|
||||||
$this->config()->get('tree_class'),
|
$this->getModelClass(),
|
||||||
$request->getVar('ID'),
|
$request->getVar('ID'),
|
||||||
null,
|
null,
|
||||||
null,
|
null,
|
||||||
@ -687,7 +688,7 @@ class CMSMain extends LeftAndMain implements CurrentPageIdentifier, PermissionPr
|
|||||||
|
|
||||||
$record = $this->getRecord($id);
|
$record = $this->getRecord($id);
|
||||||
if (!$record) {
|
if (!$record) {
|
||||||
continue; // In case a page is no longer available
|
continue; // In case a record is no longer available
|
||||||
}
|
}
|
||||||
|
|
||||||
// Create marking set with sole marked root
|
// Create marking set with sole marked root
|
||||||
@ -700,7 +701,7 @@ class CMSMain extends LeftAndMain implements CurrentPageIdentifier, PermissionPr
|
|||||||
// Find the next & previous nodes, for proper positioning (Sort isn't good enough - it's not a raw offset)
|
// Find the next & previous nodes, for proper positioning (Sort isn't good enough - it's not a raw offset)
|
||||||
$prev = null;
|
$prev = null;
|
||||||
|
|
||||||
$className = $this->config()->get('tree_class');
|
$className = $this->getModelClass();
|
||||||
$next = DataObject::get($className)
|
$next = DataObject::get($className)
|
||||||
->filter('ParentID', $record->ParentID)
|
->filter('ParentID', $record->ParentID)
|
||||||
->filter('Sort:GreaterThan', $record->Sort)
|
->filter('Sort:GreaterThan', $record->Sort)
|
||||||
@ -750,17 +751,17 @@ class CMSMain extends LeftAndMain implements CurrentPageIdentifier, PermissionPr
|
|||||||
if (!SecurityToken::inst()->checkRequest($request)) {
|
if (!SecurityToken::inst()->checkRequest($request)) {
|
||||||
$this->httpError(400);
|
$this->httpError(400);
|
||||||
}
|
}
|
||||||
if (!$this->CanOrganiseSitetree()) {
|
if (!$this->CanOrganiseTree()) {
|
||||||
$this->httpError(
|
$this->httpError(
|
||||||
403,
|
403,
|
||||||
_t(
|
_t(
|
||||||
__CLASS__.'.CANT_REORGANISE',
|
__CLASS__.'.CANT_REORGANISE2',
|
||||||
"You do not have permission to rearange the site tree. Your change was not saved."
|
"You do not have permission to rearange the tree. Your change was not saved.",
|
||||||
)
|
)
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
$className = $this->config()->get('tree_class');
|
$className = $this->getModelClass();
|
||||||
$id = $request->requestVar('ID');
|
$id = $request->requestVar('ID');
|
||||||
$parentID = $request->requestVar('ParentID');
|
$parentID = $request->requestVar('ParentID');
|
||||||
if (!is_numeric($id) || !is_numeric($parentID)) {
|
if (!is_numeric($id) || !is_numeric($parentID)) {
|
||||||
@ -768,26 +769,25 @@ class CMSMain extends LeftAndMain implements CurrentPageIdentifier, PermissionPr
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Check record exists in the DB
|
// Check record exists in the DB
|
||||||
/** @var SiteTree $node */
|
|
||||||
$node = DataObject::get_by_id($className, $id);
|
$node = DataObject::get_by_id($className, $id);
|
||||||
if (!$node) {
|
if (!$node) {
|
||||||
$this->httpError(
|
$this->httpError(
|
||||||
500,
|
500,
|
||||||
_t(
|
_t(
|
||||||
__CLASS__.'.PLEASESAVE',
|
__CLASS__.'.PLEASESAVE2',
|
||||||
"Please Save Page: This page could not be updated because it hasn't been saved yet."
|
"Please Save Record: This record could not be updated because it hasn't been saved yet."
|
||||||
)
|
)
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Check top level permissions
|
// Check top level permissions
|
||||||
$root = $node->getParentType();
|
$root = $node->getParentType(); // @TODO generalise. POC has `$node->ParentID == 0 ? 'root' : 'subpage';`
|
||||||
if (($parentID == '0' || $root == 'root') && !SiteConfig::current_site_config()->canCreateTopLevel()) {
|
if (($parentID == '0' || $root == 'root') && !SiteConfig::current_site_config()->canCreateTopLevel()) {
|
||||||
$this->httpError(
|
$this->httpError(
|
||||||
403,
|
403,
|
||||||
_t(
|
_t(
|
||||||
__CLASS__.'.CANT_REORGANISE',
|
__CLASS__.'.CANT_REORGANISE_TOPLEVEL',
|
||||||
"You do not have permission to alter Top level pages. Your change was not saved."
|
'You do not have permission to alter Top level records. Your change was not saved.'
|
||||||
)
|
)
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
@ -805,20 +805,20 @@ class CMSMain extends LeftAndMain implements CurrentPageIdentifier, PermissionPr
|
|||||||
$node->write();
|
$node->write();
|
||||||
|
|
||||||
$statusUpdates['modified'][$node->ID] = [
|
$statusUpdates['modified'][$node->ID] = [
|
||||||
'TreeTitle' => $node->TreeTitle
|
'TreeTitle' => $node->TreeTitle // @TODO generalise.
|
||||||
];
|
];
|
||||||
|
|
||||||
// Update all dependent pages
|
// Update all dependent pages // @TODO generalise!! We shouldn't reference explicitly page types here.
|
||||||
$virtualPages = VirtualPage::get()->filter("CopyContentFromID", $node->ID);
|
$virtualPages = VirtualPage::get()->filter("CopyContentFromID", $node->ID);
|
||||||
foreach ($virtualPages as $virtualPage) {
|
foreach ($virtualPages as $virtualPage) {
|
||||||
$statusUpdates['modified'][$virtualPage->ID] = [
|
$statusUpdates['modified'][$virtualPage->ID] = [
|
||||||
'TreeTitle' => $virtualPage->TreeTitle
|
'TreeTitle' => $virtualPage->TreeTitle // @TODO generalise.
|
||||||
];
|
];
|
||||||
}
|
}
|
||||||
|
|
||||||
$this->getResponse()->addHeader(
|
$this->getResponse()->addHeader(
|
||||||
'X-Status',
|
'X-Status',
|
||||||
rawurlencode(_t(__CLASS__.'.REORGANISATIONSUCCESSFUL', 'Reorganised the site tree successfully.') ?? '')
|
rawurlencode(_t(__CLASS__.'.REORGANISATIONSUCCESSFUL2', 'Reorganised the tree successfully.') ?? '')
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -830,7 +830,7 @@ class CMSMain extends LeftAndMain implements CurrentPageIdentifier, PermissionPr
|
|||||||
$node->Sort = ++$counter;
|
$node->Sort = ++$counter;
|
||||||
$node->write();
|
$node->write();
|
||||||
$statusUpdates['modified'][$node->ID] = [
|
$statusUpdates['modified'][$node->ID] = [
|
||||||
'TreeTitle' => $node->TreeTitle
|
'TreeTitle' => $node->TreeTitle // @TODO generalise.
|
||||||
];
|
];
|
||||||
} elseif (is_numeric($id)) {
|
} elseif (is_numeric($id)) {
|
||||||
// Nodes that weren't "actually moved" shouldn't be registered as
|
// Nodes that weren't "actually moved" shouldn't be registered as
|
||||||
@ -846,7 +846,7 @@ class CMSMain extends LeftAndMain implements CurrentPageIdentifier, PermissionPr
|
|||||||
|
|
||||||
$this->getResponse()->addHeader(
|
$this->getResponse()->addHeader(
|
||||||
'X-Status',
|
'X-Status',
|
||||||
rawurlencode(_t(__CLASS__.'.REORGANISATIONSUCCESSFUL', 'Reorganised the site tree successfully.') ?? '')
|
rawurlencode(_t(__CLASS__.'.REORGANISATIONSUCCESSFUL2', 'Reorganised the tree successfully.') ?? '')
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -857,64 +857,43 @@ class CMSMain extends LeftAndMain implements CurrentPageIdentifier, PermissionPr
|
|||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Whether the current member has the permission to reorganise SiteTree objects.
|
* Whether the current member has the permission to reorganise records.
|
||||||
* @return bool
|
|
||||||
*/
|
*/
|
||||||
public function CanOrganiseSitetree()
|
public function CanOrganiseTree(): bool
|
||||||
{
|
{
|
||||||
return Permission::check('SITETREE_REORGANISE');
|
return (bool) Permission::check('SITETREE_REORGANISE'); // @TODO model needs a method or config to say "this is the permission for that!!"
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @return boolean
|
* Whether the tree has been filtered in this request or not.
|
||||||
*/
|
*/
|
||||||
public function TreeIsFiltered()
|
public function TreeIsFiltered(): bool
|
||||||
{
|
{
|
||||||
$query = $this->getRequest()->getVar('q');
|
$query = $this->getRequest()->getVar('q');
|
||||||
return !empty($query);
|
return !empty($query);
|
||||||
}
|
}
|
||||||
|
|
||||||
public function ExtraTreeTools()
|
public function ExtraTreeTools(): string
|
||||||
{
|
{
|
||||||
$html = '';
|
$html = '';
|
||||||
$this->extend('updateExtraTreeTools', $html);
|
$this->extend('updateExtraTreeTools', $html);
|
||||||
return $html;
|
return $html;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* This provides information required to generate the search form
|
|
||||||
* and can be modified on extensions through updateSearchContext
|
|
||||||
*
|
|
||||||
* @return \SilverStripe\ORM\Search\SearchContext
|
|
||||||
*/
|
|
||||||
public function getSearchContext()
|
|
||||||
{
|
|
||||||
$context = SiteTree::singleton()->getDefaultSearchContext();
|
|
||||||
|
|
||||||
$this->extend('updateSearchContext', $context);
|
|
||||||
|
|
||||||
return $context;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Returns the search form schema for the current model
|
* Returns the search form schema for the current model
|
||||||
*
|
|
||||||
* @return string
|
|
||||||
*/
|
*/
|
||||||
public function getSearchFieldSchema()
|
public function getSearchFieldSchema(): string
|
||||||
{
|
{
|
||||||
$schemaUrl = $this->Link('schema/SearchForm');
|
$schemaUrl = $this->Link('schema/SearchForm');
|
||||||
|
|
||||||
$context = $this->getSearchContext();
|
$singleton = DataObject::singleton($this->getModelClass());
|
||||||
|
$context = $singleton->getDefaultSearchContext();
|
||||||
$params = $this->getRequest()->requestVar('q') ?: [];
|
$params = $this->getRequest()->requestVar('q') ?: [];
|
||||||
$context->setSearchParams($params);
|
$context->setSearchParams($params);
|
||||||
|
|
||||||
$placeholder = _t('SilverStripe\\CMS\\Search\\SearchForm.FILTERLABELTEXT', 'Search') . ' "' .
|
$placeholder = _t(SearchForm::class . '.FILTERLABELTEXT2', 'Search "{model}"', ['model' => $singleton->i18n_plural_name()]);
|
||||||
SiteTree::singleton()->i18n_plural_name() . '"';
|
|
||||||
|
|
||||||
$searchParams = $context->getSearchParams();
|
$searchParams = $context->getSearchParams();
|
||||||
|
|
||||||
$searchParams = array_combine(array_map(function ($key) {
|
$searchParams = array_combine(array_map(function ($key) {
|
||||||
return 'Search__' . $key;
|
return 'Search__' . $key;
|
||||||
}, array_keys($searchParams ?? [])), $searchParams ?? []);
|
}, array_keys($searchParams ?? [])), $searchParams ?? []);
|
||||||
@ -930,50 +909,59 @@ class CMSMain extends LeftAndMain implements CurrentPageIdentifier, PermissionPr
|
|||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Returns a Form for page searching for use in templates.
|
* Returns a Form for record searching for use in templates.
|
||||||
*
|
*
|
||||||
* Can be modified from a decorator by a 'updateSearchForm' method
|
* Can be modified from a decorator by a 'updateSearchForm' method
|
||||||
*
|
|
||||||
* @return Form
|
|
||||||
*/
|
*/
|
||||||
public function getSearchForm()
|
public function getSearchForm(): Form
|
||||||
{
|
{
|
||||||
|
$modelClass = $this->getModelClass();
|
||||||
|
$singleton = DataObject::singleton($modelClass);
|
||||||
// Create the fields
|
// Create the fields
|
||||||
$dateFrom = DateField::create(
|
$dateFrom = DateField::create(
|
||||||
'Search__LastEditedFrom',
|
'Search__LastEditedFrom',
|
||||||
_t('SilverStripe\\CMS\\Search\\SearchForm.FILTERDATEFROM', 'From')
|
_t(SearchForm::class . '.FILTERDATEFROM', 'From')
|
||||||
)->setLocale(Security::getCurrentUser()->Locale);
|
)->setLocale(Security::getCurrentUser()->Locale);
|
||||||
$dateTo = DateField::create(
|
$dateTo = DateField::create(
|
||||||
'Search__LastEditedTo',
|
'Search__LastEditedTo',
|
||||||
_t('SilverStripe\\CMS\\Search\\SearchForm.FILTERDATETO', 'To')
|
_t(SearchForm::class . '.FILTERDATETO', 'To')
|
||||||
)->setLocale(Security::getCurrentUser()->Locale);
|
)->setLocale(Security::getCurrentUser()->Locale);
|
||||||
$filters = CMSSiteTreeFilter::get_all_filters();
|
$filters = CMSSiteTreeFilter::get_all_filters();
|
||||||
// Remove 'All pages' as we set that to empty/default value
|
// Remove 'All records' as we set that to empty/default value
|
||||||
unset($filters[CMSSiteTreeFilter_Search::class]);
|
unset($filters[CMSSiteTreeFilter_Search::class]);
|
||||||
$pageFilter = DropdownField::create(
|
$recordFilter = DropdownField::create(
|
||||||
'Search__FilterClass',
|
'Search__FilterClass',
|
||||||
_t('SilverStripe\\CMS\\Controllers\\CMSMain.PAGES', 'Page status'),
|
_t(SearchForm::class . '.RECORD_STATUS', '{model} status', ['model' => $singleton->i18n_singular_name()]),
|
||||||
$filters
|
$filters
|
||||||
);
|
);
|
||||||
$pageFilter->setEmptyString(_t('SilverStripe\\CMS\\Controllers\\CMSMain.PAGESALLOPT', 'All pages'));
|
$recordFilter->setEmptyString(_t(
|
||||||
$pageClasses = DropdownField::create(
|
SearchForm::class . '.RECORDS_ALLOPT',
|
||||||
|
'All {model}',
|
||||||
|
['model' => mb_strtolower($singleton->i18n_plural_name())]
|
||||||
|
));
|
||||||
|
$classes = DropdownField::create(
|
||||||
'Search__ClassName',
|
'Search__ClassName',
|
||||||
_t('SilverStripe\\CMS\\Controllers\\CMSMain.PAGETYPEOPT', 'Page type', 'Dropdown for limiting search to a page type'),
|
_t(
|
||||||
$this->getPageTypes()
|
SearchForm::class . '.RECORD_TYPEOPT',
|
||||||
|
'{model} type',
|
||||||
|
'Dropdown for limiting search to a record type',
|
||||||
|
['model' => $singleton->i18n_singular_name()]
|
||||||
|
),
|
||||||
|
$this->getRecordTypes()
|
||||||
);
|
);
|
||||||
$pageClasses->setEmptyString(_t('SilverStripe\\CMS\\Controllers\\CMSMain.PAGETYPEANYOPT', 'Any'));
|
$classes->setEmptyString(_t(SearchForm::class . '.RECORD_TYPEANYOPT', 'Any'));
|
||||||
|
|
||||||
// Group the Datefields
|
// Group the Datefields
|
||||||
$dateGroup = FieldGroup::create(
|
$dateGroup = FieldGroup::create(
|
||||||
_t('SilverStripe\\CMS\\Search\\SearchForm.PAGEFILTERDATEHEADING', 'Last edited'),
|
_t(SearchForm::class . '.RECORD_FILTERDATEHEADING', 'Last edited'),
|
||||||
[$dateFrom, $dateTo]
|
[$dateFrom, $dateTo]
|
||||||
)->setName('Search__LastEdited')
|
)->setName('Search__LastEdited')
|
||||||
->addExtraClass('fieldgroup--fill-width');
|
->addExtraClass('fieldgroup--fill-width');
|
||||||
|
|
||||||
// Create the Field list
|
// Create the Field list
|
||||||
$fields = new FieldList(
|
$fields = new FieldList(
|
||||||
$pageFilter,
|
$recordFilter,
|
||||||
$pageClasses,
|
$classes,
|
||||||
$dateGroup
|
$dateGroup
|
||||||
);
|
);
|
||||||
|
|
||||||
@ -1000,18 +988,16 @@ class CMSMain extends LeftAndMain implements CurrentPageIdentifier, PermissionPr
|
|||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Returns a sorted array suitable for a dropdown with pagetypes and their translated name
|
* Returns a sorted array suitable for a dropdown with classes and their localised name
|
||||||
*
|
|
||||||
* @return array
|
|
||||||
*/
|
*/
|
||||||
protected function getPageTypes()
|
protected function getRecordTypes(): array
|
||||||
{
|
{
|
||||||
$pageTypes = [];
|
$types = [];
|
||||||
foreach (SiteTree::page_type_classes() as $pageTypeClass) {
|
foreach (SiteTree::page_type_classes() as $class) { // @TODO generalise!! Not fully into the POC way.
|
||||||
$pageTypes[$pageTypeClass] = SiteTree::singleton($pageTypeClass)->i18n_singular_name();
|
$types[$class] = DataObject::singleton($class)->i18n_singular_name();
|
||||||
}
|
}
|
||||||
asort($pageTypes);
|
asort($types);
|
||||||
return $pageTypes;
|
return $types;
|
||||||
}
|
}
|
||||||
|
|
||||||
public function doSearch(array $data, Form $form): HTTPResponse
|
public function doSearch(array $data, Form $form): HTTPResponse
|
||||||
@ -1028,7 +1014,7 @@ class CMSMain extends LeftAndMain implements CurrentPageIdentifier, PermissionPr
|
|||||||
{
|
{
|
||||||
$breadcrumbs = $this->Breadcrumbs();
|
$breadcrumbs = $this->Breadcrumbs();
|
||||||
if ($breadcrumbs->count() < 2) {
|
if ($breadcrumbs->count() < 2) {
|
||||||
return $this->LinkPages();
|
return $this->LinkRecords();
|
||||||
}
|
}
|
||||||
// Get second from end breadcrumb
|
// Get second from end breadcrumb
|
||||||
return $breadcrumbs
|
return $breadcrumbs
|
||||||
@ -1040,15 +1026,15 @@ class CMSMain extends LeftAndMain implements CurrentPageIdentifier, PermissionPr
|
|||||||
{
|
{
|
||||||
$items = ArrayList::create();
|
$items = ArrayList::create();
|
||||||
|
|
||||||
if (($this->getAction() !== 'index') && ($record = $this->currentPage())) {
|
if (($this->getAction() !== 'index') && ($record = $this->currentRecord())) {
|
||||||
// The page is being edited
|
// The record is being edited
|
||||||
$this->buildEditFormBreadcrumb($items, $record, $unlinked);
|
$this->buildEditFormBreadcrumb($items, $record, $unlinked);
|
||||||
} else {
|
} else {
|
||||||
// Ensure we always have the "Pages" crumb first
|
// Ensure we always have the admin section crumb first
|
||||||
$this->pushCrumb(
|
$this->pushCrumb(
|
||||||
$items,
|
$items,
|
||||||
CMSPagesController::menu_title(),
|
CMSPagesController::menu_title(),
|
||||||
$unlinked ? false : $this->LinkPages()
|
$unlinked ? false : $this->LinkRecords()
|
||||||
);
|
);
|
||||||
|
|
||||||
if ($this->TreeIsFiltered()) {
|
if ($this->TreeIsFiltered()) {
|
||||||
@ -1056,13 +1042,13 @@ class CMSMain extends LeftAndMain implements CurrentPageIdentifier, PermissionPr
|
|||||||
$this->pushCrumb(
|
$this->pushCrumb(
|
||||||
$items,
|
$items,
|
||||||
_t(CMSMain::class . '.SEARCHRESULTS', 'Search results'),
|
_t(CMSMain::class . '.SEARCHRESULTS', 'Search results'),
|
||||||
($unlinked) ? false : $this->LinkPages()
|
($unlinked) ? false : $this->LinkRecords()
|
||||||
);
|
);
|
||||||
} elseif ($parentID = $this->getRequest()->getVar('ParentID')) {
|
} elseif ($parentID = $this->getRequest()->getVar('ParentID')) {
|
||||||
// We're navigating the listview. ParentID is the page whose
|
// We're navigating the listview. ParentID is the record whose
|
||||||
// children are currently displayed.
|
// children are currently displayed.
|
||||||
if ($page = SiteTree::get()->byID($parentID)) {
|
if ($record = DataObject::get($this->getModelClass())->byID($parentID)) {
|
||||||
$this->buildListViewBreadcrumb($items, $page);
|
$this->buildListViewBreadcrumb($items, $record);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -1084,30 +1070,32 @@ class CMSMain extends LeftAndMain implements CurrentPageIdentifier, PermissionPr
|
|||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Build Breadcrumb for the Edit page form. Each crumb links back to its own edit form.
|
* Build Breadcrumb for the Edit form. Each crumb links back to its own edit form.
|
||||||
*/
|
*/
|
||||||
private function buildEditFormBreadcrumb(ArrayList $items, SiteTree $page, bool $unlinked): void
|
private function buildEditFormBreadcrumb(ArrayList $items, DataObject $record, bool $unlinked): void
|
||||||
{
|
{
|
||||||
// Find all ancestors of the provided page
|
// Find all ancestors of the provided record
|
||||||
$ancestors = $page->getAncestors(true);
|
/** @var DataObject&Hierarchy $record */
|
||||||
|
$ancestors = $record->getAncestors(true);
|
||||||
$ancestors = array_reverse($ancestors->toArray() ?? []);
|
$ancestors = array_reverse($ancestors->toArray() ?? []);
|
||||||
foreach ($ancestors as $ancestor) {
|
foreach ($ancestors as $ancestor) {
|
||||||
// Link to the ancestor's edit form
|
// Link to the ancestor's edit form
|
||||||
$this->pushCrumb(
|
$this->pushCrumb(
|
||||||
$items,
|
$items,
|
||||||
$ancestor->getMenuTitle(),
|
$ancestor->getMenuTitle(), // @TODO generalise!!
|
||||||
$unlinked ? false : $ancestor->getCMSEditLink()
|
$unlinked ? false : $ancestor->getCMSEditLink()
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Build Breadcrumb for the List view. Each crumb links to the list view for that page.
|
* Build Breadcrumb for the List view. Each crumb links to the list view for that record.
|
||||||
*/
|
*/
|
||||||
private function buildListViewBreadcrumb(ArrayList $items, SiteTree $page): void
|
private function buildListViewBreadcrumb(ArrayList $items, DataObject $record): void
|
||||||
{
|
{
|
||||||
// Find all ancestors of the provided page
|
// Find all ancestors of the provided record
|
||||||
$ancestors = $page->getAncestors(true);
|
/** @var DataObject&Hierarchy $record */
|
||||||
|
$ancestors = $record->getAncestors(true);
|
||||||
$ancestors = array_reverse($ancestors->toArray() ?? []);
|
$ancestors = array_reverse($ancestors->toArray() ?? []);
|
||||||
|
|
||||||
//turns the title and link of the breadcrumbs into template-friendly variables
|
//turns the title and link of the breadcrumbs into template-friendly variables
|
||||||
@ -1121,7 +1109,7 @@ class CMSMain extends LeftAndMain implements CurrentPageIdentifier, PermissionPr
|
|||||||
$params['ParentID'] = $ancestor->ID;
|
$params['ParentID'] = $ancestor->ID;
|
||||||
$this->pushCrumb(
|
$this->pushCrumb(
|
||||||
$items,
|
$items,
|
||||||
$ancestor->getMenuTitle(),
|
$ancestor->getMenuTitle(), // @TODO generalise!!
|
||||||
Controller::join_links($this->Link(), '?' . http_build_query($params ?? []))
|
Controller::join_links($this->Link(), '?' . http_build_query($params ?? []))
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
@ -1130,13 +1118,11 @@ class CMSMain extends LeftAndMain implements CurrentPageIdentifier, PermissionPr
|
|||||||
/**
|
/**
|
||||||
* Create serialized JSON string with site tree hints data to be injected into
|
* Create serialized JSON string with site tree hints data to be injected into
|
||||||
* 'data-hints' attribute of root node of jsTree.
|
* 'data-hints' attribute of root node of jsTree.
|
||||||
*
|
|
||||||
* @return string Serialized JSON
|
|
||||||
*/
|
*/
|
||||||
public function SiteTreeHints()
|
public function TreeHints(): string // @TODO rename
|
||||||
{
|
{
|
||||||
$classes = SiteTree::page_type_classes();
|
$classes = SiteTree::page_type_classes(); // @TODO generalise!!
|
||||||
$memberID = Security::getCurrentUser() ? Security::getCurrentUser()->ID : 0;
|
$memberID = Security::getCurrentUser()?->ID ?? 0;
|
||||||
$cache = $this->getHintsCache();
|
$cache = $this->getHintsCache();
|
||||||
$cacheKey = $this->generateHintsCacheKey($memberID);
|
$cacheKey = $this->generateHintsCacheKey($memberID);
|
||||||
$json = $cache->get($cacheKey);
|
$json = $cache->get($cacheKey);
|
||||||
@ -1154,12 +1140,12 @@ class CMSMain extends LeftAndMain implements CurrentPageIdentifier, PermissionPr
|
|||||||
$def['Root']['disallowedChildren'] = [];
|
$def['Root']['disallowedChildren'] = [];
|
||||||
|
|
||||||
// Contains all possible classes to support UI controls listing them all,
|
// Contains all possible classes to support UI controls listing them all,
|
||||||
// such as the "add page here" context menu.
|
// such as the "add record here" context menu.
|
||||||
$def['All'] = [];
|
$def['All'] = [];
|
||||||
|
|
||||||
// Identify disallows and set globals
|
// Identify disallows and set globals
|
||||||
foreach ($classes as $class) {
|
foreach ($classes as $class) {
|
||||||
$obj = singleton($class);
|
$obj = DataObject::singleton($class);
|
||||||
if ($obj instanceof HiddenClass) {
|
if ($obj instanceof HiddenClass) {
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
@ -1170,8 +1156,8 @@ class CMSMain extends LeftAndMain implements CurrentPageIdentifier, PermissionPr
|
|||||||
];
|
];
|
||||||
|
|
||||||
// Check if can be created at the root
|
// Check if can be created at the root
|
||||||
$needsPerm = $obj->config()->get('need_permission');
|
$needsPerm = $obj::config()->get('need_permission');
|
||||||
if (!$obj->config()->get('can_be_root')
|
if ($obj::config()->get('can_be_root') === false
|
||||||
|| (!array_key_exists($class, $canCreate ?? []) || !$canCreate[$class])
|
|| (!array_key_exists($class, $canCreate ?? []) || !$canCreate[$class])
|
||||||
|| ($needsPerm && !$this->can($needsPerm))
|
|| ($needsPerm && !$this->can($needsPerm))
|
||||||
) {
|
) {
|
||||||
@ -1181,18 +1167,18 @@ class CMSMain extends LeftAndMain implements CurrentPageIdentifier, PermissionPr
|
|||||||
// Hint data specific to the class
|
// Hint data specific to the class
|
||||||
$def[$class] = [];
|
$def[$class] = [];
|
||||||
|
|
||||||
$defaultChild = $obj->defaultChild();
|
$defaultChild = $obj->defaultChild(); // @TODO generalise!!
|
||||||
if ($defaultChild !== 'Page' && $defaultChild !== null) {
|
if ($defaultChild !== 'Page' && $defaultChild !== null) { // @TODO Find out where that 'Page' string comes from and fix it
|
||||||
$def[$class]['defaultChild'] = $defaultChild;
|
$def[$class]['defaultChild'] = $defaultChild;
|
||||||
}
|
}
|
||||||
|
|
||||||
$defaultParent = $obj->defaultParent();
|
$defaultParent = $obj->defaultParent(); // @TODO generalise!!
|
||||||
if ($defaultParent !== 1 && $defaultParent !== null) {
|
if ($defaultParent !== 1 && $defaultParent !== null) {
|
||||||
$def[$class]['defaultParent'] = $defaultParent;
|
$def[$class]['defaultParent'] = $defaultParent;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
$this->extend('updateSiteTreeHints', $def);
|
$this->extend('updateTreeHints', $def);
|
||||||
|
|
||||||
$json = json_encode($def);
|
$json = json_encode($def);
|
||||||
$cache->set($cacheKey, $json);
|
$cache->set($cacheKey, $json);
|
||||||
@ -1202,24 +1188,22 @@ class CMSMain extends LeftAndMain implements CurrentPageIdentifier, PermissionPr
|
|||||||
|
|
||||||
/**
|
/**
|
||||||
* Populates an array of classes in the CMS
|
* Populates an array of classes in the CMS
|
||||||
* which allows the user to change the page type.
|
* which allows the user to change the record's ClassName field.
|
||||||
*
|
|
||||||
* @return SS_List
|
|
||||||
*/
|
*/
|
||||||
public function PageTypes()
|
public function RecordTypes(): SS_List
|
||||||
{
|
{
|
||||||
$classes = SiteTree::page_type_classes();
|
$classes = SiteTree::page_type_classes(); // @TODO generalise!!
|
||||||
|
|
||||||
$result = new ArrayList();
|
$result = new ArrayList();
|
||||||
|
|
||||||
foreach ($classes as $class) {
|
foreach ($classes as $class) {
|
||||||
$instance = SiteTree::singleton($class);
|
$instance = DataObject::singleton($class);
|
||||||
if ($instance instanceof HiddenClass) {
|
if ($instance instanceof HiddenClass) {
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
// skip this type if it is restricted
|
// skip this type if it is restricted
|
||||||
$needPermissions = $instance->config()->get('need_permission');
|
$needPermissions = $instance::config()->get('need_permission'); // @TODO consider renaming that since it's so vague
|
||||||
if ($needPermissions && !$this->can($needPermissions)) {
|
if ($needPermissions && !$this->can($needPermissions)) {
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
@ -1227,8 +1211,8 @@ class CMSMain extends LeftAndMain implements CurrentPageIdentifier, PermissionPr
|
|||||||
$result->push(new ArrayData([
|
$result->push(new ArrayData([
|
||||||
'ClassName' => $class,
|
'ClassName' => $class,
|
||||||
'AddAction' => $instance->i18n_singular_name(),
|
'AddAction' => $instance->i18n_singular_name(),
|
||||||
'Description' => $instance->i18n_classDescription(),
|
'Description' => $instance->i18n_classDescription(), // @TODO generalise!!
|
||||||
'IconURL' => $instance->getPageIconURL(),
|
'IconURL' => $instance->getPageIconURL(), // @TODO generalise!!
|
||||||
'Title' => $instance->i18n_singular_name(),
|
'Title' => $instance->i18n_singular_name(),
|
||||||
]));
|
]));
|
||||||
}
|
}
|
||||||
@ -1243,20 +1227,22 @@ class CMSMain extends LeftAndMain implements CurrentPageIdentifier, PermissionPr
|
|||||||
*
|
*
|
||||||
* @param int $id Record ID
|
* @param int $id Record ID
|
||||||
* @param int $versionID optional Version id of the given record
|
* @param int $versionID optional Version id of the given record
|
||||||
* @return SiteTree
|
|
||||||
*/
|
*/
|
||||||
public function getRecord($id, $versionID = null)
|
public function getRecord($id, ?int $versionID = null): ?DataObject
|
||||||
{
|
{
|
||||||
if (!$id) {
|
if (!$id) {
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
$treeClass = $this->config()->get('tree_class');
|
$modelClass = $this->getModelClass();
|
||||||
if ($id instanceof $treeClass) {
|
if ($id instanceof $modelClass) {
|
||||||
return $id;
|
return $id;
|
||||||
}
|
}
|
||||||
if (substr($id ?? '', 0, 3) == 'new') {
|
if (substr($id ?? '', 0, 3) == 'new') {
|
||||||
return $this->getNewItem($id);
|
return $this->getNewItem($id);
|
||||||
}
|
}
|
||||||
|
if ($id === 'singleton') {
|
||||||
|
return DataObject::singleton($modelClass);
|
||||||
|
}
|
||||||
if (!is_numeric($id)) {
|
if (!is_numeric($id)) {
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
@ -1267,25 +1253,28 @@ class CMSMain extends LeftAndMain implements CurrentPageIdentifier, PermissionPr
|
|||||||
$versionID = (int) $this->getRequest()->getVar('Version');
|
$versionID = (int) $this->getRequest()->getVar('Version');
|
||||||
}
|
}
|
||||||
|
|
||||||
/** @var SiteTree $record */
|
$isVersioned = $modelClass::has_extension(Versioned::class);
|
||||||
if ($versionID) {
|
if ($versionID) {
|
||||||
$record = Versioned::get_version($treeClass, $id, $versionID);
|
if (!$isVersioned) {
|
||||||
|
throw new HTTPResponse_Exception("Cannot get a version of non-versioned $modelClass record", 400);
|
||||||
|
}
|
||||||
|
$record = Versioned::get_version($modelClass, $id, $versionID);
|
||||||
} else {
|
} else {
|
||||||
$record = DataObject::get_by_id($treeClass, $id);
|
$record = DataObject::get_by_id($modelClass, $id);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Then, try getting a record from the live site
|
// Then, try getting a record from the live site
|
||||||
if (!$record) {
|
if (!$record && $isVersioned) {
|
||||||
// $record = Versioned::get_one_by_stage($treeClass, "Live", "\"$treeClass\".\"ID\" = $id");
|
// $record = Versioned::get_one_by_stage($modelClass, "Live", "\"$modelClass\".\"ID\" = $id");
|
||||||
Versioned::set_stage(Versioned::LIVE);
|
Versioned::set_stage(Versioned::LIVE);
|
||||||
singleton($treeClass)->flushCache();
|
DataObject::singleton($modelClass)->flushCache();
|
||||||
|
|
||||||
$record = DataObject::get_by_id($treeClass, $id);
|
$record = DataObject::get_by_id($modelClass, $id);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Then, try getting a deleted record
|
// Then, try getting a deleted record
|
||||||
if (!$record) {
|
if (!$record && $isVersioned) {
|
||||||
$record = Versioned::get_latest_version($treeClass, $id);
|
$record = Versioned::get_latest_version($modelClass, $id);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Set the reading mode back to what it was.
|
// Set the reading mode back to what it was.
|
||||||
@ -1298,11 +1287,10 @@ class CMSMain extends LeftAndMain implements CurrentPageIdentifier, PermissionPr
|
|||||||
* {@inheritdoc}
|
* {@inheritdoc}
|
||||||
*
|
*
|
||||||
* @param HTTPRequest $request
|
* @param HTTPRequest $request
|
||||||
* @return Form
|
|
||||||
*/
|
*/
|
||||||
public function EditForm($request = null)
|
public function EditForm($request = null): Form
|
||||||
{
|
{
|
||||||
// set page ID from request
|
// set record ID from request
|
||||||
if ($request) {
|
if ($request) {
|
||||||
// Validate id is present
|
// Validate id is present
|
||||||
$id = $request->param('ID');
|
$id = $request->param('ID');
|
||||||
@ -1310,7 +1298,7 @@ class CMSMain extends LeftAndMain implements CurrentPageIdentifier, PermissionPr
|
|||||||
$this->httpError(400);
|
$this->httpError(400);
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
$this->setCurrentPageID($id);
|
$this->setCurrentRecordID($id);
|
||||||
}
|
}
|
||||||
return $this->getEditForm();
|
return $this->getEditForm();
|
||||||
}
|
}
|
||||||
@ -1318,13 +1306,12 @@ class CMSMain extends LeftAndMain implements CurrentPageIdentifier, PermissionPr
|
|||||||
/**
|
/**
|
||||||
* @param int $id
|
* @param int $id
|
||||||
* @param FieldList $fields
|
* @param FieldList $fields
|
||||||
* @return Form
|
|
||||||
*/
|
*/
|
||||||
public function getEditForm($id = null, $fields = null)
|
public function getEditForm($id = null, $fields = null): Form
|
||||||
{
|
{
|
||||||
// Get record
|
// Get record
|
||||||
if (!$id) {
|
if (!$id) {
|
||||||
$id = $this->currentPageID();
|
$id = $this->currentRecordID();
|
||||||
}
|
}
|
||||||
$record = $this->getRecord($id);
|
$record = $this->getRecord($id);
|
||||||
|
|
||||||
@ -1340,18 +1327,18 @@ class CMSMain extends LeftAndMain implements CurrentPageIdentifier, PermissionPr
|
|||||||
|
|
||||||
// Add extra fields
|
// Add extra fields
|
||||||
$deletedFromStage = !$record->isOnDraft();
|
$deletedFromStage = !$record->isOnDraft();
|
||||||
$fields->push($idField = new HiddenField("ID", false, $id));
|
$fields->push(new HiddenField("ID", false, $id));
|
||||||
// Necessary for different subsites
|
// Necessary for different subsites
|
||||||
$fields->push($liveLinkField = new HiddenField("AbsoluteLink", false, $record->AbsoluteLink()));
|
$fields->push($liveLinkField = new HiddenField("AbsoluteLink", false, $record->AbsoluteLink())); // @TODO generalise!!
|
||||||
$fields->push($liveLinkField = new HiddenField("LiveLink"));
|
$fields->push($liveLinkField = new HiddenField("LiveLink"));
|
||||||
$fields->push($stageLinkField = new HiddenField("StageLink"));
|
$fields->push($stageLinkField = new HiddenField("StageLink"));
|
||||||
$fields->push($archiveWarningMsgField = new HiddenField("ArchiveWarningMessage"));
|
$fields->push($archiveWarningMsgField = new HiddenField("ArchiveWarningMessage"));
|
||||||
$fields->push(new HiddenField("TreeTitle", false, $record->getTreeTitle()));
|
$fields->push(new HiddenField("TreeTitle", false, $record->getTreeTitle())); // @TODO generalise!!
|
||||||
|
|
||||||
$archiveWarningMsgField->setValue($this->getArchiveWarningMessage($record));
|
$archiveWarningMsgField->setValue($this->getArchiveWarningMessage($record));
|
||||||
|
|
||||||
// Build preview / live links
|
// Build preview / live links
|
||||||
$liveLink = $record->getAbsoluteLiveLink();
|
$liveLink = $record->getAbsoluteLiveLink(); // @TODO generalise!!
|
||||||
if ($liveLink) {
|
if ($liveLink) {
|
||||||
$liveLinkField->setValue($liveLink);
|
$liveLinkField->setValue($liveLink);
|
||||||
}
|
}
|
||||||
@ -1437,10 +1424,10 @@ class CMSMain extends LeftAndMain implements CurrentPageIdentifier, PermissionPr
|
|||||||
return $form;
|
return $form;
|
||||||
}
|
}
|
||||||
|
|
||||||
public function EmptyForm()
|
public function EmptyForm(): Form
|
||||||
{
|
{
|
||||||
$fields = new FieldList(
|
$fields = new FieldList(
|
||||||
new LabelField('PageDoesntExistLabel', _t('SilverStripe\\CMS\\Controllers\\CMSMain.PAGENOTEXISTS', "This page doesn't exist"))
|
new LabelField('RecordDoesntExistLabel', _t(__CLASS__ . '.RECORDNOTEXISTS', "This record doesn't exist"))
|
||||||
);
|
);
|
||||||
$form = parent::EmptyForm();
|
$form = parent::EmptyForm();
|
||||||
$form->setFields($fields);
|
$form->setFields($fields);
|
||||||
@ -1449,39 +1436,32 @@ class CMSMain extends LeftAndMain implements CurrentPageIdentifier, PermissionPr
|
|||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Build an archive warning message based on the page's children
|
* Build an archive warning message based on the record's children
|
||||||
*
|
|
||||||
* @param SiteTree $record
|
|
||||||
* @return string
|
|
||||||
*/
|
*/
|
||||||
/**
|
protected function getArchiveWarningMessage(DataObject $record): string
|
||||||
* Build an archive warning message based on the page's children
|
|
||||||
*
|
|
||||||
* @param SiteTree $record
|
|
||||||
* @return string
|
|
||||||
*/
|
|
||||||
protected function getArchiveWarningMessage($record)
|
|
||||||
{
|
{
|
||||||
|
$defaultMessage = _t(
|
||||||
$defaultMessage = _t('SilverStripe\\CMS\\Controllers\\CMSMain.ArchiveWarningWithChildren', 'Warning: This page and all of its child pages will be unpublished before being sent to the archive.\n\nAre you sure you want to proceed?');
|
LeftAndMain::class . '.ArchiveWarningWithChildren',
|
||||||
|
'Warning: This record and all of its child records will be unpublished before being sent to the archive.\n\nAre you sure you want to proceed?'
|
||||||
|
);
|
||||||
|
|
||||||
// Option to disable this feature as it is slow on large sites
|
// Option to disable this feature as it is slow on large sites
|
||||||
if (!$this->config()->enable_dynamic_archive_warning_message) {
|
if (!static::config()->get('enable_dynamic_archive_warning_message')) {
|
||||||
return $defaultMessage;
|
return $defaultMessage;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Get all page's descendants
|
// Get all record's descendants
|
||||||
$descendants = [];
|
$descendants = [];
|
||||||
$this->collateDescendants([$record->ID], $descendants);
|
$this->collateDescendants([$record->ID], $descendants);
|
||||||
if (!$descendants) {
|
if (!$descendants) {
|
||||||
$descendants = [];
|
$descendants = [];
|
||||||
}
|
}
|
||||||
|
|
||||||
// Get the IDs of all changeset including at least one of the pages.
|
// Get the IDs of all changeset including at least one of the records.
|
||||||
$descendants[] = $record->ID;
|
$descendants[] = $record->ID;
|
||||||
$inChangeSetIDs = ChangeSetItem::get()->filter([
|
$inChangeSetIDs = ChangeSetItem::get()->filter([
|
||||||
'ObjectID' => $descendants,
|
'ObjectID' => $descendants,
|
||||||
'ObjectClass' => SiteTree::class
|
'ObjectClass' => $this->getModelClass(),
|
||||||
])->column('ChangeSetID');
|
])->column('ChangeSetID');
|
||||||
|
|
||||||
// Count number of affected change set
|
// Count number of affected change set
|
||||||
@ -1496,20 +1476,31 @@ class CMSMain extends LeftAndMain implements CurrentPageIdentifier, PermissionPr
|
|||||||
$numCampaigns = mb_strtolower($numCampaigns ?? '');
|
$numCampaigns = mb_strtolower($numCampaigns ?? '');
|
||||||
|
|
||||||
if (count($descendants ?? []) > 0 && $affectedChangeSetCount > 0) {
|
if (count($descendants ?? []) > 0 && $affectedChangeSetCount > 0) {
|
||||||
$archiveWarningMsg = _t('SilverStripe\\CMS\\Controllers\\CMSMain.ArchiveWarningWithChildrenAndCampaigns', 'Warning: This page and all of its child pages will be unpublished and automatically removed from their associated {NumCampaigns} before being sent to the archive.\n\nAre you sure you want to proceed?', [ 'NumCampaigns' => $numCampaigns ]);
|
$archiveWarningMsg = _t(
|
||||||
|
LeftAndMain::class . '.ArchiveWarningWithChildrenAndCampaigns',
|
||||||
|
'Warning: This record and all of its child records will be unpublished and automatically removed from their associated {NumCampaigns} before being sent to the archive.\n\nAre you sure you want to proceed?',
|
||||||
|
[ 'NumCampaigns' => $numCampaigns ]
|
||||||
|
);
|
||||||
} elseif (count($descendants ?? []) > 0) {
|
} elseif (count($descendants ?? []) > 0) {
|
||||||
$archiveWarningMsg = $defaultMessage;
|
$archiveWarningMsg = $defaultMessage;
|
||||||
} elseif ($affectedChangeSetCount > 0) {
|
} elseif ($affectedChangeSetCount > 0) {
|
||||||
$archiveWarningMsg = _t('SilverStripe\\CMS\\Controllers\\CMSMain.ArchiveWarningWithCampaigns', 'Warning: This page will be unpublished and automatically removed from their associated {NumCampaigns} before being sent to the archive.\n\nAre you sure you want to proceed?', [ 'NumCampaigns' => $numCampaigns ]);
|
$archiveWarningMsg = _t(
|
||||||
|
LeftAndMain::class . '.ArchiveWarningWithCampaigns',
|
||||||
|
'Warning: This record will be unpublished and automatically removed from their associated {NumCampaigns} before being sent to the archive.\n\nAre you sure you want to proceed?',
|
||||||
|
[ 'NumCampaigns' => $numCampaigns ]
|
||||||
|
);
|
||||||
} else {
|
} else {
|
||||||
$archiveWarningMsg = _t('SilverStripe\\CMS\\Controllers\\CMSMain.ArchiveWarning', 'Warning: This page will be unpublished before being sent to the archive.\n\nAre you sure you want to proceed?');
|
$archiveWarningMsg = _t(
|
||||||
|
LeftAndMain::class . '.ArchiveWarning',
|
||||||
|
'Warning: This record will be unpublished before being sent to the archive.\n\nAre you sure you want to proceed?'
|
||||||
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
return $archiveWarningMsg;
|
return $archiveWarningMsg;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Find IDs of all descendant pages for the provided ID lists.
|
* Find IDs of all descendant records for the provided ID lists.
|
||||||
* @param int[] $recordIDs
|
* @param int[] $recordIDs
|
||||||
* @param array $collator
|
* @param array $collator
|
||||||
* @return bool
|
* @return bool
|
||||||
@ -1517,7 +1508,7 @@ class CMSMain extends LeftAndMain implements CurrentPageIdentifier, PermissionPr
|
|||||||
protected function collateDescendants($recordIDs, &$collator)
|
protected function collateDescendants($recordIDs, &$collator)
|
||||||
{
|
{
|
||||||
|
|
||||||
$children = SiteTree::get()->filter(['ParentID' => $recordIDs])->column();
|
$children = DataObject::get($this->getModelClass())->filter(['ParentID' => $recordIDs])->column();
|
||||||
if ($children) {
|
if ($children) {
|
||||||
foreach ($children as $item) {
|
foreach ($children as $item) {
|
||||||
$collator[] = $item;
|
$collator[] = $item;
|
||||||
@ -1528,10 +1519,9 @@ class CMSMain extends LeftAndMain implements CurrentPageIdentifier, PermissionPr
|
|||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* This method exclusively handles deferred ajax requests to render the
|
* This method exclusively handles deferred ajax requests to render the
|
||||||
* pages tree deferred handler (no pjax-fragment)
|
* records tree deferred handler (no pjax-fragment)
|
||||||
*
|
*
|
||||||
* @return DBHTMLText HTML response with the rendered treeview
|
* @return DBHTMLText HTML response with the rendered treeview
|
||||||
*/
|
*/
|
||||||
@ -1569,21 +1559,21 @@ class CMSMain extends LeftAndMain implements CurrentPageIdentifier, PermissionPr
|
|||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Callback to request the list of page types allowed under a given page instance.
|
* Callback to request the list of record types allowed under a given record instance.
|
||||||
* Provides a slower but more precise response over SiteTreeHints
|
* Provides a slower but more precise response over TreeHints
|
||||||
*/
|
*/
|
||||||
public function childfilter(HTTPRequest $request): HTTPResponse
|
public function childfilter(HTTPRequest $request): HTTPResponse
|
||||||
{
|
{
|
||||||
// Check valid parent specified
|
// Check valid parent specified
|
||||||
$parentID = $request->requestVar('ParentID');
|
$parentID = $request->requestVar('ParentID');
|
||||||
$parent = SiteTree::get()->byID($parentID);
|
$parent = DataObject::get($this->getModelClass())->byID($parentID);
|
||||||
if (!$parent || !$parent->exists()) {
|
if (!$parent || !$parent->exists()) {
|
||||||
$this->httpError(404);
|
$this->httpError(404);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Build hints specific to this class
|
// Build hints specific to this class
|
||||||
// Identify disallows and set globals
|
// Identify disallows and set globals
|
||||||
$classes = SiteTree::page_type_classes();
|
$classes = SiteTree::page_type_classes(); // @TODO generalise!!
|
||||||
$disallowedChildren = [];
|
$disallowedChildren = [];
|
||||||
foreach ($classes as $class) {
|
foreach ($classes as $class) {
|
||||||
$obj = singleton($class);
|
$obj = singleton($class);
|
||||||
@ -1623,8 +1613,8 @@ class CMSMain extends LeftAndMain implements CurrentPageIdentifier, PermissionPr
|
|||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Returns the pages meet a certain criteria as {@see CMSSiteTreeFilter} or the subpages of a parent page
|
* Returns the records meet a certain criteria as {@see CMSSiteTreeFilter} or the subrecords of a parent record
|
||||||
* defaulting to no filter and show all pages in first level.
|
* defaulting to no filter and show all records in first level.
|
||||||
* Doubles as search results, if any search parameters are set through {@link SearchForm()}.
|
* Doubles as search results, if any search parameters are set through {@link SearchForm()}.
|
||||||
*
|
*
|
||||||
* @param array $params Search filter criteria
|
* @param array $params Search filter criteria
|
||||||
@ -1637,7 +1627,7 @@ class CMSMain extends LeftAndMain implements CurrentPageIdentifier, PermissionPr
|
|||||||
if ($filter = $this->getQueryFilter($params)) {
|
if ($filter = $this->getQueryFilter($params)) {
|
||||||
return $filter->getFilteredPages();
|
return $filter->getFilteredPages();
|
||||||
} else {
|
} else {
|
||||||
$list = DataList::create($this->config()->get('tree_class'));
|
$list = DataObject::get($this->getModelClass());
|
||||||
$parentID = is_numeric($parentID) ? $parentID : 0;
|
$parentID = is_numeric($parentID) ? $parentID : 0;
|
||||||
return $list->filter("ParentID", $parentID);
|
return $list->filter("ParentID", $parentID);
|
||||||
}
|
}
|
||||||
@ -1658,7 +1648,7 @@ class CMSMain extends LeftAndMain implements CurrentPageIdentifier, PermissionPr
|
|||||||
$gridFieldConfig = GridFieldConfig::create()->addComponents(
|
$gridFieldConfig = GridFieldConfig::create()->addComponents(
|
||||||
Injector::inst()->create(GridFieldSortableHeader::class),
|
Injector::inst()->create(GridFieldSortableHeader::class),
|
||||||
Injector::inst()->create(GridFieldDataColumns::class),
|
Injector::inst()->create(GridFieldDataColumns::class),
|
||||||
Injector::inst()->createWithArgs(GridFieldPaginator::class, [$this->config()->get('page_length')])
|
Injector::inst()->createWithArgs(GridFieldPaginator::class, [static::config()->get('page_length')])
|
||||||
);
|
);
|
||||||
if ($parentID) {
|
if ($parentID) {
|
||||||
$linkSpec = $this->LinkListViewChildren('%d');
|
$linkSpec = $this->LinkListViewChildren('%d');
|
||||||
@ -1667,17 +1657,18 @@ class CMSMain extends LeftAndMain implements CurrentPageIdentifier, PermissionPr
|
|||||||
->setLinkSpec($linkSpec)
|
->setLinkSpec($linkSpec)
|
||||||
->setAttributes(['data-pjax-target' => 'ListViewForm,Breadcrumbs'])
|
->setAttributes(['data-pjax-target' => 'ListViewForm,Breadcrumbs'])
|
||||||
);
|
);
|
||||||
$this->setCurrentPageID($parentID);
|
$this->setCurrentRecordID($parentID);
|
||||||
}
|
}
|
||||||
$gridField = GridField::create('Page', 'Pages', $list, $gridFieldConfig);
|
$gridField = GridField::create('Record', 'Records', $list, $gridFieldConfig); // @TODO make title string i18n
|
||||||
$gridField->setAttribute('cms-loading-ignore-url-params', true);
|
$gridField->setAttribute('cms-loading-ignore-url-params', true);
|
||||||
$columns = $gridField->getConfig()->getComponentByType(GridFieldDataColumns::class);
|
$columns = $gridField->getConfig()->getComponentByType(GridFieldDataColumns::class);
|
||||||
|
|
||||||
// Don't allow navigating into children nodes on filtered lists
|
// Don't allow navigating into children nodes on filtered lists
|
||||||
|
$modelClass = $this->getModelClass();
|
||||||
$fields = [
|
$fields = [
|
||||||
'getTreeTitle' => _t('SilverStripe\\CMS\\Model\\SiteTree.PAGETITLE', 'Page Title'),
|
'getTreeTitle' => _t($modelClass . '.TREETITLE', 'Title'),
|
||||||
'i18n_singular_name' => _t('SilverStripe\\CMS\\Model\\SiteTree.PAGETYPE', 'Page Type'),
|
'i18n_singular_name' => _t($modelClass . '.TREETYPE', 'Record Type'),
|
||||||
'LastEdited' => _t('SilverStripe\\CMS\\Model\\SiteTree.LASTUPDATED', 'Last Updated'),
|
'LastEdited' => _t($modelClass . '.LASTUPDATED', 'Last Updated'),
|
||||||
];
|
];
|
||||||
$sortableHeader = $gridField->getConfig()->getComponentByType(GridFieldSortableHeader::class);
|
$sortableHeader = $gridField->getConfig()->getComponentByType(GridFieldSortableHeader::class);
|
||||||
$sortableHeader->setFieldSorting(['getTreeTitle' => 'Title']);
|
$sortableHeader->setFieldSorting(['getTreeTitle' => 'Title']);
|
||||||
@ -1696,24 +1687,24 @@ class CMSMain extends LeftAndMain implements CurrentPageIdentifier, PermissionPr
|
|||||||
|
|
||||||
$columns->setFieldFormatting([
|
$columns->setFieldFormatting([
|
||||||
'listChildrenLink' => function ($value, &$item) {
|
'listChildrenLink' => function ($value, &$item) {
|
||||||
/** @var SiteTree $item */
|
/** @var DataObject&Hierarchy $item */
|
||||||
$num = $item ? $item->numChildren() : null;
|
$num = $item?->numChildren();
|
||||||
if ($num) {
|
if ($num) {
|
||||||
return sprintf(
|
return sprintf(
|
||||||
'<a class="btn btn-secondary btn--no-text btn--icon-large font-icon-right-dir cms-panel-link list-children-link" data-pjax-target="ListViewForm,Breadcrumbs" href="%s"><span class="sr-only">%s child pages</span></a>',
|
'<a class="btn btn-secondary btn--no-text btn--icon-large font-icon-right-dir cms-panel-link list-children-link" data-pjax-target="ListViewForm,Breadcrumbs" href="%s"><span class="sr-only">%s child pages</span></a>', // @TODO generalise and i18n-ify
|
||||||
$this->LinkListViewChildren((int)$item->ID),
|
$this->LinkListViewChildren((int)$item->ID),
|
||||||
$num
|
$num
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
'getTreeTitle' => function ($value, &$item) {
|
'getTreeTitle' => function ($value, &$item) {
|
||||||
/** @var SiteTree $item */
|
/** @var DataObject $item */
|
||||||
$title = sprintf(
|
$title = sprintf(
|
||||||
'<a class="action-detail" href="%s">%s</a>',
|
'<a class="action-detail" href="%s">%s</a>',
|
||||||
$item->getCMSEditLink(),
|
$item->getCMSEditLink(),
|
||||||
$item->TreeTitle // returns HTML, does its own escaping
|
$item->TreeTitle // returns HTML, does its own escaping // @TODO generalise!!
|
||||||
);
|
);
|
||||||
$breadcrumbs = $item->Breadcrumbs(20, true, false, true, '/');
|
$breadcrumbs = $item->Breadcrumbs(20, true, false, true, '/'); // @TODO generalise!!
|
||||||
// Remove item's tile
|
// Remove item's tile
|
||||||
$breadcrumbs = preg_replace('/[^\/]+$/', '', trim($breadcrumbs ?? ''));
|
$breadcrumbs = preg_replace('/[^\/]+$/', '', trim($breadcrumbs ?? ''));
|
||||||
// Trim spaces around delimiters
|
// Trim spaces around delimiters
|
||||||
@ -1748,11 +1739,11 @@ class CMSMain extends LeftAndMain implements CurrentPageIdentifier, PermissionPr
|
|||||||
return $listview;
|
return $listview;
|
||||||
}
|
}
|
||||||
|
|
||||||
public function currentPageID()
|
public function currentRecordID()
|
||||||
{
|
{
|
||||||
$id = parent::currentPageID();
|
$id = parent::currentRecordID();
|
||||||
|
|
||||||
$this->extend('updateCurrentPageID', $id);
|
$this->extend('updateCurrentRecordID', $id);
|
||||||
|
|
||||||
return $id;
|
return $id;
|
||||||
}
|
}
|
||||||
@ -1761,18 +1752,17 @@ class CMSMain extends LeftAndMain implements CurrentPageIdentifier, PermissionPr
|
|||||||
// Data saving handlers
|
// Data saving handlers
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Save and Publish page handler
|
* Save and Publish record handler
|
||||||
*
|
*
|
||||||
* @throws HTTPResponse_Exception
|
* @throws HTTPResponse_Exception
|
||||||
*/
|
*/
|
||||||
public function save(array $data, Form $form): HTTPResponse
|
public function save(array $data, Form $form): HTTPResponse
|
||||||
{
|
{
|
||||||
$className = $this->config()->get('tree_class');
|
$className = $this->getModelClass();
|
||||||
|
|
||||||
// Existing or new record?
|
// Existing or new record?
|
||||||
$id = $data['ID'];
|
$id = $data['ID'];
|
||||||
if (substr($id ?? '', 0, 3) != 'new') {
|
if (substr($id ?? '', 0, 3) != 'new') {
|
||||||
/** @var SiteTree $record */
|
|
||||||
$record = DataObject::get_by_id($className, $id);
|
$record = DataObject::get_by_id($className, $id);
|
||||||
// Check edit permissions
|
// Check edit permissions
|
||||||
if ($record && !$record->canEdit()) {
|
if ($record && !$record->canEdit()) {
|
||||||
@ -1790,14 +1780,15 @@ class CMSMain extends LeftAndMain implements CurrentPageIdentifier, PermissionPr
|
|||||||
|
|
||||||
// Check publishing permissions
|
// Check publishing permissions
|
||||||
$doPublish = !empty($data['publish']);
|
$doPublish = !empty($data['publish']);
|
||||||
if ($record && $doPublish && !$record->canPublish()) {
|
$isVersioned = $record->hasExtension(Versioned::class);
|
||||||
|
if ($isVersioned && $doPublish && !$record->canPublish()) {
|
||||||
return Security::permissionFailure($this);
|
return Security::permissionFailure($this);
|
||||||
}
|
}
|
||||||
|
|
||||||
$record->HasBrokenLink = 0;
|
$record->HasBrokenLink = 0; // @TODO generalise!!
|
||||||
$record->HasBrokenFile = 0;
|
$record->HasBrokenFile = 0; // @TODO generalise!!
|
||||||
|
|
||||||
if (!$record->ObsoleteClassName) {
|
if ($isVersioned && !$record->ObsoleteClassName) { // @TODO I think that's specific to SiteTree??
|
||||||
$record->writeWithoutVersion();
|
$record->writeWithoutVersion();
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -1812,19 +1803,28 @@ class CMSMain extends LeftAndMain implements CurrentPageIdentifier, PermissionPr
|
|||||||
$form->saveInto($record);
|
$form->saveInto($record);
|
||||||
$record->write();
|
$record->write();
|
||||||
|
|
||||||
// If the 'Publish' button was clicked, also publish the page
|
// If the 'Publish' button was clicked, also publish the record
|
||||||
if ($doPublish) {
|
if ($doPublish) {
|
||||||
|
if (!$record->hasExtension(RecursivePublishable::class)) {
|
||||||
|
throw new HTTPResponse_Exception(get_class($record) . ' record is not publishable.', 400);
|
||||||
|
}
|
||||||
$record->publishRecursive();
|
$record->publishRecursive();
|
||||||
$message = _t(
|
$message = _t(
|
||||||
__CLASS__ . '.PUBLISHED',
|
LeftAndMain::class . '.PUBLISHED_RECORD',
|
||||||
"Published '{title}' successfully.",
|
'Published {name} "{title}"',
|
||||||
['title' => $record->Title]
|
[
|
||||||
|
'name' => $record->i18n_singular_name(),
|
||||||
|
'title' => $record->Title,
|
||||||
|
]
|
||||||
);
|
);
|
||||||
} else {
|
} else {
|
||||||
$message = _t(
|
$message = _t(
|
||||||
__CLASS__ . '.SAVED',
|
LeftAndMain::class . '.SAVED_RECORD',
|
||||||
"Saved '{title}' successfully.",
|
'Saved {name} "{title}"',
|
||||||
['title' => $record->Title]
|
[
|
||||||
|
'name' => $record->i18n_singular_name(),
|
||||||
|
'title' => $record->Title,
|
||||||
|
]
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -1835,12 +1835,11 @@ class CMSMain extends LeftAndMain implements CurrentPageIdentifier, PermissionPr
|
|||||||
/**
|
/**
|
||||||
* @param int|string $id
|
* @param int|string $id
|
||||||
* @param bool $setID
|
* @param bool $setID
|
||||||
* @return mixed|DataObject
|
|
||||||
* @throws HTTPResponse_Exception
|
* @throws HTTPResponse_Exception
|
||||||
*/
|
*/
|
||||||
public function getNewItem($id, $setID = true)
|
public function getNewItem($id, $setID = true): DataObject
|
||||||
{
|
{
|
||||||
$parentClass = $this->config()->get('tree_class');
|
$parentClass = $this->getModelClass();
|
||||||
list(, $className, $parentID) = array_pad(explode('-', $id ?? ''), 3, null);
|
list(, $className, $parentID) = array_pad(explode('-', $id ?? ''), 3, null);
|
||||||
|
|
||||||
if (!is_a($className, $parentClass ?? '', true)) {
|
if (!is_a($className, $parentClass ?? '', true)) {
|
||||||
@ -1851,23 +1850,20 @@ class CMSMain extends LeftAndMain implements CurrentPageIdentifier, PermissionPr
|
|||||||
throw new HTTPResponse_Exception($response);
|
throw new HTTPResponse_Exception($response);
|
||||||
}
|
}
|
||||||
|
|
||||||
/** @var SiteTree $newItem */
|
/** @var DataObject $newItem */
|
||||||
$newItem = Injector::inst()->create($className);
|
$newItem = Injector::inst()->create($className);
|
||||||
$newItem->Title = _t(
|
$newItem->Title = _t(
|
||||||
__CLASS__ . '.NEWPAGE',
|
LeftAndMain::class . '.NEW_RECORD',
|
||||||
"New {pagetype}",
|
'New {recordtype}',
|
||||||
'followed by a page type title',
|
['recordtype' => DataObject::singleton($className)->i18n_singular_name()]
|
||||||
['pagetype' => singleton($className)->i18n_singular_name()]
|
|
||||||
);
|
);
|
||||||
$newItem->ClassName = $className;
|
$newItem->ClassName = $className;
|
||||||
$newItem->ParentID = $parentID;
|
$newItem->ParentID = $parentID;
|
||||||
|
|
||||||
// DataObject::fieldExists only checks the current class, not the hierarchy
|
if ($newItem->hasDatabaseField('Sort')) { // @TODO Let the field name be configurable
|
||||||
// This allows the CMS to set the correct sort value
|
$table = DataObject::singleton($parentClass)->baseTable();
|
||||||
if ($newItem->castingHelper('Sort')) {
|
|
||||||
$table = DataObject::singleton(SiteTree::class)->baseTable();
|
|
||||||
$maxSort = DB::prepared_query(
|
$maxSort = DB::prepared_query(
|
||||||
"SELECT MAX(\"Sort\") FROM \"$table\" WHERE \"ParentID\" = ?",
|
"SELECT MAX(\"Sort\") FROM \"$table\" WHERE \"ParentID\" = ?", // @TODO this won't work if sort is on a subclass! Use ORM instead
|
||||||
[$parentID]
|
[$parentID]
|
||||||
)->value();
|
)->value();
|
||||||
$newItem->Sort = (int)$maxSort + 1;
|
$newItem->Sort = (int)$maxSort + 1;
|
||||||
@ -1878,55 +1874,43 @@ class CMSMain extends LeftAndMain implements CurrentPageIdentifier, PermissionPr
|
|||||||
}
|
}
|
||||||
|
|
||||||
# Some modules like subsites add extra fields that need to be set when the new item is created
|
# Some modules like subsites add extra fields that need to be set when the new item is created
|
||||||
$this->extend('augmentNewSiteTreeItem', $newItem);
|
$this->extend('updateNewItem', $newItem); // @TODO rename
|
||||||
|
|
||||||
return $newItem;
|
return $newItem;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Actually perform the publication step
|
* Reverts a record by publishing it to live.
|
||||||
*
|
* Use {@link restoreRecord()} if you want to restore a record
|
||||||
* @param Versioned|DataObject $record
|
|
||||||
* @return mixed
|
|
||||||
*/
|
|
||||||
public function performPublish($record)
|
|
||||||
{
|
|
||||||
if ($record && !$record->canPublish()) {
|
|
||||||
return Security::permissionFailure($this);
|
|
||||||
}
|
|
||||||
|
|
||||||
$record->publishRecursive();
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Reverts a page by publishing it to live.
|
|
||||||
* Use {@link restorepage()} if you want to restore a page
|
|
||||||
* which was deleted from draft without publishing.
|
* which was deleted from draft without publishing.
|
||||||
*
|
*
|
||||||
* @uses SiteTree->doRevertToLive()
|
|
||||||
*
|
|
||||||
* @throws HTTPResponse_Exception
|
* @throws HTTPResponse_Exception
|
||||||
*/
|
*/
|
||||||
public function revert(array $data, Form $form): HTTPResponse
|
public function revert(array $data, Form $form): HTTPResponse
|
||||||
{
|
{
|
||||||
|
$modelClass = $this->getModelClass();
|
||||||
if (!isset($data['ID'])) {
|
if (!isset($data['ID'])) {
|
||||||
throw new HTTPResponse_Exception("Please pass an ID in the form content", 400);
|
throw new HTTPResponse_Exception("Please pass an ID in the form content", 400);
|
||||||
}
|
}
|
||||||
|
|
||||||
$id = (int) $data['ID'];
|
if (!$modelClass::has_extension(Versioned::class)) {
|
||||||
$restoredPage = Versioned::get_latest_version(SiteTree::class, $id);
|
throw new HTTPResponse_Exception("$modelClass record cannot be reverted", 400);
|
||||||
if (!$restoredPage) {
|
|
||||||
throw new HTTPResponse_Exception("SiteTree #$id not found", 400);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
$table = DataObject::singleton(SiteTree::class)->baseTable();
|
$id = (int) $data['ID'];
|
||||||
$liveTable = DataObject::singleton(SiteTree::class)->stageTable($table, Versioned::LIVE);
|
$restoredRecord = Versioned::get_latest_version($modelClass, $id);
|
||||||
$record = Versioned::get_one_by_stage(SiteTree::class, Versioned::LIVE, [
|
if (!$restoredRecord) {
|
||||||
|
throw new HTTPResponse_Exception("Record #$id not found", 400);
|
||||||
|
}
|
||||||
|
|
||||||
|
$table = DataObject::singleton($modelClass)->baseTable();
|
||||||
|
$liveTable = DataObject::singleton($modelClass)->stageTable($table, Versioned::LIVE);
|
||||||
|
$record = Versioned::get_one_by_stage($modelClass, Versioned::LIVE, [
|
||||||
"\"$liveTable\".\"ID\"" => $id
|
"\"$liveTable\".\"ID\"" => $id
|
||||||
]);
|
]);
|
||||||
|
|
||||||
// a user can restore a page without publication rights, as it just adds a new draft state
|
// a user can restore a record without publication rights, as it just adds a new draft state
|
||||||
// (this action should just be available when page has been "deleted from draft")
|
// (this action should just be available when the record has been "deleted from draft")
|
||||||
if ($record && !$record->canEdit()) {
|
if ($record && !$record->canEdit()) {
|
||||||
return Security::permissionFailure($this);
|
return Security::permissionFailure($this);
|
||||||
}
|
}
|
||||||
@ -1939,27 +1923,27 @@ class CMSMain extends LeftAndMain implements CurrentPageIdentifier, PermissionPr
|
|||||||
$this->getResponse()->addHeader(
|
$this->getResponse()->addHeader(
|
||||||
'X-Status',
|
'X-Status',
|
||||||
rawurlencode(_t(
|
rawurlencode(_t(
|
||||||
__CLASS__ . '.RESTORED',
|
LeftAndMain::class . '.RESTORED_RECORD',
|
||||||
"Restored '{title}' successfully",
|
'Restored {name} "{title}"',
|
||||||
'Param {title} is a title',
|
[
|
||||||
['title' => $record->Title]
|
'name' => $record->i18n_singular_name(),
|
||||||
) ?? '')
|
'title' => $record->Title,
|
||||||
|
]
|
||||||
|
))
|
||||||
);
|
);
|
||||||
|
|
||||||
return $this->getResponseNegotiator()->respond($this->getRequest());
|
return $this->getResponseNegotiator()->respond($this->getRequest());
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Delete the current page from draft stage.
|
* Delete the current record from draft stage.
|
||||||
*
|
|
||||||
* @see deletefromlive()
|
|
||||||
*
|
*
|
||||||
* @throws HTTPResponse_Exception
|
* @throws HTTPResponse_Exception
|
||||||
*/
|
*/
|
||||||
public function delete(array $data, Form $form): HTTPResponse
|
public function delete(array $data, Form $form): HTTPResponse
|
||||||
{
|
{
|
||||||
$id = $data['ID'];
|
$id = $data['ID'];
|
||||||
$record = SiteTree::get()->byID($id);
|
$record = DataObject::get($this->getModelClass())->byID($id);
|
||||||
if ($record && !$record->canDelete()) {
|
if ($record && !$record->canDelete()) {
|
||||||
return Security::permissionFailure();
|
return Security::permissionFailure();
|
||||||
}
|
}
|
||||||
@ -1970,13 +1954,28 @@ class CMSMain extends LeftAndMain implements CurrentPageIdentifier, PermissionPr
|
|||||||
// Delete record
|
// Delete record
|
||||||
$record->delete();
|
$record->delete();
|
||||||
|
|
||||||
|
if ($record->hasExtension(Versioned::class) && $record->hasStages()) {
|
||||||
|
$message = _t(
|
||||||
|
LeftAndMain::class . '.ARCHIVED_RECORD',
|
||||||
|
'Archived {name} "{title}"',
|
||||||
|
[
|
||||||
|
'name' => $record->i18n_singular_name(),
|
||||||
|
'title' => $record->Title,
|
||||||
|
]
|
||||||
|
);
|
||||||
|
} else {
|
||||||
|
$message = _t(
|
||||||
|
LeftAndMain::class . '.DELETED_RECORD',
|
||||||
|
'Deleted {name} "{title}"',
|
||||||
|
[
|
||||||
|
'name' => $record->i18n_singular_name(),
|
||||||
|
'title' => $record->Title,
|
||||||
|
]
|
||||||
|
);
|
||||||
|
}
|
||||||
$this->getResponse()->addHeader(
|
$this->getResponse()->addHeader(
|
||||||
'X-Status',
|
'X-Status',
|
||||||
rawurlencode(_t(
|
rawurlencode($message)
|
||||||
__CLASS__ . '.REMOVEDPAGEFROMDRAFT',
|
|
||||||
"Removed '{title}' from the draft site",
|
|
||||||
['title' => $record->Title]
|
|
||||||
) ?? '')
|
|
||||||
);
|
);
|
||||||
|
|
||||||
// Even if the record has been deleted from stage and live, it can be viewed in "archive mode"
|
// Even if the record has been deleted from stage and live, it can be viewed in "archive mode"
|
||||||
@ -1984,14 +1983,14 @@ class CMSMain extends LeftAndMain implements CurrentPageIdentifier, PermissionPr
|
|||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Delete this page from both live and stage
|
* Delete this record from both live and stage
|
||||||
*
|
*
|
||||||
* @throws HTTPResponse_Exception
|
* @throws HTTPResponse_Exception
|
||||||
*/
|
*/
|
||||||
public function archive(array $data, Form $form): HTTPResponse
|
public function archive(array $data, Form $form): HTTPResponse
|
||||||
{
|
{
|
||||||
$id = $data['ID'];
|
$id = $data['ID'];
|
||||||
$record = SiteTree::get()->byID($id);
|
$record = DataObject::get($this->getModelClass())->byID($id);
|
||||||
if (!$record || !$record->exists()) {
|
if (!$record || !$record->exists()) {
|
||||||
throw new HTTPResponse_Exception("Bad record ID #$id", 404);
|
throw new HTTPResponse_Exception("Bad record ID #$id", 404);
|
||||||
}
|
}
|
||||||
@ -2005,10 +2004,13 @@ class CMSMain extends LeftAndMain implements CurrentPageIdentifier, PermissionPr
|
|||||||
$this->getResponse()->addHeader(
|
$this->getResponse()->addHeader(
|
||||||
'X-Status',
|
'X-Status',
|
||||||
rawurlencode(_t(
|
rawurlencode(_t(
|
||||||
__CLASS__ . '.ARCHIVEDPAGE',
|
LeftAndMain::class . '.ARCHIVED_RECORD',
|
||||||
"Archived page '{title}'",
|
'Archived {name} "{title}"',
|
||||||
['title' => $record->Title]
|
[
|
||||||
) ?? '')
|
'name' => $record->i18n_singular_name(),
|
||||||
|
'title' => $record->Title,
|
||||||
|
]
|
||||||
|
))
|
||||||
);
|
);
|
||||||
|
|
||||||
// Even if the record has been deleted from stage and live, it can be viewed in "archive mode"
|
// Even if the record has been deleted from stage and live, it can be viewed in "archive mode"
|
||||||
@ -2024,10 +2026,13 @@ class CMSMain extends LeftAndMain implements CurrentPageIdentifier, PermissionPr
|
|||||||
|
|
||||||
public function unpublish(array $data, Form $form): HTTPResponse
|
public function unpublish(array $data, Form $form): HTTPResponse
|
||||||
{
|
{
|
||||||
$className = $this->config()->get('tree_class');
|
$className = $this->getModelClass();
|
||||||
/** @var SiteTree $record */
|
|
||||||
$record = DataObject::get_by_id($className, $data['ID']);
|
$record = DataObject::get_by_id($className, $data['ID']);
|
||||||
|
|
||||||
|
if (!$record->hasExtension(Versioned::class)) {
|
||||||
|
throw new HTTPResponse_Exception(get_class($record) . ' record cannot be unpublished.', 400);
|
||||||
|
}
|
||||||
|
|
||||||
if ($record && !$record->canUnpublish()) {
|
if ($record && !$record->canUnpublish()) {
|
||||||
return Security::permissionFailure($this);
|
return Security::permissionFailure($this);
|
||||||
}
|
}
|
||||||
@ -2040,10 +2045,13 @@ class CMSMain extends LeftAndMain implements CurrentPageIdentifier, PermissionPr
|
|||||||
$this->getResponse()->addHeader(
|
$this->getResponse()->addHeader(
|
||||||
'X-Status',
|
'X-Status',
|
||||||
rawurlencode(_t(
|
rawurlencode(_t(
|
||||||
__CLASS__ . '.REMOVEDPAGE',
|
LeftAndMain::class . '.UNPUBLISHED_RECORD',
|
||||||
"Removed '{title}' from the published site",
|
'Unpublished {name} "{title}"',
|
||||||
['title' => $record->Title]
|
[
|
||||||
) ?? '')
|
'name' => $record->i18n_singular_name(),
|
||||||
|
'title' => $record->Title,
|
||||||
|
]
|
||||||
|
))
|
||||||
);
|
);
|
||||||
|
|
||||||
return $this->getResponseNegotiator()->respond($this->getRequest());
|
return $this->getResponseNegotiator()->respond($this->getRequest());
|
||||||
@ -2055,7 +2063,7 @@ class CMSMain extends LeftAndMain implements CurrentPageIdentifier, PermissionPr
|
|||||||
public function rollback()
|
public function rollback()
|
||||||
{
|
{
|
||||||
return $this->doRollback([
|
return $this->doRollback([
|
||||||
'ID' => $this->currentPageID(),
|
'ID' => $this->currentRecordID(),
|
||||||
'Version' => $this->getRequest()->param('VersionID')
|
'Version' => $this->getRequest()->param('VersionID')
|
||||||
], null);
|
], null);
|
||||||
}
|
}
|
||||||
@ -2074,8 +2082,13 @@ class CMSMain extends LeftAndMain implements CurrentPageIdentifier, PermissionPr
|
|||||||
$id = (isset($data['ID'])) ? (int) $data['ID'] : null;
|
$id = (isset($data['ID'])) ? (int) $data['ID'] : null;
|
||||||
$version = (isset($data['Version'])) ? (int) $data['Version'] : null;
|
$version = (isset($data['Version'])) ? (int) $data['Version'] : null;
|
||||||
|
|
||||||
/** @var SiteTree|Versioned $record */
|
$modelClass = $this->getModelClass();
|
||||||
$record = Versioned::get_latest_version($this->config()->get('tree_class'), $id);
|
if (!$modelClass::has_extension(Versioned::class)) {
|
||||||
|
throw new HTTPResponse_Exception("$modelClass record cannot be rolled back", 400);
|
||||||
|
}
|
||||||
|
|
||||||
|
/** @var DataObject&Versioned $record */
|
||||||
|
$record = Versioned::get_latest_version($modelClass, $id);
|
||||||
if ($record && !$record->canEdit()) {
|
if ($record && !$record->canEdit()) {
|
||||||
return Security::permissionFailure($this);
|
return Security::permissionFailure($this);
|
||||||
}
|
}
|
||||||
@ -2083,22 +2096,22 @@ class CMSMain extends LeftAndMain implements CurrentPageIdentifier, PermissionPr
|
|||||||
if ($version) {
|
if ($version) {
|
||||||
$record->rollbackRecursive($version);
|
$record->rollbackRecursive($version);
|
||||||
$message = _t(
|
$message = _t(
|
||||||
__CLASS__ . '.ROLLEDBACKVERSIONv2',
|
LeftAndMain::class . '.ROLLEDBACK_VERSION',
|
||||||
"Rolled back to version #{version}.",
|
'Rolled back to version #{version}.',
|
||||||
['version' => $data['Version']]
|
['version' => $data['Version']]
|
||||||
);
|
);
|
||||||
} else {
|
} else {
|
||||||
$record->doRevertToLive();
|
$record->doRevertToLive();
|
||||||
$record->publishRecursive();
|
$record->publishRecursive();
|
||||||
$message = _t(
|
$message = _t(
|
||||||
__CLASS__ . '.ROLLEDBACKPUBv2',
|
LeftAndMain::class . '.ROLLEDBACK_PUBLISHED',
|
||||||
"Rolled back to published version."
|
'Rolled back to published version.'
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
$this->getResponse()->addHeader('X-Status', rawurlencode($message ?? ''));
|
$this->getResponse()->addHeader('X-Status', rawurlencode($message ?? ''));
|
||||||
|
|
||||||
// Can be used in different contexts: In normal page edit view, in which case the redirect won't have any effect.
|
// Can be used in different contexts: In normal record edit view, in which case the redirect won't have any effect.
|
||||||
// Or in history view, in which case a revert causes the CMS to re-load the edit view.
|
// Or in history view, in which case a revert causes the CMS to re-load the edit view.
|
||||||
// The X-Pjax header forces a "full" content refresh on redirect.
|
// The X-Pjax header forces a "full" content refresh on redirect.
|
||||||
$url = $record->getCMSEditLink();
|
$url = $record->getCMSEditLink();
|
||||||
@ -2142,11 +2155,11 @@ class CMSMain extends LeftAndMain implements CurrentPageIdentifier, PermissionPr
|
|||||||
$forms[$urlSegment] = $formHtml;
|
$forms[$urlSegment] = $formHtml;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
$pageHtml = '';
|
$recordHtml = '';
|
||||||
foreach ($forms as $urlSegment => $html) {
|
foreach ($forms as $urlSegment => $html) {
|
||||||
$pageHtml .= '<div class="params" id="BatchActionParameters_' . $urlSegment . '" style="display:none">' . $html . '</div>';
|
$recordHtml .= '<div class="params" id="BatchActionParameters_' . $urlSegment . '" style="display:none">' . $html . '</div>';
|
||||||
}
|
}
|
||||||
return new LiteralField('BatchActionParameters', '<div id="BatchActionParameters" class="action-parameters" style="display:none">' . $pageHtml . '</div>');
|
return new LiteralField('BatchActionParameters', '<div id="BatchActionParameters" class="action-parameters" style="display:none">' . $recordHtml . '</div>');
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -2158,7 +2171,7 @@ class CMSMain extends LeftAndMain implements CurrentPageIdentifier, PermissionPr
|
|||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Restore a completely deleted page from the SiteTree_versions table.
|
* Restore a completely deleted record from the *_versions table.
|
||||||
*/
|
*/
|
||||||
public function restore(array $data, Form $form): HTTPResponse
|
public function restore(array $data, Form $form): HTTPResponse
|
||||||
{
|
{
|
||||||
@ -2166,21 +2179,29 @@ class CMSMain extends LeftAndMain implements CurrentPageIdentifier, PermissionPr
|
|||||||
return new HTTPResponse("Please pass an ID in the form content", 400);
|
return new HTTPResponse("Please pass an ID in the form content", 400);
|
||||||
}
|
}
|
||||||
|
|
||||||
$id = (int)$data['ID'];
|
$modelClass = $this->getModelClass();
|
||||||
$restoredPage = Versioned::get_latest_version(SiteTree::class, $id);
|
if (!$modelClass::has_extension(Versioned::class)) {
|
||||||
if (!$restoredPage) {
|
throw new HTTPResponse_Exception("$modelClass record cannot be restored", 400);
|
||||||
return new HTTPResponse("SiteTree #$id not found", 400);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
$restoredPage = $restoredPage->doRestoreToStage();
|
$id = (int)$data['ID'];
|
||||||
|
$restoredRecord = Versioned::get_latest_version($modelClass, $id);
|
||||||
|
if (!$restoredRecord) {
|
||||||
|
return new HTTPResponse("Record #$id not found", 400);
|
||||||
|
}
|
||||||
|
|
||||||
|
$restoredRecord = $restoredRecord->doRestoreToStage();
|
||||||
|
|
||||||
$this->getResponse()->addHeader(
|
$this->getResponse()->addHeader(
|
||||||
'X-Status',
|
'X-Status',
|
||||||
rawurlencode(_t(
|
rawurlencode(_t(
|
||||||
__CLASS__ . '.RESTORED',
|
LeftAndMain::class . '.RESTORED_RECORD',
|
||||||
"Restored '{title}' successfully",
|
'Restored {name} "{title}"',
|
||||||
['title' => $restoredPage->Title]
|
[
|
||||||
) ?? '')
|
'name' => $restoredRecord->i18n_singular_name(),
|
||||||
|
'title' => $restoredRecord->Title,
|
||||||
|
]
|
||||||
|
))
|
||||||
);
|
);
|
||||||
|
|
||||||
return $this->getResponseNegotiator()->respond($this->getRequest());
|
return $this->getResponseNegotiator()->respond($this->getRequest());
|
||||||
@ -2194,31 +2215,34 @@ class CMSMain extends LeftAndMain implements CurrentPageIdentifier, PermissionPr
|
|||||||
}
|
}
|
||||||
|
|
||||||
if (($id = $this->urlParams['ID']) && is_numeric($id)) {
|
if (($id = $this->urlParams['ID']) && is_numeric($id)) {
|
||||||
$page = SiteTree::get()->byID($id);
|
$record = DataObject::get($this->getModelClass())->byID($id);
|
||||||
if ($page && !$page->canCreate(null, ['Parent' => $page->Parent()])) {
|
if ($record && !$record->canCreate(null, ['Parent' => $record->Parent()])) {
|
||||||
return Security::permissionFailure($this);
|
return Security::permissionFailure($this);
|
||||||
}
|
}
|
||||||
if (!$page || !$page->ID) {
|
if (!$record || !$record->ID) {
|
||||||
throw new HTTPResponse_Exception("Bad record ID #$id", 404);
|
throw new HTTPResponse_Exception("Bad record ID #$id", 404);
|
||||||
}
|
}
|
||||||
|
|
||||||
$newPage = $page->duplicate();
|
$newRecord = $record->duplicate();
|
||||||
|
|
||||||
// ParentID can be hard-set in the URL. This is useful for pages with multiple parents
|
// ParentID can be hard-set in the URL. This is useful for pages with multiple parents
|
||||||
if (isset($_GET['parentID']) && is_numeric($_GET['parentID'])) {
|
if (isset($_GET['parentID']) && is_numeric($_GET['parentID'])) {
|
||||||
$newPage->ParentID = $_GET['parentID'];
|
$newRecord->ParentID = $_GET['parentID'];
|
||||||
$newPage->write();
|
$newRecord->write();
|
||||||
}
|
}
|
||||||
|
|
||||||
$this->getResponse()->addHeader(
|
$this->getResponse()->addHeader(
|
||||||
'X-Status',
|
'X-Status',
|
||||||
rawurlencode(_t(
|
rawurlencode(_t(
|
||||||
__CLASS__ . '.DUPLICATED',
|
LeftAndMain::class . '.DUPLICATED_RECORD',
|
||||||
"Duplicated '{title}' successfully",
|
'Duplicated {name} "{title}"',
|
||||||
['title' => $newPage->Title]
|
[
|
||||||
) ?? '')
|
'name' => $newRecord->i18n_singular_name(),
|
||||||
|
'title' => $newRecord->Title,
|
||||||
|
]
|
||||||
|
))
|
||||||
);
|
);
|
||||||
$url = $newPage->getCMSEditLink();
|
$url = $newRecord->getCMSEditLink();
|
||||||
$this->getResponse()->addHeader('X-ControllerURL', $url);
|
$this->getResponse()->addHeader('X-ControllerURL', $url);
|
||||||
$this->getRequest()->addHeader('X-Pjax', 'Content');
|
$this->getRequest()->addHeader('X-Pjax', 'Content');
|
||||||
$this->getResponse()->addHeader('X-Pjax', 'Content');
|
$this->getResponse()->addHeader('X-Pjax', 'Content');
|
||||||
@ -2236,25 +2260,28 @@ class CMSMain extends LeftAndMain implements CurrentPageIdentifier, PermissionPr
|
|||||||
}
|
}
|
||||||
Environment::increaseTimeLimitTo();
|
Environment::increaseTimeLimitTo();
|
||||||
if (($id = $this->urlParams['ID']) && is_numeric($id)) {
|
if (($id = $this->urlParams['ID']) && is_numeric($id)) {
|
||||||
$page = SiteTree::get()->byID($id);
|
$record = DataObject::get($this->getModelClass())->byID($id);
|
||||||
if ($page && !$page->canCreate(null, ['Parent' => $page->Parent()])) {
|
if ($record && !$record->canCreate(null, ['Parent' => $record->Parent()])) {
|
||||||
return Security::permissionFailure($this);
|
return Security::permissionFailure($this);
|
||||||
}
|
}
|
||||||
if (!$page || !$page->ID) {
|
if (!$record || !$record->ID) {
|
||||||
throw new HTTPResponse_Exception("Bad record ID #$id", 404);
|
throw new HTTPResponse_Exception("Bad record ID #$id", 404);
|
||||||
}
|
}
|
||||||
|
|
||||||
$newPage = $page->duplicateWithChildren();
|
$newRecord = $record->duplicateWithChildren();
|
||||||
|
|
||||||
$this->getResponse()->addHeader(
|
$this->getResponse()->addHeader(
|
||||||
'X-Status',
|
'X-Status',
|
||||||
rawurlencode(_t(
|
rawurlencode(_t(
|
||||||
__CLASS__ . '.DUPLICATEDWITHCHILDREN',
|
LeftAndMain::class . '.DUPLICATED_RECORD_WITH_CHILDREN',
|
||||||
"Duplicated '{title}' and children successfully",
|
'Duplicated {name} "{title}" and children',
|
||||||
['title' => $newPage->Title]
|
[
|
||||||
|
'name' => $newRecord->i18n_singular_name(),
|
||||||
|
'title' => $newRecord->Title,
|
||||||
|
]
|
||||||
) ?? '')
|
) ?? '')
|
||||||
);
|
);
|
||||||
$url = $newPage->getCMSEditLink();
|
$url = $newRecord->getCMSEditLink();
|
||||||
$this->getResponse()->addHeader('X-ControllerURL', $url);
|
$this->getResponse()->addHeader('X-ControllerURL', $url);
|
||||||
$this->getRequest()->addHeader('X-Pjax', 'Content');
|
$this->getRequest()->addHeader('X-Pjax', 'Content');
|
||||||
$this->getResponse()->addHeader('X-Pjax', 'Content');
|
$this->getResponse()->addHeader('X-Pjax', 'Content');
|
||||||
@ -2269,8 +2296,8 @@ class CMSMain extends LeftAndMain implements CurrentPageIdentifier, PermissionPr
|
|||||||
$title = CMSPagesController::menu_title();
|
$title = CMSPagesController::menu_title();
|
||||||
return [
|
return [
|
||||||
"CMS_ACCESS_CMSMain" => [
|
"CMS_ACCESS_CMSMain" => [
|
||||||
'name' => _t(__CLASS__ . '.ACCESS', "Access to '{title}' section", ['title' => $title]),
|
'name' => _t(LeftAndMain::class . '.ACCESS', "Access to '{title}' section", ['title' => $title]),
|
||||||
'category' => _t('SilverStripe\\Security\\Permission.CMS_ACCESS_CATEGORY', 'CMS Access'),
|
'category' => _t(LeftAndMain::class . '.CMS_ACCESS_CATEGORY', 'CMS Access'),
|
||||||
'help' => _t(
|
'help' => _t(
|
||||||
__CLASS__ . '.ACCESS_HELP',
|
__CLASS__ . '.ACCESS_HELP',
|
||||||
'Allow viewing of the section containing page tree and content. View and edit permissions can be handled through page specific dropdowns, as well as the separate "Content permissions".'
|
'Allow viewing of the section containing page tree and content. View and edit permissions can be handled through page specific dropdowns, as well as the separate "Content permissions".'
|
||||||
@ -2293,7 +2320,7 @@ class CMSMain extends LeftAndMain implements CurrentPageIdentifier, PermissionPr
|
|||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Cache key for SiteTreeHints() method
|
* Cache key for TreeHints() method
|
||||||
*
|
*
|
||||||
* @param $memberID
|
* @param $memberID
|
||||||
* @return string
|
* @return string
|
||||||
|
@ -2,17 +2,15 @@
|
|||||||
|
|
||||||
namespace SilverStripe\CMS\Controllers;
|
namespace SilverStripe\CMS\Controllers;
|
||||||
|
|
||||||
use Page;
|
|
||||||
use SilverStripe\Admin\LeftAndMain;
|
use SilverStripe\Admin\LeftAndMain;
|
||||||
use SilverStripe\CampaignAdmin\AddToCampaignHandler;
|
use SilverStripe\CampaignAdmin\AddToCampaignHandler;
|
||||||
use SilverStripe\CMS\Model\SiteTree;
|
|
||||||
use SilverStripe\Control\Controller;
|
use SilverStripe\Control\Controller;
|
||||||
use SilverStripe\Control\HTTPRequest;
|
use SilverStripe\Control\HTTPRequest;
|
||||||
use SilverStripe\Control\HTTPResponse;
|
use SilverStripe\Control\HTTPResponse;
|
||||||
use SilverStripe\Forms\Form;
|
use SilverStripe\Forms\Form;
|
||||||
use SilverStripe\Core\ArrayLib;
|
use SilverStripe\Core\ArrayLib;
|
||||||
use SilverStripe\ORM\FieldType\DBHTMLText;
|
|
||||||
use SilverStripe\Core\Validation\ValidationResult;
|
use SilverStripe\Core\Validation\ValidationResult;
|
||||||
|
use SilverStripe\ORM\DataObject;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @package cms
|
* @package cms
|
||||||
@ -57,7 +55,7 @@ class CMSPageEditController extends CMSMain
|
|||||||
public function addtocampaign(array $data, Form $form): HTTPResponse
|
public function addtocampaign(array $data, Form $form): HTTPResponse
|
||||||
{
|
{
|
||||||
$id = $data['ID'];
|
$id = $data['ID'];
|
||||||
$record = \Page::get()->byID($id);
|
$record = DataObject::get($this->getModelClass())->byID($id);
|
||||||
|
|
||||||
$handler = AddToCampaignHandler::create($this, $record);
|
$handler = AddToCampaignHandler::create($this, $record);
|
||||||
$response = $handler->addToCampaign($record, $data);
|
$response = $handler->addToCampaign($record, $data);
|
||||||
@ -95,15 +93,16 @@ class CMSPageEditController extends CMSMain
|
|||||||
*/
|
*/
|
||||||
public function getAddToCampaignForm($id)
|
public function getAddToCampaignForm($id)
|
||||||
{
|
{
|
||||||
|
$modelClass = $this->getModelClass();
|
||||||
// Get record-specific fields
|
// Get record-specific fields
|
||||||
$record = SiteTree::get()->byID($id);
|
$record = DataObject::get($modelClass)->byID($id);
|
||||||
|
|
||||||
if (!$record) {
|
if (!$record) {
|
||||||
$this->httpError(404, _t(
|
$this->httpError(404, _t(
|
||||||
__CLASS__ . '.ErrorNotFound',
|
__CLASS__ . '.ErrorNotFound',
|
||||||
'That {Type} couldn\'t be found',
|
'That {Type} couldn\'t be found',
|
||||||
'',
|
'',
|
||||||
['Type' => Page::singleton()->i18n_singular_name()]
|
['Type' => DataObject::singleton($modelClass)->i18n_singular_name()]
|
||||||
));
|
));
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
@ -112,7 +111,7 @@ class CMSPageEditController extends CMSMain
|
|||||||
__CLASS__.'.ErrorItemPermissionDenied',
|
__CLASS__.'.ErrorItemPermissionDenied',
|
||||||
'It seems you don\'t have the necessary permissions to add {ObjectTitle} to a campaign',
|
'It seems you don\'t have the necessary permissions to add {ObjectTitle} to a campaign',
|
||||||
'',
|
'',
|
||||||
['ObjectTitle' => Page::singleton()->i18n_singular_name()]
|
['ObjectTitle' => DataObject::singleton($modelClass)->i18n_singular_name()]
|
||||||
));
|
));
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
@ -2,6 +2,7 @@
|
|||||||
|
|
||||||
namespace SilverStripe\CMS\Controllers;
|
namespace SilverStripe\CMS\Controllers;
|
||||||
|
|
||||||
|
use SilverStripe\Forms\Form;
|
||||||
use SilverStripe\Model\ArrayData;
|
use SilverStripe\Model\ArrayData;
|
||||||
|
|
||||||
class CMSPageSettingsController extends CMSMain
|
class CMSPageSettingsController extends CMSMain
|
||||||
@ -15,11 +16,19 @@ class CMSPageSettingsController extends CMSMain
|
|||||||
|
|
||||||
private static $required_permission_codes = 'CMS_ACCESS_CMSMain';
|
private static $required_permission_codes = 'CMS_ACCESS_CMSMain';
|
||||||
|
|
||||||
public function getEditForm($id = null, $fields = null)
|
public function getEditForm($id = null, $fields = null): Form
|
||||||
{
|
{
|
||||||
$record = $this->getRecord($id ?: $this->currentPageID());
|
$record = $this->getRecord($id ?: $this->currentRecordID());
|
||||||
|
|
||||||
return parent::getEditForm($id, ($record) ? $record->getSettingsFields() : null);
|
// @TODO ideally settings isn't its own special thing...
|
||||||
|
// can we refactor this so it's just another tab in the main form? And just have it lazyload or something?
|
||||||
|
// At the very least this tab must NOT appear if there are no fields for it.
|
||||||
|
if ($record && $record->hasMethod('getSettingsFields')) {
|
||||||
|
$fields = $record->getSettingsFields();
|
||||||
|
} else {
|
||||||
|
$fields = null;
|
||||||
|
}
|
||||||
|
return parent::getEditForm($id, $fields);
|
||||||
}
|
}
|
||||||
|
|
||||||
public function getTabIdentifier()
|
public function getTabIdentifier()
|
||||||
|
@ -2,16 +2,11 @@
|
|||||||
|
|
||||||
namespace SilverStripe\CMS\Controllers;
|
namespace SilverStripe\CMS\Controllers;
|
||||||
|
|
||||||
use SilverStripe\CMS\Model\SiteTree;
|
|
||||||
use SilverStripe\Control\Controller;
|
|
||||||
use SilverStripe\Model\List\ArrayList;
|
|
||||||
use SilverStripe\ORM\DataObject;
|
use SilverStripe\ORM\DataObject;
|
||||||
use SilverStripe\Model\ArrayData;
|
|
||||||
use stdClass;
|
|
||||||
|
|
||||||
|
// @TODO What a pointless class!!!!!!
|
||||||
class CMSPagesController extends CMSMain
|
class CMSPagesController extends CMSMain
|
||||||
{
|
{
|
||||||
|
|
||||||
private static $url_segment = 'pages';
|
private static $url_segment = 'pages';
|
||||||
|
|
||||||
private static $url_rule = '/$Action/$ID/$OtherID';
|
private static $url_rule = '/$Action/$ID/$OtherID';
|
||||||
@ -27,7 +22,7 @@ class CMSPagesController extends CMSMain
|
|||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
public function isCurrentPage(DataObject $record)
|
public function isCurrentRecord(DataObject $record)
|
||||||
{
|
{
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
@ -113,7 +113,7 @@ abstract class CMSSiteTreeFilter implements LeftAndMain_SearchFilter
|
|||||||
return $this->numChildrenMethod;
|
return $this->numChildrenMethod;
|
||||||
}
|
}
|
||||||
|
|
||||||
public function getPageClasses($page)
|
public function getRecordClasses($page)
|
||||||
{
|
{
|
||||||
if ($this->_cache_ids === null) {
|
if ($this->_cache_ids === null) {
|
||||||
$this->populateIDs();
|
$this->populateIDs();
|
||||||
@ -178,7 +178,7 @@ abstract class CMSSiteTreeFilter implements LeftAndMain_SearchFilter
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public function isPageIncluded($page)
|
public function isRecordIncluded($page)
|
||||||
{
|
{
|
||||||
if ($this->_cache_ids === null) {
|
if ($this->_cache_ids === null) {
|
||||||
$this->populateIDs();
|
$this->populateIDs();
|
||||||
|
@ -18,6 +18,8 @@ use SilverStripe\View\Requirements;
|
|||||||
/**
|
/**
|
||||||
* Extension to include custom page icons
|
* Extension to include custom page icons
|
||||||
*
|
*
|
||||||
|
* @TODO AAAHHHHHHHHHHH
|
||||||
|
*
|
||||||
* @extends Extension<LeftAndMain>
|
* @extends Extension<LeftAndMain>
|
||||||
*/
|
*/
|
||||||
class LeftAndMainPageIconsExtension extends Extension implements Flushable
|
class LeftAndMainPageIconsExtension extends Extension implements Flushable
|
||||||
|
@ -1,10 +1,10 @@
|
|||||||
<?php
|
<?php
|
||||||
|
|
||||||
namespace SilverStripe\CMS\Controllers;
|
namespace SilverStripe\CMS\Forms;
|
||||||
|
|
||||||
|
use SilverStripe\CMS\Controllers\CMSMain;
|
||||||
|
use SilverStripe\CMS\Controllers\CMSPageEditController;
|
||||||
use SilverStripe\CMS\Model\SiteTree;
|
use SilverStripe\CMS\Model\SiteTree;
|
||||||
use SilverStripe\Control\Controller;
|
|
||||||
use SilverStripe\Control\Session;
|
|
||||||
use SilverStripe\Control\HTTPResponse;
|
use SilverStripe\Control\HTTPResponse;
|
||||||
use SilverStripe\Core\Config\Config;
|
use SilverStripe\Core\Config\Config;
|
||||||
use SilverStripe\Core\Convert;
|
use SilverStripe\Core\Convert;
|
||||||
@ -18,39 +18,22 @@ use SilverStripe\Forms\SelectionGroup_Item;
|
|||||||
use SilverStripe\Forms\TreeDropdownField;
|
use SilverStripe\Forms\TreeDropdownField;
|
||||||
use SilverStripe\ORM\DataObject;
|
use SilverStripe\ORM\DataObject;
|
||||||
use SilverStripe\ORM\FieldType\DBField;
|
use SilverStripe\ORM\FieldType\DBField;
|
||||||
use SilverStripe\Core\Validation\ValidationResult;
|
|
||||||
use SilverStripe\Security\Member;
|
|
||||||
use SilverStripe\Security\Security;
|
use SilverStripe\Security\Security;
|
||||||
use SilverStripe\SiteConfig\SiteConfig;
|
use SilverStripe\SiteConfig\SiteConfig;
|
||||||
|
|
||||||
class CMSPageAddController extends CMSPageEditController
|
class CMSMainAddForm extends Form
|
||||||
{
|
{
|
||||||
|
public function __construct(CMSMain $controller)
|
||||||
private static $url_segment = 'pages/add';
|
|
||||||
private static $url_rule = '/$Action/$ID/$OtherID';
|
|
||||||
private static $url_priority = 42;
|
|
||||||
private static $menu_title = 'Add page';
|
|
||||||
private static $required_permission_codes = 'CMS_ACCESS_CMSMain';
|
|
||||||
|
|
||||||
private static $allowed_actions = [
|
|
||||||
'AddForm',
|
|
||||||
'doAdd',
|
|
||||||
'doCancel'
|
|
||||||
];
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @return Form
|
|
||||||
*/
|
|
||||||
public function AddForm()
|
|
||||||
{
|
{
|
||||||
|
$modelClass = $controller->getModelClass();
|
||||||
$pageTypes = [];
|
$pageTypes = [];
|
||||||
$defaultIcon = Config::inst()->get(SiteTree::class, 'icon_class');
|
$defaultIcon = Config::inst()->get($modelClass, 'icon_class'); // @TODO need a better place for default - maybe try default on class, and fallback to default on cmsmain?
|
||||||
|
|
||||||
foreach ($this->PageTypes() as $type) {
|
foreach ($controller->RecordTypes() as $type) {
|
||||||
$class = $type->getField('ClassName');
|
$class = $type->getField('ClassName');
|
||||||
$icon = Config::inst()->get($class, 'icon_class') ?: $defaultIcon;
|
$icon = Config::inst()->get($class, 'icon_class') ?: $defaultIcon;
|
||||||
|
|
||||||
// If the icon is the SiteTree default and there's some specific icon being provided by `getPageIconURL`
|
// If the icon is the default and there's some specific icon being provided by `getPageIconURL`
|
||||||
// then we don't need to add the icon class. Otherwise the class take precedence.
|
// then we don't need to add the icon class. Otherwise the class take precedence.
|
||||||
if ($icon === $defaultIcon && !empty(singleton($class)->getPageIconURL())) {
|
if ($icon === $defaultIcon && !empty(singleton($class)->getPageIconURL())) {
|
||||||
$icon = '';
|
$icon = '';
|
||||||
@ -73,24 +56,28 @@ class CMSPageAddController extends CMSPageEditController
|
|||||||
|
|
||||||
$numericLabelTmpl = '<span class="step-label"><span class="flyout">Step %d. </span><span class="title">%s</span></span>';
|
$numericLabelTmpl = '<span class="step-label"><span class="flyout">Step %d. </span><span class="title">%s</span></span>';
|
||||||
|
|
||||||
$topTitle = _t('SilverStripe\\CMS\\Controllers\\CMSPageAddController.ParentMode_top', 'Top level');
|
$topTitle = _t(__CLASS__ . '.ParentMode_top', 'Top level');
|
||||||
$childTitle = _t('SilverStripe\\CMS\\Controllers\\CMSPageAddController.ParentMode_child', 'Under another page');
|
$childTitle = _t(
|
||||||
|
__CLASS__ . '.ParentMode_child',
|
||||||
|
'Under another {type}',
|
||||||
|
['type' => mb_strtolower(DataObject::singleton($modelClass)->i18n_singular_name())]
|
||||||
|
);
|
||||||
|
|
||||||
$fields = new FieldList(
|
$fields = FieldList::create(
|
||||||
$parentModeField = new SelectionGroup(
|
$parentModeField = SelectionGroup::create(
|
||||||
"ParentModeField",
|
'ParentModeField',
|
||||||
[
|
[
|
||||||
$topField = new SelectionGroup_Item(
|
$topField = SelectionGroup_Item::create(
|
||||||
"top",
|
'top',
|
||||||
null,
|
null,
|
||||||
$topTitle
|
$topTitle
|
||||||
),
|
),
|
||||||
new SelectionGroup_Item(
|
SelectionGroup_Item::create(
|
||||||
'child',
|
'child',
|
||||||
$parentField = new TreeDropdownField(
|
$parentField = TreeDropdownField::create(
|
||||||
"ParentID",
|
'ParentID',
|
||||||
"",
|
'',
|
||||||
SiteTree::class,
|
$modelClass,
|
||||||
'ID',
|
'ID',
|
||||||
'TreeTitle'
|
'TreeTitle'
|
||||||
),
|
),
|
||||||
@ -98,7 +85,7 @@ class CMSPageAddController extends CMSPageEditController
|
|||||||
)
|
)
|
||||||
]
|
]
|
||||||
),
|
),
|
||||||
new LiteralField(
|
LiteralField::create(
|
||||||
'RestrictedNote',
|
'RestrictedNote',
|
||||||
sprintf(
|
sprintf(
|
||||||
'<p class="alert alert-info message-restricted">%s</p>',
|
'<p class="alert alert-info message-restricted">%s</p>',
|
||||||
@ -108,8 +95,8 @@ class CMSPageAddController extends CMSPageEditController
|
|||||||
)
|
)
|
||||||
)
|
)
|
||||||
),
|
),
|
||||||
$typeField = new OptionsetField(
|
OptionsetField::create(
|
||||||
"PageType",
|
'PageType',
|
||||||
DBField::create_field(
|
DBField::create_field(
|
||||||
'HTMLFragment',
|
'HTMLFragment',
|
||||||
sprintf($numericLabelTmpl ?? '', 2, _t('SilverStripe\\CMS\\Controllers\\CMSMain.ChoosePageType', 'Choose page type'))
|
sprintf($numericLabelTmpl ?? '', 2, _t('SilverStripe\\CMS\\Controllers\\CMSMain.ChoosePageType', 'Choose page type'))
|
||||||
@ -134,9 +121,9 @@ class CMSPageAddController extends CMSPageEditController
|
|||||||
|
|
||||||
$parentModeField->addExtraClass('parent-mode');
|
$parentModeField->addExtraClass('parent-mode');
|
||||||
|
|
||||||
// CMSMain->currentPageID() automatically sets the homepage,
|
// CMSMain->currentRecordID() automatically sets the homepage,
|
||||||
// which we need to counteract in the default selection (which should default to root, ID=0)
|
// which we need to counteract in the default selection (which should default to root, ID=0)
|
||||||
if ($parentID = $this->getRequest()->getVar('ParentID')) {
|
if ($parentID = $controller->getRequest()->getVar('ParentID')) {
|
||||||
$parentModeField->setValue('child');
|
$parentModeField->setValue('child');
|
||||||
$parentField->setValue((int)$parentID);
|
$parentField->setValue((int)$parentID);
|
||||||
} else {
|
} else {
|
||||||
@ -145,35 +132,32 @@ class CMSPageAddController extends CMSPageEditController
|
|||||||
|
|
||||||
// Check if the current user has enough permissions to create top level pages
|
// Check if the current user has enough permissions to create top level pages
|
||||||
// If not, then disable the option to do that
|
// If not, then disable the option to do that
|
||||||
if (!SiteConfig::current_site_config()->canCreateTopLevel()) {
|
if (is_a($modelClass, SiteTree::class, true) && !SiteConfig::current_site_config()->canCreateTopLevel()) { // @TODO probably need to make this generic
|
||||||
$topField->setDisabled(true);
|
$topField->setDisabled(true);
|
||||||
$parentModeField->setValue('child');
|
$parentModeField->setValue('child');
|
||||||
}
|
}
|
||||||
|
|
||||||
$actions = new FieldList(
|
$actions = FieldList::create(
|
||||||
FormAction::create("doAdd", _t('SilverStripe\\CMS\\Controllers\\CMSMain.Create', "Create"))
|
FormAction::create('doAdd', _t('SilverStripe\\CMS\\Controllers\\CMSMain.Create', 'Create'))
|
||||||
->addExtraClass('btn-primary font-icon-plus-circled')
|
->addExtraClass('btn-primary font-icon-plus-circled')
|
||||||
->setUseButtonTag(true),
|
->setUseButtonTag(true),
|
||||||
FormAction::create("doCancel", _t('SilverStripe\\CMS\\Controllers\\CMSMain.Cancel', "Cancel"))
|
FormAction::create('doCancel', _t('SilverStripe\\CMS\\Controllers\\CMSMain.Cancel', 'Cancel'))
|
||||||
->addExtraClass('btn-secondary')
|
->addExtraClass('btn-secondary')
|
||||||
->setUseButtonTag(true)
|
->setUseButtonTag(true)
|
||||||
);
|
);
|
||||||
|
|
||||||
$this->extend('updatePageOptions', $fields);
|
$controller->extend('updatePageOptions', $fields);
|
||||||
|
|
||||||
$negotiator = $this->getResponseNegotiator();
|
parent::__construct($controller, 'AddForm', $fields, $actions);
|
||||||
$form = Form::create(
|
|
||||||
$this,
|
$negotiator = $controller->getResponseNegotiator();
|
||||||
"AddForm",
|
$this->setHTMLID('Form_AddForm')->setStrictFormMethodCheck(false);
|
||||||
$fields,
|
$this->setAttribute('data-hints', $controller->TreeHints());
|
||||||
$actions
|
$this->setAttribute('data-childfilter', $controller->Link('childfilter'));
|
||||||
)->setHTMLID('Form_AddForm')->setStrictFormMethodCheck(false);
|
$this->setValidationResponseCallback(function () use ($negotiator, $controller) {
|
||||||
$form->setAttribute('data-hints', $this->SiteTreeHints());
|
$request = $controller->getRequest();
|
||||||
$form->setAttribute('data-childfilter', $this->Link('childfilter'));
|
|
||||||
$form->setValidationResponseCallback(function (ValidationResult $errors) use ($negotiator, $form) {
|
|
||||||
$request = $this->getRequest();
|
|
||||||
if ($request->isAjax() && $negotiator) {
|
if ($request->isAjax() && $negotiator) {
|
||||||
$result = $form->forTemplate();
|
$result = $this->forTemplate();
|
||||||
return $negotiator->respond($request, [
|
return $negotiator->respond($request, [
|
||||||
'CurrentForm' => function () use ($result) {
|
'CurrentForm' => function () use ($result) {
|
||||||
return $result;
|
return $result;
|
||||||
@ -182,26 +166,26 @@ class CMSPageAddController extends CMSPageEditController
|
|||||||
}
|
}
|
||||||
return null;
|
return null;
|
||||||
});
|
});
|
||||||
$form->addExtraClass('flexbox-area-grow fill-height cms-add-form cms-content cms-edit-form ' . $this->BaseCSSClasses());
|
$this->addExtraClass('flexbox-area-grow fill-height cms-add-form cms-content cms-edit-form ' . $controller->BaseCSSClasses());
|
||||||
$form->setTemplate($this->getTemplatesWithSuffix('_EditForm'));
|
$this->setTemplate($controller->getTemplatesWithSuffix('_AddForm'));
|
||||||
|
|
||||||
return $form;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public function doAdd(array $data, Form $form): HTTPResponse
|
public function doAdd(array $data, Form $form): HTTPResponse
|
||||||
{
|
{
|
||||||
|
$controller = $this->getController();
|
||||||
|
$modelClass = $controller->getModelClass();
|
||||||
$className = isset($data['PageType']) ? $data['PageType'] : "Page";
|
$className = isset($data['PageType']) ? $data['PageType'] : "Page";
|
||||||
$parentID = isset($data['ParentID']) ? (int)$data['ParentID'] : 0;
|
$parentID = isset($data['ParentID']) ? (int)$data['ParentID'] : 0;
|
||||||
|
|
||||||
if (!$parentID && isset($data['Parent'])) {
|
if (!$parentID && isset($data['Parent'])) {
|
||||||
$page = SiteTree::get_by_link($data['Parent']);
|
$page = $modelClass::get_by_link($data['Parent']); // @TODO Obviously no good
|
||||||
if ($page) {
|
if ($page) {
|
||||||
$parentID = $page->ID;
|
$parentID = $page->ID;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (is_numeric($parentID) && $parentID > 0) {
|
if (is_numeric($parentID) && $parentID > 0) {
|
||||||
$parentObj = SiteTree::get()->byID($parentID);
|
$parentObj = DataObject::get($modelClass)->byID($parentID);
|
||||||
} else {
|
} else {
|
||||||
$parentObj = null;
|
$parentObj = null;
|
||||||
}
|
}
|
||||||
@ -211,16 +195,16 @@ class CMSPageAddController extends CMSPageEditController
|
|||||||
}
|
}
|
||||||
|
|
||||||
if (!singleton($className)->canCreate(Security::getCurrentUser(), ['Parent' => $parentObj])) {
|
if (!singleton($className)->canCreate(Security::getCurrentUser(), ['Parent' => $parentObj])) {
|
||||||
return Security::permissionFailure($this);
|
return Security::permissionFailure($controller);
|
||||||
}
|
}
|
||||||
|
|
||||||
$record = $this->getNewItem("new-$className-$parentID", false);
|
$record = $controller->getNewItem("new-$className-$parentID", false);
|
||||||
$this->extend('updateDoAdd', $record, $form);
|
$controller->extend('updateDoAdd', $record, $form);
|
||||||
$record->write();
|
$record->write();
|
||||||
|
|
||||||
$editController = CMSPageEditController::singleton();
|
$editController = CMSPageEditController::singleton();
|
||||||
$editController->setRequest($this->getRequest());
|
$editController->setRequest($controller->getRequest());
|
||||||
$editController->setCurrentPageID($record->ID);
|
$editController->setCurrentRecordID($record->ID);
|
||||||
|
|
||||||
$session = $this->getRequest()->getSession();
|
$session = $this->getRequest()->getSession();
|
||||||
$session->set(
|
$session->set(
|
||||||
@ -229,11 +213,11 @@ class CMSPageAddController extends CMSPageEditController
|
|||||||
);
|
);
|
||||||
$session->set("FormInfo.Form_EditForm.formError.type", 'good');
|
$session->set("FormInfo.Form_EditForm.formError.type", 'good');
|
||||||
|
|
||||||
return $this->redirect(Controller::join_links($editController->Link('show'), $record->ID));
|
return $controller->redirect($editController->Link('show/' . $record->ID));
|
||||||
}
|
}
|
||||||
|
|
||||||
public function doCancel(array $data, Form $form): HTTPResponse
|
public function doCancel(): HTTPResponse
|
||||||
{
|
{
|
||||||
return $this->redirect(CMSMain::singleton()->Link());
|
return $this->getController()->redirect(CMSMain::singleton()->Link()); // @TODO when there's no CMSPageEditController anymore, change this to $this->getController()->Link()
|
||||||
}
|
}
|
||||||
}
|
}
|
@ -7,19 +7,19 @@ use SilverStripe\ORM\DataObject;
|
|||||||
/**
|
/**
|
||||||
* This interface lets us set up objects that will tell us what the current page is.
|
* This interface lets us set up objects that will tell us what the current page is.
|
||||||
*/
|
*/
|
||||||
interface CurrentPageIdentifier
|
interface CurrentRecordIdentifier
|
||||||
{
|
{
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Get the current page ID.
|
* Get the current page ID.
|
||||||
* @return int
|
* @return int
|
||||||
*/
|
*/
|
||||||
public function currentPageID();
|
public function currentRecordID();
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Check if the given DataObject is the current page.
|
* Check if the given DataObject is the current page.
|
||||||
* @param DataObject $page The page to check.
|
* @param DataObject $page The page to check.
|
||||||
* @return boolean
|
* @return boolean
|
||||||
*/
|
*/
|
||||||
public function isCurrentPage(DataObject $page);
|
public function isCurrentRecord(DataObject $page);
|
||||||
}
|
}
|
@ -783,12 +783,12 @@ class SiteTree extends DataObject implements PermissionProvider, i18nEntityProvi
|
|||||||
*/
|
*/
|
||||||
public function isCurrent()
|
public function isCurrent()
|
||||||
{
|
{
|
||||||
$currentPage = Director::get_current_page();
|
$currentRecord = Director::get_current_page();
|
||||||
if ($currentPage instanceof ContentController) {
|
if ($currentRecord instanceof ContentController) {
|
||||||
$currentPage = $currentPage->data();
|
$currentRecord = $currentRecord->data();
|
||||||
}
|
}
|
||||||
if ($currentPage instanceof SiteTree) {
|
if ($currentRecord instanceof SiteTree) {
|
||||||
return $currentPage === $this || $currentPage->ID === $this->ID;
|
return $currentRecord === $this || $currentRecord->ID === $this->ID;
|
||||||
}
|
}
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
@ -2778,9 +2778,9 @@ class SiteTree extends DataObject implements PermissionProvider, i18nEntityProvi
|
|||||||
// Sort alphabetically, and put current on top
|
// Sort alphabetically, and put current on top
|
||||||
asort($result);
|
asort($result);
|
||||||
if (isset($result[$this->ClassName])) {
|
if (isset($result[$this->ClassName])) {
|
||||||
$currentPageTypeName = $result[$this->ClassName];
|
$currentRecordTypeName = $result[$this->ClassName];
|
||||||
unset($result[$this->ClassName]);
|
unset($result[$this->ClassName]);
|
||||||
$result = [$this->ClassName => $currentPageTypeName] + $result;
|
$result = [$this->ClassName => $currentRecordTypeName] + $result;
|
||||||
}
|
}
|
||||||
|
|
||||||
return $result;
|
return $result;
|
||||||
|
@ -256,6 +256,8 @@ en:
|
|||||||
TABCONTENT: 'Main content'
|
TABCONTENT: 'Main content'
|
||||||
TABDEPENDENT: 'Dependent pages'
|
TABDEPENDENT: 'Dependent pages'
|
||||||
TOPLEVEL: 'Site Content (Top Level)'
|
TOPLEVEL: 'Site Content (Top Level)'
|
||||||
|
TREETITLE: 'Page name'
|
||||||
|
TREETYPE: 'Page type'
|
||||||
UNTITLED: 'Untitled {pagetype}'
|
UNTITLED: 'Untitled {pagetype}'
|
||||||
URLSegment: 'URL segment'
|
URLSegment: 'URL segment'
|
||||||
UntitledDependentObject: 'Untitled {instanceType}'
|
UntitledDependentObject: 'Untitled {instanceType}'
|
||||||
|
@ -0,0 +1,47 @@
|
|||||||
|
<div class="flexbox-area-grow cms-content $Controller.BaseCSSClasses" data-layout-type="border" data-pjax-fragment="Content">
|
||||||
|
<form $FormAttributes data-layout-type="border">
|
||||||
|
<div class="toolbar toolbar--north">
|
||||||
|
<div class="toolbar__navigation">
|
||||||
|
<ol class="breadcrumb">
|
||||||
|
<li class="breadcrumb__item">
|
||||||
|
<% if $Controller.SectionTitle %>
|
||||||
|
$Controller.SectionTitle
|
||||||
|
<% else %>
|
||||||
|
<%t SilverStripe\CMS\Controllers\CMSMain.Title 'Data Models'%>
|
||||||
|
<% end_if %>
|
||||||
|
</li>
|
||||||
|
<li class="breadcrumb__item breadcrumb__item--last breadcrumb__item--no-crumb">
|
||||||
|
<h2 class="breadcrumb__item-title breadcrumb__item-title--last">
|
||||||
|
<%t SilverStripe\Admin\LeftAndMain.NewRecord 'New {name}' name=$Controller.getRecord('singleton').i18n_singular_name() %>
|
||||||
|
</h2>
|
||||||
|
</li>
|
||||||
|
</ol>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div class="panel panel--padded panel--scrollable flexbox-area-grow">
|
||||||
|
<% if $Message %>
|
||||||
|
<p id="{$FormName}_error" class="alert $AlertType">$Message</p>
|
||||||
|
<% else %>
|
||||||
|
<p id="{$FormName}_error" class="alert $AlertType" style="display: none"></p>
|
||||||
|
<% end_if %>
|
||||||
|
|
||||||
|
<fieldset>
|
||||||
|
<% if $Legend %><legend>$Legend</legend><% end_if %>
|
||||||
|
<% loop $Fields %>
|
||||||
|
$FieldHolder
|
||||||
|
<% end_loop %>
|
||||||
|
</fieldset>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div class="toolbar--south">
|
||||||
|
<% if $Actions %>
|
||||||
|
<div class="btn-toolbar">
|
||||||
|
<% loop $Actions %>
|
||||||
|
$Field
|
||||||
|
<% end_loop %>
|
||||||
|
</div>
|
||||||
|
<% end_if %>
|
||||||
|
</div>
|
||||||
|
</form>
|
||||||
|
</div>
|
@ -11,17 +11,17 @@
|
|||||||
<div class="cms-content-header-tabs cms-tabset">
|
<div class="cms-content-header-tabs cms-tabset">
|
||||||
<ul class="cms-tabset-nav-primary nav nav-tabs">
|
<ul class="cms-tabset-nav-primary nav nav-tabs">
|
||||||
<li class="nav-item content-treeview<% if $TabIdentifier == 'edit' %> ui-tabs-active<% end_if %>">
|
<li class="nav-item content-treeview<% if $TabIdentifier == 'edit' %> ui-tabs-active<% end_if %>">
|
||||||
<a href="$LinkPageEdit" class="nav-link cms-panel-link" title="Form_EditForm" data-href="$LinkPageEdit">
|
<a href="$LinkRecordEdit" class="nav-link cms-panel-link" title="Form_EditForm" data-href="$LinkRecordEdit">
|
||||||
<%t SilverStripe\\CMS\\Controllers\\CMSMain.TabContent 'Content' %>
|
<%t SilverStripe\\CMS\\Controllers\\CMSMain.TabContent 'Content' %>
|
||||||
</a>
|
</a>
|
||||||
</li>
|
</li>
|
||||||
<li class="nav-item content-listview<% if $TabIdentifier == 'settings' %> ui-tabs-active<% end_if %>">
|
<li class="nav-item content-listview<% if $TabIdentifier == 'settings' %> ui-tabs-active<% end_if %>">
|
||||||
<a href="$LinkPageSettings" class="nav-link cms-panel-link" title="Form_EditForm" data-href="$LinkPageSettings">
|
<a href="$LinkRecordSettings" class="nav-link cms-panel-link" title="Form_EditForm" data-href="$LinkRecordSettings">
|
||||||
<%t SilverStripe\\CMS\\Controllers\\CMSMain.TabSettings 'Settings' %>
|
<%t SilverStripe\\CMS\\Controllers\\CMSMain.TabSettings 'Settings' %>
|
||||||
</a>
|
</a>
|
||||||
</li>
|
</li>
|
||||||
<li class="nav-item content-listview<% if $TabIdentifier == 'history' %> ui-tabs-active<% end_if %>">
|
<li class="nav-item content-listview<% if $TabIdentifier == 'history' %> ui-tabs-active<% end_if %>">
|
||||||
<a href="$LinkPageHistory" class="nav-link cms-panel-link" title="Form_EditForm" data-href="$LinkPageHistory">
|
<a href="$LinkRecordHistory" class="nav-link cms-panel-link" title="Form_EditForm" data-href="$LinkRecordHistory">
|
||||||
<%t SilverStripe\\CMS\\Controllers\\CMSMain.TabHistory 'History' %>
|
<%t SilverStripe\\CMS\\Controllers\\CMSMain.TabHistory 'History' %>
|
||||||
</a>
|
</a>
|
||||||
</li>
|
</li>
|
||||||
|
@ -1,6 +1,6 @@
|
|||||||
<% include SilverStripe\\CMS\\Controllers\\CMSPagesController_ContentToolActions %>
|
<% include SilverStripe\\CMS\\Controllers\\CMSPagesController_ContentToolActions %>
|
||||||
|
|
||||||
<div class="ss-dialog cms-page-add-form-dialog cms-dialog-content" id="cms-page-add-form" title="<%t SilverStripe\\CMS\\Controllers\\CMSMain.AddNew 'Add new page' %>">
|
<div class="ss-dialog cms-page-add-form-dialog cms-dialog-content" id="cms-page-add-form" title="<%t SilverStripe\Admin\\LeftAndMain.AddNew 'Add new {name}' name=$getRecord('singleton').i18n_singular_name().lowercase %>">
|
||||||
$AddForm
|
$AddForm
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
|
@ -1 +0,0 @@
|
|||||||
<% include SilverStripe\\CMS\\Controllers\\CMSMain_PageList %>
|
|
@ -0,0 +1 @@
|
|||||||
|
<% include SilverStripe\\CMS\\Controllers\\CMSMain_RecordList %>
|
@ -4,7 +4,7 @@
|
|||||||
<% if $limited %>
|
<% if $limited %>
|
||||||
<ul><li class="readonly">
|
<ul><li class="readonly">
|
||||||
<span class="item">
|
<span class="item">
|
||||||
<%t SilverStripe\\CMS\\Controllers\\CMSMain.TOO_MANY_PAGES 'Too many pages' %>
|
<%t SilverStripe\\CMS\\Controllers\\CMSMain.TOO_MANY_RECORDS 'Too many records' %>
|
||||||
(<a href="{$listViewLink.ATT}" class="subtree-list-link" data-id="$node.ID" data-pjax-target="Content"><%t SilverStripe\\CMS\\Controllers\\CMSMain.SHOW_AS_LIST 'show as list' %></a>)
|
(<a href="{$listViewLink.ATT}" class="subtree-list-link" data-id="$node.ID" data-pjax-target="Content"><%t SilverStripe\\CMS\\Controllers\\CMSMain.SHOW_AS_LIST 'show as list' %></a>)
|
||||||
</span>
|
</span>
|
||||||
</li></ul>
|
</li></ul>
|
||||||
|
@ -2,7 +2,7 @@
|
|||||||
<div class="cms-content-header north vertical-align-items">
|
<div class="cms-content-header north vertical-align-items">
|
||||||
<div class="cms-content-header-info vertical-align-items fill-width">
|
<div class="cms-content-header-info vertical-align-items fill-width">
|
||||||
<div class="section-heading flexbox-area-grow">
|
<div class="section-heading flexbox-area-grow">
|
||||||
<span class="section-label"><a href="$LinkPages">{$MenuCurrentItem.Title}</a></span>
|
<span class="section-label"><a href="$LinkRecords">{$MenuCurrentItem.Title}</a></span>
|
||||||
</div>
|
</div>
|
||||||
<% include SilverStripe\\CMS\\Controllers\\CMSMain_Filter %>
|
<% include SilverStripe\\CMS\\Controllers\\CMSMain_Filter %>
|
||||||
</div>
|
</div>
|
||||||
@ -14,7 +14,7 @@
|
|||||||
data-schema="$SearchFieldSchema"
|
data-schema="$SearchFieldSchema"
|
||||||
></div>
|
></div>
|
||||||
</div>
|
</div>
|
||||||
$PageListSidebar
|
$RecordListSidebar
|
||||||
</div>
|
</div>
|
||||||
<div class="cms-panel-content-collapsed">
|
<div class="cms-panel-content-collapsed">
|
||||||
<h3 class="cms-panel-header">$SiteConfig.Title</h3>
|
<h3 class="cms-panel-header">$SiteConfig.Title</h3>
|
||||||
|
@ -1,6 +1,6 @@
|
|||||||
<% include SilverStripe\\CMS\\Controllers\\CMSPagesController_ContentToolActions View='Tree' %>
|
<% include SilverStripe\\CMS\\Controllers\\CMSPagesController_ContentToolActions View='Tree' %>
|
||||||
|
|
||||||
<div class="ss-dialog cms-page-add-form-dialog cms-dialog-content" id="cms-page-add-form" title="<%t SilverStripe\CMS\Controllers\CMSMain.AddNew 'Add new page' %>">
|
<div class="ss-dialog cms-page-add-form-dialog cms-dialog-content" id="cms-page-add-form" title="<%t SilverStripe\Admin\LeftAndMain.AddNew 'Add new {name}' name=$getRecord('singleton').i18n_singular_name().lowercase %>">
|
||||||
$AddForm
|
$AddForm
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
@ -17,15 +17,15 @@ $ExtraTreeTools
|
|||||||
data-url-tree="$LinkWithSearch($Link('getsubtree')).ATT"
|
data-url-tree="$LinkWithSearch($Link('getsubtree')).ATT"
|
||||||
data-url-savetreenode="$Link('savetreenode').ATT"
|
data-url-savetreenode="$Link('savetreenode').ATT"
|
||||||
data-url-updatetreenodes="$Link('updatetreenodes').ATT"
|
data-url-updatetreenodes="$Link('updatetreenodes').ATT"
|
||||||
data-url-addpage="{$LinkPageAdd('AddForm/?action_doAdd=1', 'ParentID=%s&PageType=%s').ATT}"
|
data-url-addpage="{$LinkRecordAdd('AddForm/?action_doAdd=1', 'ParentID=%s&RecordType=%s').ATT}"
|
||||||
data-url-editpage="$LinkPageEdit('%s').ATT"
|
data-url-editpage="$LinkRecordEdit('%s').ATT"
|
||||||
data-url-duplicate="{$Link('duplicate/%s').ATT}"
|
data-url-duplicate="{$Link('duplicate/%s').ATT}"
|
||||||
data-url-duplicatewithchildren="{$Link('duplicatewithchildren/%s').ATT}"
|
data-url-duplicatewithchildren="{$Link('duplicatewithchildren/%s').ATT}"
|
||||||
data-url-listview="{$Link('?view=list').ATT}"
|
data-url-listview="{$Link('?view=list').ATT}"
|
||||||
data-hints="$SiteTreeHints.ATT"
|
data-hints="$TreeHints.ATT"
|
||||||
data-childfilter="$Link('childfilter').ATT"
|
data-childfilter="$Link('childfilter').ATT"
|
||||||
data-extra-params="SecurityID=$SecurityID.ATT">
|
data-extra-params="SecurityID=$SecurityID.ATT">
|
||||||
$SiteTreeAsUL
|
$TreeAsUL
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<% else %>
|
<% else %>
|
||||||
@ -33,14 +33,14 @@ $ExtraTreeTools
|
|||||||
data-url-tree="$LinkWithSearch($Link('getsubtree')).ATT"
|
data-url-tree="$LinkWithSearch($Link('getsubtree')).ATT"
|
||||||
data-url-savetreenode="$Link('savetreenode').ATT"
|
data-url-savetreenode="$Link('savetreenode').ATT"
|
||||||
data-url-updatetreenodes="$Link('updatetreenodes').ATT"
|
data-url-updatetreenodes="$Link('updatetreenodes').ATT"
|
||||||
data-url-addpage="{$LinkPageAdd('AddForm/?action_doAdd=1', 'ParentID=%s&PageType=%s').ATT}"
|
data-url-addpage="{$LinkRecordAdd('AddForm/?action_doAdd=1', 'ParentID=%s&RecordType=%s').ATT}"
|
||||||
data-url-editpage="$LinkPageEdit('%s').ATT"
|
data-url-editpage="$LinkRecordEdit('%s').ATT"
|
||||||
data-url-duplicate="{$Link('duplicate/%s').ATT}"
|
data-url-duplicate="{$Link('duplicate/%s').ATT}"
|
||||||
data-url-duplicatewithchildren="{$Link('duplicatewithchildren/%s').ATT}"
|
data-url-duplicatewithchildren="{$Link('duplicatewithchildren/%s').ATT}"
|
||||||
data-url-listview="{$Link('?view=list').ATT}"
|
data-url-listview="{$Link('?view=list').ATT}"
|
||||||
data-hints="$SiteTreeHints.ATT"
|
data-hints="$TreeHints.ATT"
|
||||||
data-childfilter="$Link('childfilter').ATT"
|
data-childfilter="$Link('childfilter').ATT"
|
||||||
data-extra-params="SecurityID=$SecurityID.ATT">
|
data-extra-params="SecurityID=$SecurityID.ATT">
|
||||||
$SiteTreeAsUL
|
$TreeAsUL
|
||||||
</div>
|
</div>
|
||||||
<% end_if %>
|
<% end_if %>
|
||||||
|
@ -1,6 +1,6 @@
|
|||||||
<div class="view-controls view-controls--{$ViewState}">
|
<div class="view-controls view-controls--{$ViewState}">
|
||||||
<% if not $TreeIsFiltered %>
|
<% if not $TreeIsFiltered %>
|
||||||
<%-- Change to data-pjax-target="Content-PageList" to enable in-edit listview --%>
|
<%-- Change to data-pjax-target="Content-RecordList" to enable in-edit listview --%>
|
||||||
<a class="page-view-link btn btn-secondary btn--icon-sm btn--no-text font-icon-tree"
|
<a class="page-view-link btn btn-secondary btn--icon-sm btn--no-text font-icon-tree"
|
||||||
href="$LinkTreeView.ATT"
|
href="$LinkTreeView.ATT"
|
||||||
data-view="treeview"
|
data-view="treeview"
|
||||||
|
@ -1,45 +0,0 @@
|
|||||||
<div class="flexbox-area-grow cms-content $BaseCSSClasses" data-layout-type="border" data-pjax-fragment="Content">
|
|
||||||
<% with $AddForm %>
|
|
||||||
<form $FormAttributes data-layout-type="border">
|
|
||||||
<div class="toolbar toolbar--north">
|
|
||||||
<div class="toolbar__navigation">
|
|
||||||
<ol class="breadcrumb">
|
|
||||||
<li class="breadcrumb__item">
|
|
||||||
<%t SilverStripe\CMS\Controllers\CMSPagesController.MENUTITLE 'Pages'%>
|
|
||||||
</li>
|
|
||||||
<li class="breadcrumb__item breadcrumb__item--last breadcrumb__item--no-crumb">
|
|
||||||
<h2 class="breadcrumb__item-title breadcrumb__item-title--last">
|
|
||||||
<%t SilverStripe\CMS\Controllers\CMSPageAddController.Title 'Add page' %>
|
|
||||||
</h2>
|
|
||||||
</li>
|
|
||||||
</ol>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<div class="panel panel--padded panel--scrollable flexbox-area-grow">
|
|
||||||
<% if $Message %>
|
|
||||||
<p id="{$FormName}_error" class="alert $AlertType">$Message</p>
|
|
||||||
<% else %>
|
|
||||||
<p id="{$FormName}_error" class="alert $AlertType" style="display: none"></p>
|
|
||||||
<% end_if %>
|
|
||||||
|
|
||||||
<fieldset>
|
|
||||||
<% if $Legend %><legend>$Legend</legend><% end_if %>
|
|
||||||
<% loop $Fields %>
|
|
||||||
$FieldHolder
|
|
||||||
<% end_loop %>
|
|
||||||
</fieldset>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<div class="toolbar--south">
|
|
||||||
<% if $Actions %>
|
|
||||||
<div class="btn-toolbar">
|
|
||||||
<% loop $Actions %>
|
|
||||||
$Field
|
|
||||||
<% end_loop %>
|
|
||||||
</div>
|
|
||||||
<% end_if %>
|
|
||||||
</div>
|
|
||||||
</form>
|
|
||||||
<% end_with %>
|
|
||||||
</div>
|
|
@ -13,6 +13,6 @@
|
|||||||
|
|
||||||
<div class="flexbox-area-grow fill-height cms-content-fields ui-widget-content cms-panel-padded">
|
<div class="flexbox-area-grow fill-height cms-content-fields ui-widget-content cms-panel-padded">
|
||||||
$Tools
|
$Tools
|
||||||
$PageList
|
$RecordList
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
@ -1,7 +1,9 @@
|
|||||||
<div class="toolbar toolbar--content cms-content-toolbar">
|
<div class="toolbar toolbar--content cms-content-toolbar">
|
||||||
<div class="btn-toolbar cms-actions-buttons-row">
|
<div class="btn-toolbar cms-actions-buttons-row">
|
||||||
<% if not $TreeIsFiltered %>
|
<% if not $TreeIsFiltered %>
|
||||||
<a class="btn btn-primary cms-content-addpage-button tool-button font-icon-plus" href="$LinkPageAdd" data-url-addpage="{$LinkPageAdd('', 'ParentID=%s')}"><%t SilverStripe\CMS\Controllers\CMSMain.AddNewButton 'Add new' %></a>
|
<a class="btn btn-primary cms-content-addpage-button tool-button font-icon-plus" href="$LinkRecordAdd" data-url-addpage="{$LinkRecordAdd('', 'ParentID=%s')}">
|
||||||
|
<%t SilverStripe\Admin\\LeftAndMain.AddNew 'Add new {name}' name=$getRecord('singleton').i18n_singular_name().lowercase %>
|
||||||
|
</a>
|
||||||
|
|
||||||
<% if $View == 'Tree' %>
|
<% if $View == 'Tree' %>
|
||||||
<button type="button" class="cms-content-batchactions-button btn btn-secondary tool-button font-icon-check-mark-2 btn--last" data-toolid="batch-actions">
|
<button type="button" class="cms-content-batchactions-button btn btn-secondary tool-button font-icon-check-mark-2 btn--last" data-toolid="batch-actions">
|
||||||
@ -10,7 +12,7 @@
|
|||||||
<% end_if %>
|
<% end_if %>
|
||||||
<% end_if %>
|
<% end_if %>
|
||||||
|
|
||||||
<% include SilverStripe\\CMS\\Controllers\\CMSMain_ViewControls PJAXTarget='Content-PageList' %>
|
<% include SilverStripe\\CMS\\Controllers\\CMSMain_ViewControls PJAXTarget='Content-RecordList' %>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
|
|
||||||
|
@ -44,15 +44,15 @@ class CMSMainTest extends FunctionalTest
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public function testSiteTreeHints()
|
public function testTreeHints()
|
||||||
{
|
{
|
||||||
$cache = Injector::inst()->get(CacheInterface::class . '.CMSMain_SiteTreeHints');
|
$cache = Injector::inst()->get(CacheInterface::class . '.CMSMain_TreeHints');
|
||||||
// Login as user with root creation privileges
|
// Login as user with root creation privileges
|
||||||
$user = $this->objFromFixture(Member::class, 'rootedituser');
|
$user = $this->objFromFixture(Member::class, 'rootedituser');
|
||||||
Security::setCurrentUser($user);
|
Security::setCurrentUser($user);
|
||||||
$cache->clear();
|
$cache->clear();
|
||||||
|
|
||||||
$rawHints = singleton(CMSMain::class)->SiteTreeHints();
|
$rawHints = singleton(CMSMain::class)->TreeHints();
|
||||||
$this->assertNotNull($rawHints);
|
$this->assertNotNull($rawHints);
|
||||||
|
|
||||||
$rawHints = preg_replace('/^"(.*)"$/', '$1', Convert::xml2raw($rawHints) ?? '');
|
$rawHints = preg_replace('/^"(.*)"$/', '$1', Convert::xml2raw($rawHints) ?? '');
|
||||||
@ -611,7 +611,7 @@ class CMSMainTest extends FunctionalTest
|
|||||||
$this->assertEquals('Class A', $newPage->Title);
|
$this->assertEquals('Class A', $newPage->Title);
|
||||||
}
|
}
|
||||||
|
|
||||||
public function testSiteTreeHintsCache()
|
public function testTreeHintsCache()
|
||||||
{
|
{
|
||||||
$cms = CMSMain::create();
|
$cms = CMSMain::create();
|
||||||
/** @var Member $user */
|
/** @var Member $user */
|
||||||
@ -635,31 +635,31 @@ class CMSMainTest extends FunctionalTest
|
|||||||
|
|
||||||
// Initially, cache misses (1)
|
// Initially, cache misses (1)
|
||||||
Injector::inst()->registerService($mockPageMissesCache, $pageClass);
|
Injector::inst()->registerService($mockPageMissesCache, $pageClass);
|
||||||
$hints = $cms->SiteTreeHints();
|
$hints = $cms->TreeHints();
|
||||||
$this->assertNotNull($hints);
|
$this->assertNotNull($hints);
|
||||||
|
|
||||||
// Now it hits
|
// Now it hits
|
||||||
Injector::inst()->registerService($mockPageHitsCache, $pageClass);
|
Injector::inst()->registerService($mockPageHitsCache, $pageClass);
|
||||||
$hints = $cms->SiteTreeHints();
|
$hints = $cms->TreeHints();
|
||||||
$this->assertNotNull($hints);
|
$this->assertNotNull($hints);
|
||||||
|
|
||||||
// Mutating member record invalidates cache. Misses (2)
|
// Mutating member record invalidates cache. Misses (2)
|
||||||
$user->FirstName = 'changed';
|
$user->FirstName = 'changed';
|
||||||
$user->write();
|
$user->write();
|
||||||
Injector::inst()->registerService($mockPageMissesCache, $pageClass);
|
Injector::inst()->registerService($mockPageMissesCache, $pageClass);
|
||||||
$hints = $cms->SiteTreeHints();
|
$hints = $cms->TreeHints();
|
||||||
$this->assertNotNull($hints);
|
$this->assertNotNull($hints);
|
||||||
|
|
||||||
// Now it hits again
|
// Now it hits again
|
||||||
Injector::inst()->registerService($mockPageHitsCache, $pageClass);
|
Injector::inst()->registerService($mockPageHitsCache, $pageClass);
|
||||||
$hints = $cms->SiteTreeHints();
|
$hints = $cms->TreeHints();
|
||||||
$this->assertNotNull($hints);
|
$this->assertNotNull($hints);
|
||||||
|
|
||||||
// Different user. Misses. (3)
|
// Different user. Misses. (3)
|
||||||
$user = $this->objFromFixture(Member::class, 'allcmssectionsuser');
|
$user = $this->objFromFixture(Member::class, 'allcmssectionsuser');
|
||||||
Security::setCurrentUser($user);
|
Security::setCurrentUser($user);
|
||||||
Injector::inst()->registerService($mockPageMissesCache, $pageClass);
|
Injector::inst()->registerService($mockPageMissesCache, $pageClass);
|
||||||
$hints = $cms->SiteTreeHints();
|
$hints = $cms->TreeHints();
|
||||||
$this->assertNotNull($hints);
|
$this->assertNotNull($hints);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -703,21 +703,21 @@ class CMSMainTest extends FunctionalTest
|
|||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
public function testCanOrganiseSitetree()
|
public function testCanOrganiseTree()
|
||||||
{
|
{
|
||||||
$cms = CMSMain::create();
|
$cms = CMSMain::create();
|
||||||
|
|
||||||
$this->assertFalse($cms->CanOrganiseSitetree());
|
$this->assertFalse($cms->CanOrganiseTree());
|
||||||
|
|
||||||
$this->logInWithPermission('CMS_ACCESS_CMSMain');
|
$this->logInWithPermission('CMS_ACCESS_CMSMain');
|
||||||
$this->assertFalse($cms->CanOrganiseSitetree());
|
$this->assertFalse($cms->CanOrganiseTree());
|
||||||
|
|
||||||
$this->logOut();
|
$this->logOut();
|
||||||
$this->logInWithPermission('SITETREE_REORGANISE');
|
$this->logInWithPermission('SITETREE_REORGANISE');
|
||||||
$this->assertTrue($cms->CanOrganiseSitetree());
|
$this->assertTrue($cms->CanOrganiseTree());
|
||||||
|
|
||||||
$this->logOut();
|
$this->logOut();
|
||||||
$this->logInWithPermission('ADMIN');
|
$this->logInWithPermission('ADMIN');
|
||||||
$this->assertTrue($cms->CanOrganiseSitetree());
|
$this->assertTrue($cms->CanOrganiseTree());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -24,8 +24,8 @@ class CMSSiteTreeFilterTest extends SapphireTest
|
|||||||
$f = new CMSSiteTreeFilter_Search();
|
$f = new CMSSiteTreeFilter_Search();
|
||||||
$results = $f->pagesIncluded();
|
$results = $f->pagesIncluded();
|
||||||
|
|
||||||
$this->assertTrue($f->isPageIncluded($page1));
|
$this->assertTrue($f->isRecordIncluded($page1));
|
||||||
$this->assertTrue($f->isPageIncluded($page2));
|
$this->assertTrue($f->isRecordIncluded($page2));
|
||||||
}
|
}
|
||||||
|
|
||||||
public function testSearchFilterByTitle()
|
public function testSearchFilterByTitle()
|
||||||
@ -36,8 +36,8 @@ class CMSSiteTreeFilterTest extends SapphireTest
|
|||||||
$f = new CMSSiteTreeFilter_Search(['Title' => 'Page 1']);
|
$f = new CMSSiteTreeFilter_Search(['Title' => 'Page 1']);
|
||||||
$results = $f->pagesIncluded();
|
$results = $f->pagesIncluded();
|
||||||
|
|
||||||
$this->assertTrue($f->isPageIncluded($page1));
|
$this->assertTrue($f->isRecordIncluded($page1));
|
||||||
$this->assertFalse($f->isPageIncluded($page2));
|
$this->assertFalse($f->isRecordIncluded($page2));
|
||||||
$this->assertEquals(1, count($results ?? []));
|
$this->assertEquals(1, count($results ?? []));
|
||||||
$this->assertEquals(
|
$this->assertEquals(
|
||||||
['ID' => $page1->ID, 'ParentID' => 0],
|
['ID' => $page1->ID, 'ParentID' => 0],
|
||||||
@ -50,10 +50,10 @@ class CMSSiteTreeFilterTest extends SapphireTest
|
|||||||
$page = $this->objFromFixture(SiteTree::class, 'page8');
|
$page = $this->objFromFixture(SiteTree::class, 'page8');
|
||||||
|
|
||||||
$filter = CMSSiteTreeFilter_Search::create(['Term' => 'lake-wanaka+adventure']);
|
$filter = CMSSiteTreeFilter_Search::create(['Term' => 'lake-wanaka+adventure']);
|
||||||
$this->assertTrue($filter->isPageIncluded($page));
|
$this->assertTrue($filter->isRecordIncluded($page));
|
||||||
|
|
||||||
$filter = CMSSiteTreeFilter_Search::create(['URLSegment' => 'lake-wanaka+adventure']);
|
$filter = CMSSiteTreeFilter_Search::create(['URLSegment' => 'lake-wanaka+adventure']);
|
||||||
$this->assertTrue($filter->isPageIncluded($page));
|
$this->assertTrue($filter->isRecordIncluded($page));
|
||||||
}
|
}
|
||||||
|
|
||||||
public function testIncludesParentsForNestedMatches()
|
public function testIncludesParentsForNestedMatches()
|
||||||
@ -64,8 +64,8 @@ class CMSSiteTreeFilterTest extends SapphireTest
|
|||||||
$f = new CMSSiteTreeFilter_Search(['Title' => 'Page 3b']);
|
$f = new CMSSiteTreeFilter_Search(['Title' => 'Page 3b']);
|
||||||
$results = $f->pagesIncluded();
|
$results = $f->pagesIncluded();
|
||||||
|
|
||||||
$this->assertTrue($f->isPageIncluded($parent));
|
$this->assertTrue($f->isRecordIncluded($parent));
|
||||||
$this->assertTrue($f->isPageIncluded($child));
|
$this->assertTrue($f->isRecordIncluded($child));
|
||||||
$this->assertEquals(1, count($results ?? []));
|
$this->assertEquals(1, count($results ?? []));
|
||||||
$this->assertEquals(
|
$this->assertEquals(
|
||||||
['ID' => $child->ID, 'ParentID' => $parent->ID],
|
['ID' => $child->ID, 'ParentID' => $parent->ID],
|
||||||
@ -91,8 +91,8 @@ class CMSSiteTreeFilterTest extends SapphireTest
|
|||||||
$f = new CMSSiteTreeFilter_ChangedPages(['Term' => 'Changed']);
|
$f = new CMSSiteTreeFilter_ChangedPages(['Term' => 'Changed']);
|
||||||
$results = $f->pagesIncluded();
|
$results = $f->pagesIncluded();
|
||||||
|
|
||||||
$this->assertTrue($f->isPageIncluded($changedPage));
|
$this->assertTrue($f->isRecordIncluded($changedPage));
|
||||||
$this->assertFalse($f->isPageIncluded($unchangedPage));
|
$this->assertFalse($f->isRecordIncluded($unchangedPage));
|
||||||
$this->assertEquals(1, count($results ?? []));
|
$this->assertEquals(1, count($results ?? []));
|
||||||
$this->assertEquals(
|
$this->assertEquals(
|
||||||
['ID' => $changedPage->ID, 'ParentID' => 0],
|
['ID' => $changedPage->ID, 'ParentID' => 0],
|
||||||
@ -130,11 +130,11 @@ class CMSSiteTreeFilterTest extends SapphireTest
|
|||||||
);
|
);
|
||||||
|
|
||||||
$f = new CMSSiteTreeFilter_DeletedPages(['Term' => 'Page']);
|
$f = new CMSSiteTreeFilter_DeletedPages(['Term' => 'Page']);
|
||||||
$this->assertTrue($f->isPageIncluded($deletedPage));
|
$this->assertTrue($f->isRecordIncluded($deletedPage));
|
||||||
|
|
||||||
// Check that only changed pages are returned
|
// Check that only changed pages are returned
|
||||||
$f = new CMSSiteTreeFilter_DeletedPages(['Term' => 'No Matches']);
|
$f = new CMSSiteTreeFilter_DeletedPages(['Term' => 'No Matches']);
|
||||||
$this->assertFalse($f->isPageIncluded($deletedPage));
|
$this->assertFalse($f->isRecordIncluded($deletedPage));
|
||||||
}
|
}
|
||||||
|
|
||||||
public function testStatusDraftPagesFilter()
|
public function testStatusDraftPagesFilter()
|
||||||
@ -148,16 +148,16 @@ class CMSSiteTreeFilterTest extends SapphireTest
|
|||||||
|
|
||||||
// Check draft page is shown
|
// Check draft page is shown
|
||||||
$f = new CMSSiteTreeFilter_StatusDraftPages(['Term' => 'Page']);
|
$f = new CMSSiteTreeFilter_StatusDraftPages(['Term' => 'Page']);
|
||||||
$this->assertTrue($f->isPageIncluded($draftPage));
|
$this->assertTrue($f->isRecordIncluded($draftPage));
|
||||||
|
|
||||||
// Check filter respects parameters
|
// Check filter respects parameters
|
||||||
$f = new CMSSiteTreeFilter_StatusDraftPages(['Term' => 'No Match']);
|
$f = new CMSSiteTreeFilter_StatusDraftPages(['Term' => 'No Match']);
|
||||||
$this->assertEmpty($f->isPageIncluded($draftPage));
|
$this->assertEmpty($f->isRecordIncluded($draftPage));
|
||||||
|
|
||||||
// Ensures empty array returned if no data to show
|
// Ensures empty array returned if no data to show
|
||||||
$f = new CMSSiteTreeFilter_StatusDraftPages();
|
$f = new CMSSiteTreeFilter_StatusDraftPages();
|
||||||
$draftPage->delete();
|
$draftPage->delete();
|
||||||
$this->assertEmpty($f->isPageIncluded($draftPage));
|
$this->assertEmpty($f->isRecordIncluded($draftPage));
|
||||||
}
|
}
|
||||||
|
|
||||||
public function testDateFromToLastSameDate()
|
public function testDateFromToLastSameDate()
|
||||||
@ -171,7 +171,7 @@ class CMSSiteTreeFilterTest extends SapphireTest
|
|||||||
'LastEditedTo' => $date,
|
'LastEditedTo' => $date,
|
||||||
]);
|
]);
|
||||||
$this->assertTrue(
|
$this->assertTrue(
|
||||||
$filter->isPageIncluded($draftPage),
|
$filter->isRecordIncluded($draftPage),
|
||||||
'Using the same date for from and to should show find that page'
|
'Using the same date for from and to should show find that page'
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
@ -189,16 +189,16 @@ class CMSSiteTreeFilterTest extends SapphireTest
|
|||||||
|
|
||||||
// Check live-only page is included
|
// Check live-only page is included
|
||||||
$f = new CMSSiteTreeFilter_StatusRemovedFromDraftPages(['LastEditedFrom' => '2000-01-01 00:00']);
|
$f = new CMSSiteTreeFilter_StatusRemovedFromDraftPages(['LastEditedFrom' => '2000-01-01 00:00']);
|
||||||
$this->assertTrue($f->isPageIncluded($removedDraftPage));
|
$this->assertTrue($f->isRecordIncluded($removedDraftPage));
|
||||||
|
|
||||||
// Check filter is respected
|
// Check filter is respected
|
||||||
$f = new CMSSiteTreeFilter_StatusRemovedFromDraftPages(['LastEditedTo' => '1999-01-01 00:00']);
|
$f = new CMSSiteTreeFilter_StatusRemovedFromDraftPages(['LastEditedTo' => '1999-01-01 00:00']);
|
||||||
$this->assertEmpty($f->isPageIncluded($removedDraftPage));
|
$this->assertEmpty($f->isRecordIncluded($removedDraftPage));
|
||||||
|
|
||||||
// Ensures empty array returned if no data to show
|
// Ensures empty array returned if no data to show
|
||||||
$f = new CMSSiteTreeFilter_StatusRemovedFromDraftPages();
|
$f = new CMSSiteTreeFilter_StatusRemovedFromDraftPages();
|
||||||
$removedDraftPage->delete();
|
$removedDraftPage->delete();
|
||||||
$this->assertEmpty($f->isPageIncluded($removedDraftPage));
|
$this->assertEmpty($f->isRecordIncluded($removedDraftPage));
|
||||||
}
|
}
|
||||||
|
|
||||||
public function testStatusDeletedFilter()
|
public function testStatusDeletedFilter()
|
||||||
@ -214,10 +214,10 @@ class CMSSiteTreeFilterTest extends SapphireTest
|
|||||||
|
|
||||||
// Check deleted page is included
|
// Check deleted page is included
|
||||||
$f = new CMSSiteTreeFilter_StatusDeletedPages(['Title' => 'Page']);
|
$f = new CMSSiteTreeFilter_StatusDeletedPages(['Title' => 'Page']);
|
||||||
$this->assertTrue($f->isPageIncluded($checkParentExists));
|
$this->assertTrue($f->isRecordIncluded($checkParentExists));
|
||||||
|
|
||||||
// Check filter is respected
|
// Check filter is respected
|
||||||
$f = new CMSSiteTreeFilter_StatusDeletedPages(['Title' => 'Bobby']);
|
$f = new CMSSiteTreeFilter_StatusDeletedPages(['Title' => 'Bobby']);
|
||||||
$this->assertFalse($f->isPageIncluded($checkParentExists));
|
$this->assertFalse($f->isRecordIncluded($checkParentExists));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user