2007-07-19 12:40:05 +02:00
< ? php
/**
* 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 .
2008-06-15 15:33:53 +02:00
*
2008-02-25 03:10:37 +01:00
* @ package cms
2011-08-19 02:32:31 +02:00
* @ subpackage controller
2007-07-19 12:40:05 +02:00
* @ todo Create some base classes to contain the generic functionality that will be replicated .
*/
class CMSMain extends LeftAndMain implements CurrentPageIdentifier , PermissionProvider {
2008-02-20 10:41:33 +01:00
2012-01-24 14:02:02 +01:00
static $url_segment = 'page' ;
2008-11-02 22:27:55 +01:00
static $url_rule = '/$Action/$ID/$OtherID' ;
// Maintain a lower priority than other administration sections
// so that Director does not think they are actions of CMSMain
static $url_priority = 40 ;
2011-03-31 11:10:44 +02:00
static $menu_title = 'Edit Page' ;
2008-11-02 22:27:55 +01:00
static $menu_priority = 10 ;
2007-07-19 12:40:05 +02:00
static $tree_class = " SiteTree " ;
2007-09-27 22:56:55 +02:00
2007-07-19 12:40:05 +02:00
static $subitem_class = " Member " ;
2007-09-27 22:56:55 +02:00
2008-02-25 03:10:37 +01:00
static $allowed_actions = array (
'buildbrokenlinks' ,
'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-05 05:39:23 +02:00
'ListView' ,
'getListView' ,
2012-04-10 04:14:42 +02:00
'listchildren' ,
2008-02-25 03:10:37 +01:00
);
2007-07-19 12:40:05 +02:00
public function init () {
2011-03-29 07:00:21 +02:00
// set reading lang
2012-04-05 14:45:26 +02:00
if ( Object :: has_extension ( 'SiteTree' , 'Translatable' ) && ! $this -> request -> isAjax ()) {
2011-03-29 07:00:21 +02:00
Translatable :: choose_site_locale ( array_keys ( Translatable :: get_existing_content_languages ( 'SiteTree' )));
}
2007-07-19 12:40:05 +02:00
parent :: init ();
2009-11-21 03:38:05 +01:00
2012-02-23 20:19:03 +01:00
Requirements :: css ( CMS_DIR . '/css/screen.css' );
2009-11-21 04:19:02 +01:00
2011-04-25 11:10:22 +02:00
Requirements :: combine_files (
'cmsmain.js' ,
2012-01-06 12:01:51 +01:00
array_merge (
array (
CMS_DIR . '/javascript/CMSMain.js' ,
CMS_DIR . '/javascript/CMSMain.EditForm.js' ,
CMS_DIR . '/javascript/CMSMain.AddForm.js' ,
CMS_DIR . '/javascript/CMSPageHistoryController.js' ,
2012-03-12 11:40:43 +01:00
CMS_DIR . '/javascript/CMSMain.Tree.js' ,
2012-01-06 12:01:51 +01:00
CMS_DIR . '/javascript/SilverStripeNavigator.js'
),
Requirements :: add_i18n_javascript ( CMS_DIR . '/javascript/lang' , true , true )
2011-04-25 11:10:22 +02:00
)
);
2012-01-06 12:01:51 +01:00
2009-11-21 04:19:02 +01:00
CMSBatchActionHandler :: register ( 'publish' , 'CMSBatchAction_Publish' );
CMSBatchActionHandler :: register ( 'unpublish' , 'CMSBatchAction_Unpublish' );
CMSBatchActionHandler :: register ( 'delete' , 'CMSBatchAction_Delete' );
CMSBatchActionHandler :: register ( 'deletefromlive' , 'CMSBatchAction_DeleteFromLive' );
2007-07-19 12:40:05 +02:00
}
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
*/
function ShowSwitchView () {
return true ;
}
2010-06-03 04:45:23 +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 .
*/
function SwitchView ( $page = null ) {
if ( ! $page ) {
$page = $this -> currentPage ();
}
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 .
*
* @ return string
*/
public function Link ( $action = null ) {
return Controller :: join_links (
$this -> stat ( 'url_base' , true ),
$this -> stat ( 'url_segment' , true ), // in case we want to change the segment
'/' , // trailing slash needed if $action is null!
" $action "
);
}
2011-10-29 19:13:19 +02:00
/**
* @ return string
*/
public function PreviewLink () {
$record = $this -> getRecord ( $this -> currentPageID ());
$baseLink = ( $record && $record instanceof Page ) ? $record -> Link ( '?stage=Stage' ) : Director :: absoluteBaseURL ();
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 () {
2011-04-12 01:43:01 +02:00
$html = '' ;
// Include custom CSS for tree icons inline, as the tree might be loaded
// via Ajax, in which case we can't inject it into the HTML header easily through the HTTP response.
$css = $this -> generateTreeStylingCSS ();
2012-04-05 14:45:26 +02:00
if ( $this -> request -> isAjax ()) {
2011-04-12 01:43:01 +02:00
$html .= " <style type= \" text/css \" > \n " . $css . " </style> \n " ;
} else {
Requirements :: customCSS ( $css );
}
2007-09-15 23:54:24 +02:00
2009-02-03 03:50:25 +01:00
// Pre-cache sitetree version numbers for querying efficiency
Versioned :: prepopulate_versionnumber_cache ( " SiteTree " , " Stage " );
Versioned :: prepopulate_versionnumber_cache ( " SiteTree " , " Live " );
2011-04-12 01:43:01 +02:00
$html .= $this -> getSiteTreeFor ( $this -> stat ( 'tree_class' ));
2009-02-03 03:50:25 +01:00
2011-04-12 01:43:01 +02:00
return $html ;
2007-07-19 12:40:05 +02:00
}
2009-08-04 05:09:26 +02:00
2011-04-22 13:32:10 +02:00
function SearchForm () {
// get all page types in a dropdown-compatible format
$pageTypes = SiteTree :: page_type_classes ();
$pageTypes = array_combine ( $pageTypes , $pageTypes );
asort ( $pageTypes );
// get all filter instances
2009-08-04 05:09:26 +02:00
$filters = ClassInfo :: subclassesFor ( 'CMSSiteTreeFilter' );
2011-04-22 13:32:10 +02:00
$filterMap = array ();
// remove base class
2009-08-04 05:09:26 +02:00
array_shift ( $filters );
2011-04-22 13:32:10 +02:00
// add filters to map
2009-08-04 05:09:26 +02:00
foreach ( $filters as $filter ) {
2011-04-22 13:32:10 +02:00
$filterMap [ $filter ] = call_user_func ( array ( $filter , 'title' ));
2009-08-04 05:09:26 +02:00
}
2011-04-22 13:32:10 +02:00
// ensure that 'all pages' filter is on top position
uasort ( $filterMap ,
create_function ( '$a,$b' , 'return ($a == "CMSSiteTreeFilter_Search") ? 1 : -1;' )
);
2011-10-26 07:35:51 +02:00
$fields = new FieldList (
2011-04-22 13:32:10 +02:00
new TextField ( 'Term' , _t ( 'CMSSearch.FILTERLABELTEXT' , 'Content' )),
2011-05-01 02:34:16 +02:00
$dateGroup = new FieldGroup (
2012-04-11 06:01:15 +02:00
new HeaderField ( 'Date' , _t ( 'CMSSearch.FILTERDATEHEADING' , 'Date' ), 4 ),
2011-08-19 02:32:31 +02:00
$dateFrom = new DateField ( 'LastEditedFrom' , _t ( 'CMSSearch.FILTERDATEFROM' , 'From' )),
$dateTo = new DateField ( 'LastEditedTo' , _t ( 'CMSSearch.FILTERDATETO' , 'To' ))
2011-05-01 02:34:16 +02:00
),
2011-04-22 13:32:10 +02:00
new DropdownField (
'FilterClass' ,
2011-08-19 02:32:31 +02:00
_t ( 'CMSMain.PAGES' , 'Pages' ),
2011-04-22 13:32:10 +02:00
$filterMap
),
new DropdownField (
'ClassName' ,
_t ( 'CMSMain.PAGETYPEOPT' , 'Page Type' , PR_MEDIUM , 'Dropdown for limiting search to a page type' ),
$pageTypes ,
null ,
null ,
_t ( 'CMSMain.PAGETYPEANYOPT' , 'Any' )
)
// new TextField('MetaTags', _t('CMSMain.SearchMetaTags', 'Meta tags'))
);
2011-05-01 02:34:16 +02:00
$dateGroup -> subfieldParam = 'FieldHolder' ;
2011-04-22 13:32:10 +02:00
$dateFrom -> setConfig ( 'showcalendar' , true );
$dateTo -> setConfig ( 'showcalendar' , true );
2011-10-26 07:35:51 +02:00
$actions = new FieldList (
2012-04-11 06:01:15 +02:00
FormAction :: create ( 'doSearch' , _t ( 'CMSMain_left.ss.APPLY FILTER' , 'Apply Filter' ))
-> addExtraClass ( 'ss-ui-action-constructive' ),
Object :: create ( 'ResetFormAction' , 'clear' , _t ( 'CMSMain_left.ss.RESET' , 'Reset' ))
2011-04-22 13:32:10 +02:00
);
2012-02-16 22:59:47 +01:00
// Use <button> to allow full jQuery UI styling
foreach ( $actions -> dataFields () as $action ) $action -> setUseButtonTag ( true );
2011-04-22 13:32:10 +02:00
$form = new Form ( $this , 'SearchForm' , $fields , $actions );
$form -> setFormMethod ( 'GET' );
$form -> disableSecurityToken ();
$form -> unsetValidator ();
return $form ;
2009-05-14 08:11:18 +02:00
}
2011-04-22 13:32:10 +02:00
function doSearch ( $data , $form ) {
return $this -> getsubtree ( $this -> request );
2007-09-16 17:19:17 +02:00
}
2010-10-04 08:13:58 +02:00
2012-02-14 16:01:07 +01:00
/**
* @ return ArrayList
*/
public function Breadcrumbs ( $unlinked = false ) {
$items = parent :: Breadcrumbs ( $unlinked );
// The root element should point to the pages tree view,
// rather than the actual controller (which would just show an empty edit form)
$items [ 0 ] -> Title = self :: menu_title_for_class ( 'CMSPagesController' );
$items [ 0 ] -> Link = singleton ( 'CMSPagesController' ) -> Link ();
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 .
*
* @ return String Serialized JSON
*/
public function SiteTreeHints () {
2012-03-19 02:05:09 +01:00
$classes = ClassInfo :: subclassesFor ( $this -> stat ( 'tree_class' ) );
2007-09-15 23:54:24 +02:00
2007-07-19 12:40:05 +02:00
$def [ 'Root' ] = array ();
2011-04-15 11:27:37 +02:00
$def [ 'Root' ][ 'disallowedParents' ] = array ();
2007-09-15 23:54:24 +02:00
2007-07-19 12:40:05 +02:00
foreach ( $classes as $class ) {
$obj = singleton ( $class );
2011-12-17 04:45:09 +01:00
2007-07-19 12:40:05 +02:00
if ( $obj instanceof HiddenClass ) continue ;
2011-04-15 11:27:37 +02:00
2007-07-19 12:40:05 +02:00
$allowedChildren = $obj -> allowedChildren ();
2011-12-17 04:45:09 +01:00
// SiteTree::allowedChildren() returns null rather than an empty array if SiteTree::allowed_chldren == 'none'
if ( $allowedChildren == null ) $allowedChildren = array ();
2012-03-19 02:05:09 +01:00
// Exclude SiteTree from possible Children
$possibleChildren = array_diff ( $allowedChildren , array ( " SiteTree " ));
// Find i18n - names and build allowed children array
foreach ( $possibleChildren as $child ) {
$instance = singleton ( $child );
if ( $instance instanceof HiddenClass ) continue ;
if ( ! $instance -> canCreate ()) continue ;
// skip this type if it is restricted
if ( $instance -> stat ( 'need_permission' ) && ! $this -> can ( singleton ( $class ) -> stat ( 'need_permission' ))) continue ;
$title = $instance -> i18n_singular_name ();
$def [ $class ][ 'allowedChildren' ][] = array ( " ssclass " => $child , " ssname " => $title );
}
2012-01-05 17:01:48 +01:00
$allowedChildren = array_keys ( array_diff ( $classes , $allowedChildren ));
if ( $allowedChildren ) $def [ $class ][ 'disallowedChildren' ] = $allowedChildren ;
2011-04-15 11:27:37 +02:00
$defaultChild = $obj -> defaultChild ();
2011-12-17 04:45:09 +01:00
if ( $defaultChild != 'Page' && $defaultChild != null )
$def [ $class ][ 'defaultChild' ] = $defaultChild ;
2011-12-20 18:21:45 +01:00
$defaultParent = $obj -> defaultParent ();
2012-03-19 02:05:09 +01:00
2012-03-24 01:56:05 +01:00
$parent = SiteTree :: get_by_link ( $defaultParent );
$id = $parent ? $parent -> id : null ;
2011-12-17 04:45:09 +01:00
2011-04-15 11:27:37 +02:00
if ( $defaultParent != 1 && $defaultParent != null ) $def [ $class ][ 'defaultParent' ] = $defaultParent ;
2012-01-05 17:01:48 +01:00
if ( isset ( $def [ $class ][ 'disallowedChildren' ])) {
2011-12-17 04:45:09 +01:00
foreach ( $def [ $class ][ 'disallowedChildren' ] as $disallowedChild ) {
$def [ $disallowedChild ][ 'disallowedParents' ][] = $class ;
}
2007-07-19 12:40:05 +02:00
}
2011-04-15 11:27:37 +02:00
2011-12-17 04:45:09 +01:00
// Are any classes allowed to be parents of root?
2011-04-15 11:27:37 +02:00
$def [ 'Root' ][ 'disallowedParents' ][] = $class ;
2007-07-19 12:40:05 +02:00
}
2007-09-15 23:54:24 +02:00
2011-04-15 11:27:37 +02:00
return Convert :: raw2xml ( Convert :: raw2json ( $def ));
2007-07-19 12:40:05 +02:00
}
2011-04-12 01:43:01 +02:00
/**
* Include CSS for page icons . We 're not using the JSTree ' types ' option
* because it causes too much performance overhead just to add some icons .
*
* @ return String CSS
*/
function generateTreeStylingCSS () {
$css = '' ;
$classes = ClassInfo :: subclassesFor ( 'SiteTree' );
2007-07-19 12:40:05 +02:00
foreach ( $classes as $class ) {
2011-04-12 01:43:01 +02:00
$obj = singleton ( $class );
$iconSpec = $obj -> stat ( 'icon' );
2007-09-15 23:54:24 +02:00
2011-04-12 01:43:01 +02:00
if ( ! $iconSpec ) continue ;
2007-07-19 12:40:05 +02:00
2011-04-12 01:43:01 +02:00
// Legacy support: We no longer need separate icon definitions for folders etc.
$iconFile = ( is_array ( $iconSpec )) ? $iconSpec [ 0 ] : $iconSpec ;
2007-09-15 23:54:24 +02:00
2011-04-12 01:43:01 +02:00
// Legacy support: Add file extension if none exists
if ( ! pathinfo ( $iconFile , PATHINFO_EXTENSION )) $iconFile .= '-file.gif' ;
2007-07-19 12:40:05 +02:00
2011-04-12 01:43:01 +02:00
$iconPathInfo = pathinfo ( $iconFile );
// Base filename
$baseFilename = $iconPathInfo [ 'dirname' ] . '/' . $iconPathInfo [ 'filename' ];
$fileExtension = $iconPathInfo [ 'extension' ];
2007-09-15 23:54:24 +02:00
2011-04-12 01:43:01 +02:00
if ( Director :: fileExists ( $iconFile )) {
$css .= sprintf (
" li.class-%s > a .jstree-pageicon { background: transparent url('%s') 0 0 no-repeat; } \n " ,
$class , $iconFile
);
} else {
// Support for more sophisticated rules, e.g. sprited icons
$css .= sprintf (
" li.class-%s > a .jstree-pageicon { %s } \n " ,
$class , $iconFile
);
}
2007-09-15 23:54:24 +02:00
2007-07-19 12:40:05 +02:00
}
2007-09-15 23:54:24 +02:00
2011-04-12 01:43:01 +02:00
return $css ;
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 );
if ( $instance instanceof HiddenClass ) continue ;
2007-09-15 23:54:24 +02:00
2008-10-16 11:37:28 +02:00
if ( ! $instance -> canCreate ()) continue ;
2007-09-15 23:54:24 +02:00
2007-07-19 12:40:05 +02:00
// skip this type if it is restricted
2008-10-16 11:37:28 +02:00
if ( $instance -> stat ( 'need_permission' ) && ! $this -> can ( singleton ( $class ) -> stat ( 'need_permission' ))) continue ;
2008-02-25 03:10:37 +01:00
$addAction = $instance -> i18n_singular_name ();
2009-01-05 07:17:59 +01:00
2011-04-24 01:05:01 +02:00
// Get description
$description = _t ( $class . 'DESCRIPTION' );
if ( ! $description ) $description = $instance -> uninherited ( 'description' );
if ( $class == 'Page' && ! $description ) $description = singleton ( 'SiteTree' ) -> uninherited ( 'description' );
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
'IconURL' => $instance -> stat ( 'icon' )
2007-07-19 12:40:05 +02:00
)));
}
2008-10-16 11:37:28 +02:00
2008-02-25 03:10:37 +01:00
$result -> sort ( 'AddAction' );
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
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 ;
2011-09-02 03:24:29 +02:00
}
else if ( $id && is_numeric ( $id )) {
if ( $this -> request -> getVar ( 'Version' )) {
$versionID = ( int ) $this -> request -> getVar ( 'Version' );
}
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 {
$record = DataObject :: get_one ( $treeClass , " \" $treeClass\ " . \ " ID \" = $id " );
}
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");
2007-07-19 12:40:05 +02:00
Versioned :: reading_stage ( 'Live' );
singleton ( $treeClass ) -> flushCache ();
2009-01-08 00:01:47 +01:00
2008-11-23 23:58:18 +01:00
$record = DataObject :: get_one ( $treeClass , " \" $treeClass\ " . \ " ID \" = $id " );
2010-10-04 07:27:08 +02:00
if ( $record ) Versioned :: set_reading_mode ( '' );
2007-07-19 12:40:05 +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
* and its relevent ajax calles , like loading the tree dropdown for TreeSelectorField .
2010-10-04 08:16:17 +02:00
*/
/* if ( $record && Object :: has_extension ( 'SiteTree' , '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
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 );
}
}
2009-11-21 04:17:16 +01:00
2009-11-21 03:38:35 +01:00
/**
2011-04-16 07:53:47 +02:00
* @ param Int $id
2011-10-26 07:35:51 +02:00
* @ param FieldList $fields
2011-04-16 07:53:47 +02: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 ) {
2012-04-05 05:39:23 +02:00
2011-03-16 04:39:49 +01:00
if ( ! $id ) $id = $this -> currentPageID ();
2009-11-21 04:20:26 +01:00
$form = parent :: getEditForm ( $id );
// 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 ) {
2012-03-12 13:57:38 +01:00
$deletedFromStage = $record -> IsDeletedFromStage ;
$deleteFromLive = ! $record -> ExistsOnLive ;
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
$fields -> push ( $liveURLField = new HiddenField ( " AbsoluteLink " , false , $record -> AbsoluteLink ()));
2007-07-19 12:40:05 +02:00
$fields -> push ( $liveURLField = new HiddenField ( " LiveURLSegment " ));
$fields -> push ( $stageURLField = new HiddenField ( " StageURLSegment " ));
2009-11-21 04:20:36 +01:00
$fields -> push ( new HiddenField ( " TreeTitle " , false , $record -> TreeTitle ));
2007-09-15 23:54:24 +02:00
2009-11-21 03:38:37 +01:00
$fields -> push ( new HiddenField ( 'Sort' , '' , $record -> Sort ));
2007-09-15 23:54:24 +02:00
2007-09-05 08:42:26 +02:00
if ( $record -> ID && is_numeric ( $record -> ID ) ) {
2008-11-23 23:58:18 +01:00
$liveRecord = Versioned :: get_one_by_stage ( 'SiteTree' , 'Live' , " \" SiteTree \" . \" ID \" = $record->ID " );
2007-09-05 08:42:26 +02:00
if ( $liveRecord ) $liveURLField -> setValue ( $liveRecord -> AbsoluteLink ());
}
2012-03-12 13:57:38 +01:00
if ( ! $deletedFromStage ) {
2012-02-10 01:41:40 +01:00
$stageURLField -> setValue ( Controller :: join_links ( $record -> AbsoluteLink (), '?stage=Stage' ));
2007-09-05 08:42:26 +02:00
}
2007-07-19 12:40:05 +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
if ( in_array ( 'CMSPreviewable' , class_implements ( $record )) && ! $fields -> fieldByName ( 'SilverStripeNavigator' )) {
$navField = new LiteralField ( 'SilverStripeNavigator' , $this -> getSilverStripeNavigator ());
$navField -> setAllowHTML ( true );
$fields -> push ( $navField );
}
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 ();
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 ();
if ( $actionsFlattened ) foreach ( $actionsFlattened as $action ) $action -> setUseButtonTag ( true );
2009-03-18 14:03:52 +01:00
if ( $record -> hasMethod ( 'getCMSValidator' )) {
$validator = $record -> getCMSValidator ();
} else {
$validator = new RequiredFields ();
}
$form = new Form ( $this , " EditForm " , $fields , $actions , $validator );
2007-07-19 12:40:05 +02:00
$form -> loadDataFrom ( $record );
2012-02-10 01:41:40 +01:00
$stageURLField -> setValue ( Controller :: join_links ( $record -> getStageURLSegment (), '?stage=Stage' ));
2007-07-19 12:40:05 +02:00
$form -> disableDefaultAction ();
2011-03-31 10:51:59 +02:00
$form -> addExtraClass ( 'cms-edit-form' );
$form -> setTemplate ( $this -> getTemplatesWithSuffix ( '_EditForm' ));
// TODO Can't merge $FormAttributes in template at the moment
2012-02-14 21:52:55 +01:00
$form -> addExtraClass ( 'center ss-tabset ' . $this -> BaseCSSClasses ());
2011-03-31 10:51:59 +02:00
if ( $form -> Fields () -> hasTabset ()) $form -> Fields () -> findOrMakeTab ( 'Root' ) -> setTemplate ( 'CMSTabSet' );
2007-07-19 12:40:05 +02: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
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 ) {
2011-10-26 07:35:51 +02:00
return new Form ( $this , " EditForm " , new FieldList (
new LabelField ( 'PageDoesntExistLabel' , _t ( 'CMSMain.PAGENOTEXISTS' , " This page doesn't exist " ))), new FieldList ()
2011-03-16 04:41:46 +01:00
);
2007-07-19 12:40:05 +02:00
}
}
2011-07-06 08:38:23 +02:00
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 ()} .
2012-04-05 05:39:23 +02:00
*
* @ return SS_List
*/
2012-04-11 02:16:23 +02:00
public function getList ( & $filterOn ) {
2012-04-05 05:39:23 +02:00
$list = new DataList ( $this -> stat ( 'tree_class' ));
$request = $this -> request ;
$filter = null ;
2012-04-05 05:57:18 +02:00
$ids = array ();
2012-04-05 05:39:23 +02:00
if ( $filterClass = $request -> requestVar ( 'FilterClass' )){
if ( ! is_subclass_of ( $filterClass , 'CMSSiteTreeFilter' )) {
throw new Exception ( sprintf ( 'Invalid filter class passed: %s' , $filterClass ));
}
$filter = new $filterClass ( $request -> requestVars ());
2012-04-05 07:32:24 +02:00
$filterOn = true ;
2012-04-05 05:39:23 +02:00
foreach ( $pages = $filter -> pagesIncluded () as $pageMap ){
$ids [] = $pageMap [ 'ID' ];
}
2012-04-05 07:32:24 +02:00
if ( count ( $ids )) $list -> where ( '"' . $this -> stat ( 'tree_class' ) . '"."ID" IN (' . implode ( " , " , $ids ) . ')' );
} else {
2012-04-10 04:14:42 +02:00
$parentID = 0 ;
if ( $this -> urlParams [ 'Action' ] == 'listchildren' && $this -> urlParams [ 'ID' ]){
$parentID = $this -> urlParams [ 'ID' ];
}
$list -> filter ( " ParentID " , $parentID );
2012-04-05 05:39:23 +02:00
}
2012-04-05 07:32:24 +02:00
2012-04-05 05:39:23 +02:00
return $list ;
}
public function getListView (){
2012-04-05 07:32:24 +02:00
$filterOn = false ;
$list = $this -> getList ( $filterOn );
2012-04-05 05:39:23 +02:00
$gridFieldConfig = GridFieldConfig :: create () -> addComponents (
new GridFieldSortableHeader (),
new GridFieldDataColumns (),
2012-04-10 04:32:21 +02:00
new GridFieldPaginator ( 15 )
2012-04-05 05:39:23 +02:00
);
$gridField = new GridField ( 'Page' , 'Pages' , $list , $gridFieldConfig );
2012-04-05 07:32:24 +02:00
if ( $filterOn ){
$gridField -> setDisplayFields ( array (
'getTreeTitle' => _t ( 'SiteTree.PAGETITLE' , 'Page Title' ),
'Created' => _t ( 'SiteTree.CREATED' , 'Date Created' ),
'LastEdited' => _t ( 'SiteTree.LASTUPDATED' , 'Last Updated' ),
));
} else {
$gridField -> setDisplayFields ( array (
'listChildrenLink' => " " ,
'getTreeTitle' => _t ( 'SiteTree.PAGETITLE' , 'Page Title' ),
'Created' => _t ( 'SiteTree.CREATED' , 'Date Created' ),
'LastEdited' => _t ( 'SiteTree.LASTUPDATED' , 'Last Updated' ),
));
}
$gridField -> setFieldCasting ( array (
'Created' => 'Date->Ago' ,
'LastEdited' => 'Date->Ago' ,
2012-04-10 04:32:21 +02:00
));
$gridField -> setFieldFormatting ( array (
2012-04-10 05:48:32 +02:00
'getTreeTitle' => '<a class=\"cms-panel-link\" href=\"admin/page/edit/show/$ID\">$value</a>'
2012-04-05 07:32:24 +02:00
));
2012-04-05 05:39:23 +02:00
$listview = new Form (
$this ,
'ListView' ,
new FieldList ( $gridField ),
new FieldList ()
);
$this -> extend ( 'updateListView' , $listview );
2012-04-05 07:32:24 +02:00
2012-04-05 05:39:23 +02:00
$listview -> disableSecurityToken ();
return $listview ;
}
public function getListViewHTML (){
return $this -> getListView () -> forTemplate ();
}
public function ListView () {
return $this -> getListView ();
}
2011-07-06 08:38:23 +02:00
public function currentPageID () {
$id = parent :: currentPageID ();
// Fall back to homepage record
if ( ! $id ) {
$homepageSegment = RootURLController :: get_homepage_link ();
$homepageRecord = DataObject :: get_one ( 'SiteTree' , sprintf ( '"URLSegment" = \'%s\'' , $homepageSegment ));
if ( $homepageRecord ) $id = $homepageRecord -> ID ;
}
return $id ;
}
2012-04-05 07:32:24 +02:00
public function listchildren (){
if ( Director :: is_ajax ()){
2012-04-10 04:14:42 +02:00
return $this -> getListViewHTML ();
2012-04-05 07:32:24 +02:00
} else {
2012-04-10 04:14:42 +02:00
return $this ;
2012-04-05 07:32:24 +02:00
}
}
2007-09-15 23:54:24 +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
*/
public function save ( $data , $form ) {
$className = $this -> stat ( 'tree_class' );
// Existing or new record?
$SQL_id = Convert :: raw2sql ( $data [ 'ID' ]);
if ( substr ( $SQL_id , 0 , 3 ) != 'new' ) {
$record = DataObject :: get_by_id ( $className , $SQL_id );
if ( $record && ! $record -> canEdit ()) return Security :: permissionFailure ( $this );
2012-02-11 03:50:09 +01:00
if ( ! $record || ! $record -> ID ) throw new SS_HTTPResponse_Exception ( " Bad record ID # $SQL_id " , 404 );
2009-11-21 04:20:26 +01:00
} else {
if ( ! singleton ( $this -> stat ( 'tree_class' )) -> canCreate ()) return Security :: permissionFailure ( $this );
$record = $this -> getNewItem ( $SQL_id , false );
}
// TODO Coupling to SiteTree
$record -> HasBrokenLink = 0 ;
$record -> HasBrokenFile = 0 ;
$record -> writeWithoutVersion ();
// Update the class instance if necessary
2011-04-16 07:53:47 +02:00
if ( isset ( $data [ 'ClassName' ]) && $data [ 'ClassName' ] != $record -> ClassName ) {
2009-11-21 04:20:26 +01:00
$newClassName = $record -> ClassName ;
// The records originally saved attribute was overwritten by $form->saveInto($record) before.
// This is necessary for newClassInstance() to work as expected, and trigger change detection
// on the ClassName attribute
$record -> setClassName ( $data [ 'ClassName' ]);
// Replace $record with a new instance
$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 ();
// If the 'Save & Publish' button was clicked, also publish the page
if ( isset ( $data [ 'publish' ]) && $data [ 'publish' ] == 1 ) {
$record -> doPublish ();
// Update classname with original and get new instance (see above for explanation)
2011-04-16 07:53:47 +02:00
if ( isset ( $data [ 'ClassName' ])) {
$record -> setClassName ( $data [ 'ClassName' ]);
$publishedRecord = $record -> newClassInstance ( $record -> ClassName );
}
2009-11-21 04:20:26 +01:00
$this -> response -> addHeader (
'X-Status' ,
sprintf (
_t (
'LeftAndMain.STATUSPUBLISHEDSUCCESS' ,
" Published '%s' successfully " ,
PR_MEDIUM ,
'Status message after publishing a page, showing the page title'
),
2011-04-16 07:53:47 +02:00
$record -> Title
2009-11-21 04:20:26 +01:00
)
);
} else {
$this -> response -> addHeader ( 'X-Status' , _t ( 'LeftAndMain.SAVEDUP' ));
}
2012-04-05 22:27:47 +02:00
return $this -> getResponseNegotiator () -> respond ( $this -> request );
}
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 ()
2008-11-07 13:21:10 +01:00
*/
2007-07-19 12:40:05 +02:00
public function getNewItem ( $id , $setID = true ) {
2008-11-18 02:48:50 +01:00
list ( $dummy , $className , $parentID , $suffix ) = array_pad ( explode ( '-' , $id ), 4 , null );
2009-01-10 12:36:30 +01:00
2007-07-19 12:40:05 +02:00
$newItem = new $className ();
2007-09-15 23:54:24 +02:00
2007-07-19 12:40:05 +02:00
if ( ! $suffix ) {
$sessionTag = " NewItems. " . $parentID . " . " . $className ;
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
2007-07-19 12:40:05 +02:00
$id = $id . $suffix ;
}
2007-09-15 23:54:24 +02:00
2007-09-15 22:21:13 +02:00
$newItem -> Title = _t ( 'CMSMain.NEW' , " New " , PR_MEDIUM , '"New " followed by a className' ) . $className ;
2007-07-19 12:40:05 +02:00
$newItem -> URLSegment = " new- " . strtolower ( $className );
$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' )) {
2008-11-24 10:30:41 +01:00
$newItem -> Sort = DB :: query ( " SELECT MAX( \" Sort \" ) FROM \" SiteTree \" WHERE \" ParentID \" = ' " . Convert :: raw2sql ( $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 );
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
/**
* Delete the page from live . This means a page in draft mode might still exist .
*
* @ see delete ()
*/
2009-11-21 03:39:12 +01:00
public function deletefromlive ( $data , $form ) {
2007-07-19 12:40:05 +02:00
Versioned :: reading_stage ( 'Live' );
2009-11-21 03:39:12 +01:00
$record = DataObject :: get_by_id ( " SiteTree " , $data [ 'ID' ]);
2010-10-04 08:14:05 +02:00
if ( $record && ! ( $record -> canDelete () && $record -> canDeleteFromLive ())) return Security :: permissionFailure ( $this );
2008-11-03 15:56:36 +01:00
2007-07-27 07:26:00 +02:00
$descRemoved = '' ;
2007-10-02 07:08:36 +02:00
$descendantsRemoved = 0 ;
2012-03-12 13:57:38 +01:00
$recordTitle = $record -> Title ;
$recordID = $record -> ID ;
2007-07-19 12:40:05 +02:00
// before deleting the records, get the descendants of this tree
if ( $record ) {
2010-05-28 04:37:58 +02:00
$descendantIDs = $record -> getDescendantIDList ();
2007-09-15 23:54:24 +02:00
2007-07-19 12:40:05 +02:00
// then delete them from the live site too
2007-09-15 23:54:24 +02:00
$descendantsRemoved = 0 ;
2007-07-19 12:40:05 +02:00
foreach ( $descendantIDs as $descID )
if ( $descendant = DataObject :: get_by_id ( 'SiteTree' , $descID ) ) {
2010-04-13 05:52:07 +02:00
$descendant -> doDeleteFromLive ();
2007-07-19 12:40:05 +02:00
$descendantsRemoved ++ ;
}
2007-09-15 23:54:24 +02:00
2007-07-19 12:40:05 +02:00
// delete the record
2010-04-13 05:52:07 +02:00
$record -> doDeleteFromLive ();
2007-07-19 12:40:05 +02:00
}
Versioned :: reading_stage ( 'Stage' );
2007-07-27 07:26:00 +02:00
if ( isset ( $descendantsRemoved )) {
2007-07-19 12:40:05 +02:00
$descRemoved = " and $descendantsRemoved descendants " ;
2008-02-25 03:10:37 +01:00
$descRemoved = sprintf ( ' ' . _t ( 'CMSMain.DESCREMOVED' , 'and %s descendants' ), $descendantsRemoved );
2007-09-15 02:46:22 +02:00
} else {
$descRemoved = '' ;
2007-07-19 12:40:05 +02:00
}
2007-09-15 23:54:24 +02:00
2012-03-12 13:57:38 +01:00
$form -> sessionMessage (
2009-11-21 03:39:12 +01:00
sprintf (
_t ( 'CMSMain.REMOVED' , 'Deleted \'%s\'%s from live site' ),
2012-03-12 13:57:38 +01:00
$recordTitle ,
2009-11-21 03:39:12 +01:00
$descRemoved
2012-03-12 13:57:38 +01:00
),
'good'
2009-11-21 03:39:12 +01:00
);
2007-07-19 12:40:05 +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"
return $this -> redirect ( Controller :: join_links ( $this -> Link ( 'show' ), $recordID ));
2007-07-19 12:40:05 +02:00
}
2007-09-15 23:54:24 +02:00
2007-07-19 12:40:05 +02:00
/**
* Actually perform the publication step
*/
public function performPublish ( $record ) {
2008-11-03 15:56:36 +01:00
if ( $record && ! $record -> canPublish ()) return Security :: permissionFailure ( $this );
2008-08-12 04:59:27 +02:00
$record -> doPublish ();
2007-07-19 12:40:05 +02:00
}
2009-01-05 07:17:59 +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 ()
*/
2009-11-21 03:39:12 +01:00
public function revert ( $data , $form ) {
2010-06-03 02:00:14 +02:00
if ( ! isset ( $data [ 'ID' ])) return new SS_HTTPResponse ( " Please pass an ID in the form content " , 400 );
2009-11-21 03:39:12 +01:00
2012-02-11 03:50:09 +01:00
$id = ( int ) $data [ 'ID' ];
2011-10-07 12:15:37 +02:00
$restoredPage = Versioned :: get_latest_version ( " SiteTree " , $id );
2010-06-03 02:00:14 +02:00
if ( ! $restoredPage ) return new SS_HTTPResponse ( " SiteTree # $id not found " , 400 );
2009-11-21 03:39:12 +01:00
$record = Versioned :: get_one_by_stage (
'SiteTree' ,
'Live' ,
sprintf ( " \" SiteTree_Live \" . \" ID \" = '%d' " , ( int ) $data [ '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")
2011-10-07 12:15:37 +02:00
if ( $record && ! $record -> canEdit ()) return Security :: permissionFailure ( $this );
2012-02-11 03:50:09 +01:00
if ( ! $record || ! $record -> ID ) throw new SS_HTTPResponse_Exception ( " Bad record ID # $id " , 404 );
2009-01-05 07:17:59 +01:00
2008-11-18 02:48:50 +01:00
$record -> doRevertToLive ();
2009-11-21 03:39:12 +01:00
$this -> response -> addHeader (
'X-Status' ,
sprintf (
_t ( 'CMSMain.RESTORED' , " Restored '%s' successfully " , PR_MEDIUM , 'Param %s is a title' ),
$record -> Title
)
);
2012-04-05 22:27:47 +02:00
return $this -> getResponseNegotiator () -> respond ( $this -> request );
2007-07-19 12:40:05 +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 .
* @ see deletefromlive ()
2008-03-11 02:02:05 +01:00
*/
2009-09-10 01:47:56 +02:00
public function delete ( $data , $form ) {
2011-10-07 12:15:37 +02:00
$id = Convert :: raw2sql ( $data [ 'ID' ]);
2009-09-10 01:47:56 +02:00
$record = DataObject :: get_one (
" SiteTree " ,
2011-10-07 12:15:37 +02:00
sprintf ( " \" SiteTree \" . \" ID \" = %d " , $id )
2009-09-10 01:47:56 +02:00
);
2008-11-03 15:56:36 +01:00
if ( $record && ! $record -> canDelete ()) return Security :: permissionFailure ();
2012-02-11 03:50:09 +01:00
if ( ! $record || ! $record -> ID ) throw new SS_HTTPResponse_Exception ( " Bad record ID # $id " , 404 );
2008-11-03 15:56:36 +01:00
2008-12-17 23:41:07 +01:00
// save ID and delete record
2008-03-11 02:02:05 +01:00
$recordID = $record -> ID ;
2007-07-19 12:40:05 +02:00
$record -> delete ();
2012-03-12 13:57:38 +01:00
$form -> sessionMessage (
2009-11-21 03:39:12 +01:00
sprintf (
_t ( 'CMSMain.REMOVEDPAGEFROMDRAFT' , " Removed '%s' from the draft site " ),
$record -> Title
2012-03-12 13:57:38 +01:00
),
'good'
2009-11-21 03:39:12 +01:00
);
2012-03-12 13:26:43 +01: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"
return $this -> redirect ( Controller :: join_links ( $this -> Link ( 'show' ), $recordID ));
2007-07-19 12:40:05 +02:00
}
2010-05-28 04:23:10 +02:00
2009-11-21 03:39:12 +01:00
function publish ( $data , $form ) {
$data [ 'publish' ] = '1' ;
2009-11-21 03:36:13 +01: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
2009-11-21 03:39:12 +01:00
function unpublish ( $data , $form ) {
2011-03-16 04:41:46 +01:00
$className = $this -> stat ( 'tree_class' );
$record = DataObject :: get_by_id ( $className , $data [ 'ID' ]);
2010-04-13 05:56:00 +02:00
2011-03-16 04:41:46 +01:00
if ( $record && ! $record -> canDeleteFromLive ()) return Security :: permissionFailure ( $this );
2012-02-11 03:50:09 +01:00
if ( ! $record || ! $record -> ID ) throw new SS_HTTPResponse_Exception ( " Bad record ID # " . ( int ) $data [ 'ID' ], 404 );
2008-11-03 15:56:36 +01:00
2011-03-16 04:41:46 +01:00
$record -> doUnpublish ();
2008-10-16 05:21:49 +02:00
2009-11-21 03:39:12 +01:00
$this -> response -> addHeader (
'X-Status' ,
2011-03-16 04:41:46 +01:00
sprintf ( _t ( 'CMSMain.REMOVEDPAGE' , " Removed '%s' from the published site " ), $record -> Title )
2009-11-21 03:39:12 +01:00
);
2008-03-11 02:02:05 +01:00
2012-04-05 22:27:47 +02:00
return $this -> getResponseNegotiator () -> respond ( $this -> request );
2007-07-19 12:40:05 +02:00
}
2007-09-15 23:54:24 +02:00
2012-04-10 14:09:30 +02:00
/**
* @ return array
*/
function rollback () {
return $this -> doRollback ( array (
'ID' => $this -> currentPageID (),
'Version' => $this -> request -> param ( 'VersionID' )
), null );
}
/**
* Rolls a site back to a given version ID
*
* @ param array
* @ param Form
*
* @ return html
*/
function doRollback ( $data , $form ) {
$this -> extend ( 'onBeforeRollback' , $data [ 'ID' ]);
$id = ( isset ( $data [ 'ID' ])) ? ( int ) $data [ 'ID' ] : null ;
$version = ( isset ( $data [ 'Version' ])) ? ( int ) $data [ 'Version' ] : null ;
$record = DataObject :: get_by_id ( $this -> stat ( 'tree_class' ), $id );
if ( $record && ! $record -> canEdit ()) return Security :: permissionFailure ( $this );
if ( $version ) {
$record -> doRollbackTo ( $version );
$message = sprintf (
_t ( 'CMSMain.ROLLEDBACKVERSION' , " Rolled back to version #%d. New version number is #%d " ),
$data [ 'Version' ],
$record -> Version
);
} else {
$record -> doRollbackTo ( 'Live' );
$message = sprintf (
_t ( 'CMSMain.ROLLEDBACKPUB' , " Rolled back to published version. New version number is #%d " ),
$record -> Version
);
}
$this -> response -> addHeader ( 'X-Status' , $message );
// 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.
$url = Controller :: join_links ( singleton ( 'CMSPageEditController' ) -> Link ( 'show' ), $record -> ID );
$this -> response -> addHeader ( 'X-ControllerURL' , $url );
return $this -> getResponseNegotiator () -> respond ( $this -> request );
}
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
*/
2009-05-14 08:11:18 +02:00
function batchactions () {
return new CMSBatchActionHandler ( $this , 'batchactions' );
2007-09-16 17:04:09 +02:00
}
2009-01-06 03:18:33 +01:00
2009-10-16 00:43:58 +02:00
function BatchActionParameters () {
$batchActions = CMSBatchActionHandler :: $batch_actions ;
$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 = '' ;
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 " ;
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
*/
2009-05-14 08:11:18 +02:00
function BatchActionList () {
return $this -> batchactions () -> batchActionList ();
2007-07-19 12:40:05 +02:00
}
2009-01-06 03:18:33 +01:00
2010-11-01 02:29:02 +01:00
function buildbrokenlinks ( $request ) {
// Protect against CSRF on destructive action
if ( ! SecurityToken :: inst () -> checkRequest ( $request )) return $this -> httpError ( 400 );
2011-10-07 12:01:25 +02:00
increase_time_limit_to ();
increase_memory_limit_to ();
2007-07-19 12:40:05 +02:00
if ( $this -> urlParams [ 'ID' ]) {
$newPageSet [] = DataObject :: get_by_id ( " Page " , $this -> urlParams [ 'ID' ]);
} else {
$pages = DataObject :: get ( " Page " );
foreach ( $pages as $page ) $newPageSet [] = $page ;
$pages = null ;
}
2007-09-15 23:54:24 +02:00
2007-07-19 12:40:05 +02:00
$content = new HtmlEditorField ( 'Content' );
$download = new HtmlEditorField ( 'Download' );
foreach ( $newPageSet as $i => $page ) {
$page -> HasBrokenLink = 0 ;
$page -> HasBrokenFile = 0 ;
$content -> setValue ( $page -> Content );
$content -> saveInto ( $page );
$download -> setValue ( $page -> Download );
$download -> saveInto ( $page );
echo " <li> $page->Title (link: $page->HasBrokenLink , file: $page->HasBrokenFile ) " ;
2007-09-15 23:54:24 +02:00
2007-07-19 12:40:05 +02:00
$page -> writeWithoutVersion ();
$page -> destroy ();
$newPageSet [ $i ] = null ;
}
}
2010-11-01 02:29:02 +01:00
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 ();
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 );
2008-02-25 03:10:37 +01:00
$start = 0 ;
$pages = DataObject :: get ( " SiteTree " , " " , " " , " " , " $start ,30 " );
2007-07-19 12:40:05 +02:00
$count = 0 ;
2010-12-14 02:29:38 +01:00
while ( $pages ) {
foreach ( $pages as $page ) {
if ( $page && ! $page -> canPublish ()) return Security :: permissionFailure ( $this );
$page -> doPublish ();
$page -> destroy ();
unset ( $page );
$count ++ ;
$response .= " <li> $count </li> " ;
}
if ( $pages -> Count () > 29 ) {
$start += 30 ;
$pages = DataObject :: get ( " SiteTree " , " " , " " , " " , " $start ,30 " );
} else {
break ;
2008-02-25 03:10:37 +01:00
}
2007-07-19 12:40:05 +02:00
}
2008-08-12 04:59:27 +02:00
$response .= sprintf ( _t ( 'CMSMain.PUBPAGES' , " Done: Published %d pages " ), $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 );
$tokenField = $fields -> First ();
$tokenHtml = ( $tokenField ) ? $tokenField -> FieldHolder () : '' ;
2008-08-12 04:59:27 +02:00
$response .= '<h1>' . _t ( 'CMSMain.PUBALLFUN' , '"Publish All" functionality' ) . ' </ h1 >
2007-09-15 22:21:13 +02:00
< p > ' . _t(' CMSMain . PUBALLFUN2 ', ' Pressing this button will do the equivalent of going to every page and pressing " publish " . It\ ' s
2007-07-19 12:40:05 +02:00
intended to be used after there have been massive edits of the content , such as when the site was
2007-09-15 22:21:13 +02:00
first built . ') . ' </ 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 = " '
2010-11-01 02:29:02 +01:00
. _t ( 'CMSMain.PUBALLCONFIRM' , " Please publish every page in the site, copying content stage to live " , PR_LOW , '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
}
2008-08-12 04:59:27 +02:00
return $response ;
2007-07-19 12:40:05 +02:00
}
2009-01-10 12:36:30 +01: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 .
2009-01-05 07:17:59 +01:00
*/
2009-11-21 03:39:12 +01:00
function restore ( $data , $form ) {
if ( ! isset ( $data [ 'ID' ]) || ! is_numeric ( $data [ 'ID' ])) {
2010-06-03 02:00:14 +02:00
return new SS_HTTPResponse ( " Please pass an ID in the form content " , 400 );
2007-07-19 12:40:05 +02:00
}
2009-11-21 03:39:12 +01:00
2009-11-21 04:19:49 +01:00
$id = ( int ) $data [ 'ID' ];
2009-11-21 03:39:12 +01:00
$restoredPage = Versioned :: get_latest_version ( " SiteTree " , $id );
2010-06-03 02:00:14 +02:00
if ( ! $restoredPage ) return new SS_HTTPResponse ( " SiteTree # $id not found " , 400 );
2009-11-21 03:39:12 +01:00
$restoredPage = $restoredPage -> doRestoreToStage ();
$this -> response -> addHeader (
'X-Status' ,
sprintf (
_t ( 'CMSMain.RESTORED' , " Restored '%s' successfully " , PR_MEDIUM , 'Param %s is a title' ),
$restoredPage -> TreeTitle
)
);
2012-04-05 22:27:47 +02:00
return $this -> getResponseNegotiator () -> respond ( $this -> request );
2007-07-19 12:40:05 +02:00
}
2007-09-15 23:54:24 +02:00
2010-11-01 02:29:02 +01:00
function duplicate ( $request ) {
// Protect against CSRF on destructive action
if ( ! SecurityToken :: inst () -> checkRequest ( $request )) return $this -> httpError ( 400 );
2007-07-19 12:40:05 +02:00
if (( $id = $this -> urlParams [ 'ID' ]) && is_numeric ( $id )) {
$page = DataObject :: get_by_id ( " SiteTree " , $id );
2011-10-07 12:15:37 +02:00
if ( $page && ( ! $page -> canEdit () || ! $page -> canCreate ())) return Security :: permissionFailure ( $this );
2012-02-11 03:50:09 +01:00
if ( ! $page || ! $page -> ID ) throw new SS_HTTPResponse_Exception ( " Bad record ID # $id " , 404 );
2007-07-19 12:40:05 +02:00
$newPage = $page -> duplicate ();
2008-02-25 03:10:37 +01:00
// ParentID can be hard-set in the URL. This is useful for pages with multiple parents
if ( $_GET [ 'parentID' ] && is_numeric ( $_GET [ 'parentID' ])) {
$newPage -> ParentID = $_GET [ 'parentID' ];
$newPage -> write ();
}
2009-11-21 03:39:12 +01:00
2011-03-16 04:41:46 +01:00
// Reload form, data and actions might have changed
2009-11-21 03:39:12 +01:00
$form = $this -> getEditForm ( $newPage -> ID );
2011-03-16 04:41:46 +01:00
2011-06-08 01:30:54 +02:00
return $form -> forTemplate ();
2008-02-25 03:10:37 +01:00
} else {
user_error ( " CMSMain::duplicate() Bad ID: ' $id ' " , E_USER_WARNING );
}
}
2010-11-01 02:29:02 +01:00
function duplicatewithchildren ( $request ) {
// Protect against CSRF on destructive action
if ( ! SecurityToken :: inst () -> checkRequest ( $request )) return $this -> httpError ( 400 );
2008-02-25 03:10:37 +01:00
if (( $id = $this -> urlParams [ 'ID' ]) && is_numeric ( $id )) {
$page = DataObject :: get_by_id ( " SiteTree " , $id );
2011-10-07 12:15:37 +02:00
if ( $page && ( ! $page -> canEdit () || ! $page -> canCreate ())) return Security :: permissionFailure ( $this );
2012-02-11 03:50:09 +01:00
if ( ! $page || ! $page -> ID ) throw new SS_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
2011-03-16 04:41:46 +01:00
// Reload form, data and actions might have changed
2009-11-21 03:39:12 +01:00
$form = $this -> getEditForm ( $newPage -> ID );
2011-03-16 04:41:46 +01:00
2011-06-08 01:30:54 +02:00
return $form -> forTemplate ();
2008-01-24 01:01:52 +01:00
} else {
user_error ( " CMSMain::duplicate() Bad ID: ' $id ' " , E_USER_WARNING );
}
}
2011-03-29 10:35:00 +02:00
/**
* Return the version number of this application .
* Uses the subversion path information in < mymodule >/ silverstripe_version
2012-02-01 18:30:24 +01:00
* ( automacially replaced by build scripts ) .
2011-03-29 10:35:00 +02:00
*
* @ return string
*/
public function CMSVersion () {
2012-02-01 18:30:24 +01:00
$cmsVersion = file_get_contents ( BASE_PATH . '/cms/silverstripe_version' );
if ( ! $cmsVersion ) $cmsVersion = _t ( 'LeftAndMain.VersionUnknown' );
$sapphireVersion = file_get_contents ( BASE_PATH . '/cms/silverstripe_version' );
if ( ! $sapphireVersion ) $sapphireVersion = _t ( 'LeftAndMain.VersionUnknown' );
return sprintf (
" cms: %s, sapphire: %s " ,
$cmsVersion ,
$sapphireVersion
);
2011-03-29 10:35:00 +02:00
}
2007-07-19 12:40:05 +02:00
function providePermissions () {
2012-03-05 16:07:53 +01:00
$title = _t ( " CMSPagesController.MENUTITLE " , LeftAndMain :: menu_title_for_class ( 'CMSPagesController' ));
return array (
" CMS_ACCESS_CMSMain " => array (
'name' => sprintf ( _t ( 'CMSMain.ACCESS' , " Access to '%s' section " ), $title ),
'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
}