Webylon 3.2 API Docs
  • Package
  • Class
  • Tree
  • Deprecated
  • Download
Version: current
  • 3.2
  • 3.1

Packages

  • 1c
    • exchange
      • catalog
  • auth
  • Booking
  • building
    • company
  • cart
    • shipping
    • steppedcheckout
  • Catalog
    • monument
  • cms
    • assets
    • batchaction
    • batchactions
    • bulkloading
    • comments
    • content
    • core
    • export
    • newsletter
    • publishers
    • reports
    • security
    • tasks
  • Dashboard
  • DataObjectManager
  • event
  • faq
  • forms
    • actions
    • core
    • fields-basic
    • fields-dataless
    • fields-datetime
    • fields-files
    • fields-formatted
    • fields-formattedinput
    • fields-relational
    • fields-structural
    • transformations
    • validators
  • googlesitemaps
  • guestbook
  • installer
  • newsletter
  • None
  • photo
    • gallery
  • PHP
  • polls
  • recaptcha
  • sapphire
    • api
    • bulkloading
    • control
    • core
    • cron
    • dev
    • email
    • fields-formattedinput
    • filesystem
    • formatters
    • forms
    • i18n
    • integration
    • misc
    • model
    • parsers
    • search
    • security
    • tasks
    • testing
    • tools
    • validation
    • view
    • widgets
  • seo
    • open
      • graph
  • sfDateTimePlugin
  • spamprotection
  • stealth
    • captha
  • subsites
  • userform
    • pagetypes
  • userforms
  • webylon
  • widgets

