public function providePermissions()
 {
     $perms = array("CMS_ACCESS_LeftAndMain" => array('name' => _t('CMSMain.ACCESSALLINTERFACES', 'Access to all CMS sections'), 'category' => _t('Permission.CMS_ACCESS_CATEGORY', 'CMS Access'), 'help' => _t('CMSMain.ACCESSALLINTERFACESHELP', 'Overrules more specific access settings.'), 'sort' => -100));
     // Add any custom ModelAdmin subclasses. Can't put this on ModelAdmin itself
     // since its marked abstract, and needs to be singleton instanciated.
     foreach (ClassInfo::subclassesFor('SilverStripe\\Admin\\ModelAdmin') as $i => $class) {
         if ($class == 'SilverStripe\\Admin\\ModelAdmin') {
             continue;
         }
         if (ClassInfo::classImplements($class, 'SilverStripe\\Dev\\TestOnly')) {
             continue;
         }
         // Check if modeladmin has explicit required_permission_codes option.
         // If a modeladmin is namespaced you can apply this config to override
         // the default permission generation based on fully qualified class name.
         $code = $this->getRequiredPermissions();
         if (!$code) {
             continue;
         }
         // Get first permission if multiple specified
         if (is_array($code)) {
             $code = reset($code);
         }
         $title = LeftAndMain::menu_title($class);
         $perms[$code] = array('name' => _t('CMSMain.ACCESS', "Access to '{title}' section", "Item in permission selection identifying the admin section. Example: Access to 'Files & Images'", array('title' => $title)), 'category' => _t('Permission.CMS_ACCESS_CATEGORY', 'CMS Access'));
     }
     return $perms;
 }
 /**
  * A utility funciton to retrieve subclasses of a given class that
  * are instantiable (ie, not abstract) and have a valid menu title.
  *
  * Sorted by url_priority config.
  *
  * @todo A variation of this function could probably be moved to {@link ClassInfo}
  * @param string $root The root class to begin finding subclasses
  * @param boolean $recursive Look for subclasses recursively?
  * @param string $sort Name of config on which to sort. Can be 'menu_priority' or 'url_priority'
  * @return array Valid, unique subclasses
  */
 public static function get_cms_classes($root = null, $recursive = true, $sort = self::MENU_PRIORITY)
 {
     if (!$root) {
         $root = 'SilverStripe\\Admin\\LeftAndMain';
     }
     /** @todo Make these actual abstract classes */
     $abstractClasses = ['SilverStripe\\Admin\\LeftAndMain', 'SilverStripe\\CMS\\Controllers\\CMSMain'];
     $subClasses = array_values(ClassInfo::subclassesFor($root));
     foreach ($subClasses as $className) {
         if ($recursive && $className != $root) {
             $subClasses = array_merge($subClasses, array_values(ClassInfo::subclassesFor($className)));
         }
     }
     $subClasses = array_unique($subClasses);
     foreach ($subClasses as $key => $className) {
         // Remove abstract classes and LeftAndMain
         if (in_array($className, $abstractClasses) || ClassInfo::classImplements($className, 'SilverStripe\\Dev\\TestOnly')) {
             unset($subClasses[$key]);
         } else {
             // Separate conditional to avoid autoloading the class
             $classReflection = new ReflectionClass($className);
             if (!$classReflection->isInstantiable()) {
                 unset($subClasses[$key]);
             }
         }
     }
     // Sort by specified sorting config
     usort($subClasses, function ($a, $b) use($sort) {
         $priorityA = Config::inst()->get($a, $sort);
         $priorityB = Config::inst()->get($b, $sort);
         return $priorityB - $priorityA;
     });
     return $subClasses;
 }