2007-07-19 12:40:05 +02:00
< ? php
/**
* LeftAndMain is the parent class of all the two - pane views in the CMS .
* If you are wanting to add more areas to the CMS , you can do it by subclassing LeftAndMain .
2008-04-05 05:43:58 +02:00
*
* This is essentially an abstract class which should be subclassed .
* See { @ link CMSMain } for a good example .
*
2008-02-25 03:10:37 +01:00
* @ package cms
* @ subpackage core
2007-07-19 12:40:05 +02:00
*/
2008-04-05 05:43:58 +02:00
class LeftAndMain extends Controller {
2007-07-19 12:40:05 +02:00
static $tree_class = null ;
2008-04-05 05:43:58 +02:00
/**
* Default menu items for the core cms functionality ,
* set in cms / _config . php .
*
* @ usedby { @ link add_menu_item ()}
* @ var array
*/
protected static $menu_items = array ();
2007-07-19 12:40:05 +02:00
static $ForceReload ;
2007-09-14 21:26:56 +02:00
2008-02-25 03:10:37 +01:00
static $allowed_actions = array (
'ajaxupdateparent' ,
'ajaxupdatesort' ,
'callPageMethod' ,
'deleteitems' ,
'getitem' ,
'getsubtree' ,
'myprofile' ,
'printable' ,
'save' ,
'show' ,
);
2007-07-19 12:40:05 +02:00
function init () {
Director :: set_site_mode ( 'cms' );
2007-09-27 22:56:55 +02:00
// set language
$member = Member :: currentUser ();
2007-10-21 21:53:57 +02:00
if ( ! empty ( $member -> Locale )) {
i18n :: set_locale ( $member -> Locale );
2007-09-27 22:56:55 +02:00
}
2007-11-13 01:14:15 +01:00
// set reading lang
2008-02-25 03:10:37 +01:00
if ( Translatable :: is_enabled ()) {
Translatable :: choose_site_lang ( i18n :: get_existing_content_languages ( 'SiteTree' ));
2007-11-13 01:14:15 +01:00
}
2007-09-14 21:26:56 +02:00
2007-07-19 12:40:05 +02:00
parent :: init ();
2007-08-31 02:31:49 +02:00
// Allow customisation of the access check by a decorator
if ( $this -> hasMethod ( 'alternateAccessCheck' )) {
$isAllowed = $this -> alternateAccessCheck ();
// Default security check for LeftAndMain sub-class permissions
} else {
$isAllowed = Permission :: check ( " CMS_ACCESS_ $this->class " );
if ( ! $isAllowed && $this -> class == 'CMSMain' ) {
// When access /admin/, we should try a redirect to another part of the admin rather than be locked out
2007-07-19 12:40:05 +02:00
$menu = $this -> MainMenu ();
if (( $first = $menu -> First ()) && $first -> Link ) {
Director :: redirect ( $first -> Link );
}
}
2007-08-31 02:31:49 +02:00
}
2007-07-19 12:40:05 +02:00
2007-08-31 02:31:49 +02:00
// Don't continue if there's already been a redirection request.
if ( Director :: redirected_to ()) return ;
2007-07-19 12:40:05 +02:00
2007-08-31 02:31:49 +02:00
// Access failure!
if ( ! $isAllowed ) {
2007-07-19 12:40:05 +02:00
$messageSet = array (
2007-09-15 22:21:13 +02:00
'default' => _t ( 'LeftAndMain.PERMDEFAULT' , " Please choose an authentication method and enter your credentials to access the CMS. " ),
'alreadyLoggedIn' => _t ( 'LeftAndMain.PERMALREADY' , " I'm sorry, but you can't access that part of the CMS. If you want to log in as someone else, do so below " ),
'logInAgain' => _t ( 'LeftAndMain.PERMAGAIN' , " You have been logged out of the CMS. If you would like to log in again, enter a username and password below. " ),
2007-07-19 12:40:05 +02:00
);
Security :: permissionFailure ( $this , $messageSet );
2007-08-17 05:09:46 +02:00
return ;
2007-07-19 12:40:05 +02:00
}
2007-09-27 22:56:55 +02:00
Requirements :: javascript ( 'jsparty/prototype.js' );
Requirements :: javascript ( 'jsparty/behaviour.js' );
Requirements :: javascript ( 'jsparty/prototype_improvements.js' );
Requirements :: javascript ( 'jsparty/loader.js' );
Requirements :: javascript ( 'jsparty/hover.js' );
Requirements :: javascript ( 'jsparty/layout_helpers.js' );
Requirements :: javascript ( MCE_ROOT . 'tiny_mce_src.js' );
2007-11-07 05:50:09 +01:00
Requirements :: javascript ( 'cms/javascript/ImageEditor/Activator.js' );
2007-09-27 22:56:55 +02:00
Requirements :: javascript ( 'jsparty/tiny_mce_improvements.js' );
Requirements :: javascript ( 'jsparty/scriptaculous/effects.js' );
Requirements :: javascript ( 'jsparty/scriptaculous/dragdrop.js' );
Requirements :: javascript ( 'jsparty/scriptaculous/controls.js' );
Requirements :: css ( 'jsparty/greybox/greybox.css' );
Requirements :: javascript ( 'jsparty/greybox/AmiJS.js' );
Requirements :: javascript ( 'jsparty/greybox/greybox.js' );
Requirements :: javascript ( 'jsparty/tree/tree.js' );
Requirements :: css ( 'jsparty/tree/tree.css' );
2007-07-19 12:40:05 +02:00
2007-09-27 22:56:55 +02:00
Requirements :: javascript ( 'jsparty/tabstrip/tabstrip.js' );
Requirements :: css ( 'jsparty/tabstrip/tabstrip.css' );
2007-08-16 08:25:17 +02:00
2007-11-15 23:31:22 +01:00
Requirements :: css ( 'cms/css/TinyMCEImageEnhancement.css' );
Requirements :: javascript ( 'cms/javascript/TinyMCEImageEnhancement.js' );
2007-09-27 22:56:55 +02:00
Requirements :: javascript ( 'cms/javascript/LeftAndMain.js' );
Requirements :: javascript ( 'cms/javascript/LeftAndMain_left.js' );
Requirements :: javascript ( 'cms/javascript/LeftAndMain_right.js' );
Requirements :: css ( 'sapphire/css/Form.css' );
2008-02-25 03:10:37 +01:00
// Requirements::javascript('cms/javascript/MemberList.js');
2007-09-27 22:56:55 +02:00
Requirements :: javascript ( 'cms/javascript/ForumAdmin.js' );
Requirements :: javascript ( 'cms/javascript/SideTabs.js' );
Requirements :: javascript ( 'cms/javascript/TaskList.js' );
Requirements :: javascript ( 'cms/javascript/CommentList.js' );
Requirements :: javascript ( 'cms/javascript/SideReports.js' );
Requirements :: javascript ( 'cms/javascript/LangSelector.js' );
Requirements :: javascript ( 'cms/javascript/TranslationTab.js' );
Requirements :: javascript ( 'sapphire/javascript/Validator.js' );
Requirements :: javascript ( 'sapphire/javascript/UniqueFields.js' );
Requirements :: javascript ( 'sapphire/javascript/RedirectorPage.js' );
Requirements :: javascript ( 'sapphire/javascript/DataReport.js' );
2007-11-13 00:00:20 +01:00
Requirements :: javascript ( 'sapphire/javascript/ToggleCompositeField.js' );
2007-09-27 22:56:55 +02:00
Requirements :: css ( 'sapphire/css/SubmittedFormReportField.css' );
Requirements :: javascript ( 'sapphire/javascript/FieldEditor.js' );
Requirements :: css ( 'sapphire/css/FieldEditor.css' );
Requirements :: css ( 'sapphire/css/TableListField.css' );
Requirements :: css ( 'sapphire/css/ComplexTableField.css' );
Requirements :: javascript ( 'sapphire/javascript/TableListField.js' );
Requirements :: javascript ( 'sapphire/javascript/TableField.js' );
Requirements :: javascript ( 'sapphire/javascript/ComplexTableField.js' );
Requirements :: javascript ( 'sapphire/javascript/RelationComplexTableField.js' );
Requirements :: css ( 'sapphire/css/TreeDropdownField.css' );
Requirements :: css ( 'sapphire/css/CheckboxSetField.css' );
Requirements :: javascript ( 'jsparty/calendar/calendar.js' );
Requirements :: javascript ( 'jsparty/calendar/lang/calendar-en.js' );
Requirements :: javascript ( 'jsparty/calendar/calendar-setup.js' );
Requirements :: css ( 'sapphire/css/CalendarDateField.css' );
Requirements :: css ( 'jsparty/calendar/calendar-win2k-1.css' );
2007-11-15 23:52:42 +01:00
Requirements :: javascript ( 'sapphire/javascript/DropdownTimeField.js' );
2007-11-06 04:28:34 +01:00
Requirements :: css ( 'sapphire/css/DropdownTimeField.css' );
Requirements :: css ( 'sapphire/css/PopupDateTimeField.css' );
2007-09-27 22:56:55 +02:00
Requirements :: javascript ( 'sapphire/javascript/SelectionGroup.js' );
Requirements :: css ( 'sapphire/css/SelectionGroup.css' );
2007-11-15 23:31:22 +01:00
Requirements :: javascript ( 'jsparty/SWFUpload/SWFUpload.js' );
Requirements :: javascript ( 'cms/javascript/Upload.js' );
2007-09-27 22:56:55 +02:00
2008-02-25 03:10:37 +01:00
Requirements :: javascript ( 'sapphire/javascript/HasManyFileField.js' );
Requirements :: css ( 'sapphire/css/HasManyFileField.css' );
2007-09-27 22:56:55 +02:00
Requirements :: themedCSS ( 'typography' );
// For Widgets
Requirements :: css ( 'cms/css/WidgetAreaEditor.css' );
Requirements :: javascript ( 'cms/javascript/WidgetAreaEditor.js' );
2007-11-04 22:41:50 +01:00
// For Blog
Requirements :: javascript ( 'blog/javascript/bbcodehelp.js' );
2007-09-27 22:56:55 +02:00
Requirements :: javascript ( " sapphire/javascript/Security_login.js " );
2007-09-16 04:21:47 +02:00
2007-08-16 08:25:17 +02:00
$dummy = null ;
$this -> extend ( 'augmentInit' , $dummy );
2007-07-19 12:40:05 +02:00
}
2007-09-14 21:26:56 +02:00
2007-07-19 12:40:05 +02:00
/**
* Returns true if the current user can access the CMS
*/
function canAccessCMS () {
2007-09-14 21:26:56 +02:00
2007-07-19 12:40:05 +02:00
$member = Member :: currentUser ();
2007-09-14 21:26:56 +02:00
2007-07-19 12:40:05 +02:00
if ( $member ) {
if ( $groups = $member -> Groups ()) {
foreach ( $groups as $group ) if ( $group -> CanCMS ) return true ;
}
}
2007-09-14 21:26:56 +02:00
2007-07-19 12:40:05 +02:00
return false ;
}
2007-09-14 21:26:56 +02:00
2007-07-19 12:40:05 +02:00
/**
* Returns true if the current user has administrative rights in the CMS
*/
function canAdminCMS () {
if ( $member = Member :: currentUser ()) return $member -> isAdmin ();
}
//------------------------------------------------------------------------------------------//
// Main controllers
2007-09-14 21:26:56 +02:00
2007-07-19 12:40:05 +02:00
/**
* You should implement a Link () function in your subclass of LeftAndMain ,
* to point to the URL of that particular controller .
2008-04-05 05:43:58 +02:00
*
* @ return string
2007-07-19 12:40:05 +02:00
*/
2008-04-05 05:43:58 +02:00
public function Link () {
user_error ( 'LeftAndMain::Link(): Please implement in your subclass' , E_USER_ERROR );
}
2007-09-14 21:26:56 +02:00
2007-07-19 12:40:05 +02:00
public function show ( $params ) {
if ( $params [ 'ID' ]) $this -> setCurrentPageID ( $params [ 'ID' ]);
2007-09-15 02:56:26 +02:00
if ( isset ( $params [ 'OtherID' ]))
2007-07-19 12:40:05 +02:00
Session :: set ( 'currentMember' , $params [ 'OtherID' ]);
if ( Director :: is_ajax ()) {
SSViewer :: setOption ( 'rewriteHashlinks' , false );
return $this -> EditForm () -> formHtmlContent ();
2007-09-14 21:26:56 +02:00
2007-07-19 12:40:05 +02:00
} else {
return array ();
}
}
2007-09-14 21:26:56 +02:00
2007-07-19 12:40:05 +02:00
public function getitem () {
$this -> setCurrentPageID ( $_REQUEST [ 'ID' ]);
SSViewer :: setOption ( 'rewriteHashlinks' , false );
// Changed 3/11/2006 to not use getLastFormIn because that didn't have _form_action, _form_name, etc.
2007-09-14 21:26:56 +02:00
2007-07-19 12:40:05 +02:00
$form = $this -> EditForm ();
if ( $form ) return $form -> formHtmlContent ();
else return " " ;
}
public function getLastFormIn ( $html ) {
$parts = split ( '</?form[^>]*>' , $html );
return $parts [ sizeof ( $parts ) - 2 ];
}
//------------------------------------------------------------------------------------------//
// Main UI components
2007-09-14 21:26:56 +02:00
2007-07-19 12:40:05 +02:00
/**
* Returns the main menu of the CMS . This is also used by init () to work out which sections the user
* has access to .
2008-04-05 05:43:58 +02:00
*
* @ return DataObjectSet
2007-07-19 12:40:05 +02:00
*/
public function MainMenu () {
// Don't accidentally return a menu if you're not logged in - it's used to determine access.
if ( ! Member :: currentUserID ()) return new DataObjectSet ();
// Encode into DO set
2007-09-14 21:26:56 +02:00
$menu = new DataObjectSet ();
2008-04-05 05:43:58 +02:00
foreach ( $this -> stat ( 'menu_items' ) as $code => $menuItem ) {
if ( isset ( $menuItem [ 'controllerClass' ]) && $this -> hasMethod ( 'alternateMenuDisplayCheck' )) {
$isAllowed = $this -> alternateMenuDisplayCheck ( $menuItem [ 'controllerClass' ]);
} elseif ( isset ( $menuItem [ 'controllerClass' ])) {
$isAllowed = Permission :: check ( " CMS_ACCESS_ " . $menuItem [ 'controllerClass' ]);
2007-08-31 02:31:49 +02:00
} else {
$isAllowed = true ;
}
2008-04-05 05:43:58 +02:00
if ( ! $isAllowed ) continue ;
2007-07-19 12:40:05 +02:00
2008-04-05 05:43:58 +02:00
$linkingmode = " " ;
if ( ! ( strpos ( $this -> Link (), $menuItem [ 'url' ]) === false )) {
// HACK Hardcoding assumptions about the first default menu item
if ( $code == " content " ) {
if ( $this -> Link () == " admin/ " )
2007-07-19 12:40:05 +02:00
$linkingmode = " current " ;
2008-04-05 05:43:58 +02:00
} else {
$linkingmode = " current " ;
2007-07-19 12:40:05 +02:00
}
}
2008-04-05 05:43:58 +02:00
$menu -> push ( new ArrayData ( array (
" Title " => Convert :: raw2xml ( $menuItem [ 'title' ]),
" Code " => $code ,
" Link " => $menuItem [ 'url' ],
" LinkingMode " => $linkingmode
)));
2007-07-19 12:40:05 +02:00
}
2008-04-05 05:43:58 +02:00
// if no current item is found, assume that first item is shown
//if(!isset($foundCurrent))
2007-07-19 12:40:05 +02:00
2008-04-05 05:43:58 +02:00
return $menu ;
2007-07-19 12:40:05 +02:00
}
/**
* Return a list of appropriate templates for this class , with the given suffix
2007-09-14 21:26:56 +02:00
*/
2007-07-19 12:40:05 +02:00
protected function getTemplatesWithSuffix ( $suffix ) {
$classes = array_reverse ( ClassInfo :: ancestry ( $this -> class ));
foreach ( $classes as $class ) {
$templates [] = $class . $suffix ;
if ( $class == 'LeftAndMain' ) break ;
}
return $templates ;
}
2007-09-14 21:26:56 +02:00
2007-07-19 12:40:05 +02:00
public function Left () {
return $this -> renderWith ( $this -> getTemplatesWithSuffix ( '_left' ));
}
public function Right () {
return $this -> renderWith ( $this -> getTemplatesWithSuffix ( '_right' ));
}
public function RightBottom () {
if ( SSViewer :: hasTemplate ( $this -> getTemplatesWithSuffix ( '_rightbottom' ))) {
return $this -> renderWith ( $this -> getTemplatesWithSuffix ( '_rightbottom' ));
}
}
2007-09-14 21:26:56 +02:00
2007-07-19 12:40:05 +02:00
public function getRecord ( $id , $className = null ) {
if ( ! $className ) $className = $this -> stat ( 'tree_class' );
return DataObject :: get_by_id ( $className , $rootID );
}
function getSiteTreeFor ( $className , $rootID = null ) {
$obj = $rootID ? $this -> getRecord ( $rootID ) : singleton ( $className );
$obj -> markPartialTree ();
if ( $p = $this -> currentPage ()) $obj -> markToExpose ( $p );
2007-09-14 21:26:56 +02:00
2007-07-19 12:40:05 +02:00
// getChildrenAsUL is a flexible and complex way of traversing the tree
$siteTree = $obj -> getChildrenAsUL ( " " , '
" <li id= \" record- $child->ID\ " class = \ " " . $child -> CMSTreeClasses ( $extraArg ) . " \" > " .
2008-02-25 03:10:37 +01:00
" <a href= \" " . Director :: link ( substr ( $extraArg -> Link (), 0 , - 1 ), " show " , $child -> ID ) . " \" class= \" " . $child -> CMSTreeClasses ( $extraArg ) . " \" title= \" ' . _t('LeftAndMain.PAGETYPE','Page type: ') . ' " . $child -> class . " \" > " .
( $child -> TreeTitle ()) .
2007-07-19 12:40:05 +02:00
" </a> "
'
, $this , true );
2007-09-14 21:26:56 +02:00
// Wrap the root if needs be.
2007-07-19 12:40:05 +02:00
if ( ! $rootID ) {
$rootLink = $this -> Link () . '0' ;
2007-08-16 08:25:17 +02:00
// This lets us override the tree title with an extension
if ( $this -> hasMethod ( 'getCMSTreeTitle' )) $treeTitle = $this -> getCMSTreeTitle ();
2007-11-07 00:44:20 +01:00
else $treeTitle = _t ( 'LeftAndMain.SITECONTENTLEFT' , " Site Content " , PR_HIGH , 'Root node on left' );
2007-08-16 08:25:17 +02:00
2007-10-29 02:45:36 +01:00
$siteTree = " <ul id= \" sitetree \" class= \" tree unformatted \" ><li id= \" record-0 \" class= \" Root nodelete \" ><a href= \" $rootLink\ " >< strong > $treeTitle </ strong ></ a > "
2007-07-19 12:40:05 +02:00
. $siteTree . " </li></ul> " ;
}
2007-09-14 21:26:56 +02:00
2007-07-19 12:40:05 +02:00
return $siteTree ;
}
2007-09-14 21:26:56 +02:00
2007-07-19 12:40:05 +02:00
public function getsubtree () {
$results = $this -> getSiteTreeFor ( $this -> stat ( 'tree_class' ), $_REQUEST [ 'ID' ]);
return substr ( trim ( $results ), 4 , - 5 );
}
2007-09-14 21:26:56 +02:00
2007-07-19 12:40:05 +02:00
/**
2007-09-14 21:26:56 +02:00
* Allows you to returns a new data object to the tree ( subclass of sitetree )
* and updates the tree via javascript .
2007-07-19 12:40:05 +02:00
*/
public function returnItemToUser ( $p ) {
if ( Director :: is_ajax ()) {
// Prepare the object for insertion.
$parentID = ( int ) $p -> ParentID ;
2007-09-14 21:26:56 +02:00
$id = $p -> ID ? $p -> ID : " new- $p->class - $p->ParentID " ;
2007-07-19 12:40:05 +02:00
$treeTitle = Convert :: raw2js ( $p -> TreeTitle ());
$hasChildren = is_numeric ( $id ) && $p -> AllChildren () ? ' unexpanded' : '' ;
2007-09-14 21:26:56 +02:00
2007-07-19 12:40:05 +02:00
// Ensure there is definitly a node avaliable. if not, append to the home tree.
$response = <<< JS
var tree = $ ( 'sitetree' );
var newNode = tree . createTreeNode ( " $id " , " $treeTitle " , " { $p -> class } { $hasChildren } " );
node = tree . getTreeNodeByIdx ( $parentID );
if ( ! node ){ node = tree . getTreeNodeByIdx ( 0 ); }
node . open ();
node . appendTreeNode ( newNode );
newNode . selectTreeNode ();
JS ;
FormResponse :: add ( $response );
}
return FormResponse :: respond ();
}
/**
2007-09-15 03:00:03 +02:00
* Save and Publish page handler
2007-07-19 12:40:05 +02:00
*/
public function save ( $urlParams , $form ) {
$className = $this -> stat ( 'tree_class' );
$result = '' ;
2007-09-14 21:26:56 +02:00
2007-09-25 23:58:42 +02:00
$SQL_id = Convert :: raw2sql ( $_REQUEST [ 'ID' ]);
if ( substr ( $SQL_id , 0 , 3 ) != 'new' ) {
$record = DataObject :: get_one ( $className , " ` $className `.ID = { $SQL_id } " );
2007-07-19 12:40:05 +02:00
} else {
2007-09-25 23:58:42 +02:00
$record = $this -> getNewItem ( $SQL_id , false );
2007-07-19 12:40:05 +02:00
}
2007-09-14 21:26:56 +02:00
// We don't want to save a new version if there are no changes
2007-07-19 12:40:05 +02:00
$dataFields_new = $form -> Fields () -> dataFields ();
$dataFields_old = $record -> getAllFields ();
$changed = false ;
$hasNonRecordFields = false ;
foreach ( $dataFields_new as $datafield ) {
// if the form has fields not belonging to the record
if ( ! isset ( $dataFields_old [ $datafield -> Name ()])) {
2007-09-14 21:26:56 +02:00
$hasNonRecordFields = true ;
2007-07-19 12:40:05 +02:00
}
// if field-values have changed
if ( ! isset ( $dataFields_old [ $datafield -> Name ()]) || $dataFields_old [ $datafield -> Name ()] != $datafield -> dataValue ()) {
$changed = true ;
}
}
if ( ! $changed && ! $hasNonRecordFields ) {
// Tell the user we have saved even though we haven't, as not to confuse them
if ( is_a ( $record , " Page " )) {
$record -> Status = " Saved (update) " ;
}
2007-09-15 22:21:13 +02:00
FormResponse :: status_message ( _t ( 'LeftAndMain.SAVEDUP' , " Saved " ), " good " );
2007-07-19 12:40:05 +02:00
FormResponse :: update_status ( $record -> Status );
return FormResponse :: respond ();
}
2007-09-14 21:26:56 +02:00
2007-07-19 12:40:05 +02:00
$form -> dataFieldByName ( 'ID' ) -> Value = 0 ;
if ( isset ( $urlParams [ 'Sort' ]) && is_numeric ( $urlParams [ 'Sort' ])) {
$record -> Sort = $urlParams [ 'Sort' ];
}
// HACK: This should be turned into something more general
$originalClass = $record -> ClassName ;
$originalStatus = $record -> Status ;
$record -> HasBrokenLink = 0 ;
$record -> HasBrokenFile = 0 ;
$record -> writeWithoutVersion ();
// HACK: This should be turned into something more general
$originalURLSegment = $record -> URLSegment ;
$form -> saveInto ( $record , true );
2007-09-14 21:26:56 +02:00
2007-07-19 12:40:05 +02:00
if ( is_a ( $record , " Page " )) {
$record -> Status = ( $record -> Status == " New page " || $record -> Status == " Saved (new) " ) ? " Saved (new) " : " Saved (update) " ;
}
2007-09-14 21:26:56 +02:00
2007-07-19 12:40:05 +02:00
// $record->write();
if ( Director :: is_ajax ()) {
2007-09-25 23:58:42 +02:00
if ( $SQL_id != $record -> ID ) {
FormResponse :: add ( " $ ('sitetree').setNodeIdx( \" { $SQL_id } \" , \" $record->ID\ " ); " );
2007-07-19 12:40:05 +02:00
FormResponse :: add ( " $ ('Form_EditForm').elements.ID.value = \" $record->ID\ " ; " );
}
if ( $added = DataObjectLog :: getAdded ( 'SiteTree' )) {
foreach ( $added as $page ) {
if ( $page -> ID != $record -> ID ) $result .= $this -> addTreeNodeJS ( $page );
}
}
if ( $deleted = DataObjectLog :: getDeleted ( 'SiteTree' )) {
foreach ( $deleted as $page ) {
if ( $page -> ID != $record -> ID ) $result .= $this -> deleteTreeNodeJS ( $page );
}
}
if ( $changed = DataObjectLog :: getChanged ( 'SiteTree' )) {
foreach ( $changed as $page ) {
if ( $page -> ID != $record -> ID ) {
$title = Convert :: raw2js ( $page -> TreeTitle ());
FormResponse :: add ( " $ ('sitetree').setNodeTitle( $page->ID , \" $title\ " ) " );
}
}
}
2007-09-14 21:26:56 +02:00
2007-09-15 22:21:13 +02:00
$message = _t ( 'LeftAndMain.SAVEDUP' );
2007-07-19 12:40:05 +02:00
// Update the icon if the class has changed
if ( $originalClass != $record -> ClassName ) {
$record -> setClassName ( $record -> ClassName );
$newClass = $record -> ClassName ;
$record = $record -> newClassInstance ( $newClass );
2007-09-14 21:26:56 +02:00
2007-07-19 12:40:05 +02:00
FormResponse :: add ( " if( \$ ('sitetree').setNodeIcon) \$ ('sitetree').setNodeIcon( $record->ID , ' $originalClass ', ' $record->ClassName '); " );
}
// HACK: This should be turned into somethign more general
2007-09-14 21:26:56 +02:00
if ( ( $record -> class == 'VirtualPage' && $originalURLSegment != $record -> URLSegment ) ||
2007-07-19 12:40:05 +02:00
( $originalClass != $record -> ClassName ) || self :: $ForceReload == true ) {
FormResponse :: add ( " $ ('Form_EditForm').getPageFromServer( $record->ID ); " );
}
2007-09-14 21:26:56 +02:00
2007-07-19 12:40:05 +02:00
// After reloading action
if ( $originalStatus != $record -> Status ) {
2007-09-15 22:21:13 +02:00
$message .= sprintf ( _t ( 'LeftAndMain.STATUSTO' , " Status changed to '%s' " ), $record -> Status );
2007-07-19 12:40:05 +02:00
}
2007-09-14 21:26:56 +02:00
$record -> write ();
2008-02-25 03:10:37 +01:00
if ( ( $record -> class != 'VirtualPage' ) && $originalURLSegment != $record -> URLSegment ) {
$message .= sprintf ( _t ( 'LeftAndMain.CHANGEDURL' , " Changed URL to '%s' " ), $record -> URLSegment );
FormResponse :: add ( " \$ ('Form_EditForm').elements.URLSegment.value = \" $record->URLSegment\ " ; " );
FormResponse :: add ( " \$ ('Form_EditForm_StageURLSegment').value = \" { $record -> URLSegment } \" ; " );
}
2007-09-16 17:02:57 +02:00
// If the 'Save & Publish' button was clicked, also publish the page
if ( isset ( $urlParams [ 'publish' ]) && $urlParams [ 'publish' ] == 1 ) {
$this -> performPublish ( $record );
2007-09-25 23:58:42 +02:00
2007-10-08 00:13:50 +02:00
$record -> setClassName ( $record -> ClassName );
$newClass = $record -> ClassName ;
$publishedRecord = $record -> newClassInstance ( $newClass );
2007-09-25 23:58:42 +02:00
2007-09-16 17:02:57 +02:00
return $this -> tellBrowserAboutPublicationChange ( $publishedRecord , " Published ' $record->Title ' successfully " );
} else {
// BUGFIX: Changed icon only shows after Save button is clicked twice http://support.silverstripe.com/gsoc/ticket/76
$title = Convert :: raw2js ( $record -> TreeTitle ());
FormResponse :: add ( " $ ('sitetree').setNodeTitle( \" $record->ID\ " , \ " $title\ " ); " );
$result .= $this -> getActionUpdateJS ( $record );
FormResponse :: status_message ( $message , " good " );
FormResponse :: update_status ( $record -> Status );
return FormResponse :: respond ();
}
2007-09-15 03:00:03 +02:00
}
2007-07-19 12:40:05 +02:00
}
2007-09-14 21:26:56 +02:00
2007-07-19 12:40:05 +02:00
/**
* Return a piece of javascript that will update the actions of the main form
*/
public function getActionUpdateJS ( $record ) {
// Get the new action buttons
2007-10-08 00:13:50 +02:00
2007-07-19 12:40:05 +02:00
$tempForm = $this -> getEditForm ( $record -> ID );
$actionList = '' ;
foreach ( $tempForm -> Actions () as $action ) {
$actionList .= $action -> Field () . ' ' ;
}
2007-09-14 21:26:56 +02:00
2007-07-19 12:40:05 +02:00
FormResponse :: add ( " $ ('Form_EditForm').loadActionsFromString(' " . Convert :: raw2js ( $actionList ) . " '); " );
2007-09-14 21:26:56 +02:00
2007-07-19 12:40:05 +02:00
return FormResponse :: respond ();
}
2007-09-14 21:26:56 +02:00
2007-07-19 12:40:05 +02:00
/**
* Return JavaScript code to generate a tree node for the given page , if visible
*/
2007-10-01 07:23:04 +02:00
public function addTreeNodeJS ( $page , $select = false ) {
2007-07-19 12:40:05 +02:00
$parentID = ( int ) $page -> ParentID ;
$title = Convert :: raw2js ( $page -> TreeTitle ());
$response = <<< JS
2007-10-01 07:23:04 +02:00
var newNode = $ ( 'sitetree' ) . createTreeNode ( $page -> ID , " $title " , " $page->class " );
var parentNode = $ ( 'sitetree' ) . getTreeNodeByIdx ( $parentID );
if ( parentNode ) parentNode . appendTreeNode ( newNode );
2007-07-19 12:40:05 +02:00
JS ;
2007-10-01 07:23:04 +02:00
$response .= ( $select ? " newNode.selectTreeNode(); \n " : " " ) ;
2007-07-19 12:40:05 +02:00
FormResponse :: add ( $response );
return FormResponse :: respond ();
}
/**
* Return JavaScript code to remove a tree node for the given page , if it exists .
*/
public function deleteTreeNodeJS ( $page ) {
2007-09-14 21:26:56 +02:00
$id = $page -> ID ? $page -> ID : $page -> OldID ;
2007-07-19 12:40:05 +02:00
$response = <<< JS
2007-09-14 21:26:56 +02:00
var node = $ ( 'sitetree' ) . getTreeNodeByIdx ( $id );
if ( node && node . parentTreeNode ) node . parentTreeNode . removeTreeNode ( node );
2007-07-19 12:40:05 +02:00
$ ( 'Form_EditForm' ) . closeIfSetTo ( $id );
JS ;
FormResponse :: add ( $response );
return FormResponse :: respond ();
}
2007-09-14 21:26:56 +02:00
/**
2007-07-19 12:40:05 +02:00
* Sets a static variable on this class which means the panel will be reloaded .
*/
static function ForceReload (){
self :: $ForceReload = true ;
}
2007-09-14 21:26:56 +02:00
2007-07-19 12:40:05 +02:00
/**
* Ajax handler for updating the parent of a tree node
*/
public function ajaxupdateparent () {
$id = $_REQUEST [ 'ID' ];
$parentID = $_REQUEST [ 'ParentID' ];
if ( $parentID == 'root' ){
2007-09-14 21:26:56 +02:00
$parentID = 0 ;
2007-07-19 12:40:05 +02:00
}
$_REQUEST [ 'ajax' ] = 1 ;
2007-09-14 21:26:56 +02:00
2007-07-19 12:40:05 +02:00
if ( is_numeric ( $id ) && is_numeric ( $parentID ) && $id != $parentID ) {
$node = DataObject :: get_by_id ( $this -> stat ( 'tree_class' ), $id );
if ( $node ){
$node -> ParentID = $parentID ;
$node -> Status = " Saved (update) " ;
$node -> write ();
2007-09-14 21:26:56 +02:00
2007-07-19 12:40:05 +02:00
if ( is_numeric ( $_REQUEST [ 'CurrentlyOpenPageID' ])) {
$currentPage = DataObject :: get_by_id ( $this -> stat ( 'tree_class' ), $_REQUEST [ 'CurrentlyOpenPageID' ]);
if ( $currentPage ) {
$cleanupJS = $currentPage -> cmsCleanup_parentChanged ();
}
}
2007-09-14 21:26:56 +02:00
2007-09-15 22:21:13 +02:00
FormResponse :: status_message ( _t ( 'LeftAndMain.SAVED' , 'saved' ), 'good' );
2007-07-19 12:40:05 +02:00
FormResponse :: add ( $cleanupJS );
2007-09-14 21:26:56 +02:00
2007-07-19 12:40:05 +02:00
} else {
2007-09-15 22:21:13 +02:00
FormResponse :: status_message ( _t ( 'LeftAndMain.PLEASESAVE' , " Please Save Page: This page could not be upated because it hasn't been saved yet. " ), " good " );
2007-07-19 12:40:05 +02:00
}
2007-09-14 21:26:56 +02:00
2007-07-19 12:40:05 +02:00
return FormResponse :: respond ();
} else {
user_error ( " Error in ajaxupdateparent request; id= $id , parentID= $parentID " , E_USER_ERROR );
}
}
2007-09-14 21:26:56 +02:00
2007-07-19 12:40:05 +02:00
/**
* Ajax handler for updating the order of a number of tree nodes
* $_GET [ ID ] : An array of node ids in the correct order
* $_GET [ MovedNodeID ] : The node that actually got moved
*/
public function ajaxupdatesort () {
$className = $this -> stat ( 'tree_class' );
$counter = 0 ;
$js = '' ;
$_REQUEST [ 'ajax' ] = 1 ;
2007-09-14 21:26:56 +02:00
2007-07-19 12:40:05 +02:00
if ( is_array ( $_REQUEST [ 'ID' ])) {
2007-10-02 07:10:35 +02:00
if ( $_REQUEST [ 'MovedNodeID' ] == 0 ){ //Sorting root
$movedNode = DataObject :: get ( $className , " `ParentID`=0 " );
} else {
$movedNode = DataObject :: get_by_id ( $className , $_REQUEST [ 'MovedNodeID' ]);
}
2007-07-19 12:40:05 +02:00
foreach ( $_REQUEST [ 'ID' ] as $id ) {
if ( $id == $movedNode -> ID ) {
$movedNode -> Sort = ++ $counter ;
$movedNode -> Status = " Saved (update) " ;
$movedNode -> write ();
2007-09-14 21:26:56 +02:00
2007-07-19 12:40:05 +02:00
$title = Convert :: raw2js ( $movedNode -> TreeTitle ());
$js .= " $ ('sitetree').setNodeTitle( $movedNode->ID , \" $title\ " ) \n " ;
2007-09-14 21:26:56 +02:00
2007-07-19 12:40:05 +02:00
// Nodes that weren't "actually moved" shouldn't be registered as having been edited; do a direct SQL update instead
} else if ( is_numeric ( $id )) {
++ $counter ;
DB :: query ( " UPDATE ` $className ` SET `Sort` = $counter WHERE `ID` = ' $id ' " );
}
}
// Virtual pages require selected to be null if the page is the same.
FormResponse :: add (
" if( $ ('sitetree').selected && $ ('sitetree').selected[0]) {
var idx = $ ( 'sitetree' ) . selected [ 0 ] . getIdx ();
if ( idx ){
$ ( 'Form_EditForm' ) . getPageFromServer ( idx );
}
} \n " . $js
);
2007-09-15 22:21:13 +02:00
FormResponse :: status_message ( _t ( 'LeftAndMain.SAVED' ), 'good' );
2007-07-19 12:40:05 +02:00
} else {
2007-09-15 22:21:13 +02:00
FormResponse :: error ( _t ( 'LeftAndMain.REQUESTERROR' , " Error in request " ));
2007-07-19 12:40:05 +02:00
}
2007-09-14 21:26:56 +02:00
2007-07-19 12:40:05 +02:00
return FormResponse :: respond ();
}
/**
* Delete a number of items
*/
public function deleteitems () {
$ids = split ( ' *, *' , $_REQUEST [ 'csvIDs' ]);
2007-09-14 21:26:56 +02:00
2007-07-19 12:40:05 +02:00
$script = " st = \$ ('sitetree'); \n " ;
foreach ( $ids as $id ) {
if ( is_numeric ( $id )) {
DataObject :: delete_by_id ( $this -> stat ( 'tree_class' ), $id );
$script .= " node = st.getTreeNodeByIdx( $id ); if(node) node.parentTreeNode.removeTreeNode(node); $ ('Form_EditForm').closeIfSetTo( $id ); \n " ;
}
}
FormResponse :: add ( $script );
2007-09-14 21:26:56 +02:00
2007-07-19 12:40:05 +02:00
return FormResponse :: respond ();
}
2007-09-14 21:26:56 +02:00
2007-07-19 12:40:05 +02:00
public function EditForm () {
$id = isset ( $_REQUEST [ 'ID' ]) ? $_REQUEST [ 'ID' ] : $this -> currentPageID ();
if ( $id ) return $this -> getEditForm ( $id );
}
2007-09-27 22:56:55 +02:00
public function myprofile () {
$form = $this -> Member_ProfileForm ();
return $this -> customise ( array (
'Form' => $form
)) -> renderWith ( 'BlankPage' );
}
public function Member_ProfileForm () {
return new Member_ProfileForm ( $this , 'Member_ProfileForm' , Member :: currentUser ());
}
2007-09-14 21:26:56 +02:00
2007-07-19 12:40:05 +02:00
public function printable () {
$id = $_REQUEST [ 'ID' ] ? $_REQUEST [ 'ID' ] : $this -> currentPageID ();
2007-09-14 21:26:56 +02:00
2007-07-19 12:40:05 +02:00
if ( $id ) $form = $this -> getEditForm ( $id );
$form -> transform ( new PrintableTransformation ());
$form -> actions = null ;
2007-09-14 21:26:56 +02:00
2007-07-19 12:40:05 +02:00
Requirements :: clear ();
Requirements :: css ( 'cms/css/LeftAndMain_printable.css' );
return array (
" PrintForm " => $form
);
}
2007-09-14 21:26:56 +02:00
2007-07-19 12:40:05 +02:00
public function currentPageID () {
if ( isset ( $_REQUEST [ 'ID' ]) && is_numeric ( $_REQUEST [ 'ID' ])) {
return $_REQUEST [ 'ID' ];
2007-08-08 03:16:02 +02:00
} elseif ( isset ( $this -> urlParams [ 'ID' ]) && is_numeric ( $this -> urlParams [ 'ID' ])) {
2007-07-19 12:40:05 +02:00
return $this -> urlParams [ 'ID' ];
} elseif ( Session :: get ( " { $this -> class } .currentPage " )) {
return Session :: get ( " { $this -> class } .currentPage " );
} else {
return null ;
}
}
2007-09-14 21:26:56 +02:00
2007-07-19 12:40:05 +02:00
public function setCurrentPageID ( $id ) {
Session :: set ( " { $this -> class } .currentPage " , $id );
}
2007-09-14 21:26:56 +02:00
2007-07-19 12:40:05 +02:00
public function currentPage () {
$id = $this -> currentPageID ();
if ( $id && is_numeric ( $id )) {
return DataObject :: get_by_id ( $this -> stat ( 'tree_class' ), $id );
}
}
2007-09-14 21:26:56 +02:00
2007-07-19 12:40:05 +02:00
public function isCurrentPage ( DataObject $page ) {
return $page -> ID == Session :: get ( " { $this -> class } .currentPage " );
}
2007-09-14 21:26:56 +02:00
2007-07-19 12:40:05 +02:00
/**
* Return the CMS ' s HTML - editor toolbar
*/
public function EditorToolbar () {
return new HtmlEditorField_Toolbar ( $this , " EditorToolbar " );
}
2007-09-14 21:26:56 +02:00
2007-07-19 12:40:05 +02:00
/**
* Return the version number of this application
*/
public function CMSVersion () {
$sapphireVersionFile = file_get_contents ( '../sapphire/silverstripe_version' );
$jspartyVersionFile = file_get_contents ( '../jsparty/silverstripe_version' );
$cmsVersionFile = file_get_contents ( '../cms/silverstripe_version' );
2007-09-14 21:26:56 +02:00
2007-07-19 12:40:05 +02:00
if ( strstr ( $sapphireVersionFile , " /sapphire/trunk " )) {
$sapphireVersion = " trunk " ;
} else {
preg_match ( " /sapphire \ /(?:(?:branches)|(?:tags))(?: \ /rc)? \ /([A-Za-z0-9._-]+) \ /silverstripe_version/ " , $sapphireVersionFile , $matches );
$sapphireVersion = $matches [ 1 ];
}
2007-09-14 21:26:56 +02:00
2007-07-19 12:40:05 +02:00
if ( strstr ( $jspartyVersionFile , " /jsparty/trunk " )) {
$jspartyVersion = " trunk " ;
} else {
preg_match ( " /jsparty \ /(?:(?:branches)|(?:tags))(?: \ /rc)? \ /([A-Za-z0-9._-]+) \ /silverstripe_version/ " , $jspartyVersionFile , $matches );
$jspartyVersion = $matches [ 1 ];
}
2007-09-14 21:26:56 +02:00
2007-07-19 12:40:05 +02:00
if ( strstr ( $cmsVersionFile , " /cms/trunk " )) {
$cmsVersion = " trunk " ;
} else {
preg_match ( " /cms \ /(?:(?:branches)|(?:tags))(?: \ /rc)? \ /([A-Za-z0-9._-]+) \ /silverstripe_version/ " , $cmsVersionFile , $matches );
$cmsVersion = $matches [ 1 ];
2007-09-14 21:26:56 +02:00
}
2007-07-19 12:40:05 +02:00
if ( $sapphireVersion == $jspartyVersion && $jspartyVersion == $cmsVersion ) {
return $sapphireVersion ;
} else {
return " cms: $cmsVersion , sapphire: $sapphireVersion , jsparty: $jspartyVersion " ;
}
}
/**
* The application name is customisable by calling
* LeftAndMain :: setApplicationName ( " Something New " )
2007-09-14 21:26:56 +02:00
*/
2007-11-02 04:10:31 +01:00
static $application_name = " SilverStripe CMS " , $application_logo_text = " SilverStripe " ;
2007-07-19 12:40:05 +02:00
static function setApplicationName ( $name , $logoText = null ) {
self :: $application_name = $name ;
self :: $application_logo_text = $logoText ? $logoText : $name ;
}
function ApplicationName () {
return self :: $application_name ;
}
function ApplicationLogoText () {
return self :: $application_logo_text ;
}
static $application_logo = " cms/images/mainmenu/logo.gif " , $application_logo_style = " " ;
2007-09-14 21:26:56 +02:00
2007-07-19 12:40:05 +02:00
static function setLogo ( $logo , $logoStyle ) {
self :: $application_logo = $logo ;
self :: $application_logo_style = $logoStyle ;
self :: $application_logo_text = " " ;
}
function LogoStyle () {
2008-02-25 03:10:37 +01:00
return " background: url( " . self :: $application_logo . " ) no-repeat; " . self :: $application_logo_style ;
2007-07-19 12:40:05 +02:00
}
/**
* Return the base directory of the tiny_mce codebase
*/
function MceRoot () {
return MCE_ROOT ;
}
2007-08-27 07:06:57 +02:00
/**
* Use this as an action handler for custom CMS buttons .
*/
function callPageMethod ( $data , $form ) {
$methodName = $form -> buttonClicked () -> extraData ();
$record = $this -> CurrentPage ();
return $record -> $methodName ( $data , $form );
}
2008-04-05 03:40:36 +02:00
2008-04-06 03:57:31 +02:00
/**
* Generate the default entries for the CMS main menu .
*/
public static function populate_default_menu () {
self :: add_menu_item (
" content " ,
_t ( 'LeftAndMain.SITECONTENT' , " Site Content " , PR_HIGH , " Menu title " ),
" admin/ " ,
" CMSMain "
);
self :: add_menu_item (
" files " ,
_t ( 'LeftAndMain.FILESIMAGES' , " Files & Images " , PR_HIGH , " Menu title " ),
" admin/assets/ " ,
" AssetAdmin "
);
if ( ReportAdmin :: has_reports ()) {
self :: add_menu_item (
" report " ,
_t ( 'LeftAndMain.REPORTS' , " Reports " , PR_HIGH , 'Menu title' ),
" admin/reports/ " ,
" ReportAdmin "
);
}
self :: add_menu_item (
" security " ,
_t ( 'LeftAndMain.SECURITY' , " Security " , PR_HIGH , 'Menu title' ),
" admin/security/ " ,
" SecurityAdmin "
);
self :: add_menu_item (
" comments " ,
_t ( 'LeftAndMain.COMMENTS' , " Comments " , PR_HIGH , 'Menu title' ),
" admin/comments/ " ,
" CommentAdmin "
);
self :: add_menu_item (
" help " ,
_t ( 'LeftAndMain.HELP' , " Help " , PR_HIGH , 'Menu title' ),
" http://userhelp.silverstripe.com "
);
}
2008-04-05 05:43:58 +02:00
/**
* Add a navigation item to the main administration menu showing in the top bar .
*
* @ param string $code Unique identifier for this menu item ( e . g . used by { @ link replace_menu_item ()} and
* { @ link remove_menu_item } . Also used as a CSS - class for icon customization .
* @ param string $menuTitle Localized title showing in the menu bar
* @ param string $url A relative URL that will be linked in the menu bar .
* Make sure to add a matching route via { @ link Director :: addRules ()} to this url .
* @ param string $controllerClass The controller class for this menu , used to check permisssions .
* If blank , it ' s assumed that this is public , and always shown to users who
* have the rights to access some other part of the admin area .
2008-04-06 03:57:31 +02:00
* @ return boolean Success
2008-04-05 05:43:58 +02:00
*/
public static function add_menu_item ( $code , $menuTitle , $url , $controllerClass = null ) {
$menuItems = singleton ( 'LeftAndMain' ) -> stat ( 'menu_items' , true );
2008-04-06 03:57:31 +02:00
if ( isset ( $menuItems [ $code ])) return false ;
/*
2008-04-05 05:43:58 +02:00
if ( isset ( $menuItems [ $code ])) {
user_error ( " LeftAndMain::add_menu_item(): A menu item with code ' { $menuItems } '
already exists , can ' t add it . Please use replace_menu_item () to explicitly replace it " ,
E_USER_ERROR
);
}
2008-04-06 03:57:31 +02:00
*/
2008-04-05 05:43:58 +02:00
2008-04-06 03:57:31 +02:00
return self :: replace_menu_item ( $code , $menuTitle , $url , $controllerClass );
}
/**
* Get a single menu item by its code value .
*
* @ param string $code
* @ return array
*/
public static function get_menu_item ( $code ) {
$menuItems = singleton ( 'LeftAndMain' ) -> stat ( 'menu_items' , true );
return ( isset ( $menuItems [ $code ])) ? $menuItems [ $code ] : false ;
}
/**
* Get all menu entries .
*
* @ return array
*/
public static function get_menu_items () {
return singleton ( 'LeftAndMain' ) -> stat ( 'menu_items' , true );
2008-04-05 05:43:58 +02:00
}
/**
* Removes an existing item from the menu .
*
* @ param string $code Unique identifier for this menu item
*/
public static function remove_menu_item ( $code ) {
$menuItems = singleton ( 'LeftAndMain' ) -> stat ( 'menu_items' , true );
if ( isset ( $menuItems [ $code ])) unset ( $menuItems [ $code ]);
// replace the whole array
Object :: addStaticVars (
'LeftAndMain' ,
array ( 'menu_items' => $menuItems ),
true
);
}
2008-04-06 03:57:31 +02:00
/**
* Clears the entire menu
*
*/
public static function clear_menu () {
Object :: addStaticVars (
'LeftAndMain' ,
array ( 'menu_items' => array ()),
true
);
}
2008-04-05 05:43:58 +02:00
/**
* Replace a navigation item to the main administration menu showing in the top bar .
*
* @ param string $code Unique identifier for this menu item ( e . g . used by { @ link replace_menu_item ()} and
* { @ link remove_menu_item } . Also used as a CSS - class for icon customization .
* @ param string $menuTitle Localized title showing in the menu bar
* @ param string $url A relative URL that will be linked in the menu bar .
* Make sure to add a matching route via { @ link Director :: addRules ()} to this url .
* @ param string $controllerClass The controller class for this menu , used to check permisssions .
* If blank , it ' s assumed that this is public , and always shown to users who
* have the rights to access some other part of the admin area .
2008-04-06 03:57:31 +02:00
* @ return boolean Success
2008-04-05 05:43:58 +02:00
*/
public static function replace_menu_item ( $code , $menuTitle , $url , $controllerClass = null ) {
$menuItems = singleton ( 'LeftAndMain' ) -> stat ( 'menu_items' , true );
$menuItems [ $code ] = array (
'title' => $menuTitle ,
'url' => $url ,
'controllerClass' => $controllerClass
);
Object :: addStaticVars (
'LeftAndMain' ,
array ( 'menu_items' => $menuItems ),
true
);
2008-04-06 03:57:31 +02:00
return true ;
2008-04-05 05:43:58 +02:00
}
2007-07-19 12:40:05 +02:00
}
2008-04-05 03:40:36 +02:00
?>