Classes

  • BigFilesReport
  • BrokenLinksReport
  • CMSMain
  • CMSMainMarkingFilter
  • CMSMenu
  • CMSMenuItem
  • CMSSiteTreeFilter
  • CMSSiteTreeFilter_ChangedPages
  • CMSSiteTreeFilter_DeletedPages
  • CMSSiteTreeFilter_Search
  • NonUsedFilesReport
  • RedirectorPage
  • RedirectorPage_Controller
  • SideReport_BrokenFiles
  • SideReport_BrokenLinks
  • SideReport_BrokenRedirectorPages
  • SideReport_BrokenVirtualPages
  • SideReport_EmptyPages
  • SideReport_RecentlyEdited
  • SideReport_ToDo
  • SideReportView
  • SideReportWrapper
  • SilverStripeNavigator
  • SilverStripeNavigatorItem
  • SilverStripeNavigatorItem_ArchiveLink
  • SilverStripeNavigatorItem_CMSLink
  • SilverStripeNavigatorItem_LiveLink
  • SilverStripeNavigatorItem_StageLink
  • WidgetAreaEditor
  1 <?php
  2 /**
  3  * The object manages the main CMS menu.
  4  * See {@link LeftAndMain::init()} for example usage.
  5  * 
  6  * @package cms
  7  * @subpackage content
  8  */
  9 class CMSMenu extends SS_Object implements IteratorAggregate, i18nEntityProvider
 10 {
 11     
 12     /**
 13      * An array of changes to be made to the menu items, in the order that the changes should be
 14      * applied.  Each item is a map in one of the two forms:
 15      *  - array('type' => 'add', 'item' => new CMSMenuItem(...) )
 16      *  - array('type' => 'remove', 'code' => 'codename' )
 17      */
 18     protected static $menu_item_changes = array();
 19     
 20     /**
 21      * Set to true if clear_menu() is called, to indicate that the default menu shouldn't be
 22      * included
 23      */
 24     protected static $menu_is_cleared = false;
 25 
 26     /**
 27      * Generate CMS main menu items by collecting valid 
 28      * subclasses of {@link LeftAndMain}
 29      */
 30     public static function populate_menu() {
 31         self::$menu_is_cleared = false;
 32     }
 33 
 34     /**
 35      * Add Director rules for all of the CMS controllers.
 36      */
 37     public static function add_director_rules() {
 38         array_map(array('self','add_director_rule_for_controller'), self::get_cms_classes());
 39     }
 40 
 41     /**
 42      * Add a LeftAndMain controller to the CMS menu.
 43      *
 44      * @param string $controllerClass The class name of the controller
 45      * @return The result of the operation
 46      * @todo A director rule is added when a controller link is added, but it won't be removed
 47      *          when the item is removed. Functionality needed in {@link Director}.
 48      */ 
 49     public static function add_controller($controllerClass) {
 50         if($menuItem = self::menuitem_for_controller($controllerClass)) {
 51             self::add_menu_item_obj($controllerClass, $menuItem);
 52         }
 53     }
 54     
 55     /**
 56      * Return a CMSMenuItem to add the given controller to the CMSMenu
 57      */
 58     protected static function menuitem_for_controller($controllerClass) {
 59         $urlBase      = SS_Object::get_static($controllerClass, 'url_base');
 60         $urlSegment   = SS_Object::get_static($controllerClass, 'url_segment');
 61         $menuPriority = SS_Object::get_static($controllerClass, 'menu_priority');
 62         
 63         // Don't add menu items defined the old way
 64         if($urlSegment === null && $controllerClass != "CMSMain") return;
 65 
 66         $link = Controller::join_links($urlBase, $urlSegment) . '/';
 67 
 68         // doesn't work if called outside of a controller context (e.g. in _config.php)
 69         // as the locale won't be detected properly. Use {@link LeftAndMain->MainMenu()} to update
 70         // titles for existing menu entries
 71         $defaultTitle = LeftAndMain::menu_title_for_class($controllerClass);
 72         $menuTitle = _t("{$controllerClass}.MENUTITLE", $defaultTitle);
 73 
 74         return new CMSMenuItem($menuTitle, $link, $controllerClass, $menuPriority);
 75     }
 76     
 77     /**
 78      * Add the appropriate Director rules for the given controller.
 79      */
 80     protected static function add_director_rule_for_controller($controllerClass) {
 81         $urlBase      = SS_Object::get_static($controllerClass, 'url_base');
 82         $urlSegment   = SS_Object::get_static($controllerClass, 'url_segment');
 83         $urlRule      = SS_Object::get_static($controllerClass, 'url_rule');
 84         $urlPriority  = SS_Object::get_static($controllerClass, 'url_priority');
 85         
 86         if($urlSegment || $controllerClass == "CMSMain") {
 87             $link = Controller::join_links($urlBase, $urlSegment) . '/';
 88         
 89             // Make director rule
 90             if($urlRule[0] == '/') $urlRule = substr($urlRule,1);
 91             $rule = $link . '/' . $urlRule; // the / will combine with the / on the end of $link to make a //
 92             Director::addRules($urlPriority, array(
 93                 $rule => $controllerClass
 94             ));
 95         }
 96     }
 97     
 98     /**
 99      * Add an arbitrary URL to the CMS menu.
100      *
101      * @param string $code A unique identifier (used to create a CSS ID and as it's key in {@link $menu_items}
102      * @param string $menuTitle The link's title in the CMS menu
103      * @param string $url The url of the link
104      * @param integer $priority The menu priority (sorting order) of the menu item.  Higher priorities will be further left.
105      * @return boolean The result of the operation.
106      */
107     public static function add_link($code, $menuTitle, $url, $priority = -1) {
108         return self::add_menu_item($code, $menuTitle, $url, null, $priority);
109     }
110     
111     /**
112      * Add a navigation item to the main administration menu showing in the top bar.
113      *
114      * uses {@link CMSMenu::$menu_items}
115      *
116      * @param string $code Unique identifier for this menu item (e.g. used by {@link replace_menu_item()} and
117      *                  {@link remove_menu_item}. Also used as a CSS-class for icon customization.
118      * @param string $menuTitle Localized title showing in the menu bar 
119      * @param string $url A relative URL that will be linked in the menu bar.
120      * @param string $controllerClass The controller class for this menu, used to check permisssions.  
121      *                  If blank, it's assumed that this is public, and always shown to users who 
122      *                  have the rights to access some other part of the admin area.
123      * @return boolean Success
124      */
125     public static function add_menu_item($code, $menuTitle, $url, $controllerClass = null, $priority = -1) {
126         // If a class is defined, then force the use of that as a code.  This helps prevent menu item duplication
127         if($controllerClass) $code = $controllerClass;
128         
129         return self::replace_menu_item($code, $menuTitle, $url, $controllerClass, $priority);
130     }
131     
132     /**
133      * Get a single menu item by its code value.
134      *
135      * @param string $code
136      * @return array
137      */
138     public static function get_menu_item($code) {
139         $menuItems = self::get_menu_items();
140         return (isset($menuItems[$code])) ? $menuItems[$code] : false; 
141     }
142     
143     /**
144      * Get all menu entries.
145      *
146      * @return array
147      */
148     public static function get_menu_items() {
149         $menuItems = array();
150 
151         // Set up default menu items
152         if(!self::$menu_is_cleared) {
153             $cmsClasses = self::get_cms_classes();
154             foreach($cmsClasses as $cmsClass) {
155                 $menuItem = self::menuitem_for_controller($cmsClass);
156                 if($menuItem) $menuItems[$cmsClass] = $menuItem;
157             }
158         }
159         
160         // Apply changes
161         foreach(self::$menu_item_changes as $change) {
162             switch($change['type']) {
163                 case 'add':
164                     $menuItems[$change['code']] = $change['item'];
165                     break;
166                 
167                 case 'remove':
168                     unset($menuItems[$change['code']]);
169                     break;
170                     
171                 default:
172                     user_error("Bad menu item change type {$change[type]}", E_USER_WARNING);
173             }
174         }
175         
176         // Sort menu items according to priority
177         $menuPriority = array();
178         $i = 0;
179         foreach($menuItems as $key => $menuItem) {
180             $i++;
181             // This funny litle formula ensures that the first item added with the same priority will be left-most.
182             $menuPriority[$key] = $menuItem->priority*100 - $i;
183         }
184         array_multisort($menuPriority, SORT_DESC, $menuItems);
185         
186         return $menuItems;
187     }
188     
189     /**
190      * Get all menu items that the passed member can view.
191      * Defaults to {@link Member::currentUser()}.
192      * 
193      * @param Member $member
194      * @return array
195      */
196     public static function get_viewable_menu_items($member = null) {
197         if(!$member && $member !== FALSE) {
198             $member = Member::currentUser();
199         }
200         
201         $viewableMenuItems = array();
202         $allMenuItems = self::get_menu_items();
203         if($allMenuItems) foreach($allMenuItems as $code => $menuItem) {
204             // exclude all items which have a controller to perform permission
205             // checks on
206             if($menuItem->controller && !singleton($menuItem->controller)->canView($member)) continue;
207             
208             $viewableMenuItems[$code] = $menuItem;
209         }
210         
211         return $viewableMenuItems;
212     }
213     
214     /**
215      * Removes an existing item from the menu.
216      *
217      * @param string $code Unique identifier for this menu item
218      */
219     public static function remove_menu_item($code) {
220         self::$menu_item_changes[] = array('type' => 'remove', 'code' => $code);
221     }
222     
223     /**
224      * Clears the entire menu
225      */
226     public static function clear_menu() {
227         self::$menu_item_changes = array();
228         self::$menu_is_cleared = true;
229     }
230 
231     /**
232      * Replace a navigation item to the main administration menu showing in the top bar.
233      *
234      * @param string $code Unique identifier for this menu item (e.g. used by {@link replace_menu_item()} and
235      *                  {@link remove_menu_item}. Also used as a CSS-class for icon customization.
236      * @param string $menuTitle Localized title showing in the menu bar 
237      * @param string $url A relative URL that will be linked in the menu bar.
238      *                  Make sure to add a matching route via {@link Director::addRules()} to this url.
239      * @param string $controllerClass The controller class for this menu, used to check permisssions.  
240      *                  If blank, it's assumed that this is public, and always shown to users who 
241      *                  have the rights to access some other part of the admin area.
242      * @return boolean Success
243      */
244     public static function replace_menu_item($code, $menuTitle, $url, $controllerClass = null, $priority = -1) {
245         self::$menu_item_changes[] = array(
246             'type' => 'add',
247             'code' => $code,
248             'item' => new CMSMenuItem($menuTitle, $url, $controllerClass, $priority),
249         );
250     }
251     
252     /**
253      * Add a previously built menuitem object to the menu
254      */
255     protected static function add_menu_item_obj($code, $cmsMenuItem) {
256         self::$menu_item_changes[] = array(
257             'type' => 'add',
258             'code' => $code,
259             'item' => $cmsMenuItem,
260         );
261     }
262 
263     /**
264      * A utility funciton to retrieve subclasses of a given class that
265      * are instantiable (ie, not abstract) and have a valid menu title.
266      *
267      * @todo A variation of this function could probably be moved to {@link ClassInfo}
268      * @param string $root The root class to begin finding subclasses
269      * @param boolean $recursive Look for subclasses recursively?
270      * @return array Valid, unique subclasses
271      */
272     public static function get_cms_classes($root = 'LeftAndMain', $recursive = true) {
273         $subClasses = array_values(ClassInfo::subclassesFor($root));
274         foreach($subClasses as $className) {
275             if($recursive && $className != $root) {
276                 $subClasses = array_merge($subClasses, array_values(ClassInfo::subclassesFor($className)));
277             }
278         }
279         $subClasses = array_unique($subClasses);
280         foreach($subClasses as $key => $className) {
281             // Remove abstract classes and LeftAndMain
282             $classReflection = new ReflectionClass($className);
283             if(
284                 !$classReflection->isInstantiable() 
285                 || 'LeftAndMain' == $className 
286                 || ClassInfo::classImplements($className, 'TestOnly')
287             ) {
288                 unset($subClasses[$key]);
289             }           
290         }
291         
292         return $subClasses;
293     }
294     
295     /**
296      * IteratorAggregate Interface Method.  Iterates over the menu items.
297      */
298     function getIterator() {
299         return new ArrayIterator(self::get_menu_items());
300     }
301 
302     /**
303      * Provide menu titles to the i18n entity provider
304      */
305     function provideI18nEntities() {
306         $cmsClasses = self::get_cms_classes();
307         $entities = array();
308         foreach($cmsClasses as $cmsClass) {
309             $defaultTitle = LeftAndMain::menu_title_for_class($cmsClass);
310             $ownerModule = i18n::get_owner_module($cmsClass);
311             $entities["{$cmsClass}.MENUTITLE"] = array($defaultTitle, PR_HIGH, 'Menu title', $ownerModule);
312         }
313         return $entities;
314     }
315 }
316 ?>
[Raise a SilverStripe Framework issue/bug](https://github.com/silverstripe/silverstripe-framework/issues/new)
- [Raise a SilverStripe CMS issue/bug](https://github.com/silverstripe/silverstripe-cms/issues/new)
- Please use the Silverstripe Forums to ask development related questions. -
Webylon 3.2 API Docs API documentation generated by ApiGen 2.8.0