array(), 'css' => array(), 'themedcss' => array(), ); function init() { Director::set_site_mode('cms'); // set language $member = Member::currentUser(); if(!empty($member->Locale)) { i18n::set_locale($member->Locale); } // set reading lang if(Translatable::is_enabled() && !Director::is_ajax()) { Translatable::choose_site_lang(array_keys(i18n::get_existing_content_languages('SiteTree'))); } parent::init(); // 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 $menu = $this->MainMenu(); if(($first = $menu->First()) && $first->Link) { Director::redirect($first->Link); } } } // Don't continue if there's already been a redirection request. if(Director::redirected_to()) return; // Access failure! if(!$isAllowed) { $messageSet = array( '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."), ); Security::permissionFailure($this, $messageSet); return; } // Audit logging hook if(empty($_REQUEST['executeForm']) && !Director::is_ajax()) $this->extend('accessedCMS'); Requirements::css(CMS_DIR . '/css/typography.css'); Requirements::css(CMS_DIR . '/css/layout.css'); Requirements::css(CMS_DIR . '/css/cms_left.css'); Requirements::css(CMS_DIR . '/css/cms_right.css'); if(isset($_REQUEST['debug_firebug'])) { // Firebug is a useful console for debugging javascript // Its available as a Firefox extension or a javascript library // for easy inclusion in other browsers (just append ?debug_firebug=1 to the URL) Requirements::javascript(THIRDPARTY_DIR . '/firebug/firebug-lite-compressed.js'); } else { // By default, we include fake-objects for all firebug calls // to avoid javascript errors when referencing console.log() etc in javascript code Requirements::javascript(THIRDPARTY_DIR . '/firebug/firebugx.js'); } Requirements::javascript(THIRDPARTY_DIR . '/prototype.js'); Requirements::javascript(THIRDPARTY_DIR . '/jquery/jquery.js'); Requirements::javascript(THIRDPARTY_DIR . '/behaviour.js'); Requirements::javascript(THIRDPARTY_DIR . '/prototype_improvements.js'); Requirements::javascript(THIRDPARTY_DIR . '/loader.js'); Requirements::javascript(THIRDPARTY_DIR . '/hover.js'); Requirements::javascript(THIRDPARTY_DIR . '/layout_helpers.js'); Requirements::javascript(SAPPHIRE_DIR . "/javascript/i18n.js"); Requirements::javascript(MCE_ROOT . 'tiny_mce_src.js'); Requirements::javascript(CMS_DIR . '/javascript/ImageEditor/Activator.js'); Requirements::javascript(THIRDPARTY_DIR . '/tiny_mce_improvements.js'); Requirements::javascript(THIRDPARTY_DIR . '/scriptaculous/effects.js'); Requirements::javascript(THIRDPARTY_DIR . '/scriptaculous/dragdrop.js'); Requirements::javascript(THIRDPARTY_DIR . '/scriptaculous/controls.js'); Requirements::css(THIRDPARTY_DIR . '/greybox/greybox.css'); Requirements::javascript(THIRDPARTY_DIR . '/greybox/AmiJS.js'); Requirements::javascript(THIRDPARTY_DIR . '/greybox/greybox.js'); Requirements::javascript(THIRDPARTY_DIR . '/tree/tree.js'); Requirements::css(THIRDPARTY_DIR . '/tree/tree.css'); Requirements::javascript(THIRDPARTY_DIR . '/tabstrip/tabstrip.js'); Requirements::css(THIRDPARTY_DIR . '/tabstrip/tabstrip.css'); Requirements::css(CMS_DIR . '/css/TinyMCEImageEnhancement.css'); Requirements::javascript(CMS_DIR . '/javascript/TinyMCEImageEnhancement.js'); Requirements::javascript(CMS_DIR . '/javascript/LeftAndMain.js'); Requirements::javascript(CMS_DIR . '/javascript/LeftAndMain_left.js'); Requirements::javascript(CMS_DIR . '/javascript/LeftAndMain_right.js'); Requirements::css(SAPPHIRE_DIR . '/css/Form.css'); Requirements::javascript(CMS_DIR . '/javascript/ForumAdmin.js'); Requirements::javascript(CMS_DIR . '/javascript/SideTabs.js'); Requirements::javascript(CMS_DIR . '/javascript/TaskList.js'); Requirements::javascript(CMS_DIR . '/javascript/CommentList.js'); Requirements::javascript(CMS_DIR . '/javascript/SideReports.js'); Requirements::javascript(CMS_DIR . '/javascript/LangSelector.js'); Requirements::javascript(CMS_DIR . '/javascript/TranslationTab.js'); Requirements::javascript(SAPPHIRE_DIR . '/javascript/Validator.js'); Requirements::javascript(SAPPHIRE_DIR . '/javascript/UniqueFields.js'); Requirements::javascript(SAPPHIRE_DIR . '/javascript/RedirectorPage.js'); Requirements::javascript(SAPPHIRE_DIR . '/javascript/ToggleCompositeField.js'); Requirements::css(SAPPHIRE_DIR . '/css/SubmittedFormReportField.css'); Requirements::css(SAPPHIRE_DIR . '/css/TableListField.css'); Requirements::css(SAPPHIRE_DIR . '/css/ComplexTableField.css'); Requirements::javascript(SAPPHIRE_DIR . '/javascript/TableListField.js'); Requirements::javascript(SAPPHIRE_DIR . '/javascript/TableField.js'); Requirements::javascript(SAPPHIRE_DIR . '/javascript/ComplexTableField.js'); Requirements::javascript(SAPPHIRE_DIR . '/javascript/RelationComplexTableField.js'); Requirements::css(SAPPHIRE_DIR . '/css/TreeDropdownField.css'); Requirements::css(SAPPHIRE_DIR . '/css/CheckboxSetField.css'); Requirements::javascript(THIRDPARTY_DIR . '/calendar/calendar.js'); Requirements::javascript(THIRDPARTY_DIR . '/calendar/lang/calendar-en.js'); Requirements::javascript(THIRDPARTY_DIR . '/calendar/calendar-setup.js'); Requirements::css(SAPPHIRE_DIR . '/css/CalendarDateField.css'); Requirements::css(THIRDPARTY_DIR . '/calendar/calendar-win2k-1.css'); Requirements::javascript(SAPPHIRE_DIR . '/javascript/DropdownTimeField.js'); Requirements::css(SAPPHIRE_DIR . '/css/DropdownTimeField.css'); Requirements::css(SAPPHIRE_DIR . '/css/PopupDateTimeField.css'); Requirements::javascript(SAPPHIRE_DIR . '/javascript/SelectionGroup.js'); Requirements::css(SAPPHIRE_DIR . '/css/SelectionGroup.css'); Requirements::javascript(THIRDPARTY_DIR . '/SWFUpload/SWFUpload.js'); Requirements::javascript(CMS_DIR . '/javascript/Upload.js'); Requirements::javascript(SAPPHIRE_DIR . '/javascript/HasManyFileField.js'); Requirements::css(SAPPHIRE_DIR . '/css/HasManyFileField.css'); Requirements::themedCSS('typography'); // For Widgets Requirements::css(CMS_DIR . '/css/WidgetAreaEditor.css'); Requirements::javascript(CMS_DIR . '/javascript/WidgetAreaEditor.js'); Requirements::javascript(SAPPHIRE_DIR . "/javascript/Security_login.js"); foreach (self::$extra_requirements['javascript'] as $file) { Requirements::javascript($file[0]); } foreach (self::$extra_requirements['css'] as $file) { Requirements::css($file[0], $file[1]); } foreach (self::$extra_requirements['themedcss'] as $file) { Requirements::css($file[0], $file[1]); } Requirements::customScript('Behaviour.addLoader(hideLoading);'); $dummy = null; $this->extend('augmentInit', $dummy); } //------------------------------------------------------------------------------------------// // Main controllers /** * You should implement a Link() function in your subclass of LeftAndMain, * to point to the URL of that particular controller. * * @return string */ public function Link() { user_error('LeftAndMain::Link(): Please implement in your subclass', E_USER_ERROR); } public function show($params) { if($params['ID']) $this->setCurrentPageID($params['ID']); if(isset($params['OtherID'])) Session::set('currentMember', $params['OtherID']); if(Director::is_ajax()) { SSViewer::setOption('rewriteHashlinks', false); return $this->EditForm()->formHtmlContent(); } else { return array(); } } 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. $form = $this->EditForm(); if($form) return $form->formHtmlContent(); else return ""; } public function getLastFormIn($html) { $parts = split(']*>', $html); return $parts[sizeof($parts)-2]; } //------------------------------------------------------------------------------------------// // Main UI components /** * Returns the main menu of the CMS. This is also used by init() to work out which sections the user * has access to. * * @return DataObjectSet */ 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 $menu = new DataObjectSet(); 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']); } else { $isAllowed = true; } if(!$isAllowed) continue; $linkingmode = ""; if(!(strpos($this->Link(), $menuItem['url']) === false)) { // HACK Hardcoding assumptions about the first default menu item if($code == "content") { if($this->Link() == "admin/") $linkingmode = "current"; } else { $linkingmode = "current"; } } $menu->push(new ArrayData(array( "Title" => Convert::raw2xml($menuItem['title']), "Code" => $code, "Link" => $menuItem['url'], "LinkingMode" => $linkingmode ))); } // if no current item is found, assume that first item is shown //if(!isset($foundCurrent)) return $menu; } /** * Return a list of appropriate templates for this class, with the given suffix */ protected function getTemplatesWithSuffix($suffix) { $classes = array_reverse(ClassInfo::ancestry($this->class)); foreach($classes as $class) { $templates[] = $class . $suffix; if($class == 'LeftAndMain') break; } return $templates; } 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')); } } 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); // getChildrenAsUL is a flexible and complex way of traversing the tree $siteTree = $obj->getChildrenAsUL("", ' "
  • ID\" class=\"" . $child->CMSTreeClasses($extraArg) . "\">" . "Link(),0,-1), "show", $child->ID) . "\" class=\"" . $child->CMSTreeClasses($extraArg) . "\" title=\"' . _t('LeftAndMain.PAGETYPE','Page type: ') . '".$child->class."\" >" . ($child->TreeTitle()) . "" ' ,$this, true); // Wrap the root if needs be. if(!$rootID) { $rootLink = $this->Link() . '0'; // This lets us override the tree title with an extension if($this->hasMethod('getCMSTreeTitle')) $treeTitle = $this->getCMSTreeTitle(); else $treeTitle = _t('LeftAndMain.SITECONTENTLEFT',"Site Content",PR_HIGH,'Root node on left'); $siteTree = ""; } return $siteTree; } public function getsubtree() { $results = $this->getSiteTreeFor($this->stat('tree_class'), $_REQUEST['ID']); return substr(trim($results), 4,-5); } /** * Allows you to returns a new data object to the tree (subclass of sitetree) * and updates the tree via javascript. */ public function returnItemToUser($p) { if(Director::is_ajax()) { // Prepare the object for insertion. $parentID = (int)$p->ParentID; $id = $p->ID ? $p->ID : "new-$p->class-$p->ParentID"; $treeTitle = Convert::raw2js($p->TreeTitle()); $hasChildren = is_numeric( $id ) && $p->AllChildren() ? ' unexpanded' : ''; // Ensure there is definitly a node avaliable. if not, append to the home tree. $response = <<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(); } /** * Save and Publish page handler */ public function save($urlParams, $form) { $className = $this->stat('tree_class'); $result = ''; $SQL_id = Convert::raw2sql($_REQUEST['ID']); if(substr($SQL_id,0,3) != 'new') { $record = DataObject::get_one($className, "`$className`.ID = {$SQL_id}"); } else { $record = $this->getNewItem($SQL_id, false); } // We don't want to save a new version if there are no changes $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()])) { $hasNonRecordFields = true; } // 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)"; } FormResponse::status_message(_t('LeftAndMain.SAVEDUP',"Saved"), "good"); FormResponse::update_status($record->Status); return FormResponse::respond(); } $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); if(is_a($record, "Page")) { $record->Status = ($record->Status == "New page" || $record->Status == "Saved (new)") ? "Saved (new)" : "Saved (update)"; } // $record->write(); if(Director::is_ajax()) { if($SQL_id != $record->ID) { FormResponse::add("$('sitetree').setNodeIdx(\"{$SQL_id}\", \"$record->ID\");"); 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\");"); } } } $message = _t('LeftAndMain.SAVEDUP'); // Update the icon if the class has changed if($originalClass != $record->ClassName) { $record->setClassName( $record->ClassName ); $newClass = $record->ClassName; $record = $record->newClassInstance( $newClass ); FormResponse::add("if(\$('sitetree').setNodeIcon) \$('sitetree').setNodeIcon($record->ID, '$originalClass', '$record->ClassName');"); } // HACK: This should be turned into somethign more general if( ($record->class == 'VirtualPage' && $originalURLSegment != $record->URLSegment) || ($originalClass != $record->ClassName) || self::$ForceReload == true) { FormResponse::add("$('Form_EditForm').getPageFromServer($record->ID);"); } // After reloading action if($originalStatus != $record->Status) { $message .= sprintf(_t('LeftAndMain.STATUSTO'," Status changed to '%s'"),$record->Status); } $record->write(); 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}\";"); } // If the 'Save & Publish' button was clicked, also publish the page if (isset($urlParams['publish']) && $urlParams['publish'] == 1) { $record->doPublish(); $record->setClassName($record->ClassName); $newClass = $record->ClassName; $publishedRecord = $record->newClassInstance($newClass); 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(); } } } /** * Return a piece of javascript that will update the actions of the main form */ public function getActionUpdateJS($record) { // Get the new action buttons $tempForm = $this->getEditForm($record->ID); $actionList = ''; foreach($tempForm->Actions() as $action) { $actionList .= $action->Field() . ' '; } FormResponse::add("$('Form_EditForm').loadActionsFromString('" . Convert::raw2js($actionList) . "');"); return FormResponse::respond(); } /** * Return JavaScript code to generate a tree node for the given page, if visible */ public function addTreeNodeJS($page, $select = false) { $parentID = (int)$page->ParentID; $title = Convert::raw2js($page->TreeTitle()); $response = <<ID, "$title", "$page->class"); var parentNode = $('sitetree').getTreeNodeByIdx($parentID); if(parentNode) parentNode.appendTreeNode(newNode); JS; $response .= ($select ? "newNode.selectTreeNode();\n" : "") ; 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) { $id = $page->ID ? $page->ID : $page->OldID; $response = <<stat('tree_class'), $id); if($node){ $node->ParentID = $parentID; $node->Status = "Saved (update)"; $node->write(); if(is_numeric($_REQUEST['CurrentlyOpenPageID'])) { $currentPage = DataObject::get_by_id($this->stat('tree_class'), $_REQUEST['CurrentlyOpenPageID']); if($currentPage) { $cleanupJS = $currentPage->cmsCleanup_parentChanged(); } } FormResponse::status_message(_t('LeftAndMain.SAVED','saved'), 'good'); FormResponse::add($cleanupJS); }else{ FormResponse::status_message(_t('LeftAndMain.PLEASESAVE',"Please Save Page: This page could not be upated because it hasn't been saved yet."),"good"); } return FormResponse::respond(); } else { user_error("Error in ajaxupdateparent request; id=$id, parentID=$parentID", E_USER_ERROR); } } /** * 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; if(is_array($_REQUEST['ID'])) { if($_REQUEST['MovedNodeID']==0){ //Sorting root $movedNode = DataObject::get($className, "`ParentID`=0"); }else{ $movedNode = DataObject::get_by_id($className, $_REQUEST['MovedNodeID']); } foreach($_REQUEST['ID'] as $id) { if($id == $movedNode->ID) { $movedNode->Sort = ++$counter; $movedNode->Status = "Saved (update)"; $movedNode->write(); $title = Convert::raw2js($movedNode->TreeTitle()); $js .="$('sitetree').setNodeTitle($movedNode->ID, \"$title\");\n"; // 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 ); FormResponse::status_message(_t('LeftAndMain.SAVED'), 'good'); } else { FormResponse::error(_t('LeftAndMain.REQUESTERROR',"Error in request")); } return FormResponse::respond(); } /** * Delete a number of items */ public function deleteitems() { $ids = split(' *, *', $_REQUEST['csvIDs']); $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); return FormResponse::respond(); } public function EditForm() { $id = isset($_REQUEST['ID']) ? $_REQUEST['ID'] : $this->currentPageID(); if($id) return $this->getEditForm($id); } 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()); } public function printable() { $id = $_REQUEST['ID'] ? $_REQUEST['ID'] : $this->currentPageID(); if($id) $form = $this->getEditForm($id); $form->transform(new PrintableTransformation()); $form->actions = null; Requirements::clear(); Requirements::css(CMS_DIR . '/css/LeftAndMain_printable.css'); return array( "PrintForm" => $form ); } public function currentPageID() { if(isset($_REQUEST['ID']) && is_numeric($_REQUEST['ID'])) { return $_REQUEST['ID']; } elseif (isset($this->urlParams['ID']) && is_numeric($this->urlParams['ID'])) { return $this->urlParams['ID']; } elseif(Session::get("{$this->class}.currentPage")) { return Session::get("{$this->class}.currentPage"); } else { return null; } } public function setCurrentPageID($id) { Session::set("{$this->class}.currentPage", $id); } public function currentPage() { $id = $this->currentPageID(); if($id && is_numeric($id)) { return DataObject::get_by_id($this->stat('tree_class'), $id); } } public function isCurrentPage(DataObject $page) { return $page->ID == Session::get("{$this->class}.currentPage"); } /** * Return the CMS's HTML-editor toolbar */ public function EditorToolbar() { return Object::create('HtmlEditorField_Toolbar', $this, "EditorToolbar"); } /** * 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'); 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]; } 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]; } 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]; } if($sapphireVersion == $jspartyVersion && $jspartyVersion == $cmsVersion) { return $sapphireVersion; } else { return "cms: $cmsVersion, sapphire: $sapphireVersion, jsparty: $jspartyVersion"; } } /** * The application name. Customisable by calling * LeftAndMain::setApplicationName() - the first parameter. * * @var String */ static $application_name = 'SilverStripe CMS'; /** * The application logo text. Customisable by calling * LeftAndMain::setApplicationName() - the second parameter. * * @var String */ static $application_logo_text = 'SilverStripe'; /** * Set the application name, and the logo text. * * @param String $name The application name * @param String $logoText The logo text */ static $application_link = "http://www.silverstripe.com/"; static function setApplicationName($name, $logoText = null, $link = null) { self::$application_name = $name; self::$application_logo_text = $logoText ? $logoText : $name; if($link) self::$application_link = $link; } /** * Get the application name. * @return String */ function getApplicationName() { return self::$application_name; } /** * Get the application logo text. * @return String */ function getApplicationLogoText() { return self::$application_logo_text; } function ApplicationLink() { return self::$application_link; } /** * Return the title of the current section, as shown on the main menu */ function SectionTitle() { // Get menu - use obj() to cache it in the same place as the template engine $menu = $this->obj('MainMenu'); foreach($menu as $menuItem) { if($menuItem->LinkingMode == 'current') return $menuItem->Title; } } /** * The application logo path. Customisable by calling * LeftAndMain::setLogo() - the first parameter. * * @var unknown_type */ static $application_logo = 'cms/images/mainmenu/logo.gif'; /** * The application logo style. Customisable by calling * LeftAndMain::setLogo() - the second parameter. * * @var String */ static $application_logo_style = ''; /** * Set the CMS application logo. * * @param String $logo Relative path to the logo * @param String $logoStyle Custom CSS styles for the logo * e.g. "border: 1px solid red; padding: 5px;" */ static function setLogo($logo, $logoStyle) { self::$application_logo = $logo; self::$application_logo_style = $logoStyle; self::$application_logo_text = ''; } protected static $loading_image = 'cms/images/loading.gif'; /** * Set the image shown when the CMS is loading. */ static function set_loading_image($loadingImage) { self::$loading_image = $loadingImage; } function LoadingImage() { return self::$loading_image; } function LogoStyle() { return "background: url(" . self::$application_logo . ") no-repeat; " . self::$application_logo_style; } /** * Return the base directory of the tiny_mce codebase */ function MceRoot() { return MCE_ROOT; } /** * 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); } /** * 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" ); 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" ); } /** * 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. * @return boolean Success */ public static function add_menu_item($code, $menuTitle, $url, $controllerClass = null) { $menuItems = singleton('LeftAndMain')->stat('menu_items', true); if(isset($menuItems[$code])) return false; /* 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 ); } */ 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); } /** * 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 ); } /** * Clears the entire menu * */ public static function clear_menu() { Object::addStaticVars( 'LeftAndMain', array('menu_items' => array()), true ); } /** * 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. * @return boolean Success */ 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 ); return true; } /** * Register the given javascript file as required in the CMS. * Filenames should be relative to the base, eg, SAPPHIRE_DIR . '/javascript/loader.js' */ public static function require_javascript($file) { self::$extra_requirements['javascript'][] = array($file); } /** * Register the given stylesheet file as required. * * @param $file String Filenames should be relative to the base, eg, THIRDPARTY_DIR . '/tree/tree.css' * @param $media String Comma-separated list of media-types (e.g. "screen,projector") * @see http://www.w3.org/TR/REC-CSS2/media.html */ public static function require_css($file, $media = null) { self::$extra_requirements['css'][] = array($file, $media); } /** * Register the given "themeable stylesheet" as required. * Themeable stylesheets have globally unique names, just like templates and PHP files. * Because of this, they can be replaced by similarly named CSS files in the theme directory. * * @param $name String The identifier of the file. For example, css/MyFile.css would have the identifier "MyFile" * @param $media String Comma-separated list of media-types (e.g. "screen,projector") */ static function require_themed_css($name, $media = null) { self::$extra_requirements['themedcss'][] = array($name, $media); } } ?>