Пример #1
0
	public function testAdvancedMenuHandling() {
	
		// Populate from CMS Classes, check for existance of SecurityAdmin
		CMSMenu::clear_menu();
		CMSMenu::populate_menu();
		$menuItem = CMSMenu::get_menu_item('SecurityAdmin');
		$this->assertType('CMSMenuItem', $menuItem, 'SecurityAdmin menu item exists');
		$this->assertEquals($menuItem->url, singleton('SecurityAdmin')->Link(), 'Menu item has the correct link');
		$this->assertEquals($menuItem->controller, 'SecurityAdmin', 'Menu item has the correct controller class');
		$this->assertEquals(
			$menuItem->priority, 
			singleton('SecurityAdmin')->stat('menu_priority'), 
			'Menu item has the correct priority'
		);		
		
		// Check that menu order is correct by priority
		// Note this will break if populate_menu includes normal links (ie, as not controller)
		$menuItems = CMSMenu::get_menu_items();
		$priority = 9999; // ok, *could* be set larger, but shouldn't need to be!
		foreach($menuItems as $menuItem) {
			$this->assertEquals(
				$menuItem->priority, 
				singleton($menuItem->controller)->stat('menu_priority'), 
				"Menu item $menuItem->title has the correct priority"
			);			
			$this->assertLessThanOrEqual($priority, $menuItem->priority, 'Menu item is of lower or equal priority');
		}
	}
 /**
  * Alternative security checker for LeftAndMain.
  * If security isn't found, then it will switch to a subsite where we do have access.
  */
 public function alternateAccessCheck()
 {
     $className = $this->owner->class;
     // Switch to the subsite of the current page
     if ($this->owner->class == 'CMSMain' && ($currentPage = $this->owner->currentPage())) {
         if (Subsite::currentSubsiteID() != $currentPage->SubsiteID) {
             Subsite::changeSubsite($currentPage->SubsiteID);
         }
     }
     // Switch to a subsite that this user can actually access.
     $member = Member::currentUser();
     if ($member && $member->isAdmin()) {
         return true;
     }
     //admin can access all subsites
     $sites = Subsite::accessible_sites("CMS_ACCESS_{$this->owner->class}")->toDropdownMap();
     if ($sites && !isset($sites[Subsite::currentSubsiteID()])) {
         $siteIDs = array_keys($sites);
         Subsite::changeSubsite($siteIDs[0]);
         return true;
     }
     // Switch to a different top-level menu item
     $menu = CMSMenu::get_menu_items();
     foreach ($menu as $candidate) {
         if ($candidate->controller != $this->owner->class) {
             $sites = Subsite::accessible_sites("CMS_ACCESS_{$candidate->controller}")->toDropdownMap();
             if ($sites && !isset($sites[Subsite::currentSubsiteID()])) {
                 $siteIDs = array_keys($sites);
                 Subsite::changeSubsite($siteIDs[0]);
                 $cClass = $candidate->controller;
                 $cObj = new $cClass();
                 Director::redirect($cObj->Link());
                 return null;
             }
         }
     }
     // If all of those fail, you really don't have access to the CMS
     return null;
 }
 /**
  * Redirect the user to something accessible if the current section/subsite is forbidden.
  *
  * This is done via onBeforeInit as it needs to be done before the LeftAndMain::init has a
  * chance to forbids access via alternateAccessCheck.
  *
  * If we need to change the subsite we force the redirection to /admin/ so the frontend is
  * fully re-synchronised with the internal session. This is better than risking some panels
  * showing data from another subsite.
  */
 public function onBeforeInit()
 {
     // We are accessing the CMS, so we need to let Subsites know we will be using the session.
     Subsite::$use_session_subsiteid = true;
     // FIRST, check if we need to change subsites due to the URL.
     // Catch forced subsite changes that need to cause CMS reloads.
     if (isset($_GET['SubsiteID'])) {
         // Clear current page when subsite changes (or is set for the first time)
         if (!Session::get('SubsiteID') || $_GET['SubsiteID'] != Session::get('SubsiteID')) {
             Session::clear("{$this->owner->class}.currentPage");
         }
         // Update current subsite in session
         Subsite::changeSubsite($_GET['SubsiteID']);
         //Redirect to clear the current page
         if ($this->owner->canView(Member::currentUser())) {
             //Redirect to clear the current page
             return $this->owner->redirect($this->owner->Link());
         }
         //Redirect to the default CMS section
         return $this->owner->redirect('admin/');
     }
     // Automatically redirect the session to appropriate subsite when requesting a record.
     // This is needed to properly initialise the session in situations where someone opens the CMS via a link.
     $record = $this->owner->currentPage();
     if ($record && isset($record->SubsiteID) && is_numeric($record->SubsiteID) && isset($this->owner->urlParams['ID'])) {
         if ($this->shouldChangeSubsite($this->owner->class, $record->SubsiteID, Subsite::currentSubsiteID())) {
             // Update current subsite in session
             Subsite::changeSubsite($record->SubsiteID);
             if ($this->owner->canView(Member::currentUser())) {
                 //Redirect to clear the current page
                 return $this->owner->redirect($this->owner->getRequest()->getURL());
             }
             //Redirect to the default CMS section
             return $this->owner->redirect('admin/');
         }
     }
     // SECOND, check if we need to change subsites due to lack of permissions.
     if (!$this->owner->canAccess()) {
         $member = Member::currentUser();
         // Current section is not accessible, try at least to stick to the same subsite.
         $menu = CMSMenu::get_menu_items();
         foreach ($menu as $candidate) {
             if ($candidate->controller && $candidate->controller != $this->owner->class) {
                 $accessibleSites = singleton($candidate->controller)->sectionSites($member);
                 if ($accessibleSites->count() && $accessibleSites->find('ID', Subsite::currentSubsiteID())) {
                     // Section is accessible, redirect there.
                     return $this->owner->redirect(singleton($candidate->controller)->Link());
                 }
             }
         }
         // If no section is available, look for other accessible subsites.
         foreach ($menu as $candidate) {
             if ($candidate->controller) {
                 $accessibleSites = singleton($candidate->controller)->sectionSites($member);
                 if ($accessibleSites->count()) {
                     Subsite::changeSubsite($accessibleSites->First()->ID);
                     return $this->owner->redirect(singleton($candidate->controller)->Link());
                 }
             }
         }
         // We have not found any accessible section or subsite. User should be denied access.
         return Security::permissionFailure($this->owner);
     }
     // Current site is accessible. Allow through.
     return;
 }