2007-07-19 12:40:05 +02:00
< ? php
/**
* The main " content " area of the CMS .
* 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
* @ subpackage content
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
2008-11-02 22:27:55 +01:00
static $url_segment = '' ;
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 ;
static $menu_title = 'Site Content' ;
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 (
'addmember' ,
'addpage' ,
'buildbrokenlinks' ,
'canceldraftchangesdialog' ,
'compareversions' ,
'createtranslation' ,
'delete' ,
'deletefromlive' ,
'deleteitems' ,
2009-01-06 03:18:33 +01:00
'DeleteItemsForm' ,
2008-02-25 03:10:37 +01:00
'dialog' ,
'duplicate' ,
'duplicatewithchildren' ,
2008-04-26 08:40:00 +02:00
'filtersitetree' ,
2008-02-25 03:10:37 +01:00
'getpagecount' ,
'getversion' ,
'publishall' ,
'publishitems' ,
2009-01-06 03:18:33 +01:00
'PublishItemsForm' ,
2008-02-25 03:10:37 +01:00
'restorepage' ,
'revert' ,
'rollback' ,
'sidereport' ,
'submit' ,
'switchlanguage' ,
'unpublish' ,
'versions' ,
2008-08-09 05:54:55 +02:00
'EditForm' ,
'AddPageOptionsForm' ,
2008-09-25 16:50:33 +02:00
'SiteTreeAsUL' ,
2008-02-25 03:10:37 +01:00
);
2007-09-16 17:19:17 +02:00
/**
* SiteTree Columns that can be filtered using the the Site Tree Search button
*/
2007-09-27 22:56:55 +02:00
static $site_tree_filter_options = array (
2007-11-07 00:28:54 +01:00
'ClassName' => array ( 'CMSMain.PAGETYPE' , 'Page Type' ),
'Status' => array ( 'CMSMain.STATUS' , 'Status' ),
'MetaDescription' => array ( 'CMSMain.METADESC' , 'Description' ),
'MetaKeywords' => array ( 'CMSMain.METAKEYWORDS' , 'Keywords' )
2007-09-27 22:56:55 +02:00
);
2007-11-07 07:05:52 +01:00
static function T_SiteTreeFilterOptions (){
return array (
'ClassName' => _t ( 'CMSMain.PAGETYPEOPT' , 'Page Type' , 0 , " The dropdown title in CMSMain left SiteTreeFilterOptions " ),
'Status' => _t ( 'CMSMain.STATUSOPT' , 'Status' , 0 , " The dropdown title in CMSMain left SiteTreeFilterOptions " ),
'MetaDescription' => _t ( 'CMSMain.METADESCOPT' , 'Description' , 0 , " The dropdown title in CMSMain left SiteTreeFilterOptions " ),
'MetaKeywords' => _t ( 'CMSMain.METAKEYWORDSOPT' , 'Keywords' , 0 , " The dropdown title in CMSMain left SiteTreeFilterOptions " ),
);
}
2007-09-15 23:54:24 +02:00
2007-07-19 12:40:05 +02:00
public function init () {
parent :: init ();
2008-11-10 02:47:13 +01:00
Merged, debugged and enhanced Translatable patches from branches/translatable at r64523, r64523, 64523, thanks wakeless!
API CHANGE Changed Translatable schema from auxilliary tables (SiteTree_lang, SiteTree_lang_Live) to automatically filtered records on the original table (SiteTree, SiteTree_Live), using $Lang and $OriginalID properties. Incompatible update to old schema, migration script is in the works.
API CHANGE Removed Translatable::get_one(), Translatable::write()
ENHANCEMENT Simplified Translatable tree generation by using getSiteTreeFor() in CMSMain->createtranslation()
ENHANCEMENT Added AllChildrenIncludingDeleted(), augmentNumChildrenCountQuery(), augmentAllChildrenIncludingDeleted(), augmentStageChildren() to Translatable class to allow for more stable tree generation.
ENHANCEMENT Moved definition of Translatable schema from augmentDatabase() to Translatable->extraStatics()
ENHANCEMENT Changes to the CMS language selection refresh the whole admin interface instead of the tree only. This way we can add a URL parameter ?lang=<lang> to /admin, which makes the specific language bookmarkable and reloadable. Changes to LangSelector.js
ENHANCEMENT Added fallback to ModelAsController->getNestedController() to fetch page with matching URLSegment but different language in case no page is found in the current language.
ENHANCEMENT Added helper methods to Translatable: getTranslation(), hasTranslation(), isTranslation(), findOriginalIDs()
ENHANCEMENT Getters and setters for Translatable->getOriginalPage() etc.
ENHANCEMENT Hooking Translatable into ModelAsController and ContentController initialization in order to call choose_site_lang()
ENHANCEMENT Simplified Translatable->augmentSQL(), augmentWrite() by not using auxilliary tables
ENHANCEMENT Showing clickable links for Translations in Translatable->updateCMSFields()
BUGFIX Modifying Hierarchy/SiteTree Children getters to accept optional "context" which can be used to set a language explicitly through the $Lang property, rather than implicitly reyling on the static Translatable::current_lang()
BUGFIX Fixed TranslatableTest to work with new datamodel
BUGFIX Temporarily disabled cookie/session selection in Translatable::choose_site_lang() until we have a good test suite for the side effects.
MINOR Added "untranslated" CSS styles to tree nodes and marking them as inactive/grey
git-svn-id: svn://svn.silverstripe.com/silverstripe/open/modules/cms/trunk@69959 467b73ca-7a2a-4603-9d3b-597d59a354a9
2009-01-10 13:15:30 +01:00
// "Lang" attribute is either explicitly added by LeftAndMain Javascript logic,
// or implied on a translated record (see {@link Translatable->updateCMSFields()}).
2009-01-10 12:36:30 +01:00
if ( Translatable :: is_enabled ()) {
Merged, debugged and enhanced Translatable patches from branches/translatable at r64523, r64523, 64523, thanks wakeless!
API CHANGE Changed Translatable schema from auxilliary tables (SiteTree_lang, SiteTree_lang_Live) to automatically filtered records on the original table (SiteTree, SiteTree_Live), using $Lang and $OriginalID properties. Incompatible update to old schema, migration script is in the works.
API CHANGE Removed Translatable::get_one(), Translatable::write()
ENHANCEMENT Simplified Translatable tree generation by using getSiteTreeFor() in CMSMain->createtranslation()
ENHANCEMENT Added AllChildrenIncludingDeleted(), augmentNumChildrenCountQuery(), augmentAllChildrenIncludingDeleted(), augmentStageChildren() to Translatable class to allow for more stable tree generation.
ENHANCEMENT Moved definition of Translatable schema from augmentDatabase() to Translatable->extraStatics()
ENHANCEMENT Changes to the CMS language selection refresh the whole admin interface instead of the tree only. This way we can add a URL parameter ?lang=<lang> to /admin, which makes the specific language bookmarkable and reloadable. Changes to LangSelector.js
ENHANCEMENT Added fallback to ModelAsController->getNestedController() to fetch page with matching URLSegment but different language in case no page is found in the current language.
ENHANCEMENT Added helper methods to Translatable: getTranslation(), hasTranslation(), isTranslation(), findOriginalIDs()
ENHANCEMENT Getters and setters for Translatable->getOriginalPage() etc.
ENHANCEMENT Hooking Translatable into ModelAsController and ContentController initialization in order to call choose_site_lang()
ENHANCEMENT Simplified Translatable->augmentSQL(), augmentWrite() by not using auxilliary tables
ENHANCEMENT Showing clickable links for Translations in Translatable->updateCMSFields()
BUGFIX Modifying Hierarchy/SiteTree Children getters to accept optional "context" which can be used to set a language explicitly through the $Lang property, rather than implicitly reyling on the static Translatable::current_lang()
BUGFIX Fixed TranslatableTest to work with new datamodel
BUGFIX Temporarily disabled cookie/session selection in Translatable::choose_site_lang() until we have a good test suite for the side effects.
MINOR Added "untranslated" CSS styles to tree nodes and marking them as inactive/grey
git-svn-id: svn://svn.silverstripe.com/silverstripe/open/modules/cms/trunk@69959 467b73ca-7a2a-4603-9d3b-597d59a354a9
2009-01-10 13:15:30 +01:00
// $Lang serves as a "context" which can be inspected by Translatable - hence it
// has the same name as the database property on Translatable.
if ( $this -> getRequest () -> requestVar ( " Lang " )) {
$this -> Lang = $this -> getRequest () -> requestVar ( " Lang " );
} elseif ( $this -> getRequest () -> requestVar ( " lang " )) {
$this -> Lang = $this -> getRequest () -> requestVar ( " lang " );
} else {
$this -> Lang = Translatable :: default_lang ();
}
2009-01-10 12:36:30 +01:00
Translatable :: set_reading_lang ( $this -> Lang );
}
2008-11-10 02:47:13 +01:00
// collect languages for TinyMCE spellchecker plugin
if ( Translatable :: is_enabled ()) {
2009-01-10 12:36:30 +01:00
$spellcheckLangs = Translatable :: get_existing_content_languages ();
2008-11-10 02:47:13 +01:00
} else {
2008-11-10 02:48:43 +01:00
$defaultLang = Translatable :: default_lang ();
2008-11-10 02:47:13 +01:00
$spellcheckLangs = array ( $defaultLang => i18n :: get_language_name ( $defaultLang ));
}
$spellcheckSpec = array ();
foreach ( $spellcheckLangs as $lang => $title ) $spellcheckSpec [] = " { $title } = { $lang } " ;
2007-07-19 12:40:05 +02:00
2007-09-27 22:56:55 +02:00
// We don't want this showing up in every ajax-response, it should always be present in a CMS-environment
if ( ! Director :: is_ajax ()) {
2008-11-12 05:31:53 +01:00
Requirements :: javascript ( MCE_ROOT . " tiny_mce_src.js " );
ENHANCEMENT Introduced constants for system paths like /sapphire in preparation for a more flexible directory reorganisation. Instead of hardcoding your path, please use the following constants: BASE_PATH, BASE_URL, SAPPHIRE_DIR, SAPPHIRE_PATH, CMS_DIR, CMS_PATH, THIRDPARTY_DIR, THIRDPARTY_PATH, ASSETS_DIR, ASSETS_PATH, THEMES_DIR, THEMES_PATH
git-svn-id: svn://svn.silverstripe.com/silverstripe/open/modules/cms/trunk@63154 467b73ca-7a2a-4603-9d3b-597d59a354a9
2008-09-27 18:02:38 +02:00
Requirements :: javascriptTemplate ( CMS_DIR . " /javascript/tinymce.template.js " , array (
" ContentCSS " => ( SSViewer :: current_theme () ? THEMES_DIR . " / " . SSViewer :: current_theme () : project ()) . " /css/editor.css " ,
2007-09-27 22:56:55 +02:00
" BaseURL " => Director :: absoluteBaseURL (),
2008-11-10 02:47:13 +01:00
" Lang " => i18n :: get_tinymce_lang (),
'SpellcheckLangs' => '+' . implode ( ',' , $spellcheckSpec )
2007-09-27 22:56:55 +02:00
));
}
2009-01-05 07:17:59 +01:00
// Always block the HtmlEditorField.js otherwise it will be sent with an ajax request
Requirements :: block ( SAPPHIRE_DIR . '/javascript/HtmlEditorField.js' );
2007-09-27 22:56:55 +02:00
ENHANCEMENT Introduced constants for system paths like /sapphire in preparation for a more flexible directory reorganisation. Instead of hardcoding your path, please use the following constants: BASE_PATH, BASE_URL, SAPPHIRE_DIR, SAPPHIRE_PATH, CMS_DIR, CMS_PATH, THIRDPARTY_DIR, THIRDPARTY_PATH, ASSETS_DIR, ASSETS_PATH, THEMES_DIR, THEMES_PATH
git-svn-id: svn://svn.silverstripe.com/silverstripe/open/modules/cms/trunk@63154 467b73ca-7a2a-4603-9d3b-597d59a354a9
2008-09-27 18:02:38 +02:00
Requirements :: javascript ( CMS_DIR . '/javascript/CMSMain.js' );
Requirements :: javascript ( CMS_DIR . '/javascript/CMSMain_left.js' );
Requirements :: javascript ( CMS_DIR . '/javascript/CMSMain_right.js' );
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 ;
}
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 "
);
}
2007-07-19 12:40:05 +02:00
/**
* Return the entire site tree as a nested set of ULs
*/
public function SiteTreeAsUL () {
$this -> generateDataTreeHints ();
$this -> generateTreeStylingJS ();
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 " );
2007-07-19 12:40:05 +02:00
return $this -> getSiteTreeFor ( " SiteTree " );
}
2007-09-15 23:54:24 +02:00
2007-09-16 17:19:17 +02:00
/**
* Returns the SiteTree columns that can be filtered using the the Site Tree Search button as a DataObjectSet
*/
public function SiteTreeFilterOptions () {
$filter_options = new DataObjectSet ();
2007-11-07 07:05:52 +01:00
foreach ( self :: T_SiteTreeFilterOptions () as $key => $value ) {
2007-09-16 17:19:17 +02:00
$record = array (
'Column' => $key ,
2007-11-07 07:05:52 +01:00
'Title' => $value ,
2007-09-16 17:19:17 +02:00
);
$filter_options -> push ( new ArrayData ( $record ));
}
return $filter_options ;
}
public function SiteTreeFilterDateField () {
$dateField = new CalendarDateField ( 'SiteTreeFilterDate' );
return $dateField -> Field ();
}
/**
* Returns a filtered Site Tree
*/
2008-04-26 08:40:00 +02:00
public function filtersitetree () {
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 " );
2007-09-16 17:19:17 +02:00
$className = 'SiteTree' ;
$rootID = null ;
$obj = $rootID ? $this -> getRecord ( $rootID ) : singleton ( $className );
2007-09-19 16:04:50 +02:00
$obj -> setMarkingFilterFunction ( 'cmsMainMarkingFilterFunction' );
2007-09-16 17:19:17 +02:00
$obj -> markPartialTree ();
if ( $p = $this -> currentPage ()) $obj -> markToExpose ( $p );
// getChildrenAsUL is a flexible and complex way of traversing the tree
$siteTree = $obj -> getChildrenAsUL ( " " , '
" <li id= \" record- $child->ID\ " class = \ " " . $child -> CMSTreeClasses ( $extraArg ) . " \" > " .
2007-09-16 18:32:30 +02:00
" <a href= \" " . Director :: link ( substr ( $extraArg -> Link (), 0 , - 1 ), " show " , $child -> ID ) . " \" " . (( $child -> canEdit () || $child -> canAddChildren ()) ? " " : " class= \" disabled \" " ) . " title= \" ' . _t('LeftAndMain.PAGETYPE') . ' " . $child -> class . " \" > " .
2007-09-16 17:19:17 +02:00
( $child -> TreeTitle ()) .
" </a> "
'
, $this , true );
// Wrap the root if needs be.
if ( ! $rootID ) {
$rootLink = $this -> Link () . '0' ;
$siteTree = " <ul id= \" sitetree \" class= \" tree unformatted \" ><li id= \" record-0 \" class= \" Root nodelete \" ><a href= \" $rootLink\ " > " .
2007-11-05 23:19:20 +01:00
_t ( 'LeftAndMain.TREESITECONTENT' , " Site Content " , PR_HIGH , 'Root node on left' ) . " </a> "
2007-09-16 17:19:17 +02:00
. $siteTree . " </li></ul> " ;
}
return $siteTree ;
}
2007-07-19 12:40:05 +02:00
public function generateDataTreeHints () {
$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 ();
2007-09-15 23:54:24 +02:00
2007-07-19 12:40:05 +02:00
foreach ( $classes as $class ) {
$obj = singleton ( $class );
if ( $obj instanceof HiddenClass ) continue ;
2007-09-15 23:54:24 +02:00
2007-07-19 12:40:05 +02:00
$allowedChildren = $obj -> allowedChildren ();
if ( $allowedChildren != " none " ) $def [ $class ][ 'allowedChildren' ] = $allowedChildren ;
$def [ $class ][ 'defaultChild' ] = $obj -> defaultChild ();
2008-11-02 01:24:46 +01:00
$def [ $class ][ 'defaultParent' ] = isset ( SiteTree :: get_by_url ( $obj -> defaultParent ()) -> ID ) ? SiteTree :: get_by_url ( $obj -> defaultParent ()) -> ID : null ;
2007-07-19 12:40:05 +02:00
if ( is_array ( $allowedChildren )) foreach ( $allowedChildren as $allowedChild ) {
$def [ $allowedChild ][ 'allowedParents' ][] = $class ;
}
if ( $obj -> stat ( 'can_be_root' )) {
$def [ 'Root' ][ 'allowedChildren' ][] = $class ;
}
}
2007-09-15 23:54:24 +02:00
2007-07-19 12:40:05 +02:00
// Put data hints into a script tag at the top
Requirements :: customScript ( " siteTreeHints = " . $this -> jsDeclaration ( $def ) . " ; " );
}
public function generateTreeStylingJS () {
$classes = ClassInfo :: subclassesFor ( 'SiteTree' );
foreach ( $classes as $class ) {
$obj = singleton ( $class );
if ( $obj instanceof HiddenClass ) continue ;
if ( $icon = $obj -> stat ( 'icon' )) $iconInfo [ $class ] = $icon ;
}
$iconInfo [ 'BrokenLink' ] = 'cms/images/treeicons/brokenlink' ;
2007-09-15 23:54:24 +02:00
2007-07-19 12:40:05 +02:00
$js = " var _TREE_ICONS = []; \n " ;
2007-09-15 23:54:24 +02:00
2007-07-19 12:40:05 +02:00
foreach ( $iconInfo as $class => $icon ) {
// SiteTree::$icon can be set to array($icon, $option)
// $option can be "file" or "folder" to force the icon to always be the file or the folder form
$option = null ;
if ( is_array ( $icon )) list ( $icon , $option ) = $icon ;
$fileImage = ( $option == " folder " ) ? $icon . '-openfolder.gif' : $icon . '-file.gif' ;
$openFolderImage = $icon . '-openfolder.gif' ;
if ( ! Director :: fileExists ( $openFolderImage ) || $option = " file " ) $openFolderImage = $fileImage ;
$closedFolderImage = $icon . '-closedfolder.gif' ;
if ( ! Director :: fileExists ( $closedFolderImage ) || $option = " file " ) $closedFolderImage = $fileImage ;
2007-09-15 23:54:24 +02:00
2007-07-19 12:40:05 +02:00
$js .= <<< JS
_TREE_ICONS [ '$class' ] = {
fileIcon : '$fileImage' ,
openFolderIcon : '$openFolderImage' ,
closedFolderIcon : '$closedFolderImage'
};
2007-09-15 23:54:24 +02:00
2007-07-19 12:40:05 +02:00
JS ;
}
2007-09-15 23:54:24 +02:00
2007-07-19 12:40:05 +02:00
Requirements :: customScript ( $js );
}
/**
* Return a javascript instanciation of this array
*/
protected function jsDeclaration ( $array ) {
if ( is_array ( $array )) {
$object = false ;
foreach ( array_keys ( $array ) as $key ) {
if ( ! is_numeric ( $key )) {
$object = true ;
break ;
}
}
2007-09-15 23:54:24 +02:00
2007-07-19 12:40:05 +02:00
if ( $object ) {
foreach ( $array as $k => $v ) {
$parts [] = " $k : " . $this -> jsDeclaration ( $v );
}
return " { \n " . implode ( " , \n " , $parts ) . " } \n " ;
} else {
foreach ( $array as $part ) $parts [] = $this -> jsDeclaration ( $part );
return " [ " . implode ( " , " , $parts ) . " ] \n " ;
}
} else {
return " ' " . addslashes ( $array ) . " ' " ;
}
}
2007-09-15 23:54:24 +02:00
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 .
*
* @ return DataObjectSet
2007-07-19 12:40:05 +02:00
*/
public function PageTypes () {
$classes = ClassInfo :: getValidSubClasses ();
array_shift ( $classes );
$result = new DataObjectSet ();
2008-02-25 03:10:37 +01:00
$kill_ancestors = array ();
2007-09-15 23:54:24 +02:00
2007-07-19 12:40:05 +02:00
// figure out if there are any classes we don't want to appear
foreach ( $classes as $class ) {
2008-10-16 11:37:28 +02:00
$instance = singleton ( $class );
2007-07-19 12:40:05 +02:00
2008-10-16 11:37:28 +02:00
// do any of the progeny want to hide an ancestor?
if ( $ancestor_to_hide = $instance -> stat ( 'hide_ancestor' )) {
// note for killing later
$kill_ancestors [] = $ancestor_to_hide ;
2007-07-19 12:40:05 +02:00
}
}
2008-10-16 11:37:28 +02:00
// If any of the descendents don't want any of the elders to show up, cruelly render the elders surplus to requirements.
if ( $kill_ancestors ) {
foreach ( $kill_ancestors as $mark ) {
// unset from $classes
$idx = array_search ( $mark , $classes );
unset ( $classes [ $idx ]);
}
}
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
// if we're in translation mode, the link between the translated pagetype
// title and the actual classname might not be obvious, so we add it in parantheses
// Example: class "RedirectorPage" has the title "Weiterleitung" in German,
// so it shows up as "Weiterleitung (RedirectorPage)"
if ( i18n :: get_locale () != 'en_US' ) {
$addAction .= " ( { $class } ) " ;
}
2007-09-15 23:54:24 +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 ,
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
/**
* Get a databsae record to be managed by the CMS
*/
public function getRecord ( $id ) {
2007-09-15 23:54:24 +02:00
2007-07-19 12:40:05 +02:00
$treeClass = $this -> stat ( 'tree_class' );
2007-09-15 23:54:24 +02:00
2007-07-19 12:40:05 +02:00
if ( $id && is_numeric ( $id )) {
2008-11-23 23:58:18 +01:00
$record = DataObject :: get_one ( $treeClass , " \" $treeClass\ " . \ " ID \" = $id " );
2007-09-15 23:54:24 +02:00
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 " );
2008-12-17 23:41:07 +01:00
if ( $record ) Versioned :: reading_stage ( null );
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 );
}
}
public function getEditForm ( $id ) {
$record = $this -> getRecord ( $id );
2007-09-15 23:54:24 +02:00
2007-07-19 12:40:05 +02:00
if ( $record ) {
2008-12-17 23:41:07 +01:00
if ( $record -> IsDeletedFromStage ) $record -> Status = _t ( 'CMSMain.REMOVEDFD' , " Removed from the draft site " );
2007-09-15 23:54:24 +02:00
2007-07-19 12:40:05 +02:00
$fields = $record -> getCMSFields ( $this );
2007-09-15 23:09:13 +02:00
if ( $fields == null ) {
user_error ( " getCMSFields returned null on a 'Page' object - it should return a FieldSet object. Perhaps you forgot to put a return statement at the end of your method? " , E_USER_ERROR );
}
2007-07-19 12:40:05 +02:00
$fields -> push ( $idField = new HiddenField ( " ID " ));
$fields -> push ( $liveURLField = new HiddenField ( " LiveURLSegment " ));
$fields -> push ( $stageURLField = new HiddenField ( " StageURLSegment " ));
2007-09-15 23:54:24 +02:00
2007-07-19 12:40:05 +02:00
/*if( substr($record->ID, 0, 3 ) == 'new' )*/
$fields -> push ( new HiddenField ( 'Sort' , '' , $record -> Sort ));
2007-09-15 23:54:24 +02:00
2007-07-19 12:40:05 +02:00
$idField -> setValue ( $id );
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 ());
}
2008-12-17 23:41:07 +01:00
if ( ! $record -> IsDeletedFromStage ) {
2007-09-05 08:42:26 +02:00
$stageURLField -> setValue ( $record -> AbsoluteLink ());
}
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 ();
// add default actions if none are defined
if ( ! $actions || ! $actions -> Count ()) {
2008-03-11 02:02:05 +01:00
if ( $record -> canEdit ()) {
2008-12-04 23:38:58 +01:00
$actions -> push ( new FormAction ( 'save' , _t ( 'CMSMain.SAVE' , 'Save' )));
2008-03-11 02:02:05 +01:00
$actions -> push ( $deleteAction = new FormAction ( 'delete' , _t ( 'CMSMain.DELETE' , 'Delete from the draft site' )));
$deleteAction -> addExtraClass ( 'delete' );
}
2007-07-19 12:40:05 +02:00
}
}
2007-09-15 23:54:24 +02:00
2007-07-19 12:40:05 +02:00
$form = new Form ( $this , " EditForm " , $fields , $actions );
$form -> loadDataFrom ( $record );
$form -> disableDefaultAction ();
2009-01-05 07:17:59 +01:00
if ( ! $record -> canEdit () || $record -> IsDeletedFromStage ) {
$readonlyFields = $form -> Fields () -> makeReadonly ();
$form -> setFields ( $readonlyFields );
}
2007-07-19 12:40:05 +02:00
return $form ;
} else if ( $id ) {
return new Form ( $this , " EditForm " , new FieldSet (
2008-10-16 15:27:12 +02:00
new LabelField ( 'PageDoesntExistLabel' , _t ( 'CMSMain.PAGENOTEXISTS' , " This page doesn't exist " ))), new FieldSet ());
2007-09-15 23:54:24 +02:00
2007-07-19 12:40:05 +02:00
}
}
2007-09-15 23:54:24 +02:00
2007-07-19 12:40:05 +02:00
//------------------------------------------------------------------------------------------//
// Data saving handlers
public function addpage () {
2008-11-18 02:48:50 +01:00
$className = isset ( $_REQUEST [ 'PageType' ]) ? $_REQUEST [ 'PageType' ] : " Page " ;
$parent = isset ( $_REQUEST [ 'ParentID' ]) ? $_REQUEST [ 'ParentID' ] : 0 ;
$suffix = isset ( $_REQUEST [ 'Suffix' ]) ? " - " . $_REQUEST [ 'Suffix' ] : null ;
2007-09-15 23:54:24 +02:00
2009-01-10 12:36:30 +01:00
if ( ! $parent && isset ( $_REQUEST [ 'Parent' ])) {
$page = SiteTree :: get_by_url ( $_REQUEST [ 'Parent' ]);
if ( $page ) $parent = $page -> ID ;
}
2007-09-15 23:54:24 +02:00
2007-07-19 12:40:05 +02:00
if ( is_numeric ( $parent )) $parentObj = DataObject :: get_by_id ( " SiteTree " , $parent );
if ( ! $parentObj || ! $parentObj -> ID ) $parent = 0 ;
2008-11-03 15:56:36 +01:00
if ( $parentObj && ! $parentObj -> canAddChildren ()) return Security :: permissionFailure ( $this );
if ( ! singleton ( $className ) -> canCreate ()) return Security :: permissionFailure ( $this );
2007-09-15 23:54:24 +02:00
2007-11-02 02:52:04 +01:00
$p = $this -> getNewItem ( " new- $className - $parent " . $suffix , false );
$p -> write ();
2007-09-15 23:54:24 +02:00
2007-07-19 12:40:05 +02:00
return $this -> returnItemToUser ( $p );
}
2007-09-15 23:54:24 +02:00
2008-11-07 13:21:10 +01:00
/**
* @ uses LeftAndMainDecorator -> augmentNewSiteTreeItem ()
*/
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
2008-11-03 15:56:36 +01:00
if ( Translatable :: is_enabled ()) {
Merged, debugged and enhanced Translatable patches from branches/translatable at r64523, r64523, 64523, thanks wakeless!
API CHANGE Changed Translatable schema from auxilliary tables (SiteTree_lang, SiteTree_lang_Live) to automatically filtered records on the original table (SiteTree, SiteTree_Live), using $Lang and $OriginalID properties. Incompatible update to old schema, migration script is in the works.
API CHANGE Removed Translatable::get_one(), Translatable::write()
ENHANCEMENT Simplified Translatable tree generation by using getSiteTreeFor() in CMSMain->createtranslation()
ENHANCEMENT Added AllChildrenIncludingDeleted(), augmentNumChildrenCountQuery(), augmentAllChildrenIncludingDeleted(), augmentStageChildren() to Translatable class to allow for more stable tree generation.
ENHANCEMENT Moved definition of Translatable schema from augmentDatabase() to Translatable->extraStatics()
ENHANCEMENT Changes to the CMS language selection refresh the whole admin interface instead of the tree only. This way we can add a URL parameter ?lang=<lang> to /admin, which makes the specific language bookmarkable and reloadable. Changes to LangSelector.js
ENHANCEMENT Added fallback to ModelAsController->getNestedController() to fetch page with matching URLSegment but different language in case no page is found in the current language.
ENHANCEMENT Added helper methods to Translatable: getTranslation(), hasTranslation(), isTranslation(), findOriginalIDs()
ENHANCEMENT Getters and setters for Translatable->getOriginalPage() etc.
ENHANCEMENT Hooking Translatable into ModelAsController and ContentController initialization in order to call choose_site_lang()
ENHANCEMENT Simplified Translatable->augmentSQL(), augmentWrite() by not using auxilliary tables
ENHANCEMENT Showing clickable links for Translations in Translatable->updateCMSFields()
BUGFIX Modifying Hierarchy/SiteTree Children getters to accept optional "context" which can be used to set a language explicitly through the $Lang property, rather than implicitly reyling on the static Translatable::current_lang()
BUGFIX Fixed TranslatableTest to work with new datamodel
BUGFIX Temporarily disabled cookie/session selection in Translatable::choose_site_lang() until we have a good test suite for the side effects.
MINOR Added "untranslated" CSS styles to tree nodes and marking them as inactive/grey
git-svn-id: svn://svn.silverstripe.com/silverstripe/open/modules/cms/trunk@69959 467b73ca-7a2a-4603-9d3b-597d59a354a9
2009-01-10 13:15:30 +01:00
if ( Translatable :: default_lang () != $this -> Lang ) {
Translatable :: set_reading_lang ( Translatable :: default_lang ());
$originalItem = DataObject :: get_by_id ( $className , $suffix );
Translatable :: set_reading_lang ( $this -> Lang );
$translation = $originalItem -> getTranslation ( $this -> Lang );
2009-01-16 05:16:19 +01:00
if ( ! $translation ) $translation = $originalItem -> createTranslation ( $this -> Lang );
Merged, debugged and enhanced Translatable patches from branches/translatable at r64523, r64523, 64523, thanks wakeless!
API CHANGE Changed Translatable schema from auxilliary tables (SiteTree_lang, SiteTree_lang_Live) to automatically filtered records on the original table (SiteTree, SiteTree_Live), using $Lang and $OriginalID properties. Incompatible update to old schema, migration script is in the works.
API CHANGE Removed Translatable::get_one(), Translatable::write()
ENHANCEMENT Simplified Translatable tree generation by using getSiteTreeFor() in CMSMain->createtranslation()
ENHANCEMENT Added AllChildrenIncludingDeleted(), augmentNumChildrenCountQuery(), augmentAllChildrenIncludingDeleted(), augmentStageChildren() to Translatable class to allow for more stable tree generation.
ENHANCEMENT Moved definition of Translatable schema from augmentDatabase() to Translatable->extraStatics()
ENHANCEMENT Changes to the CMS language selection refresh the whole admin interface instead of the tree only. This way we can add a URL parameter ?lang=<lang> to /admin, which makes the specific language bookmarkable and reloadable. Changes to LangSelector.js
ENHANCEMENT Added fallback to ModelAsController->getNestedController() to fetch page with matching URLSegment but different language in case no page is found in the current language.
ENHANCEMENT Added helper methods to Translatable: getTranslation(), hasTranslation(), isTranslation(), findOriginalIDs()
ENHANCEMENT Getters and setters for Translatable->getOriginalPage() etc.
ENHANCEMENT Hooking Translatable into ModelAsController and ContentController initialization in order to call choose_site_lang()
ENHANCEMENT Simplified Translatable->augmentSQL(), augmentWrite() by not using auxilliary tables
ENHANCEMENT Showing clickable links for Translations in Translatable->updateCMSFields()
BUGFIX Modifying Hierarchy/SiteTree Children getters to accept optional "context" which can be used to set a language explicitly through the $Lang property, rather than implicitly reyling on the static Translatable::current_lang()
BUGFIX Fixed TranslatableTest to work with new datamodel
BUGFIX Temporarily disabled cookie/session selection in Translatable::choose_site_lang() until we have a good test suite for the side effects.
MINOR Added "untranslated" CSS styles to tree nodes and marking them as inactive/grey
git-svn-id: svn://svn.silverstripe.com/silverstripe/open/modules/cms/trunk@69959 467b73ca-7a2a-4603-9d3b-597d59a354a9
2009-01-10 13:15:30 +01:00
if ( $setID ) $translation -> ID = $id ;
return $translation ;
2007-09-16 18:32:30 +02:00
}
}
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
if ( $newItem -> castingHelperPair ( '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 ( Member :: currentUser () )
$newItem -> OwnerID = Member :: currentUser () -> ID ;
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 ()
*/
2007-07-19 12:40:05 +02:00
public function deletefromlive ( $urlParams , $form ) {
$id = $_REQUEST [ 'ID' ];
Versioned :: reading_stage ( 'Live' );
$record = DataObject :: get_by_id ( " SiteTree " , $id );
2008-11-03 15:56:36 +01:00
if ( $record && ! $record -> canDelete ()) return Security :: permissionFailure ( $this );
2007-07-27 07:26:00 +02:00
$descRemoved = '' ;
2007-10-02 07:08:36 +02:00
$descendantsRemoved = 0 ;
2007-07-19 12:40:05 +02:00
// before deleting the records, get the descendants of this tree
if ( $record ) {
$descendantIDs = $record -> getDescendantIDList ( 'SiteTree' );
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 ) ) {
$descendant -> delete ();
$descendantsRemoved ++ ;
}
2007-09-15 23:54:24 +02:00
2007-07-19 12:40:05 +02:00
// delete the record
$record -> delete ();
}
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
2007-07-19 12:40:05 +02:00
FormResponse :: add ( $this -> deleteTreeNodeJS ( $record ));
2008-02-25 03:10:37 +01:00
FormResponse :: status_message ( sprintf ( _t ( 'CMSMain.REMOVED' , 'Deleted \'%s\'%s from live site' ), $record -> Title , $descRemoved ), 'good' );
2007-07-19 12:40:05 +02:00
return FormResponse :: respond ();
}
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 ()
*/
2007-07-19 12:40:05 +02:00
public function revert ( $urlParams , $form ) {
2008-12-17 23:41:07 +01:00
$id = ( int ) $_REQUEST [ 'ID' ];
$record = Versioned :: get_one_by_stage ( 'SiteTree' , 'Live' , " \" 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")
2008-11-14 03:23:26 +01:00
if ( isset ( $record ) && $record && ! $record -> canEdit ()) return Security :: permissionFailure ( $this );
2009-01-05 07:17:59 +01:00
2008-11-18 02:48:50 +01:00
$record -> doRevertToLive ();
2007-07-19 12:40:05 +02:00
2008-11-18 02:48:50 +01:00
$title = Convert :: raw2js ( $record -> Title );
2007-07-19 12:40:05 +02:00
FormResponse :: get_page ( $id );
FormResponse :: add ( " $ ('sitetree').setNodeTitle( $id , ' $title '); " );
2007-09-15 22:21:13 +02:00
FormResponse :: status_message ( sprintf ( _t ( 'CMSMain.RESTORED' , " Restored '%s' successfully " , PR_MEDIUM , 'Param %s is a title' ), $title ), 'good' );
2007-07-19 12:40:05 +02:00
2007-09-15 23:54:24 +02:00
return FormResponse :: respond ();
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
*/
2007-07-19 12:40:05 +02:00
public function delete ( $urlParams , $form ) {
$id = $_REQUEST [ 'ID' ];
2008-11-24 10:30:41 +01:00
$record = DataObject :: get_one ( " SiteTree " , " \" SiteTree \" . \" ID \" = $id " );
2008-11-03 15:56:36 +01:00
if ( $record && ! $record -> canDelete ()) return Security :: permissionFailure ();
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 ();
2008-03-11 02:02:05 +01:00
if ( Director :: is_ajax ()) {
2008-12-17 23:41:07 +01:00
// need a valid ID value even if the record doesn't have one in the database
// (its still present in the live tables)
$liveRecord = Versioned :: get_one_by_stage ( 'SiteTree' , 'Live' , " \" SiteTree_Live \" . \" ID \" = $recordID " );
// if the page has never been published to live, we need to act the same way as in deletefromlive()
if ( $liveRecord ) {
// the form is readonly now, so we need to refresh the representation
FormResponse :: get_page ( $recordID );
return $this -> tellBrowserAboutPublicationChange ( $liveRecord , sprintf ( _t ( 'CMSMain.REMOVEDPAGEFROMDRAFT' , " Removed '%s' from the draft site " ), $record -> Title ));
} else {
FormResponse :: add ( $this -> deleteTreeNodeJS ( $record ));
FormResponse :: status_message ( sprintf ( _t ( 'CMSMain.REMOVEDPAGEFROMDRAFT' , " Removed '%s' from the draft site " ), $record -> Title ), 'good' );
return FormResponse :: respond ();
}
2008-03-11 02:02:05 +01:00
} else {
Director :: redirectBack ();
}
2007-07-19 12:40:05 +02:00
}
2007-09-15 23:54:24 +02:00
2009-02-03 03:50:25 +01:00
/*
2007-07-19 12:40:05 +02:00
* Return a dropdown for selecting reports
*/
function ReportSelector () {
$reports = ClassInfo :: subclassesFor ( " SideReport " );
2007-09-15 23:54:24 +02:00
2007-09-15 22:21:13 +02:00
$options [ " " ] = _t ( 'CMSMain.CHOOSEREPORT' , " (Choose a report) " );
2007-07-19 12:40:05 +02:00
foreach ( $reports as $report ) {
if ( $report != 'SideReport' ) $options [ $report ] = singleton ( $report ) -> title ();
}
2008-02-25 03:10:37 +01:00
return new DropdownField ( " ReportSelector " , _t ( 'CMSMain.REPORT' , 'Report' ), $options );
2007-07-19 12:40:05 +02:00
}
/**
* Get the content for a side report
*/
function sidereport () {
$reportClass = $this -> urlParams [ 'ID' ];
2008-10-08 03:49:49 +02:00
$report = ClassInfo :: exists ( $reportClass ) ? new $reportClass () : false ;
return $report ? $report -> getHTML () : false ;
2007-07-19 12:40:05 +02:00
}
/**
* Get the versions of the current page
*/
function versions () {
$pageID = $this -> urlParams [ 'ID' ];
$page = $this -> getRecord ( $pageID );
if ( $page ) {
2008-11-23 01:31:13 +01:00
$versions = $page -> allVersions ( $_REQUEST [ 'unpublished' ] ? " " : " \" SiteTree \" .WasPublished = 1 " );
2007-07-19 12:40:05 +02:00
return array (
'Versions' => $versions ,
2007-09-15 23:54:24 +02:00
);
2007-07-19 12:40:05 +02:00
} else {
2007-09-15 22:21:13 +02:00
return sprintf ( _t ( 'CMSMain.VERSIONSNOPAGE' , " Can't find page #%d " , PR_LOW ), $pageID );
2007-07-19 12:40:05 +02:00
}
}
2007-09-15 23:54:24 +02:00
2007-07-19 12:40:05 +02:00
/**
* Roll a page back to a previous version
*/
function rollback () {
2007-09-19 16:04:50 +02:00
if ( isset ( $_REQUEST [ 'Version' ]) && ( bool ) $_REQUEST [ 'Version' ]) {
2007-07-19 12:40:05 +02:00
$record = $this -> performRollback ( $_REQUEST [ 'ID' ], $_REQUEST [ 'Version' ]);
2007-09-16 18:32:30 +02:00
echo sprintf ( _t ( 'CMSMain.ROLLEDBACKVERSION' , " Rolled back to version #%d. New version number is #%d " ), $_REQUEST [ 'Version' ], $record -> Version );
2007-07-19 12:40:05 +02:00
} else {
$record = $this -> performRollback ( $_REQUEST [ 'ID' ], " Live " );
2007-09-15 22:21:13 +02:00
echo sprintf ( _t ( 'CMSMain.ROLLEDBACKPUB' , " Rolled back to published version. New version number is #%d " ), $record -> Version );
2007-07-19 12:40:05 +02:00
}
}
2007-09-15 23:54:24 +02:00
2007-07-19 12:40:05 +02:00
function unpublish () {
$SQL_id = Convert :: raw2sql ( $_REQUEST [ 'ID' ]);
$page = DataObject :: get_by_id ( " SiteTree " , $SQL_id );
2008-11-03 15:56:36 +01:00
if ( $page && ! $page -> canPublish ()) return Security :: permissionFailure ( $this );
2008-10-16 05:21:49 +02:00
$page -> doUnpublish ();
2007-09-14 03:19:13 +02:00
return $this -> tellBrowserAboutPublicationChange ( $page , sprintf ( _t ( 'CMSMain.REMOVEDPAGE' , " Removed '%s' from the published site " ), $page -> Title ));
2007-07-19 12:40:05 +02:00
}
2008-03-11 02:02:05 +01:00
2007-07-19 12:40:05 +02:00
/**
* Return a few pieces of information about a change to a page
* - Send the new status message
* - Update the action buttons
* - Update the treenote
* - Send a status message
*/
function tellBrowserAboutPublicationChange ( $page , $statusMessage ) {
$JS_title = Convert :: raw2js ( $page -> TreeTitle ());
2007-09-15 23:54:24 +02:00
2008-12-17 23:41:07 +01:00
$JS_stageURL = $page -> IsDeletedFromStage ? '' : Convert :: raw2js ( $page -> AbsoluteLink ());
2008-11-23 23:58:18 +01:00
$liveRecord = Versioned :: get_one_by_stage ( 'SiteTree' , 'Live' , " \" SiteTree \" . \" ID \" = $page->ID " );
2009-01-08 00:01:47 +01:00
2008-03-11 02:20:24 +01:00
$JS_liveURL = $liveRecord ? Convert :: raw2js ( $liveRecord -> AbsoluteLink ()) : '' ;
2007-07-19 12:40:05 +02:00
FormResponse :: add ( $this -> getActionUpdateJS ( $page ));
FormResponse :: update_status ( $page -> Status );
2008-03-11 02:02:05 +01:00
if ( $JS_stageURL || $JS_liveURL ) {
2008-07-18 05:40:32 +02:00
FormResponse :: add ( " \$ ('sitetree').setNodeTitle( $page->ID , ' $JS_title '); " );
2008-03-11 02:02:05 +01:00
} else {
FormResponse :: add ( " var node = $ ('sitetree').getTreeNodeByIdx(' $page->ID '); " );
2008-11-18 02:48:50 +01:00
FormResponse :: add ( " if(node && node.parentTreeNode) node.parentTreeNode.removeTreeNode(node); " );
2008-03-11 02:02:05 +01:00
FormResponse :: add ( " $ ('Form_EditForm').reloadIfSetTo( $page->ID ); " );
}
2007-07-19 12:40:05 +02:00
FormResponse :: status_message ( $statusMessage , 'good' );
2008-07-18 05:40:32 +02:00
FormResponse :: add ( " $ ('Form_EditForm').elements.StageURLSegment.value = ' $JS_stageURL '; " );
FormResponse :: add ( " $ ('Form_EditForm').elements.LiveURLSegment.value = ' $JS_liveURL '; " );
2007-07-19 12:40:05 +02:00
FormResponse :: add ( " $ ('Form_EditForm').notify('PagePublished', $ ('Form_EditForm').elements.ID.value); " );
2007-09-15 23:54:24 +02:00
2007-07-19 12:40:05 +02:00
return FormResponse :: respond ();
}
2007-09-15 23:54:24 +02:00
2007-07-19 12:40:05 +02:00
function performRollback ( $id , $version ) {
$record = DataObject :: get_by_id ( $this -> stat ( 'tree_class' ), $id );
2008-11-03 15:56:36 +01:00
if ( $record && ! $record -> canPublish ()) return Security :: permissionFailure ( $this );
2008-10-16 05:21:49 +02:00
$record -> doRollbackTo ( $version );
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
function getversion () {
$id = $this -> urlParams [ 'ID' ];
2007-09-16 18:32:30 +02:00
$version = str_replace ( '&ajax=1' , '' , $this -> urlParams [ 'OtherID' ]);
2007-07-19 12:40:05 +02:00
$record = Versioned :: get_version ( " SiteTree " , $id , $version );
2009-01-05 07:17:59 +01:00
$versionAuthor = DataObject :: get_by_id ( 'Member' , $record -> AuthorID );
2007-07-19 12:40:05 +02:00
if ( $record ) {
2008-11-03 15:56:36 +01:00
if ( $record && ! $record -> canView ()) return Security :: permissionFailure ( $this );
2007-07-19 12:40:05 +02:00
$fields = $record -> getCMSFields ( $this );
$fields -> removeByName ( " Status " );
$fields -> push ( new HiddenField ( " ID " ));
$fields -> push ( new HiddenField ( " Version " ));
2009-01-05 07:17:59 +01:00
$fields -> insertBefore (
new LiteralField (
'YouAreViewingHeader' ,
'<p class="message notice">' .
sprintf (
_t (
'CMSMain.VIEWING' ,
" You are viewing version #%s, created %s by %s " ,
PR_MEDIUM ,
'Version number is a linked string, created is a relative time (e.g. 2 days ago), by a specific author'
),
" <a href= \" admin/getversion/ $record->ID / $version\ " title = \ " " . $versionAuthor -> Title . " \" > $version </a> " ,
$record -> obj ( 'LastEdited' ) -> Ago (),
$versionAuthor -> Title
) .
'</p>'
),
'Root'
);
2007-07-19 12:40:05 +02:00
$actions = new FieldSet (
2007-09-15 22:21:13 +02:00
new FormAction ( " email " , _t ( 'CMSMain.EMAIL' , " Email " )),
new FormAction ( " print " , _t ( 'CMSMain.PRINT' , " Print " )),
new FormAction ( " rollback " , _t ( 'CMSMain.ROLLBACK' , " Roll back to this version " ))
2007-07-19 12:40:05 +02:00
);
2007-09-15 23:54:24 +02:00
2007-07-19 12:40:05 +02:00
// encode the message to appear in the body of the email
2007-10-29 01:55:52 +01:00
$archiveURL = Director :: absoluteBaseURL () . $record -> URLSegment . '?archiveDate=' . $record -> obj ( 'LastEdited' ) -> URLDatetime ();
2007-07-19 12:40:05 +02:00
$archiveEmailMessage = urlencode ( $this -> customise ( array ( 'ArchiveDate' => $record -> obj ( 'LastEdited' ), 'ArchiveURL' => $archiveURL ) ) -> renderWith ( 'ViewArchivedEmail' ) );
2007-09-15 23:54:24 +02:00
2007-07-19 12:40:05 +02:00
$archiveEmailMessage = preg_replace ( '/\+/' , '%20' , $archiveEmailMessage );
2007-09-15 23:54:24 +02:00
2007-07-19 12:40:05 +02:00
$fields -> push ( new HiddenField ( 'ArchiveEmailMessage' , '' , $archiveEmailMessage ) );
$fields -> push ( new HiddenField ( 'ArchiveEmailSubject' , '' , preg_replace ( '/\+/' , '%20' , urlencode ( 'Archived version of ' . $record -> Title ) ) ) );
$fields -> push ( new HiddenField ( 'ArchiveURL' , '' , $archiveURL ) );
2007-09-15 23:54:24 +02:00
2007-07-19 12:40:05 +02:00
$form = new Form ( $this , " EditForm " , $fields , $actions );
$form -> loadDataFrom ( $record );
$form -> loadDataFrom ( array (
" ID " => $id ,
" Version " => $version ,
));
2009-01-05 07:17:59 +01:00
// historical version shouldn't be editable
$readonlyFields = $form -> Fields () -> makeReadonly ();
$form -> setFields ( $readonlyFields );
2007-09-15 23:54:24 +02:00
2007-07-19 12:40:05 +02:00
$templateData = $this -> customise ( array (
" EditForm " => $form
));
2007-09-15 23:54:24 +02:00
2007-07-19 12:40:05 +02:00
SSViewer :: setOption ( 'rewriteHashlinks' , false );
2009-01-05 07:17:59 +01:00
if ( Director :: is_ajax ()) {
$result = $templateData -> renderWith ( $this -> class . '_right' );
$parts = split ( '</?form[^>]*>' , $result );
return $parts [ sizeof ( $parts ) - 2 ];
} else {
return $templateData -> renderWith ( 'LeftAndMain' );
}
2007-07-19 12:40:05 +02:00
}
}
2007-09-15 23:54:24 +02:00
2007-07-19 12:40:05 +02:00
function compareversions () {
2009-01-05 07:17:59 +01:00
$id = ( int ) $this -> urlParams [ 'ID' ];
$version1 = ( int ) $_REQUEST [ 'From' ];
$version2 = ( int ) $_REQUEST [ 'To' ];
2007-09-15 23:54:24 +02:00
2007-07-19 12:40:05 +02:00
if ( $version1 > $version2 ) {
$toVersion = $version1 ;
$fromVersion = $version2 ;
} else {
$toVersion = $version2 ;
$fromVersion = $version1 ;
}
$page = DataObject :: get_by_id ( " SiteTree " , $id );
2008-11-03 15:56:36 +01:00
if ( $page && ! $page -> canView ()) return Security :: permissionFailure ( $this );
2007-07-19 12:40:05 +02:00
$record = $page -> compareVersions ( $fromVersion , $toVersion );
2009-01-05 07:17:59 +01:00
$fromVersionRecord = Versioned :: get_version ( 'SiteTree' , $id , $fromVersion );
$toVersionRecord = Versioned :: get_version ( 'SiteTree' , $id , $toVersion );
2007-07-19 12:40:05 +02:00
if ( $record ) {
2009-01-05 07:17:59 +01:00
$fromDateNice = $fromVersionRecord -> obj ( 'LastEdited' ) -> Ago ();
$toDateNice = $toVersionRecord -> obj ( 'LastEdited' ) -> Ago ();
$fromAuthor = DataObject :: get_by_id ( 'Member' , $fromVersionRecord -> AuthorID );
$toAuthor = DataObject :: get_by_id ( 'Member' , $toVersionRecord -> AuthorID );
2007-07-19 12:40:05 +02:00
$fields = $record -> getCMSFields ( $this );
$fields -> push ( new HiddenField ( " ID " ));
$fields -> push ( new HiddenField ( " Version " ));
2009-01-05 07:17:59 +01:00
$fields -> insertBefore (
new LiteralField (
'YouAreComparingHeader' ,
'<p class="message notice">' .
sprintf (
_t ( 'CMSMain.COMPARINGV' , " Comparing versions %s and %s " ),
" <a href= \" admin/getversion/ $id / $fromVersionRecord->Version\ " title = \ " $fromAuthor->Title\ " > $fromVersionRecord -> Version </ a > < small > ( $fromDateNice ) </ small > " ,
" <a href= \" admin/getversion/ $id / $toVersionRecord->Version\ " title = \ " $toAuthor->Title\ " > $toVersionRecord -> Version </ a > < small > ( $toDateNice ) </ small > "
) .
'</p>'
),
" Root "
);
2007-07-19 12:40:05 +02:00
$actions = new FieldSet ();
$form = new Form ( $this , " EditForm " , $fields , $actions );
$form -> loadDataFrom ( $record );
$form -> loadDataFrom ( array (
" ID " => $id ,
2008-02-25 03:10:37 +01:00
" Version " => $fromVersion ,
2007-07-19 12:40:05 +02:00
));
2009-01-05 07:17:59 +01:00
// comparison views shouldn't be editable
$readonlyFields = $form -> Fields () -> makeReadonly ();
$form -> setFields ( $readonlyFields );
2007-07-19 12:40:05 +02:00
foreach ( $form -> Fields () -> dataFields () as $field ) {
$field -> dontEscape = true ;
}
2007-09-15 23:54:24 +02:00
2007-07-19 12:40:05 +02:00
return $this -> sendFormToBrowser ( array (
" EditForm " => $form
));
}
}
2007-09-15 23:54:24 +02:00
2007-07-19 12:40:05 +02:00
function sendFormToBrowser ( $templateData ) {
if ( Director :: is_ajax ()) {
SSViewer :: setOption ( 'rewriteHashlinks' , false );
$result = $this -> customise ( $templateData ) -> renderWith ( $this -> class . '_right' );
$parts = split ( '</?form[^>]*>' , $result );
return $parts [ sizeof ( $parts ) - 2 ];
} else {
return array (
" Right " => $this -> customise ( $templateData ) -> renderWith ( $this -> class . '_right' ),
);
}
}
2007-09-15 23:54:24 +02:00
2007-07-19 12:40:05 +02:00
function dialog () {
Requirements :: clear ();
2007-09-15 23:54:24 +02:00
2007-07-19 12:40:05 +02:00
$buttons = new DataObjectSet ;
if ( $_REQUEST [ 'Buttons' ]) foreach ( $_REQUEST [ 'Buttons' ] as $button ) {
list ( $name , $title ) = explode ( ',' , $button , 2 );
$buttons -> push ( new ArrayData ( array (
" Name " => $name ,
" Title " => $title ,
)));
}
2007-09-15 23:54:24 +02:00
2007-07-19 12:40:05 +02:00
return array (
" Message " => htmlentities ( $_REQUEST [ 'Message' ]),
" Buttons " => $buttons ,
" Modal " => $_REQUEST [ 'Modal' ] ? true : false ,
);
}
2007-09-15 23:54:24 +02:00
2007-07-19 12:40:05 +02:00
function canceldraftchangesdialog () {
Requirements :: clear ();
ENHANCEMENT Introduced constants for system paths like /sapphire in preparation for a more flexible directory reorganisation. Instead of hardcoding your path, please use the following constants: BASE_PATH, BASE_URL, SAPPHIRE_DIR, SAPPHIRE_PATH, CMS_DIR, CMS_PATH, THIRDPARTY_DIR, THIRDPARTY_PATH, ASSETS_DIR, ASSETS_PATH, THEMES_DIR, THEMES_PATH
git-svn-id: svn://svn.silverstripe.com/silverstripe/open/modules/cms/trunk@63154 467b73ca-7a2a-4603-9d3b-597d59a354a9
2008-09-27 18:02:38 +02:00
Requirements :: css ( CMS_DIR . 'css/dialog.css' );
2008-09-29 20:49:35 +02:00
Requirements :: javascript ( THIRDPARTY_DIR . '/prototype.js' );
Requirements :: javascript ( THIRDPARTY_DIR . '/behaviour.js' );
Requirements :: javascript ( THIRDPARTY_DIR . '/prototype_improvements.js' );
ENHANCEMENT Introduced constants for system paths like /sapphire in preparation for a more flexible directory reorganisation. Instead of hardcoding your path, please use the following constants: BASE_PATH, BASE_URL, SAPPHIRE_DIR, SAPPHIRE_PATH, CMS_DIR, CMS_PATH, THIRDPARTY_DIR, THIRDPARTY_PATH, ASSETS_DIR, ASSETS_PATH, THEMES_DIR, THEMES_PATH
git-svn-id: svn://svn.silverstripe.com/silverstripe/open/modules/cms/trunk@63154 467b73ca-7a2a-4603-9d3b-597d59a354a9
2008-09-27 18:02:38 +02:00
Requirements :: javascript ( CMS_DIR . '/javascript/dialog.js' );
2007-09-15 23:54:24 +02:00
2007-09-15 22:21:13 +02:00
$message = _t ( 'CMSMain.COPYPUBTOSTAGE' , " Do you really want to copy the published content to the stage site? " );
$buttons = " <button name= \" OK \" > " . _t ( 'CMSMain.OK' , 'OK' ) . " </button><button name= \" Cancel \" > " . _t ( 'CMSMain.CANCEL' , " Cancel " ) . " </button> " ;
2007-09-15 23:54:24 +02:00
2007-07-19 12:40:05 +02:00
return $this -> customise ( array (
'Message' => $message ,
'Buttons' => $buttons ,
'DialogType' => 'alert'
)) -> renderWith ( 'Dialog' );
}
2007-09-15 23:54:24 +02:00
2007-09-16 17:04:09 +02:00
/**
* Publishes a number of items .
* Called by AJAX
*/
public function publishitems () {
// This method can't be called without ajax.
if ( ! Director :: is_ajax ()) {
Director :: redirectBack ();
return ;
}
2008-08-12 04:59:27 +02:00
$ids = split ( ' *, *' , $this -> requestParams [ 'csvIDs' ]);
2007-09-16 17:04:09 +02:00
$notifications = array ();
$idList = array ();
// make sure all the ids are numeric.
// Add all the children to the list of IDs if they are missing
foreach ( $ids as $id ) {
$brokenPageList = '' ;
if ( is_numeric ( $id )) {
$record = DataObject :: get_by_id ( $this -> stat ( 'tree_class' ), $id );
2008-11-03 15:56:36 +01:00
2007-09-16 17:04:09 +02:00
if ( $record ) {
2008-11-03 15:56:36 +01:00
if ( $record && ! $record -> canPublish ()) return Security :: permissionFailure ( $this );
2007-09-16 17:04:09 +02:00
// Publish this page
2008-08-12 04:59:27 +02:00
$record -> doPublish ();
2007-09-16 17:04:09 +02:00
// Now make sure the 'changed' icon is removed
$publishedRecord = DataObject :: get_by_id ( $this -> stat ( 'tree_class' ), $id );
$JS_title = Convert :: raw2js ( $publishedRecord -> TreeTitle ());
FormResponse :: add ( " \$ ('sitetree').setNodeTitle( $id , ' $JS_title '); " );
FormResponse :: add ( " $ ('Form_EditForm').reloadIfSetTo( $record->ID ); " );
$record -> destroy ();
unset ( $record );
}
}
}
if ( sizeof ( $ids ) > 1 ) $message = sprintf ( _t ( 'CMSMain.PAGESPUB' , " %d pages published " ), sizeof ( $ids ));
else $message = sprintf ( _t ( 'CMSMain.PAGEPUB' , " %d page published " ), sizeof ( $ids ));
FormResponse :: add ( 'statusMessage("' . $message . '","good");' );
return FormResponse :: respond ();
}
2009-01-06 03:18:33 +01:00
/**
* @ return Form
*/
public function PublishItemsForm () {
$form = new Form (
$this ,
'PublishItemsForm' ,
new FieldSet (
new HiddenField ( 'csvIDs' ),
new CheckboxField ( 'ShowDrafts' , _t ( 'CMSMain_left.ss.SHOWONLYCHANGED' , 'Show only changed pages' ))
),
new FieldSet (
new FormAction ( 'publishitems' , _t ( 'CMSMain_left.ss.PUBLISHCONFIRM' , 'Publish the selected pages' ))
)
);
$form -> addExtraClass ( 'actionparams' );
return $form ;
}
2007-09-16 17:04:09 +02:00
2007-07-19 12:40:05 +02:00
/**
* Delete a number of items .
* This code supports notification
*/
public function deleteitems () {
// This method can't be called without ajax.
if ( ! Director :: is_ajax ()) {
2007-09-15 23:54:24 +02:00
Director :: redirectBack ();
2007-07-19 12:40:05 +02:00
return ;
}
2007-09-15 23:54:24 +02:00
2007-07-19 12:40:05 +02:00
$ids = split ( ' *, *' , $_REQUEST [ 'csvIDs' ]);
2007-09-15 23:54:24 +02:00
2007-07-19 12:40:05 +02:00
$notifications = array ();
2007-09-15 23:54:24 +02:00
2007-07-19 12:40:05 +02:00
$idList = array ();
2007-09-15 23:54:24 +02:00
2007-07-19 12:40:05 +02:00
// make sure all the ids are numeric.
// Add all the children to the list of IDs if they are missing
foreach ( $ids as $id ) {
$brokenPageList = '' ;
if ( is_numeric ( $id )) {
$record = DataObject :: get_by_id ( $this -> stat ( 'tree_class' ), $id );
2007-09-15 23:54:24 +02:00
2007-07-19 12:40:05 +02:00
if ( $record ) {
2008-11-03 15:56:36 +01:00
if ( $record && ! $record -> canDelete ()) return Security :: permissionFailure ( $this );
2007-07-19 12:40:05 +02:00
// add all the children for this record if they are not already in the list
// this check is a little slower but will prevent circular dependencies
// (should they exist, which they probably shouldn't) from causing
// the function to not terminate
$children = $record -> AllChildren ();
2007-09-15 23:54:24 +02:00
2007-07-19 12:40:05 +02:00
if ( $children )
foreach ( $children as $child )
if ( array_search ( $child -> ID , $ids ) !== FALSE )
$ids [] = $child -> ID ;
2007-09-15 23:54:24 +02:00
2007-07-19 12:40:05 +02:00
if ( $record -> hasMethod ( 'BackLinkTracking' )) {
$brokenPages = $record -> BackLinkTracking ();
foreach ( $brokenPages as $brokenPage ) {
$brokenPageList .= " <li style= \" font-size: 65% \" > " . $brokenPage -> Breadcrumbs ( 3 , true ) . " </li> " ;
$brokenPage -> HasBrokenLink = true ;
$notifications [ $brokenPage -> OwnerID ][] = $brokenPage ;
$brokenPage -> writeWithoutVersion ();
}
}
2007-09-15 23:54:24 +02:00
2007-07-19 12:40:05 +02:00
$record -> delete ();
$record -> destroy ();
// DataObject::delete_by_id($this->stat('tree_class'), $id);
2007-09-15 23:54:24 +02:00
2007-07-19 12:40:05 +02:00
// check to see if the record exists on the live site, if it doesn't remove the tree node
2008-11-23 01:31:13 +01:00
$liveRecord = Versioned :: get_one_by_stage ( $this -> stat ( 'tree_class' ), 'Live' , " \" { $this -> stat ( 'tree_class' ) } \" . \" ID \" = { $id } " );
2007-09-15 23:54:24 +02:00
2007-07-19 12:40:05 +02:00
if ( $liveRecord ) {
$title = Convert :: raw2js ( $record -> TreeTitle ());
FormResponse :: add ( " $ ('sitetree').setNodeTitle( $record->OldID , ' $title '); " );
FormResponse :: add ( " $ ('Form_EditForm').reloadIfSetTo( $record->OldID ); " );
} else {
FormResponse :: add ( " var node = $ ('sitetree').getTreeNodeByIdx(' $id '); " );
2008-11-18 02:48:50 +01:00
FormResponse :: add ( " if(node && node.parentTreeNode) node.parentTreeNode.removeTreeNode(node); " );
2007-07-19 12:40:05 +02:00
FormResponse :: add ( " $ ('Form_EditForm').reloadIfSetTo( $record->OldID ); " );
}
}
}
}
2007-09-15 23:54:24 +02:00
2007-07-19 12:40:05 +02:00
if ( $notifications ) foreach ( $notifications as $memberID => $pages ) {
if ( class_exists ( 'Page_BrokenLinkEmail' )) {
$email = new Page_BrokenLinkEmail ();
$email -> populateTemplate ( new ArrayData ( array (
" Recipient " => DataObject :: get_by_id ( " Member " , $memberID ),
2007-09-15 23:54:24 +02:00
" BrokenPages " => new DataObjectSet ( $pages ),
2007-07-19 12:40:05 +02:00
)));
$email -> debug ();
$email -> send ();
}
}
2007-09-15 23:54:24 +02:00
2007-09-16 17:04:09 +02:00
if ( sizeof ( $ids ) > 1 ) $message = sprintf ( _t ( 'CMSMain.PAGESDEL' , " %d pages deleted " ), sizeof ( $ids ));
else $message = sprintf ( _t ( 'CMSMain.PAGEDEL' , " %d page deleted " ), sizeof ( $ids ));
2007-09-15 02:46:22 +02:00
if ( isset ( $brokenPageList ) && $brokenPageList != '' ) {
2007-09-15 22:21:13 +02:00
$message .= _t ( 'CMSMain.NOWBROKEN' , " The following pages now have broken links: " ) . " <ul> " . addslashes ( $brokenPageList ) . " </ul> " . _t ( 'CMSMain.NOWBROKEN2' , " Their owners have been emailed and they will fix up those pages. " );
2007-07-19 12:40:05 +02:00
}
2007-09-16 17:04:09 +02:00
FormResponse :: add ( 'statusMessage("' . $message . '","good");' );
2007-09-15 23:54:24 +02:00
2007-07-19 12:40:05 +02:00
return FormResponse :: respond ();
}
2009-01-06 03:18:33 +01:00
/**
* @ return Form
*/
function DeleteItemsForm () {
$form = new Form (
$this ,
'DeleteItemsForm' ,
new FieldSet (
new LiteralField ( 'SelectedPagesNote' ,
sprintf ( '<p>%s</p>' , _t ( 'CMSMain_left.ss.SELECTPAGESACTIONS' , 'Select the pages that you want to change & then click an action:' ))
),
new HiddenField ( 'csvIDs' )
),
new FieldSet (
new FormAction ( 'deleteitems' , _t ( 'CMSMain_left.ss.DELETECONFIRM' , 'Delete the selected pages' ))
)
);
$form -> addExtraClass ( 'actionparams' );
return $form ;
}
2007-09-15 23:54:24 +02:00
2007-07-19 12:40:05 +02:00
function buildbrokenlinks () {
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 ;
$lastUsage = ( memory_get_usage () - $lastPoint );
$lastPoint = memory_get_usage ();
$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 ;
}
}
function AddPageOptionsForm () {
$pageTypes = array ();
2007-09-15 23:54:24 +02:00
2007-07-19 12:40:05 +02:00
foreach ( $this -> PageTypes () as $arrayData ) {
$pageTypes [ $arrayData -> getField ( 'ClassName' )] = $arrayData -> getField ( 'AddAction' );
}
2007-09-15 23:54:24 +02:00
2007-07-19 12:40:05 +02:00
return new Form ( $this , " AddPageOptionsForm " , new FieldSet (
2007-09-15 23:54:24 +02:00
new HiddenField ( " ParentID " ),
2007-07-19 12:40:05 +02:00
new DropdownField ( " PageType " , " " , $pageTypes )
// "Page to copy" => new TreeDropdownField("DuplicateSection", "", "SiteTree"),
2007-09-15 23:54:24 +02:00
),
2007-07-19 12:40:05 +02:00
new FieldSet (
2007-09-15 22:21:13 +02:00
new FormAction ( " addpage " , _t ( 'CMSMain.GO' , " Go " ))
2007-07-19 12:40:05 +02:00
));
}
2007-09-15 23:54:24 +02:00
2007-07-19 12:40:05 +02:00
/**
* Helper function to get page count
*/
function getpagecount () {
2008-11-10 06:06:08 +01:00
ini_set ( 'max_execution_time' , 0 );
2007-07-19 12:40:05 +02:00
$excludePages = split ( " *, * " , $_GET [ 'exclude' ]);
2007-09-15 23:54:24 +02:00
2008-11-24 10:30:41 +01:00
$pages = DataObject :: get ( " SiteTree " , " \" ParentID \" = 0 " );
2007-07-19 12:40:05 +02:00
foreach ( $pages as $page ) $pageArr [] = $page ;
2007-09-15 23:54:24 +02:00
2007-07-19 12:40:05 +02:00
while ( list ( $i , $page ) = each ( $pageArr )) {
if ( ! in_array ( $page -> URLSegment , $excludePages )) {
if ( $children = $page -> AllChildren ()) {
foreach ( $children as $child ) $pageArr [] = $child ;
}
if ( ! $_GET [ 'onlywithcontent' ] || strlen ( Convert :: xml2raw ( $page -> Content )) > 100 ) {
echo " <li> " . $page -> Breadcrumbs ( null , true ) . " </li> " ;
$count ++ ;
} else {
2007-09-15 22:21:13 +02:00
echo " <li style= \" color: #777 \" > " . $page -> Breadcrumbs ( null , true ) . " - " . _t ( 'CMSMain.NOCONTENT' , " no content " ) . " </li> " ;
2007-07-19 12:40:05 +02:00
}
2007-09-15 23:54:24 +02:00
2007-07-19 12:40:05 +02:00
}
}
2007-09-15 23:54:24 +02:00
2007-09-15 22:21:13 +02:00
echo '<p>' . _t ( 'CMSMain.TOTALPAGES' , " Total pages: " ) . " $count </p> " ;
2007-07-19 12:40:05 +02:00
}
2007-09-15 23:54:24 +02:00
2007-07-19 12:40:05 +02:00
function publishall () {
2008-10-08 23:33:07 +02:00
ini_set ( " memory_limit " , - 1 );
2008-11-10 06:06:08 +01:00
ini_set ( 'max_execution_time' , 0 );
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' ])) {
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 ;
2008-02-25 03:10:37 +01:00
while ( true ) {
foreach ( $pages as $page ) {
2008-11-03 15:56:36 +01:00
if ( $page && ! $page -> canPublish ()) return Security :: permissionFailure ( $this );
2008-08-12 04:59:27 +02:00
$page -> doPublish ();
2008-02-25 03:10:37 +01:00
$page -> destroy ();
unset ( $page );
$count ++ ;
2008-08-12 04:59:27 +02:00
$response .= " <li> $count </li> " ;
2008-02-25 03:10:37 +01:00
}
if ( $pages -> Count () > 29 ) {
$start += 30 ;
$pages = DataObject :: get ( " SiteTree " , " " , " " , " " , " $start ,30 " );
} else {
break ;
}
2007-07-19 12:40:05 +02:00
}
2007-09-15 23:54:24 +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 {
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 = " '
2007-09-15 22:21:13 +02:00
. _t ( 'CMSMain.PUBALLCONFIRM' , " Please publish every page in the site, copying content stage to live " , PR_LOW , 'Confirmation button' ) . ' " />
</ 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
/**
* Restore a previously deleted page .
* Internal action which shouldn ' t be executed through URL - handlers .
*/
2007-07-19 12:40:05 +02:00
function restorepage () {
if ( $id = $this -> urlParams [ 'ID' ]) {
$restoredPage = Versioned :: get_latest_version ( " SiteTree " , $id );
$restoredPage -> ID = $restoredPage -> RecordID ;
2009-01-05 07:17:59 +01:00
// if no record can be found on draft stage (meaning it has been "deleted from draft" before),
// create an empty record
2008-11-23 23:58:18 +01:00
if ( ! DB :: query ( " SELECT \" ID \" FROM \" SiteTree \" WHERE \" ID \" = $restoredPage->ID " ) -> value ()) {
2008-11-24 10:30:41 +01:00
DB :: query ( " INSERT INTO \" SiteTree \" ( \" ID \" ) VALUES ( $restoredPage->ID ) " );
2007-07-19 12:40:05 +02:00
}
2009-01-05 07:17:59 +01:00
2007-07-19 12:40:05 +02:00
$restoredPage -> forceChange ();
$restoredPage -> writeWithoutVersion ();
2009-01-05 07:17:59 +01:00
2007-07-19 12:40:05 +02:00
} else {
2007-09-15 23:54:24 +02:00
echo _t ( 'CMSMain.VISITRESTORE' , " visit restorepage/(ID) " , PR_LOW , 'restorepage/(ID) should not be translated (is an URL)' );
2007-07-19 12:40:05 +02:00
}
}
2007-09-15 23:54:24 +02:00
2007-07-19 12:40:05 +02:00
function duplicate () {
if (( $id = $this -> urlParams [ 'ID' ]) && is_numeric ( $id )) {
$page = DataObject :: get_by_id ( " SiteTree " , $id );
2008-11-03 15:56:36 +01:00
if ( $page && ! $page -> canEdit ()) return Security :: permissionFailure ( $this );
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 ();
}
return $this -> returnItemToUser ( $newPage );
} else {
user_error ( " CMSMain::duplicate() Bad ID: ' $id ' " , E_USER_WARNING );
}
}
function duplicatewithchildren () {
if (( $id = $this -> urlParams [ 'ID' ]) && is_numeric ( $id )) {
$page = DataObject :: get_by_id ( " SiteTree " , $id );
2008-11-03 15:56:36 +01:00
if ( $page && ! $page -> canEdit ()) return Security :: permissionFailure ( $this );
2008-02-25 03:10:37 +01:00
$newPage = $page -> duplicateWithChildren ();
2008-01-24 01:01:52 +01:00
return $this -> returnItemToUser ( $newPage );
} else {
user_error ( " CMSMain::duplicate() Bad ID: ' $id ' " , E_USER_WARNING );
}
}
2007-09-16 18:32:30 +02:00
2009-02-03 03:50:25 +01:00
/**
* Switch the cms language and reload the site tree
*
*/
function switchlanguage ( $lang , $donotcreate = null ) {
//is it's a clean switch (to an existing language deselect the current page)
if ( is_string ( $lang )) $dontunloadPage = true ;
$lang = ( is_string ( $lang ) ? $lang : urldecode ( $this -> urlParams [ 'ID' ]));
if ( $lang != Translatable :: default_lang ()) {
Translatable :: set_reading_lang ( Translatable :: default_lang ());
$tree_class = $this -> stat ( 'tree_class' );
$obj = new $tree_class ;
$allIDs = $obj -> getDescendantIDList ();
$allChildren = $obj -> AllChildren ();
$classesMap = $allChildren -> map ( 'ID' , 'ClassName' );
$titlesMap = $allChildren -> map ();
Translatable :: set_reading_lang ( $lang );
$obj = new $tree_class ;
$languageIDs = $obj -> getDescendantIDList ();
$notcreatedlist = array_diff ( $allIDs , $languageIDs );
FormResponse :: add ( " $ ('addpage').getElementsByTagName('button')[0].disabled=true; " );
//FormResponse::add("$('Form_AddPageOptionsForm').getElementsByTagName('div')[1].getElementsByTagName('input')[0].disabled=true;");
FormResponse :: add ( " $ ('Translating_Message').innerHTML = 'Translating mode - " . i18n :: get_language_name ( $lang ) . " '; " );
FormResponse :: add ( " Element.removeClassName('Translating_Message','nonTranslating'); " );
} else {
Translatable :: set_reading_lang ( $lang );
FormResponse :: add ( " $ ('addpage').getElementsByTagName('button')[0].disabled=false; " );
//FormResponse::add("$('Form_AddPageOptionsForm').getElementsByTagName('div')[1].getElementsByTagName('input')[0].disabled=false;");
FormResponse :: add ( " Element.addClassName('Translating_Message','nonTranslating'); " );
}
$obj = singleton ( $this -> stat ( 'tree_class' ));
$obj -> markPartialTree ();
$siteTree = $obj -> getChildrenAsUL ( " " , '
" <li id= \" record- $child->ID\ " class = \ " " . $child -> CMSTreeClasses ( $extraArg ) . " \" > " .
" <a href= \" " . Director :: link ( substr ( $extraArg -> Link (), 0 , - 1 ), " show " , $child -> ID ) . " \" " . (( $child -> canEdit () || $child -> canAddChildren ()) ? " " : " class= \" disabled \" " ) . " title= \" ' . _t('LeftAndMain.PAGETYPE') . ' " . $child -> class . " \" > " .
( Convert :: raw2js ( $child -> TreeTitle ())) .
" </a> "
'
, $this , true );
$rootLink = $this -> Link () . '0' ;
$siteTree = " <li id= \" record-0 \" class= \" Root nodelete \" ><a href= \" $rootLink\ " > " .
_t ( 'LeftAndMain.SITECONTENT' ) . " </a> "
. $siteTree . " </li></ul> " ;
FormResponse :: add ( " $ ('sitetree').innerHTML =' " . ereg_replace ( " [ \n ] " , " \\ \n " , $siteTree ) . " '; " );
FormResponse :: add ( " SiteTree.applyTo('#sitetree'); " );
if ( isset ( $notcreatedlist )) {
foreach ( $notcreatedlist as $notcreated ) {
if ( $notcreated == $donotcreate ) continue ;
$id = " new- { $classesMap [ $notcreated ] } -0- $notcreated " ;
Session :: set ( $id . '_originalLangID' , $notcreated );
$treeTitle = Convert :: raw2js ( $titlesMap [ $notcreated ]);
$response = <<< JS
var tree = $ ( 'sitetree' );
var newNode = tree . createTreeNode ( " $id " , " $treeTitle " , " $classesMap[$notcreated] (untranslated) " );
addClass ( newNode , 'untranslated' );
node = tree . getTreeNodeByIdx ( 0 );
node . open ();
node . appendTreeNode ( newNode );
JS ;
FormResponse :: add ( $response );
}
}
if ( ! isset ( $dontunloadPage )) FormResponse :: add ( " node = $ ('sitetree').getTreeNodeByIdx(0); node.selectTreeNode(); " );
return FormResponse :: respond ();
}
2007-09-16 18:32:30 +02:00
/**
* Create a new translation from an existing item , switch to this language and reload the tree .
*/
function createtranslation () {
if ( ! Director :: is_ajax ()) {
Director :: redirectBack ();
return ;
}
$langCode = $_REQUEST [ 'newlang' ];
$originalLangID = $_REQUEST [ 'ID' ];
$record = $this -> getRecord ( $originalLangID );
Merged, debugged and enhanced Translatable patches from branches/translatable at r64523, r64523, 64523, thanks wakeless!
API CHANGE Changed Translatable schema from auxilliary tables (SiteTree_lang, SiteTree_lang_Live) to automatically filtered records on the original table (SiteTree, SiteTree_Live), using $Lang and $OriginalID properties. Incompatible update to old schema, migration script is in the works.
API CHANGE Removed Translatable::get_one(), Translatable::write()
ENHANCEMENT Simplified Translatable tree generation by using getSiteTreeFor() in CMSMain->createtranslation()
ENHANCEMENT Added AllChildrenIncludingDeleted(), augmentNumChildrenCountQuery(), augmentAllChildrenIncludingDeleted(), augmentStageChildren() to Translatable class to allow for more stable tree generation.
ENHANCEMENT Moved definition of Translatable schema from augmentDatabase() to Translatable->extraStatics()
ENHANCEMENT Changes to the CMS language selection refresh the whole admin interface instead of the tree only. This way we can add a URL parameter ?lang=<lang> to /admin, which makes the specific language bookmarkable and reloadable. Changes to LangSelector.js
ENHANCEMENT Added fallback to ModelAsController->getNestedController() to fetch page with matching URLSegment but different language in case no page is found in the current language.
ENHANCEMENT Added helper methods to Translatable: getTranslation(), hasTranslation(), isTranslation(), findOriginalIDs()
ENHANCEMENT Getters and setters for Translatable->getOriginalPage() etc.
ENHANCEMENT Hooking Translatable into ModelAsController and ContentController initialization in order to call choose_site_lang()
ENHANCEMENT Simplified Translatable->augmentSQL(), augmentWrite() by not using auxilliary tables
ENHANCEMENT Showing clickable links for Translations in Translatable->updateCMSFields()
BUGFIX Modifying Hierarchy/SiteTree Children getters to accept optional "context" which can be used to set a language explicitly through the $Lang property, rather than implicitly reyling on the static Translatable::current_lang()
BUGFIX Fixed TranslatableTest to work with new datamodel
BUGFIX Temporarily disabled cookie/session selection in Translatable::choose_site_lang() until we have a good test suite for the side effects.
MINOR Added "untranslated" CSS styles to tree nodes and marking them as inactive/grey
git-svn-id: svn://svn.silverstripe.com/silverstripe/open/modules/cms/trunk@69959 467b73ca-7a2a-4603-9d3b-597d59a354a9
2009-01-10 13:15:30 +01:00
2009-01-16 05:16:19 +01:00
$this -> Lang = $langCode ;
Translatable :: set_reading_lang ( $langCode );
Merged, debugged and enhanced Translatable patches from branches/translatable at r64523, r64523, 64523, thanks wakeless!
API CHANGE Changed Translatable schema from auxilliary tables (SiteTree_lang, SiteTree_lang_Live) to automatically filtered records on the original table (SiteTree, SiteTree_Live), using $Lang and $OriginalID properties. Incompatible update to old schema, migration script is in the works.
API CHANGE Removed Translatable::get_one(), Translatable::write()
ENHANCEMENT Simplified Translatable tree generation by using getSiteTreeFor() in CMSMain->createtranslation()
ENHANCEMENT Added AllChildrenIncludingDeleted(), augmentNumChildrenCountQuery(), augmentAllChildrenIncludingDeleted(), augmentStageChildren() to Translatable class to allow for more stable tree generation.
ENHANCEMENT Moved definition of Translatable schema from augmentDatabase() to Translatable->extraStatics()
ENHANCEMENT Changes to the CMS language selection refresh the whole admin interface instead of the tree only. This way we can add a URL parameter ?lang=<lang> to /admin, which makes the specific language bookmarkable and reloadable. Changes to LangSelector.js
ENHANCEMENT Added fallback to ModelAsController->getNestedController() to fetch page with matching URLSegment but different language in case no page is found in the current language.
ENHANCEMENT Added helper methods to Translatable: getTranslation(), hasTranslation(), isTranslation(), findOriginalIDs()
ENHANCEMENT Getters and setters for Translatable->getOriginalPage() etc.
ENHANCEMENT Hooking Translatable into ModelAsController and ContentController initialization in order to call choose_site_lang()
ENHANCEMENT Simplified Translatable->augmentSQL(), augmentWrite() by not using auxilliary tables
ENHANCEMENT Showing clickable links for Translations in Translatable->updateCMSFields()
BUGFIX Modifying Hierarchy/SiteTree Children getters to accept optional "context" which can be used to set a language explicitly through the $Lang property, rather than implicitly reyling on the static Translatable::current_lang()
BUGFIX Fixed TranslatableTest to work with new datamodel
BUGFIX Temporarily disabled cookie/session selection in Translatable::choose_site_lang() until we have a good test suite for the side effects.
MINOR Added "untranslated" CSS styles to tree nodes and marking them as inactive/grey
git-svn-id: svn://svn.silverstripe.com/silverstripe/open/modules/cms/trunk@69959 467b73ca-7a2a-4603-9d3b-597d59a354a9
2009-01-10 13:15:30 +01:00
// creating a record in-memory, which means setting the $Lang property
// will have no effect as the record is loaded through another javascript
// call and CMSMain->getitem(). The CMS submits the currently selected language
// through javascript, which will cause $Lang to be written to the database.
// @todo Explicitly set $Lang property for in-memory object so we don't need javascript modifying GET-calls to save the new object
2009-01-16 05:16:19 +01:00
$translatedRecord = $record -> createTranslation ( $langCode );
2007-09-16 18:32:30 +02:00
2009-01-16 05:16:19 +01:00
$url = sprintf (
" %s/%d/?lang=%s " ,
$this -> Link ( 'show' ),
$translatedRecord -> ID ,
$langCode
);
FormResponse :: add ( sprintf ( 'window.location.href = "%s";' , $url ));
return FormResponse :: respond ();
2007-09-16 18:32:30 +02:00
}
2007-07-19 12:40:05 +02:00
/**
* Provide the permission codes used by LeftAndMain .
* Can 't put it on LeftAndMain since that' s an abstract base class .
*/
function providePermissions () {
$classes = ClassInfo :: subclassesFor ( 'LeftAndMain' );
2007-09-15 23:54:24 +02:00
2007-07-19 12:40:05 +02:00
foreach ( $classes as $class ) {
2009-01-05 07:17:59 +01:00
$title = _t ( " { $class } .MENUTITLE " , LeftAndMain :: menu_title_for_class ( $class ));
$perms [ " CMS_ACCESS_ " . $class ] = sprintf (
_t (
'CMSMain.ACCESS' ,
" Access to '%s' (%s) " ,
PR_MEDIUM ,
" Item in permission selection identifying the admin section, with title and classname. Example: Access to 'Files & Images' (AssetAdmin) "
),
$title ,
$class
);
2007-07-19 12:40:05 +02:00
}
2009-01-05 07:17:59 +01:00
$perms [ " CMS_ACCESS_LeftAndMain " ] = _t (
'CMSMain.ACCESSALLINTERFACES' ,
'Access to all CMS interfaces'
);
2007-07-19 12:40:05 +02:00
return $perms ;
}
2009-01-05 07:17:59 +01:00
2007-09-16 18:32:30 +02:00
/**
* Return a dropdown with existing languages
*/
function LangSelector () {
2009-01-10 12:36:30 +01:00
$langs = Translatable :: get_existing_content_languages ( 'SiteTree' );
2007-09-16 18:32:30 +02:00
return new DropdownField ( " LangSelector " , " Language " , $langs , Translatable :: current_lang ());
}
/**
* Determine if there are more than one languages in our site tree
*/
function MultipleLanguages () {
2009-01-10 12:36:30 +01:00
$langs = Translatable :: get_existing_content_languages ( 'SiteTree' );
2007-09-16 22:53:31 +02:00
return ( count ( $langs ) > 1 );
2007-09-16 18:32:30 +02:00
}
/**
* Get the name of the language that we are translating in
*/
function EditingLang () {
2007-09-19 16:04:50 +02:00
if ( ! Translatable :: is_default_lang ()) {
return i18n :: get_language_name ( Translatable :: current_lang ());
} else {
return false ;
}
2007-09-16 18:32:30 +02:00
}
2007-07-19 12:40:05 +02:00
}
2007-09-19 16:04:50 +02:00
2007-11-15 23:46:52 +01:00
$filterCache = array ();
2007-09-16 17:19:17 +02:00
// TODO: Find way to put this in a class
2007-09-19 16:04:50 +02:00
function cmsMainMarkingFilterFunction ( $node ) {
2007-09-16 17:19:17 +02:00
// Expand all nodes
// $node->markingFinished();
2007-11-15 23:46:52 +01:00
$failed_filter = false ;
// First check for the generic search term in the URLSegment, Title, MenuTitle, & Content
if ( ! empty ( $_REQUEST [ 'SiteTreeSearchTerm' ])) {
// For childless nodes, show only those matching the filter
$filter = strtolower ( $_REQUEST [ 'SiteTreeSearchTerm' ]);
if ( strpos ( strtolower ( $node -> URLSegment ) , $filter ) === false
&& strpos ( strtolower ( $node -> Title ) , $filter ) === false
&& strpos ( strtolower ( $node -> MenuTitle ) , $filter ) === false
&& strpos ( strtolower ( $node -> Content ) , $filter ) === false ) {
$failed_filter = true ;
}
}
// Check the 'Edited Since' date
if ( ! empty ( $_REQUEST [ 'SiteTreeFilterDate' ])) {
$edited_since = mktime ( 0 , 0 , 0 , substr ( $_REQUEST [ 'SiteTreeFilterDate' ], 3 , 2 ),
substr ( $_REQUEST [ 'SiteTreeFilterDate' ], 0 , 2 ), substr ( $_REQUEST [ 'SiteTreeFilterDate' ], 6 , 4 ));
if ( strtotime ( $node -> LastEdited ) < $edited_since ) {
$failed_filter = true ;
2007-09-16 17:19:17 +02:00
}
2007-11-15 23:46:52 +01:00
}
// Now check if a specified Criteria attribute matches
foreach ( CMSMain :: T_SiteTreeFilterOptions () as $key => $value )
{
if ( ! empty ( $_REQUEST [ $key ])) {
$parameterName = $key ;
$filter = strtolower ( $_REQUEST [ $key ]);
// Show node only if the filter string exists anywere in the filter paramater (ignoring case)
if ( strpos ( strtolower ( $node -> $parameterName ) , $filter ) === false ) {
2007-09-16 17:19:17 +02:00
$failed_filter = true ;
}
}
2007-11-15 23:46:52 +01:00
}
// Each filter must match or it fails
if ( true == $failed_filter ) {
// Don't ever hide nodes with children, because otherwise if one of their children matches the search, it wouldn't be shown.
if ( $node -> AllChildrenIncludingDeleted () -> count () > 0 ) {
// Open all nodes with children so it is easy to see any children that match the search.
foreach ( $node -> AllChildrenIncludingDeleted () as $childNode ) {
if ( cmsMainMarkingFilterFunction ( $childNode )) {
$node -> markOpened ();
$filterCache [ $node -> ID ] = true ;
return true ;
2007-09-16 17:19:17 +02:00
}
}
}
2007-11-15 23:46:52 +01:00
$filterCache [ $node -> ID ] = false ;
return false ;
} else {
if ( $node -> AllChildrenIncludingDeleted () -> count () > 0 ) {
$node -> markOpened ();
2007-09-16 17:19:17 +02:00
}
2007-11-15 23:46:52 +01:00
$filterCache [ $node -> ID ] = true ;
return true ;
2007-09-16 17:19:17 +02:00
}
}
2007-07-19 12:40:05 +02:00
2009-01-05 07:17:59 +01:00
?>