2007-07-19 12:40:05 +02:00
< ? php
2016-06-16 06:57:19 +02:00
2016-07-22 01:32:32 +02:00
namespace SilverStripe\CMS\Controllers ;
2016-08-23 04:36:06 +02:00
use SilverStripe\Admin\AdminRootController ;
use SilverStripe\Admin\CMSBatchActionHandler ;
use SilverStripe\Admin\CMSPreviewable ;
use SilverStripe\Admin\LeftAndMain ;
2016-10-25 02:22:31 +02:00
use SilverStripe\CMS\BatchActions\CMSBatchAction_Archive ;
use SilverStripe\CMS\BatchActions\CMSBatchAction_Publish ;
use SilverStripe\CMS\BatchActions\CMSBatchAction_Restore ;
use SilverStripe\CMS\BatchActions\CMSBatchAction_Unpublish ;
2016-08-23 04:36:06 +02:00
use SilverStripe\CMS\Model\CurrentPageIdentifier ;
use SilverStripe\CMS\Model\RedirectorPage ;
use SilverStripe\CMS\Model\SiteTree ;
use SilverStripe\Control\Controller ;
use SilverStripe\Control\Director ;
use SilverStripe\Control\Session ;
2016-09-09 01:26:24 +02:00
use SilverStripe\Control\HTTPRequest ;
use SilverStripe\Control\HTTPResponse ;
use SilverStripe\Control\HTTPResponse_Exception ;
2016-08-23 04:36:06 +02:00
use SilverStripe\Core\Convert ;
use SilverStripe\Core\Injector\Injector ;
2016-09-09 01:26:24 +02:00
use SilverStripe\Core\Cache ;
2016-08-23 04:36:06 +02:00
use SilverStripe\Forms\DateField ;
use SilverStripe\Forms\DropdownField ;
use SilverStripe\Forms\FieldGroup ;
use SilverStripe\Forms\FieldList ;
use SilverStripe\Forms\Form ;
use SilverStripe\Forms\FormAction ;
2016-09-08 09:33:32 +02:00
use SilverStripe\Forms\FormField ;
2016-08-23 04:36:06 +02:00
use SilverStripe\Forms\GridField\GridField ;
use SilverStripe\Forms\GridField\GridFieldConfig ;
use SilverStripe\Forms\GridField\GridFieldDataColumns ;
use SilverStripe\Forms\GridField\GridFieldLevelup ;
use SilverStripe\Forms\GridField\GridFieldPaginator ;
use SilverStripe\Forms\GridField\GridFieldSortableHeader ;
use SilverStripe\Forms\HiddenField ;
use SilverStripe\Forms\LabelField ;
use SilverStripe\Forms\LiteralField ;
use SilverStripe\Forms\RequiredFields ;
use SilverStripe\Forms\ResetFormAction ;
2016-09-08 09:33:32 +02:00
use SilverStripe\Forms\TabSet ;
2016-08-23 04:36:06 +02:00
use SilverStripe\Forms\TextField ;
2016-06-16 06:57:19 +02:00
use SilverStripe\ORM\ArrayList ;
use SilverStripe\ORM\DataList ;
2016-08-23 04:36:06 +02:00
use SilverStripe\ORM\DataObject ;
2016-06-16 06:57:19 +02:00
use SilverStripe\ORM\DB ;
2016-10-21 05:15:34 +02:00
use SilverStripe\ORM\FieldType\DBHTMLText ;
2016-08-23 04:36:06 +02:00
use SilverStripe\ORM\HiddenClass ;
use SilverStripe\ORM\SS_List ;
2016-12-09 04:00:46 +01:00
use SilverStripe\ORM\ValidationResult ;
2016-08-23 04:36:06 +02:00
use SilverStripe\ORM\Versioning\Versioned ;
2016-06-23 01:51:20 +02:00
use SilverStripe\Security\Member ;
use SilverStripe\Security\Permission ;
use SilverStripe\Security\PermissionProvider ;
2016-08-23 04:36:06 +02:00
use SilverStripe\Security\Security ;
use SilverStripe\Security\SecurityToken ;
use SilverStripe\View\ArrayData ;
use SilverStripe\View\Requirements ;
2016-07-22 01:32:32 +02:00
use Translatable ;
use Zend_Cache ;
use InvalidArgumentException ;
2016-08-23 04:36:06 +02:00
2016-04-26 01:56:37 +02:00
2007-07-19 12:40:05 +02:00
/**
* The main " content " area of the CMS .
2011-08-19 02:32:31 +02:00
*
2007-07-19 12:40:05 +02:00
* This class creates a 2 - frame layout - left - tree and right - form - to sit beneath the main
* admin menu .
2015-08-14 02:39:45 +02:00
*
2007-07-19 12:40:05 +02:00
* @ todo Create some base classes to contain the generic functionality that will be replicated .
2016-08-11 04:10:51 +02:00
*
* @ mixin LeftAndMainPageIconsExtension
2007-07-19 12:40:05 +02:00
*/
class CMSMain extends LeftAndMain implements CurrentPageIdentifier , PermissionProvider {
2015-08-14 02:39:45 +02:00
2013-03-18 11:47:15 +01:00
private static $url_segment = 'pages' ;
2015-08-14 02:39:45 +02:00
2013-03-18 11:47:15 +01:00
private static $url_rule = '/$Action/$ID/$OtherID' ;
2015-08-14 02:39:45 +02:00
2008-11-02 22:27:55 +01:00
// Maintain a lower priority than other administration sections
// so that Director does not think they are actions of CMSMain
2013-03-18 11:47:15 +01:00
private static $url_priority = 39 ;
2015-08-14 02:39:45 +02:00
2013-03-18 11:47:15 +01:00
private static $menu_title = 'Edit Page' ;
2015-08-14 02:39:45 +02:00
2016-12-20 01:26:02 +01:00
private static $menu_icon_class = 'font-icon-sitemap' ;
2013-03-18 11:47:15 +01:00
private static $menu_priority = 10 ;
2015-08-14 02:39:45 +02:00
2016-10-25 02:22:31 +02:00
private static $tree_class = SiteTree :: class ;
2015-08-14 02:39:45 +02:00
2016-10-25 02:22:31 +02:00
private static $subitem_class = Member :: class ;
2015-08-14 02:39:45 +02:00
2016-08-10 06:08:39 +02:00
private static $session_namespace = 'SilverStripe\\CMS\\Controllers\\CMSMain' ;
2016-08-11 04:10:51 +02:00
private static $required_permission_codes = 'CMS_ACCESS_CMSMain' ;
2014-04-28 05:22:17 +02:00
/**
* Amount of results showing on a single page .
*
* @ config
* @ var int
*/
private static $page_length = 15 ;
2015-08-14 02:39:45 +02:00
2013-03-18 11:47:15 +01:00
private static $allowed_actions = array (
2015-05-15 01:51:23 +02:00
'archive' ,
2008-02-25 03:10:37 +01:00
'deleteitems' ,
2009-01-06 03:18:33 +01:00
'DeleteItemsForm' ,
2008-02-25 03:10:37 +01:00
'dialog' ,
'duplicate' ,
'duplicatewithchildren' ,
'publishall' ,
'publishitems' ,
2009-01-06 03:18:33 +01:00
'PublishItemsForm' ,
2008-02-25 03:10:37 +01:00
'submit' ,
2008-08-09 05:54:55 +02:00
'EditForm' ,
2011-04-22 13:32:10 +02:00
'SearchForm' ,
2008-09-25 16:50:33 +02:00
'SiteTreeAsUL' ,
2009-05-14 08:11:18 +02:00
'getshowdeletedsubtree' ,
2010-12-22 21:00:33 +01:00
'batchactions' ,
2012-04-16 15:55:19 +02:00
'treeview' ,
'listview' ,
'ListViewForm' ,
2015-03-11 06:54:08 +01:00
'childfilter' ,
2008-02-25 03:10:37 +01:00
);
2015-05-15 01:51:23 +02:00
2015-02-11 00:13:55 +01:00
private static $casting = array (
'TreeIsFiltered' => 'Boolean' ,
'AddForm' => 'HTMLFragment' ,
'LinkPages' => 'Text' ,
'Link' => 'Text' ,
'ListViewForm' => 'HTMLFragment' ,
'ExtraTreeTools' => 'HTMLFragment' ,
2016-10-21 05:15:34 +02:00
'PageList' => 'HTMLFragment' ,
'PageListSidebar' => 'HTMLFragment' ,
2015-02-11 00:13:55 +01:00
'SiteTreeHints' => 'HTMLFragment' ,
'SecurityID' => 'Text' ,
'SiteTreeAsUL' => 'HTMLFragment' ,
);
2017-01-21 23:35:14 +01:00
protected function init () {
2011-03-29 07:00:21 +02:00
// set reading lang
2015-04-30 01:04:02 +02:00
if ( SiteTree :: has_extension ( 'Translatable' ) && ! $this -> getRequest () -> isAjax ()) {
2016-07-22 01:32:32 +02:00
Translatable :: choose_site_locale ( array_keys ( Translatable :: get_existing_content_languages ( 'SilverStripe\\CMS\\Model\\SiteTree' )));
2011-03-29 07:00:21 +02:00
}
2015-08-14 02:39:45 +02:00
2007-07-19 12:40:05 +02:00
parent :: init ();
2013-10-23 14:29:24 +02:00
2016-09-21 03:07:03 +02:00
Requirements :: javascript ( CMS_DIR . '/client/dist/js/bundle.js' );
Requirements :: javascript ( CMS_DIR . '/client/dist/js/SilverStripeNavigator.js' );
2016-04-19 13:22:18 +02:00
Requirements :: css ( CMS_DIR . '/client/dist/styles/bundle.css' );
2012-06-13 09:46:43 +02:00
Requirements :: customCSS ( $this -> generatePageIconsCss ());
2016-05-09 05:31:31 +02:00
Requirements :: add_i18n_javascript ( CMS_DIR . '/client/lang' , false , true );
2012-01-06 12:01:51 +01:00
2016-10-25 02:22:31 +02:00
CMSBatchActionHandler :: register ( 'restore' , CMSBatchAction_Restore :: class );
CMSBatchActionHandler :: register ( 'archive' , CMSBatchAction_Archive :: class );
CMSBatchActionHandler :: register ( 'unpublish' , CMSBatchAction_Unpublish :: class );
CMSBatchActionHandler :: register ( 'publish' , CMSBatchAction_Publish :: class );
2007-07-19 12:40:05 +02:00
}
2012-04-16 15:55:19 +02:00
2012-09-19 12:07:46 +02:00
public function index ( $request ) {
2012-04-16 15:55:19 +02:00
// 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.
2016-08-11 04:10:51 +02:00
if ( ! $request -> param ( 'Action' )) {
$this -> setCurrentPageID ( null );
}
2012-04-16 15:55:19 +02:00
return parent :: index ( $request );
}
2012-05-12 08:08:10 +02:00
public function getResponseNegotiator () {
2012-04-16 15:55:19 +02:00
$negotiator = parent :: getResponseNegotiator ();
2016-10-21 05:15:34 +02:00
// ListViewForm
$negotiator -> setCallback ( 'ListViewForm' , function () {
return $this -> ListViewForm () -> forTemplate ();
});
// PageList view
$negotiator -> setCallback ( 'Content-PageList' , function () {
return $this -> PageList () -> forTemplate ();
});
// PageList view for edit controller
$negotiator -> setCallback ( 'Content-PageList-Sidebar' , function () {
return $this -> PageListSidebar () -> forTemplate ();
2012-04-16 15:55:19 +02:00
});
2016-10-21 05:15:34 +02:00
2012-04-16 15:55:19 +02:00
return $negotiator ;
}
2016-10-21 05:15:34 +02:00
/**
* Get pages listing area
*
* @ return DBHTMLText
*/
public function PageList () {
return $this -> renderWith ( $this -> getTemplatesWithSuffix ( '_PageList' ));
}
/**
* Page list view for edit - form
*
* @ return DBHTMLText
*/
public function PageListSidebar () {
return $this -> renderWith ( $this -> getTemplatesWithSuffix ( '_PageList_Sidebar' ));
}
2008-06-24 05:22:39 +02:00
/**
* If this is set to true , the " switchView " context in the
* template is shown , with links to the staging and publish site .
*
* @ return boolean
*/
2012-09-19 12:07:46 +02:00
public function ShowSwitchView () {
2008-06-24 05:22:39 +02:00
return true ;
}
2015-08-14 02:39:45 +02:00
2010-10-13 06:15:18 +02:00
/**
* Overloads the LeftAndMain :: ShowView . Allows to pass a page as a parameter , so we are able
* to switch view also for archived versions .
2016-08-11 04:10:51 +02:00
*
* @ param SiteTree $page
* @ return array
2010-10-13 06:15:18 +02:00
*/
2012-09-19 12:07:46 +02:00
public function SwitchView ( $page = null ) {
2010-10-13 06:15:18 +02:00
if ( ! $page ) {
$page = $this -> currentPage ();
}
2015-08-14 02:39:45 +02:00
2010-10-13 06:15:18 +02:00
if ( $page ) {
2010-06-03 04:45:23 +02:00
$nav = SilverStripeNavigator :: get_for_record ( $page );
return $nav [ 'items' ];
}
}
2007-09-15 23:54:24 +02:00
2007-07-19 12:40:05 +02:00
//------------------------------------------------------------------------------------------//
// Main controllers
//------------------------------------------------------------------------------------------//
// Main UI components
2007-09-15 23:54:24 +02:00
2008-11-18 02:48:50 +01:00
/**
* Override { @ link LeftAndMain } Link to allow blank URL segment for CMSMain .
2014-02-10 21:35:13 +01:00
*
* @ param string | null $action Action to link to .
2008-11-18 02:48:50 +01:00
* @ return string
*/
public function Link ( $action = null ) {
2012-05-15 21:30:32 +02:00
$link = Controller :: join_links (
2016-07-18 13:44:20 +02:00
AdminRootController :: admin_url (),
2016-08-11 04:10:51 +02:00
$this -> stat ( 'url_segment' ), // in case we want to change the segment
2008-11-18 02:48:50 +01:00
'/' , // trailing slash needed if $action is null!
" $action "
);
2012-05-15 21:30:32 +02:00
$this -> extend ( 'updateLink' , $link );
return $link ;
2008-11-18 02:48:50 +01:00
}
2012-04-16 15:55:19 +02:00
public function LinkPages () {
2016-08-10 06:08:39 +02:00
return CMSPagesController :: singleton () -> Link ();
2012-04-16 15:55:19 +02:00
}
2012-05-15 21:30:32 +02:00
public function LinkPagesWithSearch () {
return $this -> LinkWithSearch ( $this -> LinkPages ());
}
2016-10-21 05:15:34 +02:00
/**
* Get link to tree view
*
* @ return string
*/
2012-04-16 15:55:19 +02:00
public function LinkTreeView () {
2016-10-21 05:15:34 +02:00
// Tree view is just default link to main pages section (no /treeview suffix)
return $this -> LinkWithSearch ( CMSMain :: singleton () -> Link ());
2012-04-16 15:55:19 +02:00
}
2016-10-21 05:15:34 +02:00
/**
* Get link to list view
*
* @ return string
*/
2012-04-16 15:55:19 +02:00
public function LinkListView () {
2016-10-21 05:15:34 +02:00
// Note : Force redirect to top level page controller
return $this -> LinkWithSearch ( CMSMain :: singleton () -> Link ( 'listview' ));
2012-04-16 15:55:19 +02:00
}
2012-04-30 16:42:45 +02:00
public function LinkPageEdit ( $id = null ) {
2016-08-10 06:08:39 +02:00
if ( ! $id ) {
$id = $this -> currentPageID ();
}
2012-04-30 16:42:45 +02:00
return $this -> LinkWithSearch (
2016-08-10 06:08:39 +02:00
Controller :: join_links ( CMSPageEditController :: singleton () -> Link ( 'show' ), $id )
2012-04-30 16:42:45 +02:00
);
2012-04-16 15:55:19 +02:00
}
public function LinkPageSettings () {
if ( $id = $this -> currentPageID ()) {
return $this -> LinkWithSearch (
2016-08-10 06:08:39 +02:00
Controller :: join_links ( CMSPageSettingsController :: singleton () -> Link ( 'show' ), $id )
2012-04-16 15:55:19 +02:00
);
2016-08-10 06:08:39 +02:00
} else {
return null ;
2012-04-16 15:55:19 +02:00
}
}
public function LinkPageHistory () {
if ( $id = $this -> currentPageID ()) {
return $this -> LinkWithSearch (
2016-08-10 06:08:39 +02:00
Controller :: join_links ( CMSPageHistoryController :: singleton () -> Link ( 'show' ), $id )
2012-04-16 15:55:19 +02:00
);
2016-08-10 06:08:39 +02:00
} else {
return null ;
2012-04-16 15:55:19 +02:00
}
}
2013-03-19 22:13:10 +01:00
public function LinkWithSearch ( $link ) {
2012-04-16 15:55:19 +02:00
// Whitelist to avoid side effects
$params = array (
2015-04-30 01:04:02 +02:00
'q' => ( array ) $this -> getRequest () -> getVar ( 'q' ),
'ParentID' => $this -> getRequest () -> getVar ( 'ParentID' )
2012-04-16 15:55:19 +02:00
);
2012-05-15 21:30:32 +02:00
$link = Controller :: join_links (
2012-04-16 15:55:19 +02:00
$link ,
array_filter ( array_values ( $params )) ? '?' . http_build_query ( $params ) : null
);
2012-05-15 21:30:32 +02:00
$this -> extend ( 'updateLinkWithSearch' , $link );
return $link ;
2012-04-16 15:55:19 +02:00
}
2013-10-10 04:09:24 +02:00
public function LinkPageAdd ( $extra = null , $placeholders = null ) {
2016-08-10 06:08:39 +02:00
$link = CMSPageAddController :: singleton () -> Link ();
2012-08-16 09:29:51 +02:00
$this -> extend ( 'updateLinkPageAdd' , $link );
2013-10-10 04:09:24 +02:00
if ( $extra ) {
$link = Controller :: join_links ( $link , $extra );
}
if ( $placeholders ) {
2017-01-10 05:41:26 +01:00
$link .= ( strpos ( $link , '?' ) === false ? " ? $placeholders " : " & $placeholders " );
2013-10-10 04:09:24 +02:00
}
2012-08-16 09:29:51 +02:00
return $link ;
2012-04-16 15:55:19 +02:00
}
2015-02-08 01:30:16 +01:00
2011-10-29 19:13:19 +02:00
/**
* @ return string
*/
2012-04-18 22:59:31 +02:00
public function LinkPreview () {
2011-10-29 19:13:19 +02:00
$record = $this -> getRecord ( $this -> currentPageID ());
2015-02-08 01:30:16 +01:00
$baseLink = Director :: absoluteBaseURL ();
2017-01-03 08:38:45 +01:00
if ( $record && $record instanceof SiteTree ) {
2015-02-08 01:30:16 +01:00
// if we are an external redirector don't show a link
if ( $record instanceof RedirectorPage && $record -> RedirectionType == 'External' ) {
$baseLink = false ;
}
else {
$baseLink = $record -> Link ( '?stage=Stage' );
}
}
2011-10-29 19:13:19 +02:00
return $baseLink ;
}
2008-11-18 02:48:50 +01:00
2007-07-19 12:40:05 +02:00
/**
* Return the entire site tree as a nested set of ULs
*/
public function SiteTreeAsUL () {
2009-02-03 03:50:25 +01:00
// Pre-cache sitetree version numbers for querying efficiency
2016-10-25 02:22:31 +02:00
Versioned :: prepopulate_versionnumber_cache ( SiteTree :: class , " Stage " );
Versioned :: prepopulate_versionnumber_cache ( SiteTree :: class , " Live " );
2012-06-11 13:24:58 +02:00
$html = $this -> getSiteTreeFor ( $this -> stat ( 'tree_class' ));
2009-02-03 03:50:25 +01:00
2012-05-15 21:30:32 +02:00
$this -> extend ( 'updateSiteTreeAsUL' , $html );
2011-04-12 01:43:01 +02:00
return $html ;
2007-07-19 12:40:05 +02:00
}
2012-04-16 15:55:19 +02:00
/**
* @ return boolean
*/
public function TreeIsFiltered () {
2015-06-15 06:33:30 +02:00
$query = $this -> getRequest () -> getVar ( 'q' );
2016-07-22 01:32:32 +02:00
if ( ! $query || ( count ( $query ) === 1 && isset ( $query [ 'FilterClass' ]) && $query [ 'FilterClass' ] === 'SilverStripe\\CMS\\Controllers\\CMSSiteTreeFilter_Search' )) {
2015-06-15 06:33:30 +02:00
return false ;
}
return true ;
2012-04-16 15:55:19 +02:00
}
2012-05-15 21:30:32 +02:00
public function ExtraTreeTools () {
$html = '' ;
$this -> extend ( 'updateExtraTreeTools' , $html );
return $html ;
}
2015-08-14 02:39:45 +02:00
2012-10-30 05:56:14 +01:00
/**
* Returns a Form for page searching for use in templates .
2015-08-14 02:39:45 +02:00
*
2012-10-30 05:56:14 +01:00
* Can be modified from a decorator by a 'updateSearchForm' method
*
* @ return Form
*/
2012-09-19 12:07:46 +02:00
public function SearchForm () {
2012-10-30 05:56:14 +01:00
// Create the fields
2015-06-16 00:49:19 +02:00
$content = new TextField ( 'q[Term]' , _t ( 'CMSSearch.FILTERLABELTEXT' , 'Search' ));
2012-10-30 05:56:14 +01:00
$dateFrom = new DateField (
2015-08-14 02:39:45 +02:00
'q[LastEditedFrom]' ,
2012-10-30 05:56:14 +01:00
_t ( 'CMSSearch.FILTERDATEFROM' , 'From' )
);
$dateFrom -> setConfig ( 'showcalendar' , true );
$dateTo = new DateField (
'q[LastEditedTo]' ,
_t ( 'CMSSearch.FILTERDATETO' , 'To' )
);
$dateTo -> setConfig ( 'showcalendar' , true );
$pageFilter = new DropdownField (
2015-08-14 02:39:45 +02:00
'q[FilterClass]' ,
_t ( 'CMSMain.PAGES' , 'Page status' ),
2012-10-30 05:56:14 +01:00
CMSSiteTreeFilter :: get_all_filters ()
);
$pageClasses = new DropdownField (
2015-08-14 02:39:45 +02:00
'q[ClassName]' ,
_t ( 'CMSMain.PAGETYPEOPT' , 'Page type' , 'Dropdown for limiting search to a page type' ),
2012-10-30 05:56:14 +01:00
$this -> getPageTypes ()
);
$pageClasses -> setEmptyString ( _t ( 'CMSMain.PAGETYPEANYOPT' , 'Any' ));
2015-08-14 02:39:45 +02:00
2012-10-30 05:56:14 +01:00
// Group the Datefields
$dateGroup = new FieldGroup (
$dateFrom ,
$dateTo
2011-04-22 13:32:10 +02:00
);
2016-08-11 04:10:51 +02:00
$dateGroup -> setTitle ( _t ( 'CMSSearch.PAGEFILTERDATEHEADING' , 'Last edited' ));
2015-08-14 02:39:45 +02:00
2016-10-26 03:01:13 +02:00
// view mode
$viewMode = HiddenField :: create ( 'view' , false , $this -> ViewState ());
2012-10-30 05:56:14 +01:00
// Create the Field list
2011-10-26 07:35:51 +02:00
$fields = new FieldList (
2012-10-30 05:56:14 +01:00
$content ,
$pageFilter ,
2016-07-25 07:25:22 +02:00
$pageClasses ,
2016-10-26 03:01:13 +02:00
$dateGroup ,
$viewMode
2011-04-22 13:32:10 +02:00
);
2015-08-14 02:39:45 +02:00
2012-10-30 05:56:14 +01:00
// Create the Search and Reset action
2011-10-26 07:35:51 +02:00
$actions = new FieldList (
2015-06-16 00:49:19 +02:00
FormAction :: create ( 'doSearch' , _t ( 'CMSMain_left_ss.APPLY_FILTER' , 'Search' ))
2016-11-30 21:31:15 +01:00
-> addExtraClass ( 'btn btn-primary' ),
2016-08-10 06:08:39 +02:00
ResetFormAction :: create ( 'clear' , _t ( 'CMSMain_left_ss.CLEAR_FILTER' , 'Clear' ))
2016-11-30 21:31:15 +01:00
-> addExtraClass ( 'btn btn-secondary' )
2011-04-22 13:32:10 +02:00
);
2012-02-16 22:59:47 +01:00
2012-10-30 05:56:14 +01:00
// Use <button> to allow full jQuery UI styling on the all of the Actions
2016-08-11 04:10:51 +02:00
/** @var FormAction $action */
2012-10-30 05:56:14 +01:00
foreach ( $actions -> dataFields () as $action ) {
2016-08-10 06:08:39 +02:00
/** @var FormAction $action */
2012-10-30 05:56:14 +01:00
$action -> setUseButtonTag ( true );
}
2015-08-14 02:39:45 +02:00
2012-10-30 05:56:14 +01:00
// Create the form
2016-08-10 06:08:39 +02:00
/** @skipUpgrade */
$form = Form :: create ( $this , 'SearchForm' , $fields , $actions )
2012-04-16 15:55:19 +02:00
-> addExtraClass ( 'cms-search-form' )
-> setFormMethod ( 'GET' )
-> setFormAction ( $this -> Link ())
-> disableSecurityToken ()
-> unsetValidator ();
2015-08-14 02:39:45 +02:00
2012-10-30 05:56:14 +01:00
// Load the form with previously sent search data
2015-04-30 01:04:02 +02:00
$form -> loadDataFrom ( $this -> getRequest () -> getVars ());
2012-04-16 15:55:19 +02:00
2012-10-30 05:56:14 +01:00
// Allow decorators to modify the form
2012-06-11 10:36:41 +02:00
$this -> extend ( 'updateSearchForm' , $form );
2015-08-14 02:39:45 +02:00
2011-04-22 13:32:10 +02:00
return $form ;
2009-05-14 08:11:18 +02:00
}
2015-08-14 02:39:45 +02:00
2012-10-30 05:56:14 +01:00
/**
* Returns a sorted array suitable for a dropdown with pagetypes and their translated name
2015-08-14 02:39:45 +02:00
*
2012-10-30 05:56:14 +01:00
* @ return array
*/
protected function getPageTypes () {
$pageTypes = array ();
foreach ( SiteTree :: page_type_classes () as $pageTypeClass ) {
2016-08-10 06:08:39 +02:00
$pageTypes [ $pageTypeClass ] = SiteTree :: singleton ( $pageTypeClass ) -> i18n_singular_name ();
2012-10-30 05:56:14 +01:00
}
asort ( $pageTypes );
return $pageTypes ;
}
2015-08-14 02:39:45 +02:00
2012-09-19 12:07:46 +02:00
public function doSearch ( $data , $form ) {
2015-04-30 01:04:02 +02:00
return $this -> getsubtree ( $this -> getRequest ());
2007-09-16 17:19:17 +02:00
}
2010-10-04 08:13:58 +02:00
2012-02-14 16:01:07 +01:00
/**
2014-02-10 21:35:13 +01:00
* @ param bool $unlinked
2012-02-14 16:01:07 +01:00
* @ return ArrayList
*/
public function Breadcrumbs ( $unlinked = false ) {
$items = parent :: Breadcrumbs ( $unlinked );
2016-01-20 03:28:58 +01:00
if ( $items -> count () > 1 ) {
// Specific to the SiteTree admin section, we never show the cms section and current
// page in the same breadcrumbs block.
$items -> shift ();
}
2012-02-14 16:01:07 +01:00
return $items ;
}
2011-04-15 11:27:37 +02:00
/**
* Create serialized JSON string with site tree hints data to be injected into
* 'data-hints' attribute of root node of jsTree .
2015-08-14 02:39:45 +02:00
*
2015-09-28 11:31:31 +02:00
* @ return string Serialized JSON
2011-04-15 11:27:37 +02:00
*/
public function SiteTreeHints () {
2012-09-14 21:03:40 +02:00
$classes = SiteTree :: page_type_classes ();
2007-09-15 23:54:24 +02:00
2016-08-11 03:18:02 +02:00
$cacheCanCreate = array ();
foreach ( $classes as $class ) $cacheCanCreate [ $class ] = singleton ( $class ) -> canCreate ();
2007-09-15 23:54:24 +02:00
2016-08-11 03:18:02 +02:00
// Generate basic cache key. Too complex to encompass all variations
2016-09-09 01:26:24 +02:00
$cache = Cache :: factory ( 'CMSMain_SiteTreeHints' );
2016-08-11 03:18:02 +02:00
$cacheKey = md5 ( implode ( '_' , array ( Member :: currentUserID (), implode ( ',' , $cacheCanCreate ), implode ( ',' , $classes ))));
2016-08-11 04:10:51 +02:00
if ( $this -> getRequest () -> getVar ( 'flush' )) {
$cache -> clean ( Zend_Cache :: CLEANING_MODE_ALL );
}
2016-08-11 03:18:02 +02:00
$json = $cache -> load ( $cacheKey );
2012-04-13 18:42:15 +02:00
if ( ! $json ) {
$def [ 'Root' ] = array ();
2012-12-03 16:33:06 +01:00
$def [ 'Root' ][ 'disallowedChildren' ] = array ();
// Contains all possible classes to support UI controls listing them all,
// such as the "add page here" context menu.
2015-03-11 06:54:08 +01:00
$def [ 'All' ] = array ();
2012-03-19 02:05:09 +01:00
2012-12-03 16:33:06 +01:00
// Identify disallows and set globals
2012-04-13 18:42:15 +02:00
foreach ( $classes as $class ) {
$obj = singleton ( $class );
2015-03-11 06:54:08 +01:00
if ( $obj instanceof HiddenClass ) continue ;
2012-12-03 16:33:06 +01:00
2015-03-11 06:54:08 +01:00
// Name item
$def [ 'All' ][ $class ] = array (
'title' => $obj -> i18n_singular_name ()
);
2012-12-03 16:33:06 +01:00
2015-03-11 06:54:08 +01:00
// Check if can be created at the root
$needsPerm = $obj -> stat ( 'need_permission' );
2012-12-03 16:33:06 +01:00
if (
2015-03-11 06:54:08 +01:00
! $obj -> stat ( 'can_be_root' )
2012-12-03 16:33:06 +01:00
|| ( ! array_key_exists ( $class , $cacheCanCreate ) || ! $cacheCanCreate [ $class ])
|| ( $needsPerm && ! $this -> can ( $needsPerm ))
) {
$def [ 'Root' ][ 'disallowedChildren' ][] = $class ;
}
2012-03-19 02:05:09 +01:00
2015-03-11 06:54:08 +01:00
// Hint data specific to the class
2012-12-03 16:33:06 +01:00
$def [ $class ] = array ();
2012-03-19 02:05:09 +01:00
2012-12-03 16:33:06 +01:00
$defaultChild = $obj -> defaultChild ();
2015-03-11 06:54:08 +01:00
if ( $defaultChild !== 'Page' && $defaultChild !== null ) {
2012-12-03 16:33:06 +01:00
$def [ $class ][ 'defaultChild' ] = $defaultChild ;
2012-04-13 18:42:15 +02:00
}
2012-03-19 02:05:09 +01:00
2012-04-13 18:42:15 +02:00
$defaultParent = $obj -> defaultParent ();
2015-03-11 06:54:08 +01:00
if ( $defaultParent !== 1 && $defaultParent !== null ) {
2012-12-03 16:33:06 +01:00
$def [ $class ][ 'defaultParent' ] = $defaultParent ;
2011-12-17 04:45:09 +01:00
}
2007-07-19 12:40:05 +02:00
}
2007-09-15 23:54:24 +02:00
2013-10-10 16:31:07 +02:00
$this -> extend ( 'updateSiteTreeHints' , $def );
2012-12-03 16:33:06 +01:00
$json = Convert :: raw2json ( $def );
2012-04-13 18:42:15 +02:00
$cache -> save ( $json , $cacheKey );
}
return $json ;
2007-07-19 12:40:05 +02:00
}
/**
2008-10-16 11:37:28 +02:00
* Populates an array of classes in the CMS
* which allows the user to change the page type .
*
2011-10-26 07:39:21 +02:00
* @ return SS_List
2007-07-19 12:40:05 +02:00
*/
public function PageTypes () {
2009-02-03 04:22:20 +01:00
$classes = SiteTree :: page_type_classes ();
2007-07-19 12:40:05 +02:00
2011-05-05 12:40:26 +02:00
$result = new ArrayList ();
2008-01-17 06:31:38 +01:00
2007-07-19 12:40:05 +02:00
foreach ( $classes as $class ) {
2008-10-16 11:37:28 +02:00
$instance = singleton ( $class );
2016-08-10 06:08:39 +02:00
if ( $instance instanceof HiddenClass ) {
continue ;
}
2007-09-15 23:54:24 +02:00
2007-07-19 12:40:05 +02:00
// skip this type if it is restricted
2016-08-10 06:08:39 +02:00
if ( $instance -> stat ( 'need_permission' ) && ! $this -> can ( singleton ( $class ) -> stat ( 'need_permission' ))) {
continue ;
}
2008-10-16 11:37:28 +02:00
2008-02-25 03:10:37 +01:00
$addAction = $instance -> i18n_singular_name ();
2015-08-14 02:39:45 +02:00
2012-08-26 23:05:13 +02:00
// Get description (convert 'Page' to 'SiteTree' for correct localization lookups)
2016-08-10 06:08:39 +02:00
$i18nClass = ( $class == 'Page' ) ? 'SilverStripe\\CMS\\Model\\SiteTree' : $class ;
$description = _t ( $i18nClass . '.DESCRIPTION' );
2012-08-12 04:44:48 +02:00
if ( ! $description ) {
$description = $instance -> uninherited ( 'description' );
}
2015-08-14 02:39:45 +02:00
2012-08-12 04:44:48 +02:00
if ( $class == 'Page' && ! $description ) {
2016-08-10 06:08:39 +02:00
$description = SiteTree :: singleton () -> uninherited ( 'description' );
2012-08-12 04:44:48 +02:00
}
2015-08-14 02:39:45 +02:00
2007-07-19 12:40:05 +02:00
$result -> push ( new ArrayData ( array (
2008-10-16 11:37:28 +02:00
'ClassName' => $class ,
'AddAction' => $addAction ,
2011-04-24 01:05:01 +02:00
'Description' => $description ,
// TODO Sprite support
2012-08-26 23:05:13 +02:00
'IconURL' => $instance -> stat ( 'icon' ),
'Title' => singleton ( $class ) -> i18n_singular_name (),
2007-07-19 12:40:05 +02:00
)));
}
2015-08-14 02:39:45 +02:00
2012-06-15 05:30:08 +02:00
$result = $result -> sort ( 'AddAction' );
2015-08-14 02:39:45 +02:00
2007-07-19 12:40:05 +02:00
return $result ;
}
2007-09-15 23:54:24 +02:00
2007-07-19 12:40:05 +02:00
/**
2011-08-19 02:32:31 +02:00
* Get a database record to be managed by the CMS .
*
* @ param int $id Record ID
* @ param int $versionID optional Version id of the given record
2016-01-26 06:38:42 +01:00
* @ return SiteTree
2007-07-19 12:40:05 +02:00
*/
2011-08-19 02:32:31 +02:00
public function getRecord ( $id , $versionID = null ) {
2007-07-19 12:40:05 +02:00
$treeClass = $this -> stat ( 'tree_class' );
2007-09-15 23:54:24 +02:00
2011-03-16 04:39:49 +01:00
if ( $id instanceof $treeClass ) {
return $id ;
2015-08-14 02:39:45 +02:00
}
2011-09-02 03:24:29 +02:00
else if ( $id && is_numeric ( $id )) {
2016-06-09 05:13:09 +02:00
$currentStage = Versioned :: get_reading_mode ();
2015-04-30 01:04:02 +02:00
if ( $this -> getRequest () -> getVar ( 'Version' )) {
$versionID = ( int ) $this -> getRequest () -> getVar ( 'Version' );
2011-09-02 03:24:29 +02:00
}
2015-08-14 02:39:45 +02:00
2011-08-26 04:03:21 +02:00
if ( $versionID ) {
$record = Versioned :: get_version ( $treeClass , $id , $versionID );
2011-01-12 00:00:59 +01:00
} else {
2013-06-21 00:45:33 +02:00
$record = DataObject :: get_by_id ( $treeClass , $id );
2011-01-12 00:00:59 +01:00
}
2007-09-15 23:54:24 +02:00
2009-05-01 00:47:28 +02:00
// Then, try getting a record from the live site
2007-07-19 12:40:05 +02:00
if ( ! $record ) {
2008-11-23 23:58:18 +01:00
// $record = Versioned::get_one_by_stage($treeClass, "Live", "\"$treeClass\".\"ID\" = $id");
2016-03-17 01:02:50 +01:00
Versioned :: set_stage ( Versioned :: LIVE );
2007-07-19 12:40:05 +02:00
singleton ( $treeClass ) -> flushCache ();
2009-01-08 00:01:47 +01:00
2013-06-21 00:45:33 +02:00
$record = DataObject :: get_by_id ( $treeClass , $id );
2007-07-19 12:40:05 +02:00
}
2015-08-14 02:39:45 +02:00
2009-05-01 00:47:28 +02:00
// Then, try getting a deleted record
if ( ! $record ) {
$record = Versioned :: get_latest_version ( $treeClass , $id );
}
// Don't open a page from a different locale
2010-10-04 08:16:50 +02:00
/** The record ' s Locale is saved in database in 2.4 , and not related with Session ,
* we should not check their locale matches the Translatable :: get_current_locale ,
* here as long as we all the HTTPRequest is init with right locale .
* This bit breaks the all FileIFrameField functions if the field is used in CMS
2015-08-14 02:39:45 +02:00
* and its relevent ajax calles , like loading the tree dropdown for TreeSelectorField .
2010-10-04 08:16:17 +02:00
*/
2012-10-09 23:59:52 +02:00
/* if ( $record && SiteTree :: has_extension ( 'Translatable' ) && $record -> Locale && $record -> Locale != Translatable :: get_current_locale ()) {
2009-05-01 00:47:28 +02:00
$record = null ;
2010-10-04 08:16:17 +02:00
} */
2009-05-01 00:47:28 +02:00
2016-06-09 05:13:09 +02:00
// Set the reading mode back to what it was.
Versioned :: set_reading_mode ( $currentStage );
2007-07-19 12:40:05 +02:00
return $record ;
2007-09-15 23:54:24 +02:00
2007-07-19 12:40:05 +02:00
} else if ( substr ( $id , 0 , 3 ) == 'new' ) {
return $this -> getNewItem ( $id );
}
}
2015-08-14 02:39:45 +02:00
2009-11-21 03:38:35 +01:00
/**
2015-09-28 11:31:31 +02:00
* @ param int $id
2011-10-26 07:35:51 +02:00
* @ param FieldList $fields
2016-03-01 04:14:35 +01:00
* @ return Form
2009-11-21 03:38:35 +01:00
*/
2011-04-16 07:53:47 +02:00
public function getEditForm ( $id = null , $fields = null ) {
2011-03-16 04:39:49 +01:00
if ( ! $id ) $id = $this -> currentPageID ();
2016-03-09 05:40:43 +01:00
$form = parent :: getEditForm ( $id , $fields );
2015-08-14 02:39:45 +02:00
2009-11-21 04:20:26 +01:00
// TODO Duplicate record fetching (see parent implementation)
2011-03-16 04:39:49 +01:00
$record = $this -> getRecord ( $id );
if ( $record && ! $record -> canView ()) return Security :: permissionFailure ( $this );
2010-04-14 05:28:42 +02:00
2011-04-16 07:53:47 +02:00
if ( ! $fields ) $fields = $form -> Fields ();
2009-11-21 04:20:26 +01:00
$actions = $form -> Actions ();
2007-09-15 23:54:24 +02:00
2007-07-19 12:40:05 +02:00
if ( $record ) {
2016-10-05 03:08:34 +02:00
$deletedFromStage = ! $record -> isOnDraft ();
2012-03-12 13:57:38 +01:00
2009-11-21 03:38:37 +01:00
$fields -> push ( $idField = new HiddenField ( " ID " , false , $id ));
2010-04-12 11:41:45 +02:00
// Necessary for different subsites
2012-08-28 19:07:12 +02:00
$fields -> push ( $liveLinkField = new HiddenField ( " AbsoluteLink " , false , $record -> AbsoluteLink ()));
$fields -> push ( $liveLinkField = new HiddenField ( " LiveLink " ));
$fields -> push ( $stageLinkField = new HiddenField ( " StageLink " ));
2009-11-21 04:20:36 +01:00
$fields -> push ( new HiddenField ( " TreeTitle " , false , $record -> TreeTitle ));
2007-09-15 23:54:24 +02:00
2007-09-05 08:42:26 +02:00
if ( $record -> ID && is_numeric ( $record -> ID ) ) {
2012-08-28 19:07:12 +02:00
$liveLink = $record -> getAbsoluteLiveLink ();
if ( $liveLink ) $liveLinkField -> setValue ( $liveLink );
if ( ! $deletedFromStage ) {
$stageLink = Controller :: join_links ( $record -> AbsoluteLink (), '?stage=Stage' );
if ( $stageLink ) $stageLinkField -> setValue ( $stageLink );
2012-08-27 18:20:56 +02:00
}
2007-09-05 08:42:26 +02:00
}
2015-08-14 02:39:45 +02:00
2011-08-12 17:03:11 +02:00
// Added in-line to the form, but plucked into different view by LeftAndMain.Preview.js upon load
2016-08-10 06:08:39 +02:00
/** @skipUpgrade */
if ( $record instanceof CMSPreviewable && ! $fields -> fieldByName ( 'SilverStripeNavigator' )) {
$navField = new LiteralField ( 'SilverStripeNavigator' , $this -> getSilverStripeNavigator ());
2011-08-12 17:03:11 +02:00
$navField -> setAllowHTML ( true );
$fields -> push ( $navField );
}
2015-08-14 02:39:45 +02:00
2007-07-19 12:40:05 +02:00
// getAllCMSActions can be used to completely redefine the action list
if ( $record -> hasMethod ( 'getAllCMSActions' )) {
$actions = $record -> getAllCMSActions ();
} else {
2008-12-04 23:38:58 +01:00
$actions = $record -> getCMSActions ();
2012-11-21 21:46:45 +01:00
// Find and remove action menus that have no actions.
2016-08-11 04:10:51 +02:00
if ( $actions && $actions -> count ()) {
/** @var TabSet $tabset */
2012-11-21 21:46:45 +01:00
$tabset = $actions -> fieldByName ( 'ActionMenus' );
if ( $tabset ) {
foreach ( $tabset -> getChildren () as $tab ) {
if ( ! $tab -> getChildren () -> count ()) {
$tabset -> removeByName ( $tab -> getName ());
}
}
}
}
2007-07-19 12:40:05 +02:00
}
2012-02-16 22:59:47 +01:00
// Use <button> to allow full jQuery UI styling
$actionsFlattened = $actions -> dataFields ();
2016-08-11 04:10:51 +02:00
if ( $actionsFlattened ) {
/** @var FormAction $action */
foreach ( $actionsFlattened as $action ) {
$action -> setUseButtonTag ( true );
}
}
2015-08-14 02:39:45 +02:00
2009-03-18 14:03:52 +01:00
if ( $record -> hasMethod ( 'getCMSValidator' )) {
$validator = $record -> getCMSValidator ();
} else {
$validator = new RequiredFields ();
}
2015-08-14 02:39:45 +02:00
2011-03-31 10:51:59 +02:00
// TODO Can't merge $FormAttributes in template at the moment
2012-07-13 17:37:35 +02:00
$form -> addExtraClass ( 'center ' . $this -> BaseCSSClasses ());
2013-10-03 12:25:05 +02:00
// Set validation exemptions for specific actions
2016-01-27 03:38:48 +01:00
$form -> setValidationExemptActions ( array ( 'restore' , 'revert' , 'deletefromlive' , 'delete' , 'unpublish' , 'rollback' , 'doRollback' ));
2007-07-19 12:40:05 +02:00
2012-12-03 22:16:34 +01:00
// Announce the capability so the frontend can decide whether to allow preview or not.
2016-08-11 03:18:02 +02:00
if ( $record instanceof CMSPreviewable ) {
2012-12-03 22:16:34 +01:00
$form -> addExtraClass ( 'cms-previewable' );
}
2016-10-10 23:12:46 +02:00
$form -> addExtraClass ( 'fill-height flexbox-area-grow' );
2012-12-03 22:16:34 +01:00
2012-03-12 13:57:38 +01:00
if ( ! $record -> canEdit () || $deletedFromStage ) {
2009-01-05 07:17:59 +01:00
$readonlyFields = $form -> Fields () -> makeReadonly ();
$form -> setFields ( $readonlyFields );
}
2011-08-19 02:32:31 +02:00
2016-03-07 23:58:26 +01:00
$form -> Fields () -> setForm ( $form );
2010-02-11 02:20:20 +01:00
$this -> extend ( 'updateEditForm' , $form );
2007-07-19 12:40:05 +02:00
return $form ;
} else if ( $id ) {
2016-03-01 04:14:35 +01:00
$form = Form :: create ( $this , " EditForm " , new FieldList (
2011-10-26 07:35:51 +02:00
new LabelField ( 'PageDoesntExistLabel' , _t ( 'CMSMain.PAGENOTEXISTS' , " This page doesn't exist " ))), new FieldList ()
2013-05-10 15:00:57 +02:00
) -> setHTMLID ( 'Form_EditForm' );
return $form ;
2007-07-19 12:40:05 +02:00
}
}
2012-04-16 15:55:19 +02:00
/**
2016-09-09 01:26:24 +02:00
* @ param HTTPRequest $request
2015-09-28 11:31:31 +02:00
* @ return string HTML
2012-04-16 15:55:19 +02:00
*/
public function treeview ( $request ) {
2016-10-21 05:15:34 +02:00
return $this -> getResponseNegotiator () -> respond ( $request );
2012-04-16 15:55:19 +02:00
}
2014-02-10 21:35:13 +01:00
/**
2016-09-09 01:26:24 +02:00
* @ param HTTPRequest $request
2015-09-28 11:31:31 +02:00
* @ return string HTML
2014-02-10 21:35:13 +01:00
*/
2012-04-16 15:55:19 +02:00
public function listview ( $request ) {
2016-10-21 05:15:34 +02:00
return $this -> getResponseNegotiator () -> respond ( $request );
}
/**
* @ return string
*/
public function ViewState () {
2016-10-26 03:01:13 +02:00
$mode = $this -> getRequest () -> requestVar ( 'view' )
? : $this -> getRequest () -> param ( 'Action' );
2016-10-21 05:15:34 +02:00
switch ( $mode ) {
case 'listview' :
case 'treeview' :
return $mode ;
default :
return 'treeview' ;
}
2012-04-16 15:55:19 +02:00
}
2015-03-11 06:54:08 +01:00
/**
* Callback to request the list of page types allowed under a given page instance .
* Provides a slower but more precise response over SiteTreeHints
*
2016-09-09 01:26:24 +02:00
* @ param HTTPRequest $request
* @ return HTTPResponse
2015-03-11 06:54:08 +01:00
*/
public function childfilter ( $request ) {
// Check valid parent specified
$parentID = $request -> requestVar ( 'ParentID' );
$parent = SiteTree :: get () -> byID ( $parentID );
if ( ! $parent || ! $parent -> exists ()) return $this -> httpError ( 404 );
// Build hints specific to this class
// Identify disallows and set globals
$classes = SiteTree :: page_type_classes ();
$disallowedChildren = array ();
foreach ( $classes as $class ) {
$obj = singleton ( $class );
if ( $obj instanceof HiddenClass ) continue ;
if ( ! $obj -> canCreate ( null , array ( 'Parent' => $parent ))) {
$disallowedChildren [] = $class ;
}
}
$this -> extend ( 'updateChildFilter' , $disallowedChildren , $parentID );
return $this
2015-08-14 02:39:45 +02:00
-> getResponse ()
2015-03-11 06:54:08 +01:00
-> addHeader ( 'Content-Type' , 'application/json; charset=utf-8' )
-> setBody ( Convert :: raw2json ( $disallowedChildren ));
}
2015-08-14 02:39:45 +02:00
2014-08-06 05:00:48 +02:00
/**
* Safely reconstruct a selected filter from a given set of query parameters
*
* @ param array $params Query parameters to use
* @ return CMSSiteTreeFilter The filter class , or null if none present
* @ throws InvalidArgumentException if invalid filter class is passed .
*/
protected function getQueryFilter ( $params ) {
if ( empty ( $params [ 'FilterClass' ])) return null ;
$filterClass = $params [ 'FilterClass' ];
2016-07-22 01:32:32 +02:00
if ( ! is_subclass_of ( $filterClass , 'SilverStripe\\CMS\\Controllers\\CMSSiteTreeFilter' )) {
2014-08-06 05:00:48 +02:00
throw new InvalidArgumentException ( " Invalid filter class passed: { $filterClass } " );
}
return $filterClass :: create ( $params );
}
2012-04-05 05:39:23 +02:00
/**
2012-04-11 02:16:23 +02:00
* Returns the pages meet a certain criteria as { @ see CMSSiteTreeFilter } or the subpages of a parent page
* defaulting to no filter and show all pages in first level .
* Doubles as search results , if any search parameters are set through { @ link SearchForm ()} .
2015-08-14 02:39:45 +02:00
*
2014-08-06 05:00:48 +02:00
* @ param array $params Search filter criteria
* @ param int $parentID Optional parent node to filter on ( can ' t be combined with other search criteria )
2012-04-05 05:39:23 +02:00
* @ return SS_List
2014-08-06 05:00:48 +02:00
* @ throws InvalidArgumentException if invalid filter class is passed .
2012-04-05 05:39:23 +02:00
*/
2014-08-06 05:00:48 +02:00
public function getList ( $params = array (), $parentID = 0 ) {
if ( $filter = $this -> getQueryFilter ( $params )) {
return $filter -> getFilteredPages ();
2012-04-16 15:55:19 +02:00
} else {
2014-08-06 05:00:48 +02:00
$list = DataList :: create ( $this -> stat ( 'tree_class' ));
$parentID = is_numeric ( $parentID ) ? $parentID : 0 ;
return $list -> filter ( " ParentID " , $parentID );
2012-04-05 05:39:23 +02:00
}
}
2015-08-14 02:39:45 +02:00
2016-08-11 04:10:51 +02:00
/**
* @ return Form
*/
2012-05-01 05:50:06 +02:00
public function ListViewForm () {
2015-04-30 01:04:02 +02:00
$params = $this -> getRequest () -> requestVar ( 'q' );
$list = $this -> getList ( $params , $parentID = $this -> getRequest () -> requestVar ( 'ParentID' ));
2015-08-14 02:39:45 +02:00
$gridFieldConfig = GridFieldConfig :: create () -> addComponents (
2012-04-05 05:39:23 +02:00
new GridFieldSortableHeader (),
new GridFieldDataColumns (),
2014-04-28 05:22:17 +02:00
new GridFieldPaginator ( self :: config () -> page_length )
2012-04-05 05:39:23 +02:00
);
2012-05-07 03:42:56 +02:00
if ( $parentID ){
2016-09-20 03:02:56 +02:00
$linkSpec = $this -> Link ();
2016-10-26 03:01:13 +02:00
$linkSpec = $linkSpec . ( strstr ( $linkSpec , '?' ) ? '&' : '?' ) . 'ParentID=%d&view=listview' ;
2012-05-07 03:42:56 +02:00
$gridFieldConfig -> addComponent (
2012-06-26 05:53:39 +02:00
GridFieldLevelup :: create ( $parentID )
2016-09-20 03:02:56 +02:00
-> setLinkSpec ( $linkSpec )
2012-06-26 05:53:39 +02:00
-> setAttributes ( array ( 'data-pjax' => 'ListViewForm,Breadcrumbs' ))
2012-05-07 03:42:56 +02:00
);
}
2012-04-05 05:39:23 +02:00
$gridField = new GridField ( 'Page' , 'Pages' , $list , $gridFieldConfig );
2016-08-11 04:10:51 +02:00
/** @var GridFieldDataColumns $columns */
2016-08-23 04:36:06 +02:00
$columns = $gridField -> getConfig () -> getComponentByType ( 'SilverStripe\\Forms\\GridField\\GridFieldDataColumns' );
2012-04-19 01:53:46 +02:00
2012-04-16 15:55:19 +02:00
// Don't allow navigating into children nodes on filtered lists
2012-05-01 05:50:06 +02:00
$fields = array (
'getTreeTitle' => _t ( 'SiteTree.PAGETITLE' , 'Page Title' ),
2013-01-22 15:37:20 +01:00
'singular_name' => _t ( 'SiteTree.PAGETYPE' ),
2012-05-01 05:50:06 +02:00
'LastEdited' => _t ( 'SiteTree.LASTUPDATED' , 'Last Updated' ),
);
2016-08-11 04:10:51 +02:00
/** @var GridFieldSortableHeader $sortableHeader */
2016-08-23 04:36:06 +02:00
$sortableHeader = $gridField -> getConfig () -> getComponentByType ( 'SilverStripe\\Forms\\GridField\\GridFieldSortableHeader' );
2016-08-11 04:10:51 +02:00
$sortableHeader -> setFieldSorting ( array ( 'getTreeTitle' => 'Title' ));
2013-03-14 18:59:19 +01:00
$gridField -> getState () -> ParentID = $parentID ;
2012-05-01 05:50:06 +02:00
2012-05-30 12:12:26 +02:00
if ( ! $params ) {
2012-05-01 05:50:06 +02:00
$fields = array_merge ( array ( 'listChildrenLink' => '' ), $fields );
2012-04-05 07:32:24 +02:00
}
2012-05-01 05:50:06 +02:00
$columns -> setDisplayFields ( $fields );
2012-04-19 01:53:46 +02:00
$columns -> setFieldCasting ( array (
2016-06-16 06:57:19 +02:00
'Created' => 'DBDatetime->Ago' ,
'LastEdited' => 'DBDatetime->FormatFromSettings' ,
2015-02-11 00:13:55 +01:00
'getTreeTitle' => 'HTMLFragment'
2012-04-10 04:32:21 +02:00
));
2012-04-16 15:55:19 +02:00
$controller = $this ;
2012-04-19 01:53:46 +02:00
$columns -> setFieldFormatting ( array (
2012-06-15 06:36:45 +02:00
'listChildrenLink' => function ( $value , & $item ) use ( $controller ) {
2016-08-11 04:10:51 +02:00
/** @var SiteTree $item */
2012-06-15 06:36:45 +02:00
$num = $item ? $item -> numChildren () : null ;
2012-04-16 15:55:19 +02:00
if ( $num ) {
return sprintf (
2016-07-11 05:13:31 +02:00
'<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>' ,
2013-09-24 12:12:57 +02:00
Controller :: join_links (
2015-08-14 02:39:45 +02:00
$controller -> Link (),
2016-10-26 03:01:13 +02:00
sprintf ( " ?ParentID=%d&view=listview " , ( int ) $item -> ID )
2013-09-24 12:12:57 +02:00
),
2012-04-16 15:55:19 +02:00
$num
2012-05-01 05:50:06 +02:00
);
2012-04-16 15:55:19 +02:00
}
},
2012-06-15 06:36:45 +02:00
'getTreeTitle' => function ( $value , & $item ) use ( $controller ) {
2013-09-24 12:12:57 +02:00
return sprintf (
2013-12-06 11:18:47 +01:00
'<a class="action-detail" href="%s">%s</a>' ,
Controller :: join_links (
2016-08-10 06:08:39 +02:00
CMSPageEditController :: singleton () -> Link ( 'show' ),
2013-12-06 11:18:47 +01:00
( int ) $item -> ID
),
2013-09-24 12:12:57 +02:00
$item -> TreeTitle // returns HTML, does its own escaping
);
2012-06-15 06:36:45 +02:00
}
2012-04-05 07:32:24 +02:00
));
2015-08-14 02:39:45 +02:00
2016-03-01 04:14:35 +01:00
$negotiator = $this -> getResponseNegotiator ();
$listview = Form :: create (
2012-04-05 05:39:23 +02:00
$this ,
2012-04-16 15:55:19 +02:00
'ListViewForm' ,
2012-04-05 05:39:23 +02:00
new FieldList ( $gridField ),
new FieldList ()
2013-05-10 15:00:57 +02:00
) -> setHTMLID ( 'Form_ListViewForm' );
2012-05-30 15:05:17 +02:00
$listview -> setAttribute ( 'data-pjax-fragment' , 'ListViewForm' );
2016-12-09 04:00:46 +01:00
$listview -> setValidationResponseCallback ( function ( ValidationResult $errors ) use ( $negotiator , $listview ) {
2016-03-01 04:14:35 +01:00
$request = $this -> getRequest ();
if ( $request -> isAjax () && $negotiator ) {
$result = $listview -> forTemplate ();
return $negotiator -> respond ( $request , array (
'CurrentForm' => function () use ( $result ) {
return $result ;
}
));
}
});
2012-04-05 05:39:23 +02:00
$this -> extend ( 'updateListView' , $listview );
2015-08-14 02:39:45 +02:00
2012-04-05 05:39:23 +02:00
$listview -> disableSecurityToken ();
return $listview ;
}
2015-08-14 02:39:45 +02:00
2011-07-06 08:38:23 +02:00
public function currentPageID () {
$id = parent :: currentPageID ();
2015-08-14 02:39:45 +02:00
2013-10-21 08:42:45 +02:00
$this -> extend ( 'updateCurrentPageID' , $id );
2011-07-06 08:38:23 +02:00
return $id ;
}
2015-08-14 02:39:45 +02:00
2007-07-19 12:40:05 +02:00
//------------------------------------------------------------------------------------------//
// Data saving handlers
2009-11-21 04:20:26 +01:00
/**
* Save and Publish page handler
2016-03-17 01:02:50 +01:00
*
* @ param array $data
* @ param Form $form
2016-09-09 01:26:24 +02:00
* @ return HTTPResponse
* @ throws HTTPResponse_Exception
2009-11-21 04:20:26 +01:00
*/
public function save ( $data , $form ) {
$className = $this -> stat ( 'tree_class' );
// Existing or new record?
2013-06-21 00:45:33 +02:00
$id = $data [ 'ID' ];
if ( substr ( $id , 0 , 3 ) != 'new' ) {
2016-03-17 01:02:50 +01:00
/** @var SiteTree $record */
2013-06-21 00:45:33 +02:00
$record = DataObject :: get_by_id ( $className , $id );
2016-03-17 01:02:50 +01:00
// Check edit permissions
if ( $record && ! $record -> canEdit ()) {
return Security :: permissionFailure ( $this );
}
if ( ! $record || ! $record -> ID ) {
2016-09-09 01:26:24 +02:00
throw new HTTPResponse_Exception ( " Bad record ID # $id " , 404 );
2016-03-17 01:02:50 +01:00
}
2009-11-21 04:20:26 +01:00
} else {
2016-03-17 01:02:50 +01:00
if ( ! $className :: singleton () -> canCreate ()) {
return Security :: permissionFailure ( $this );
}
2013-06-21 00:45:33 +02:00
$record = $this -> getNewItem ( $id , false );
2009-11-21 04:20:26 +01:00
}
2015-08-14 02:39:45 +02:00
2016-03-17 01:02:50 +01:00
// Check publishing permissions
$doPublish = ! empty ( $data [ 'publish' ]);
if ( $record && $doPublish && ! $record -> canPublish ()) {
return Security :: permissionFailure ( $this );
}
2009-11-21 04:20:26 +01:00
// TODO Coupling to SiteTree
$record -> HasBrokenLink = 0 ;
$record -> HasBrokenFile = 0 ;
2016-03-17 01:02:50 +01:00
if ( ! $record -> ObsoleteClassName ) {
$record -> writeWithoutVersion ();
}
2009-11-21 04:20:26 +01:00
// Update the class instance if necessary
2011-04-16 07:53:47 +02:00
if ( isset ( $data [ 'ClassName' ]) && $data [ 'ClassName' ] != $record -> ClassName ) {
2016-09-05 08:46:00 +02:00
// Replace $record with a new instance of the new class
$newClassName = $data [ 'ClassName' ];
2009-11-21 04:20:26 +01:00
$record = $record -> newClassInstance ( $newClassName );
}
// save form data into record
2011-04-16 07:53:47 +02:00
$form -> saveInto ( $record );
2009-11-21 04:20:26 +01:00
$record -> write ();
2015-08-14 02:39:45 +02:00
2009-11-21 04:20:26 +01:00
// If the 'Save & Publish' button was clicked, also publish the page
2016-03-17 01:02:50 +01:00
if ( $doPublish ) {
2016-04-01 05:17:37 +02:00
$record -> publishRecursive ();
2016-03-17 01:02:50 +01:00
$message = _t (
'CMSMain.PUBLISHED' ,
" Published ' { title}' successfully. " ,
[ 'title' => $record -> Title ]
);
} else {
$message = _t (
'CMSMain.SAVED' ,
" Saved ' { title}' successfully. " ,
[ 'title' => $record -> Title ]
);
2015-08-14 02:39:45 +02:00
}
2009-11-21 04:20:26 +01:00
2016-03-17 01:02:50 +01:00
$this -> getResponse () -> addHeader ( 'X-Status' , rawurlencode ( $message ));
2015-04-30 01:04:02 +02:00
return $this -> getResponseNegotiator () -> respond ( $this -> getRequest ());
2012-04-05 22:27:47 +02:00
}
2007-09-15 23:54:24 +02:00
2008-11-07 13:21:10 +01:00
/**
2011-04-15 11:37:15 +02:00
* @ uses LeftAndMainExtension -> augmentNewSiteTreeItem ()
2016-08-11 04:10:51 +02:00
*
* @ param int | string $id
* @ param bool $setID
* @ return mixed | DataObject
2016-09-09 01:26:24 +02:00
* @ throws HTTPResponse_Exception
2008-11-07 13:21:10 +01:00
*/
2007-07-19 12:40:05 +02:00
public function getNewItem ( $id , $setID = true ) {
2014-03-19 07:27:39 +01:00
$parentClass = $this -> stat ( 'tree_class' );
2008-11-18 02:48:50 +01:00
list ( $dummy , $className , $parentID , $suffix ) = array_pad ( explode ( '-' , $id ), 4 , null );
2014-03-19 07:27:39 +01:00
2016-08-11 04:10:51 +02:00
if ( ! is_a ( $className , $parentClass , true )) {
2014-03-19 07:27:39 +01:00
$response = Security :: permissionFailure ( $this );
if ( ! $response ) {
2015-08-14 02:39:45 +02:00
$response = $this -> getResponse ();
2014-03-19 07:27:39 +01:00
}
2016-09-09 01:26:24 +02:00
throw new HTTPResponse_Exception ( $response );
2014-03-19 07:27:39 +01:00
}
2015-08-14 02:39:45 +02:00
2016-08-11 04:10:51 +02:00
/** @var SiteTree $newItem */
$newItem = Injector :: inst () -> create ( $className );
2013-06-21 00:45:33 +02:00
if ( ! $suffix ) {
2007-07-19 12:40:05 +02:00
$sessionTag = " NewItems. " . $parentID . " . " . $className ;
2013-06-21 00:45:33 +02:00
if ( Session :: get ( $sessionTag )) {
$suffix = '-' . Session :: get ( $sessionTag );
Session :: set ( $sessionTag , Session :: get ( $sessionTag ) + 1 );
}
else
Session :: set ( $sessionTag , 1 );
2007-09-15 23:54:24 +02:00
2013-06-21 00:45:33 +02:00
$id = $id . $suffix ;
}
2007-09-15 23:54:24 +02:00
2012-08-20 22:25:18 +02:00
$newItem -> Title = _t (
'CMSMain.NEWPAGE' ,
" New { pagetype} " , 'followed by a page type title' ,
array ( 'pagetype' => singleton ( $className ) -> i18n_singular_name ())
);
2007-07-19 12:40:05 +02:00
$newItem -> ClassName = $className ;
$newItem -> ParentID = $parentID ;
2007-09-15 23:54:24 +02:00
2008-02-25 03:10:37 +01:00
// DataObject::fieldExists only checks the current class, not the hierarchy
// This allows the CMS to set the correct sort value
2010-10-04 08:06:50 +02:00
if ( $newItem -> castingHelper ( 'Sort' )) {
2013-06-21 00:45:33 +02:00
$newItem -> Sort = DB :: prepared_query ( 'SELECT MAX("Sort") FROM "SiteTree" WHERE "ParentID" = ?' , array ( $parentID )) -> value () + 1 ;
2007-07-19 12:40:05 +02:00
}
2007-09-15 23:54:24 +02:00
2007-07-19 12:40:05 +02:00
if ( $setID ) $newItem -> ID = $id ;
2007-09-15 23:54:24 +02:00
2008-02-25 03:10:37 +01:00
# Some modules like subsites add extra fields that need to be set when the new item is created
$this -> extend ( 'augmentNewSiteTreeItem' , $newItem );
2015-08-14 02:39:45 +02:00
2007-07-19 12:40:05 +02:00
return $newItem ;
}
2007-09-15 23:54:24 +02:00
2008-12-17 23:41:07 +01:00
/**
2016-03-17 01:02:50 +01:00
* Actually perform the publication step
2015-08-14 02:39:45 +02:00
*
2016-03-17 01:02:50 +01:00
* @ param Versioned | DataObject $record
* @ return mixed
2008-12-17 23:41:07 +01:00
*/
2016-03-17 01:02:50 +01:00
public function performPublish ( $record ) {
if ( $record && ! $record -> canPublish ()) {
2016-01-26 06:38:42 +01:00
return Security :: permissionFailure ( $this );
}
2015-08-14 02:39:45 +02:00
2016-04-01 05:17:37 +02:00
$record -> publishRecursive ();
2007-07-19 12:40:05 +02:00
}
2009-01-05 07:17:59 +01:00
/**
2016-03-17 01:02:50 +01:00
* 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 .
*
* @ uses SiteTree -> doRevertToLive ()
*
* @ param array $data
* @ param Form $form
2016-09-09 01:26:24 +02:00
* @ return HTTPResponse
* @ throws HTTPResponse_Exception
2009-01-05 07:17:59 +01:00
*/
2009-11-21 03:39:12 +01:00
public function revert ( $data , $form ) {
2016-03-17 01:02:50 +01:00
if ( ! isset ( $data [ 'ID' ])) {
2016-09-09 01:26:24 +02:00
throw new HTTPResponse_Exception ( " Please pass an ID in the form content " , 400 );
2016-03-17 01:02:50 +01:00
}
2015-08-14 02:39:45 +02:00
2012-02-11 03:50:09 +01:00
$id = ( int ) $data [ 'ID' ];
2016-10-25 02:22:31 +02:00
$restoredPage = Versioned :: get_latest_version ( SiteTree :: class , $id );
2016-03-17 01:02:50 +01:00
if ( ! $restoredPage ) {
2016-09-09 01:26:24 +02:00
throw new HTTPResponse_Exception ( " SiteTree # $id not found " , 400 );
2016-03-17 01:02:50 +01:00
}
2015-08-14 02:39:45 +02:00
2016-03-17 01:02:50 +01:00
/** @var SiteTree $record */
2016-07-22 01:32:32 +02:00
$record = Versioned :: get_one_by_stage ( 'SilverStripe\\CMS\\Model\\SiteTree' , 'Live' , array (
2013-06-21 00:45:33 +02:00
'"SiteTree_Live"."ID"' => $id
));
2008-12-04 23:38:58 +01:00
2009-01-05 07:17:59 +01:00
// a user can restore a page without publication rights, as it just adds a new draft state
// (this action should just be available when page has been "deleted from draft")
2016-03-17 01:02:50 +01:00
if ( $record && ! $record -> canEdit ()) {
return Security :: permissionFailure ( $this );
}
if ( ! $record || ! $record -> ID ) {
2016-09-09 01:26:24 +02:00
throw new HTTPResponse_Exception ( " Bad record ID # $id " , 404 );
2016-03-17 01:02:50 +01:00
}
2009-01-05 07:17:59 +01:00
2008-11-18 02:48:50 +01:00
$record -> doRevertToLive ();
2015-08-14 02:39:45 +02:00
$this -> getResponse () -> addHeader (
2009-11-21 03:39:12 +01:00
'X-Status' ,
2012-05-14 15:11:35 +02:00
rawurlencode ( _t (
2012-05-01 21:43:43 +02:00
'CMSMain.RESTORED' ,
" Restored ' { title}' successfully " ,
'Param %s is a title' ,
array ( 'title' => $record -> Title )
2012-05-14 15:11:35 +02:00
))
2009-11-21 03:39:12 +01:00
);
2015-08-14 02:39:45 +02:00
2015-04-30 01:04:02 +02:00
return $this -> getResponseNegotiator () -> respond ( $this -> getRequest ());
2007-07-19 12:40:05 +02:00
}
2015-08-14 02:39:45 +02:00
2008-03-11 02:02:05 +01:00
/**
2008-12-17 23:41:07 +01:00
* Delete the current page from draft stage .
2016-03-17 01:02:50 +01:00
*
2008-12-17 23:41:07 +01:00
* @ see deletefromlive ()
2016-03-17 01:02:50 +01:00
*
* @ param array $data
* @ param Form $form
2016-09-09 01:26:24 +02:00
* @ return HTTPResponse
* @ throws HTTPResponse_Exception
2008-03-11 02:02:05 +01:00
*/
2009-09-10 01:47:56 +02:00
public function delete ( $data , $form ) {
2013-06-21 00:45:33 +02:00
$id = $data [ 'ID' ];
2016-08-10 06:08:39 +02:00
$record = SiteTree :: get () -> byID ( $id );
2016-03-17 01:02:50 +01:00
if ( $record && ! $record -> canDelete ()) {
return Security :: permissionFailure ();
}
if ( ! $record || ! $record -> ID ) {
2016-09-09 01:26:24 +02:00
throw new HTTPResponse_Exception ( " Bad record ID # $id " , 404 );
2016-03-17 01:02:50 +01:00
}
2015-08-14 02:39:45 +02:00
2015-05-15 01:51:23 +02:00
// Delete record
2007-07-19 12:40:05 +02:00
$record -> delete ();
2012-03-12 13:57:38 +01:00
2015-08-14 02:39:45 +02:00
$this -> getResponse () -> addHeader (
2012-05-09 00:53:05 +02:00
'X-Status' ,
2012-05-14 15:11:35 +02:00
rawurlencode ( sprintf ( _t ( 'CMSMain.REMOVEDPAGEFROMDRAFT' , " Removed '%s' from the draft site " ), $record -> Title ))
2009-11-21 03:39:12 +01:00
);
2015-08-14 02:39:45 +02:00
2012-03-12 13:57:38 +01:00
// Even if the record has been deleted from stage and live, it can be viewed in "archive mode"
2015-04-30 01:04:02 +02:00
return $this -> getResponseNegotiator () -> respond ( $this -> getRequest ());
2007-07-19 12:40:05 +02:00
}
2010-05-28 04:23:10 +02:00
2015-05-15 01:51:23 +02:00
/**
* Delete this page from both live and stage
*
2016-01-26 06:38:42 +01:00
* @ param array $data
* @ param Form $form
2016-09-09 01:26:24 +02:00
* @ return HTTPResponse
* @ throws HTTPResponse_Exception
2015-05-15 01:51:23 +02:00
*/
public function archive ( $data , $form ) {
$id = $data [ 'ID' ];
2016-03-17 01:02:50 +01:00
/** @var SiteTree $record */
2016-08-10 06:08:39 +02:00
$record = SiteTree :: get () -> byID ( $id );
2015-05-15 01:51:23 +02:00
if ( ! $record || ! $record -> exists ()) {
2016-09-09 01:26:24 +02:00
throw new HTTPResponse_Exception ( " Bad record ID # $id " , 404 );
2015-05-15 01:51:23 +02:00
}
if ( ! $record -> canArchive ()) {
return Security :: permissionFailure ();
}
// Archive record
$record -> doArchive ();
2015-08-14 02:39:45 +02:00
$this -> getResponse () -> addHeader (
2015-05-15 01:51:23 +02:00
'X-Status' ,
rawurlencode ( sprintf ( _t ( 'CMSMain.ARCHIVEDPAGE' , " Archived page '%s' " ), $record -> Title ))
);
// Even if the record has been deleted from stage and live, it can be viewed in "archive mode"
return $this -> getResponseNegotiator () -> respond ( $this -> getRequest ());
}
2012-09-19 12:07:46 +02:00
public function publish ( $data , $form ) {
2009-11-21 03:39:12 +01:00
$data [ 'publish' ] = '1' ;
2015-08-14 02:39:45 +02:00
2009-11-21 03:39:12 +01:00
return $this -> save ( $data , $form );
2009-11-21 03:36:13 +01:00
}
2007-09-15 23:54:24 +02:00
2012-09-19 12:07:46 +02:00
public function unpublish ( $data , $form ) {
2011-03-16 04:41:46 +01:00
$className = $this -> stat ( 'tree_class' );
2016-01-26 06:38:42 +01:00
/** @var SiteTree $record */
2011-03-16 04:41:46 +01:00
$record = DataObject :: get_by_id ( $className , $data [ 'ID' ]);
2015-08-14 02:39:45 +02:00
2016-01-26 06:38:42 +01:00
if ( $record && ! $record -> canUnpublish ()) {
return Security :: permissionFailure ( $this );
}
if ( ! $record || ! $record -> ID ) {
2016-09-09 01:26:24 +02:00
throw new HTTPResponse_Exception ( " Bad record ID # " . ( int ) $data [ 'ID' ], 404 );
2016-01-26 06:38:42 +01:00
}
2015-08-14 02:39:45 +02:00
2011-03-16 04:41:46 +01:00
$record -> doUnpublish ();
2015-08-14 02:39:45 +02:00
$this -> getResponse () -> addHeader (
2009-11-21 03:39:12 +01:00
'X-Status' ,
2012-05-14 15:11:35 +02:00
rawurlencode ( _t ( 'CMSMain.REMOVEDPAGE' , " Removed ' { title}' from the published site " , array ( 'title' => $record -> Title )))
2009-11-21 03:39:12 +01:00
);
2015-08-14 02:39:45 +02:00
2015-04-30 01:04:02 +02:00
return $this -> getResponseNegotiator () -> respond ( $this -> getRequest ());
2007-07-19 12:40:05 +02:00
}
2007-09-15 23:54:24 +02:00
2012-04-10 14:09:30 +02:00
/**
2016-09-09 01:26:24 +02:00
* @ return HTTPResponse
2012-04-10 14:09:30 +02:00
*/
2012-09-19 12:07:46 +02:00
public function rollback () {
2012-04-10 14:09:30 +02:00
return $this -> doRollback ( array (
'ID' => $this -> currentPageID (),
2015-04-30 01:04:02 +02:00
'Version' => $this -> getRequest () -> param ( 'VersionID' )
2012-04-10 14:09:30 +02:00
), null );
}
/**
* Rolls a site back to a given version ID
*
2016-03-17 01:02:50 +01:00
* @ param array $data
* @ param Form $form
2016-09-09 01:26:24 +02:00
* @ return HTTPResponse
2012-04-10 14:09:30 +02:00
*/
2012-09-19 12:07:46 +02:00
public function doRollback ( $data , $form ) {
2012-04-10 14:09:30 +02:00
$this -> extend ( 'onBeforeRollback' , $data [ 'ID' ]);
2015-08-14 02:39:45 +02:00
2012-04-10 14:09:30 +02:00
$id = ( isset ( $data [ 'ID' ])) ? ( int ) $data [ 'ID' ] : null ;
$version = ( isset ( $data [ 'Version' ])) ? ( int ) $data [ 'Version' ] : null ;
2016-03-17 01:02:50 +01:00
/** @var DataObject|Versioned $record */
2012-04-10 14:09:30 +02:00
$record = DataObject :: get_by_id ( $this -> stat ( 'tree_class' ), $id );
2016-03-17 01:02:50 +01:00
if ( $record && ! $record -> canEdit ()) {
return Security :: permissionFailure ( $this );
}
2015-08-14 02:39:45 +02:00
2012-04-10 14:09:30 +02:00
if ( $version ) {
$record -> doRollbackTo ( $version );
2012-05-01 21:43:43 +02:00
$message = _t (
2013-05-15 04:13:01 +02:00
'CMSMain.ROLLEDBACKVERSIONv2' ,
" Rolled back to version #%d. " ,
array ( 'version' => $data [ 'Version' ])
2012-04-10 14:09:30 +02:00
);
} else {
2016-05-23 07:36:58 +02:00
$record -> doRevertToLive ();
2012-05-01 21:43:43 +02:00
$message = _t (
2013-05-15 04:13:01 +02:00
'CMSMain.ROLLEDBACKPUBv2' , " Rolled back to published version. "
2012-04-10 14:09:30 +02:00
);
}
2015-08-14 02:39:45 +02:00
$this -> getResponse () -> addHeader ( 'X-Status' , rawurlencode ( $message ));
2012-04-10 14:09:30 +02:00
// Can be used in different contexts: In normal page 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.
2012-08-27 14:19:40 +02:00
// The X-Pjax header forces a "full" content refresh on redirect.
2016-08-10 06:08:39 +02:00
$url = Controller :: join_links ( CMSPageEditController :: singleton () -> Link ( 'show' ), $record -> ID );
2015-08-14 02:39:45 +02:00
$this -> getResponse () -> addHeader ( 'X-ControllerURL' , $url );
2015-04-30 01:04:02 +02:00
$this -> getRequest () -> addHeader ( 'X-Pjax' , 'Content' );
2015-08-14 02:39:45 +02:00
$this -> getResponse () -> addHeader ( 'X-Pjax' , 'Content' );
2012-08-27 14:19:40 +02:00
2015-04-30 01:04:02 +02:00
return $this -> getResponseNegotiator () -> respond ( $this -> getRequest ());
2012-04-10 14:09:30 +02:00
}
2007-09-16 17:04:09 +02:00
/**
2009-05-14 08:11:18 +02:00
* Batch Actions Handler
2007-09-16 17:04:09 +02:00
*/
2012-09-19 12:07:46 +02:00
public function batchactions () {
2009-05-14 08:11:18 +02:00
return new CMSBatchActionHandler ( $this , 'batchactions' );
2007-09-16 17:04:09 +02:00
}
2015-08-14 02:39:45 +02:00
2012-09-19 12:07:46 +02:00
public function BatchActionParameters () {
2013-03-18 11:47:15 +01:00
$batchActions = CMSBatchActionHandler :: config () -> batch_actions ;
2009-10-16 00:43:58 +02:00
$forms = array ();
2009-10-16 00:44:08 +02:00
foreach ( $batchActions as $urlSegment => $batchAction ) {
2010-01-13 01:09:30 +01:00
$SNG_action = singleton ( $batchAction );
if ( $SNG_action -> canView () && $fieldset = $SNG_action -> getParameterFields ()) {
2009-10-16 00:43:58 +02:00
$formHtml = '' ;
2016-08-11 04:10:51 +02:00
/** @var FormField $field */
2009-10-16 00:43:58 +02:00
foreach ( $fieldset as $field ) {
$formHtml .= $field -> Field ();
}
2009-10-16 00:44:08 +02:00
$forms [ $urlSegment ] = $formHtml ;
2009-10-16 00:43:58 +02:00
}
}
$pageHtml = '' ;
2009-10-16 00:44:08 +02:00
foreach ( $forms as $urlSegment => $html ) {
$pageHtml .= " <div class= \" params \" id= \" BatchActionParameters_ $urlSegment\ " > $html </ div > \n\n " ;
2015-08-14 02:39:45 +02:00
}
2009-10-16 00:43:58 +02:00
return new LiteralField ( " BatchActionParameters " , '<div id="BatchActionParameters" style="display:none">' . $pageHtml . '</div>' );
}
2007-07-19 12:40:05 +02:00
/**
2009-05-14 08:11:18 +02:00
* Returns a list of batch actions
2007-07-19 12:40:05 +02:00
*/
2012-09-19 12:07:46 +02:00
public function BatchActionList () {
2009-05-14 08:11:18 +02:00
return $this -> batchactions () -> batchActionList ();
2007-07-19 12:40:05 +02:00
}
2015-08-14 02:39:45 +02:00
2012-09-19 12:07:46 +02:00
public function publishall ( $request ) {
2011-10-07 11:14:55 +02:00
if ( ! Permission :: check ( 'ADMIN' )) return Security :: permissionFailure ( $this );
increase_time_limit_to ();
increase_memory_limit_to ();
2015-08-14 02:39:45 +02:00
2008-08-12 04:59:27 +02:00
$response = " " ;
2007-09-15 23:54:24 +02:00
2008-08-12 04:59:27 +02:00
if ( isset ( $this -> requestParams [ 'confirm' ])) {
2010-11-01 02:29:02 +01:00
// Protect against CSRF on destructive action
if ( ! SecurityToken :: inst () -> checkRequest ( $request )) return $this -> httpError ( 400 );
2015-08-14 02:39:45 +02:00
2008-02-25 03:10:37 +01:00
$start = 0 ;
2016-08-10 06:08:39 +02:00
$pages = SiteTree :: get () -> limit ( " $start ,30 " );
2007-07-19 12:40:05 +02:00
$count = 0 ;
2010-12-14 02:29:38 +01:00
while ( $pages ) {
2016-08-11 04:10:51 +02:00
/** @var SiteTree $page */
2010-12-14 02:29:38 +01:00
foreach ( $pages as $page ) {
2016-04-01 05:17:37 +02:00
if ( $page && ! $page -> canPublish ()) {
return Security :: permissionFailure ( $this );
}
2015-08-14 02:39:45 +02:00
2016-04-01 05:17:37 +02:00
$page -> publishRecursive ();
2010-12-14 02:29:38 +01:00
$page -> destroy ();
unset ( $page );
$count ++ ;
$response .= " <li> $count </li> " ;
}
2016-08-10 06:08:39 +02:00
if ( $pages -> count () > 29 ) {
2010-12-14 02:29:38 +01:00
$start += 30 ;
2016-08-10 06:08:39 +02:00
$pages = SiteTree :: get () -> limit ( " $start ,30 " );
2010-12-14 02:29:38 +01:00
} else {
break ;
2008-02-25 03:10:37 +01:00
}
2007-07-19 12:40:05 +02:00
}
2012-05-01 21:43:43 +02:00
$response .= _t ( 'CMSMain.PUBPAGES' , " Done: Published { count} pages " , array ( 'count' => $count ));
2007-09-15 23:54:24 +02:00
2007-07-19 12:40:05 +02:00
} else {
2010-11-01 02:29:02 +01:00
$token = SecurityToken :: inst ();
2011-10-26 07:35:51 +02:00
$fields = new FieldList ();
2010-11-02 20:22:50 +01:00
$token -> updateFieldSet ( $fields );
2016-08-11 04:10:51 +02:00
$tokenField = $fields -> first ();
2010-11-02 20:22:50 +01:00
$tokenHtml = ( $tokenField ) ? $tokenField -> FieldHolder () : '' ;
2016-12-05 22:58:26 +01:00
$publishAllDescription = _t (
'CMSMain.PUBALLFUN2' ,
'Pressing this button will do the equivalent of going to every page and pressing "publish". '
. 'It\'s intended to be used after there have been massive edits of the content, such as when '
. 'the site was first built.'
);
2008-08-12 04:59:27 +02:00
$response .= '<h1>' . _t ( 'CMSMain.PUBALLFUN' , '"Publish All" functionality' ) . ' </ h1 >
2016-12-05 22:58:26 +01:00
< p > ' . $publishAllDescription . ' </ p >
2007-07-19 12:40:05 +02:00
< form method = " post " action = " publishall " >
2007-09-15 23:54:24 +02:00
< input type = " submit " name = " confirm " value = " '
2012-04-13 21:54:56 +02:00
. _t ( 'CMSMain.PUBALLCONFIRM' , " Please publish every page in the site, copying content stage to live " , 'Confirmation button' ) . '" />'
2010-11-02 20:22:50 +01:00
. $tokenHtml .
2010-11-01 02:29:02 +01:00
'</form>' ;
2007-07-19 12:40:05 +02:00
}
2015-08-14 02:39:45 +02:00
2008-08-12 04:59:27 +02:00
return $response ;
2007-07-19 12:40:05 +02:00
}
2015-08-14 02:39:45 +02:00
2009-01-05 07:17:59 +01:00
/**
2009-05-01 00:47:28 +02:00
* Restore a completely deleted page from the SiteTree_versions table .
2016-08-11 04:10:51 +02:00
*
* @ param array $data
* @ param Form $form
2016-09-09 01:26:24 +02:00
* @ return HTTPResponse
2009-01-05 07:17:59 +01:00
*/
2012-09-19 12:07:46 +02:00
public function restore ( $data , $form ) {
2009-11-21 03:39:12 +01:00
if ( ! isset ( $data [ 'ID' ]) || ! is_numeric ( $data [ 'ID' ])) {
2016-09-09 01:26:24 +02:00
return new HTTPResponse ( " Please pass an ID in the form content " , 400 );
2007-07-19 12:40:05 +02:00
}
2015-08-14 02:39:45 +02:00
2009-11-21 04:19:49 +01:00
$id = ( int ) $data [ 'ID' ];
2016-08-11 04:10:51 +02:00
/** @var SiteTree $restoredPage */
2016-10-25 02:22:31 +02:00
$restoredPage = Versioned :: get_latest_version ( SiteTree :: class , $id );
2016-08-11 04:10:51 +02:00
if ( ! $restoredPage ) {
2016-09-09 01:26:24 +02:00
return new HTTPResponse ( " SiteTree # $id not found " , 400 );
2016-08-11 04:10:51 +02:00
}
2015-08-14 02:39:45 +02:00
2009-11-21 03:39:12 +01:00
$restoredPage = $restoredPage -> doRestoreToStage ();
2015-08-14 02:39:45 +02:00
$this -> getResponse () -> addHeader (
2009-11-21 03:39:12 +01:00
'X-Status' ,
2012-05-14 15:11:35 +02:00
rawurlencode ( _t (
2012-05-01 21:43:43 +02:00
'CMSMain.RESTORED' ,
2015-08-14 02:39:45 +02:00
" Restored ' { title}' successfully " ,
2013-05-25 01:37:26 +02:00
array ( 'title' => $restoredPage -> Title )
2012-05-14 15:11:35 +02:00
))
2009-11-21 03:39:12 +01:00
);
2015-08-14 02:39:45 +02:00
2015-04-30 01:04:02 +02:00
return $this -> getResponseNegotiator () -> respond ( $this -> getRequest ());
2007-07-19 12:40:05 +02:00
}
2007-09-15 23:54:24 +02:00
2012-09-19 12:07:46 +02:00
public function duplicate ( $request ) {
2010-11-01 02:29:02 +01:00
// Protect against CSRF on destructive action
if ( ! SecurityToken :: inst () -> checkRequest ( $request )) return $this -> httpError ( 400 );
2015-08-14 02:39:45 +02:00
2007-07-19 12:40:05 +02:00
if (( $id = $this -> urlParams [ 'ID' ]) && is_numeric ( $id )) {
2016-08-11 04:10:51 +02:00
/** @var SiteTree $page */
2016-08-10 06:08:39 +02:00
$page = SiteTree :: get () -> byID ( $id );
2015-05-21 10:51:07 +02:00
if ( $page && ( ! $page -> canEdit () || ! $page -> canCreate ( null , array ( 'Parent' => $page -> Parent ())))) {
return Security :: permissionFailure ( $this );
}
2016-09-09 01:26:24 +02:00
if ( ! $page || ! $page -> ID ) throw new HTTPResponse_Exception ( " Bad record ID # $id " , 404 );
2007-07-19 12:40:05 +02:00
$newPage = $page -> duplicate ();
2015-08-14 02:39:45 +02:00
2008-02-25 03:10:37 +01:00
// ParentID can be hard-set in the URL. This is useful for pages with multiple parents
2013-03-11 21:20:01 +01:00
if ( isset ( $_GET [ 'parentID' ]) && is_numeric ( $_GET [ 'parentID' ])) {
2008-02-25 03:10:37 +01:00
$newPage -> ParentID = $_GET [ 'parentID' ];
$newPage -> write ();
}
2015-08-14 02:39:45 +02:00
$this -> getResponse () -> addHeader (
2013-03-11 21:20:01 +01:00
'X-Status' ,
rawurlencode ( _t (
'CMSMain.DUPLICATED' ,
2015-08-14 02:39:45 +02:00
" Duplicated ' { title}' successfully " ,
2013-03-11 21:20:01 +01:00
array ( 'title' => $newPage -> Title )
))
);
2016-08-10 06:08:39 +02:00
$url = Controller :: join_links ( CMSPageEditController :: singleton () -> Link ( 'show' ), $newPage -> ID );
2015-08-14 02:39:45 +02:00
$this -> getResponse () -> addHeader ( 'X-ControllerURL' , $url );
2015-04-30 01:04:02 +02:00
$this -> getRequest () -> addHeader ( 'X-Pjax' , 'Content' );
2015-08-14 02:39:45 +02:00
$this -> getResponse () -> addHeader ( 'X-Pjax' , 'Content' );
2015-04-30 01:04:02 +02:00
return $this -> getResponseNegotiator () -> respond ( $this -> getRequest ());
2008-02-25 03:10:37 +01:00
} else {
2016-09-09 01:26:24 +02:00
return new HTTPResponse ( " CMSMain::duplicate() Bad ID: ' $id ' " , 400 );
2008-02-25 03:10:37 +01:00
}
}
2012-09-19 12:07:46 +02:00
public function duplicatewithchildren ( $request ) {
2010-11-01 02:29:02 +01:00
// Protect against CSRF on destructive action
if ( ! SecurityToken :: inst () -> checkRequest ( $request )) return $this -> httpError ( 400 );
2013-03-11 21:20:01 +01:00
increase_time_limit_to ();
2008-02-25 03:10:37 +01:00
if (( $id = $this -> urlParams [ 'ID' ]) && is_numeric ( $id )) {
2016-08-11 04:10:51 +02:00
/** @var SiteTree $page */
2016-08-10 06:08:39 +02:00
$page = SiteTree :: get () -> byID ( $id );
2015-05-21 10:51:07 +02:00
if ( $page && ( ! $page -> canEdit () || ! $page -> canCreate ( null , array ( 'Parent' => $page -> Parent ())))) {
return Security :: permissionFailure ( $this );
}
2016-09-09 01:26:24 +02:00
if ( ! $page || ! $page -> ID ) throw new HTTPResponse_Exception ( " Bad record ID # $id " , 404 );
2008-02-25 03:10:37 +01:00
$newPage = $page -> duplicateWithChildren ();
2008-01-24 01:01:52 +01:00
2015-08-14 02:39:45 +02:00
$this -> getResponse () -> addHeader (
2013-03-11 21:20:01 +01:00
'X-Status' ,
rawurlencode ( _t (
'CMSMain.DUPLICATEDWITHCHILDREN' ,
2015-08-14 02:39:45 +02:00
" Duplicated ' { title}' and children successfully " ,
2013-03-11 21:20:01 +01:00
array ( 'title' => $newPage -> Title )
))
);
2016-08-10 06:08:39 +02:00
$url = Controller :: join_links ( CMSPageEditController :: singleton () -> Link ( 'show' ), $newPage -> ID );
2015-08-14 02:39:45 +02:00
$this -> getResponse () -> addHeader ( 'X-ControllerURL' , $url );
2015-04-30 01:04:02 +02:00
$this -> getRequest () -> addHeader ( 'X-Pjax' , 'Content' );
2015-08-14 02:39:45 +02:00
$this -> getResponse () -> addHeader ( 'X-Pjax' , 'Content' );
2015-04-30 01:04:02 +02:00
return $this -> getResponseNegotiator () -> respond ( $this -> getRequest ());
2008-01-24 01:01:52 +01:00
} else {
2016-09-09 01:26:24 +02:00
return new HTTPResponse ( " CMSMain::duplicatewithchildren() Bad ID: ' $id ' " , 400 );
2008-01-24 01:01:52 +01:00
}
}
2015-08-14 02:39:45 +02:00
2012-09-19 12:07:46 +02:00
public function providePermissions () {
2016-05-02 00:42:47 +02:00
$title = CMSPagesController :: menu_title ();
2012-03-05 16:07:53 +01:00
return array (
" CMS_ACCESS_CMSMain " => array (
2012-05-01 21:43:43 +02:00
'name' => _t ( 'CMSMain.ACCESS' , " Access to ' { title}' section " , array ( 'title' => $title )),
2012-03-05 16:07:53 +01:00
'category' => _t ( 'Permission.CMS_ACCESS_CATEGORY' , 'CMS Access' ),
'help' => _t (
'CMSMain.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".'
),
'sort' => - 99 // below "CMS_ACCESS_LeftAndMain", but above everything else
)
2010-10-13 06:12:59 +02:00
);
2007-07-19 12:40:05 +02:00
}
2007-09-16 22:53:31 +02:00
2007-07-19 12:40:05 +02:00
}