/** * Create a new subsite from the template and verify that all the template's pages are copied */ function testSubsiteCreation() { Subsite::$write_hostmap = false; // Create the instance $template = $this->objFromFixture('Subsite', 'main'); // Test that changeSubsite is working Subsite::changeSubsite($template->ID); $tmplStaff = $this->objFromFixture('Page', 'staff'); $tmplHome = DataObject::get_one('Page', "\"URLSegment\" = 'home'"); // Publish all the pages in the template, testing that DataObject::get only returns pages from the chosen subsite $pages = DataObject::get("SiteTree"); $totalPages = $pages->Count(); foreach ($pages as $page) { $this->assertEquals($template->ID, $page->SubsiteID); $page->publish('Stage', 'Live'); } // Create a new site $subsite = $template->duplicate(); // Check title $this->assertEquals($subsite->Title, $template->Title); // Another test that changeSubsite is working $subsite->activate(); $siteHome = DataObject::get_one('Page', "\"URLSegment\" = 'home'"); $this->assertNotEquals($siteHome, false, 'Home Page for subsite not found'); $this->assertEquals($subsite->ID, $siteHome->SubsiteID, 'createInstance() copies existing pages retaining the same URLSegment'); Subsite::changeSubsite(0); }
/** * Create a new subsite from the template and verify that all the template's pages are copied */ function testSubsiteCreation() { Subsite::$write_hostmap = false; // Create the instance $template = $this->objFromFixture('Subsite_Template', 'main'); // Test that changeSubsite is working Subsite::changeSubsite($template->ID); $tmplHome = DataObject::get_one('SiteTree', "\"URLSegment\" = 'home'"); // Publish all the pages in the template, testing that DataObject::get only returns pages from the chosen subsite $pages = DataObject::get("SiteTree"); $totalPages = $pages->TotalItems(); foreach ($pages as $page) { $this->assertEquals($template->ID, $page->SubsiteID); $page->publish('Stage', 'Live'); } // Create a new site $subsite = $template->createInstance('My Site', 'something.test.com'); // Check title $this->assertEquals($subsite->Title, 'My Site'); // Check that domain generation is working $this->assertEquals('something.test.com', $subsite->domain()); // Another test that changeSubsite is working $subsite->activate(); $siteHome = DataObject::get_one('SiteTree', "\"URLSegment\" = 'home'"); $this->assertNotNull($siteHome); $this->assertEquals($subsite->ID, $siteHome->SubsiteID, 'createInstance() copies existing pages retaining the same URLSegment'); $this->assertEquals($siteHome->MasterPageID, $tmplHome->ID, 'Check master page value'); // Check linking of child pages $tmplStaff = $this->objFromFixture('SiteTree', 'staff'); $siteStaff = DataObject::get_one('SiteTree', "\"URLSegment\" = '" . Convert::raw2sql($tmplStaff->URLSegment) . "'"); $this->assertEquals($siteStaff->MasterPageID, $tmplStaff->ID); Subsite::changeSubsite(0); }
function testWritingSubsiteID() { $this->objFromFixture('Member', 'admin')->logIn(); $subsite = $this->objFromFixture('Subsite', 'domaintest1'); FileSubsites::$default_root_folders_global = true; Subsite::changeSubsite(0); $file = new File(); $file->write(); $file->onAfterUpload(); $this->assertEquals((int) $file->SubsiteID, 0); Subsite::changeSubsite($subsite->ID); $this->assertTrue($file->canEdit()); $file = new File(); $file->write(); $this->assertEquals((int) $file->SubsiteID, 0); $this->assertTrue($file->canEdit()); FileSubsites::$default_root_folders_global = false; Subsite::changeSubsite($subsite->ID); $file = new File(); $file->write(); $this->assertEquals($file->SubsiteID, $subsite->ID); // Test inheriting from parent folder $folder = new Folder(); $folder->write(); $this->assertEquals($folder->SubsiteID, $subsite->ID); FileSubsites::$default_root_folders_global = true; $file = new File(); $file->ParentID = $folder->ID; $file->onAfterUpload(); $this->assertEquals($folder->SubsiteID, $file->SubsiteID); }
function testEachSubsiteHasAUniqueSiteConfig() { $subsite1 = $this->objFromFixture('Subsite', 'domaintest1'); $subsite2 = $this->objFromFixture('Subsite', 'domaintest2'); $this->assertTrue(is_array(singleton('SiteConfigSubsites')->extraStatics())); Subsite::changeSubsite(0); $sc = SiteConfig::current_site_config(); $sc->Title = 'RootSite'; $sc->write(); Subsite::changeSubsite($subsite1->ID); $sc = SiteConfig::current_site_config(); $sc->Title = 'Subsite1'; $sc->write(); Subsite::changeSubsite($subsite2->ID); $sc = SiteConfig::current_site_config(); $sc->Title = 'Subsite2'; $sc->write(); Subsite::changeSubsite(0); $this->assertEquals(SiteConfig::current_site_config()->Title, 'RootSite'); Subsite::changeSubsite($subsite1->ID); $this->assertEquals(SiteConfig::current_site_config()->Title, 'Subsite1'); Subsite::changeSubsite($subsite2->ID); $this->assertEquals(SiteConfig::current_site_config()->Title, 'Subsite2'); $keys = SiteConfig::current_site_config()->extend('cacheKeyComponent'); $this->assertContains('subsite-' . $subsite2->ID, $keys); }
function activateState($state) { if (Controller::has_curr()) { Subsite::changeSubsite($state); } else { // TODO: This is a nasty hack - calling Subsite::changeSubsite after request ends // throws error because no current controller to access session on $_REQUEST['SubsiteID'] = $state; } }
function run($request) { $subsiteFromId = $request->getVar('from'); if (!is_numeric($subsiteFromId)) { throw new InvalidArgumentException('Missing "from" parameter'); } $subsiteFrom = DataObject::get_by_id('Subsite', $subsiteFromId); if (!$subsiteFrom) { throw new InvalidArgumentException('Subsite not found'); } $subsiteToId = $request->getVar('to'); if (!is_numeric($subsiteToId)) { throw new InvalidArgumentException('Missing "to" parameter'); } $subsiteTo = DataObject::get_by_id('Subsite', $subsiteToId); if (!$subsiteTo) { throw new InvalidArgumentException('Subsite not found'); } $useVirtualPages = (bool) $request->getVar('virtual'); Subsite::changeSubsite($subsiteFrom); // Copy data from this template to the given subsite. Does this using an iterative depth-first search. // This will make sure that the new parents on the new subsite are correct, and there are no funny // issues with having to check whether or not the new parents have been added to the site tree // when a page, etc, is duplicated $stack = array(array(0, 0)); while (count($stack) > 0) { list($sourceParentID, $destParentID) = array_pop($stack); $children = Versioned::get_by_stage('SiteTree', 'Live', "\"ParentID\" = {$sourceParentID}", ''); if ($children) { foreach ($children as $child) { if ($useVirtualPages) { $childClone = new SubsitesVirtualPage(); $childClone->writeToStage('Stage'); $childClone->CopyContentFromID = $child->ID; $childClone->SubsiteID = $subsiteTo->ID; } else { $childClone = $child->duplicateToSubsite($subsiteTo->ID, true); } $childClone->ParentID = $destParentID; $childClone->writeToStage('Stage'); $childClone->publish('Stage', 'Live'); array_push($stack, array($child->ID, $childClone->ID)); $this->log(sprintf('Copied "%s" (#%d, %s)', $child->Title, $child->ID, $child->Link())); } } unset($children); } }
public function loadFixtures() { if (ClassInfo::exists('Subsite')) { $currentSubsite = Subsite::currentSubsiteID(); } foreach (self::$preload_fixtures as $desc) { $fixtureFile = $desc['file']; if (file_exists(Director::baseFolder() . '/' . $fixtureFile)) { $siteID = null; if (isset($desc['subsite'])) { $site = DataObject::get_one('Subsite', '"Title" = \'' . Convert::raw2sql($desc['subsite']) . '\''); if ($site && $site->ID) { $siteID = $site->ID; } if (!$siteID) { // no site, so just skip this file load continue; } } // need to disable the filter when running dev/build so that it actually searches // within the relevant subsite, not the 'current' one. if (ClassInfo::exists('Subsite')) { Subsite::$disable_subsite_filter = true; } $filter = $desc['filter'] . ($siteID ? ' AND "SubsiteID"=' . $siteID : ''); $existing = DataObject::get_one($desc['type'], $filter); if (ClassInfo::exists('Subsite')) { Subsite::$disable_subsite_filter = false; } if (!$existing) { if ($siteID) { Subsite::changeSubsite($siteID); } $fixture = new YamlFixture($fixtureFile); $fixture->saveIntoDatabase(); DB::alteration_message('YAML bootstrap loaded from ' . $fixtureFile, 'created'); } } } if (ClassInfo::exists('Subsite')) { Subsite::changeSubsite($currentSubsite); } }
function testAlternateAccessCheck() { $admin = $this->objFromFixture("Member", "admin"); $this->loginAs($admin); $ids = array(); $subsite1 = $this->objFromFixture('Subsite', 'domaintest1'); $subsite2 = $this->objFromFixture('Subsite', 'domaintest2'); $subsite3 = $this->objFromFixture('Subsite', 'domaintest3'); $ids[] = $subsite1->ID; $ids[] = $subsite2->ID; $ids[] = $subsite3->ID; $ids[] = 0; foreach ($ids as $id) { Subsite::changeSubsite($id); //switch to main site (subsite ID zero) $left = new LeftAndMain(); $this->assertTrue($left->canView(), "Admin user can view subsites LeftAndMain with id = '{$id}'"); $this->assertEquals($id, Subsite::currentSubsiteID(), "The current subsite has not been changed in the process of checking permissions for admin user."); } }
public function test_calc_directory_for_subsite() { //Template: $subsite = $this->objFromFixture('Subsite', 'main'); //check calculation $this->assertEquals('template', SubsiteUploadDirRules::calc_directory_for_subsite($subsite)); //check the generated folder Subsite::changeSubsite($subsite->ID); $this->assertEquals('template', SubsiteUploadDirRules::get_directory_for_current_subsite()); //Subsite1 Template: $subsite = $this->objFromFixture('Subsite', 'subsite1'); //check calculation $this->assertEquals('subsite1-template', SubsiteUploadDirRules::calc_directory_for_subsite($subsite)); //check the generated folder Subsite::changeSubsite($subsite->ID); $this->assertEquals('subsite1-template', SubsiteUploadDirRules::get_directory_for_current_subsite()); //Test 3: $subsite = $this->objFromFixture('Subsite', 'domaintest3'); //check calculation $this->assertEquals('test-3', SubsiteUploadDirRules::calc_directory_for_subsite($subsite)); //check the generated folder Subsite::changeSubsite($subsite->ID); $this->assertEquals('test-3', SubsiteUploadDirRules::get_directory_for_current_subsite()); Subsite::changeSubsite(0); // if (class_exists('Subsite') && Object::has_extension('Subsite', 'AssetsFolderExtension')) { // // $subsite = Subsite::get()->first(); // // // //Setting subsite via $_GET // //this is not bes practice, but this seems to be the only way that works // //when running this over the command line // // //Subsite::changeSubsite($subsite->ID); // $_GET['SubsiteID'] = $subsite->ID; // // $this->assertEquals('my-test-subsite', SubsiteUploadDirRules::calc_directory_for_subsite()); // } }
function testAdminIsRedirectedToObjectsSubsite() { $member = $this->objFromFixture('Member', 'admin'); Session::set("loggedInAs", $member->ID); $mainSubsitePage = $this->objFromFixture('Page', 'mainSubsitePage'); $subsite1Home = $this->objFromFixture('Page', 'subsite1_home'); Config::inst()->nest(); Config::inst()->update('CMSPageEditController', 'treats_subsite_0_as_global', false); Subsite::changeSubsite(0); $this->getAndFollowAll("admin/pages/edit/show/{$subsite1Home->ID}"); $this->assertEquals(Subsite::currentSubsiteID(), $subsite1Home->SubsiteID, 'Loading an object switches the subsite'); $this->assertRegExp("#^admin/pages.*#", $this->mainSession->lastUrl(), 'Lands on the correct section'); Config::inst()->update('CMSPageEditController', 'treats_subsite_0_as_global', true); Subsite::changeSubsite(0); $this->getAndFollowAll("admin/pages/edit/show/{$subsite1Home->ID}"); $this->assertEquals(Subsite::currentSubsiteID(), $subsite1Home->SubsiteID, 'Loading a non-main-site object still switches the subsite if configured with treats_subsite_0_as_global'); $this->assertRegExp("#^admin/pages.*#", $this->mainSession->lastUrl(), 'Lands on the correct section'); $this->getAndFollowAll("admin/pages/edit/show/{$mainSubsitePage->ID}"); $this->assertNotEquals(Subsite::currentSubsiteID(), $mainSubsitePage->SubsiteID, 'Loading a main-site object does not change the subsite if configured with treats_subsite_0_as_global'); $this->assertRegExp("#^admin/pages.*#", $this->mainSession->lastUrl(), 'Lands on the correct section'); Config::inst()->unnest(); }
function testAccessChecksDontChangeCurrentSubsite() { $admin = $this->objFromFixture("Member", "admin"); $this->loginAs($admin); $ids = array(); $subsite1 = $this->objFromFixture('Subsite', 'domaintest1'); $subsite2 = $this->objFromFixture('Subsite', 'domaintest2'); $subsite3 = $this->objFromFixture('Subsite', 'domaintest3'); $ids[] = $subsite1->ID; $ids[] = $subsite2->ID; $ids[] = $subsite3->ID; $ids[] = 0; // Enable session-based subsite tracking. Subsite::$use_session_subsiteid = true; foreach ($ids as $id) { Subsite::changeSubsite($id); $this->assertEquals($id, Subsite::currentSubsiteID()); $left = new LeftAndMain(); $this->assertTrue($left->canView(), "Admin user can view subsites LeftAndMain with id = '{$id}'"); $this->assertEquals($id, Subsite::currentSubsiteID(), "The current subsite has not been changed in the process of checking permissions for admin user."); } }
/** * Create a duplicate of this page and save it to another subsite * @param $subsiteID int|Subsite The Subsite to copy to, or its ID */ public function duplicateToSubsite($subsiteID = null) { if (is_object($subsiteID)) { $subsite = $subsiteID; $subsiteID = $subsite->ID; } else { $subsite = DataObject::get_by_id('Subsite', $subsiteID); } $oldSubsite = Subsite::currentSubsiteID(); if ($subsiteID) { Subsite::changeSubsite($subsiteID); } else { $subsiteID = $oldSubsite; } $page = $this->owner->duplicate(false); $page->CheckedPublicationDifferences = $page->AddedToStage = true; $subsiteID = $subsiteID ? $subsiteID : $oldSubsite; $page->SubsiteID = $subsiteID; // MasterPageID is here for legacy purposes, to satisfy the subsites_relatedpages module $page->MasterPageID = $this->owner->ID; $page->write(); Subsite::changeSubsite($oldSubsite); return $page; }
function testPageTypesBlacklistInCMSMain() { $editor = $this->objFromFixture('Member', 'editor'); Session::set("loggedInAs", $editor->ID); $cmsmain = new CMSMain(); $s1 = $this->objFromFixture('Subsite', 'domaintest1'); $s2 = $this->objFromFixture('Subsite', 'domaintest2'); $s1->PageTypeBlacklist = 'SiteTreeSubsitesTest_ClassA,ErrorPage'; $s1->write(); Subsite::changeSubsite($s1); $hints = Convert::json2array($cmsmain->SiteTreeHints()); $classes = $hints['Root']['disallowedChildren']; $this->assertContains('ErrorPage', $classes); $this->assertContains('SiteTreeSubsitesTest_ClassA', $classes); $this->assertNotContains('SiteTreeSubsitesTest_ClassB', $classes); Subsite::changeSubsite($s2); $hints = Convert::json2array($cmsmain->SiteTreeHints()); $classes = $hints['Root']['disallowedChildren']; $this->assertNotContains('ErrorPage', $classes); $this->assertNotContains('SiteTreeSubsitesTest_ClassA', $classes); $this->assertNotContains('SiteTreeSubsitesTest_ClassB', $classes); }
/** * 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; }
/** * Similar to {@link SiteTreeSubsitesTest->testTwoPagesWithSameURLOnDifferentSubsites()} * and {@link SiteTreeSubsitesTest->testPagesInDifferentSubsitesCanShareURLSegment()}. */ function testSubsiteVirtualPageCanHaveSameUrlsegmentAsOtherSubsite() { Subsite::$write_hostmap = false; $subsite1 = $this->objFromFixture('Subsite', 'subsite1'); $subsite2 = $this->objFromFixture('Subsite', 'subsite2'); Subsite::changeSubsite($subsite1->ID); $subsite1Page = $this->objFromFixture('Page', 'subsite1_staff'); $subsite1Page->URLSegment = 'staff'; $subsite1Page->write(); // saving on subsite1, and linking to subsite1 $subsite1Vp = new SubsitesVirtualPage(); $subsite1Vp->CopyContentFromID = $subsite1Page->ID; $subsite1Vp->SubsiteID = $subsite1->ID; $subsite1Vp->write(); $this->assertNotEquals($subsite1Vp->URLSegment, $subsite1Page->URLSegment, "Doesn't allow explicit URLSegment overrides when already existing in same subsite"); //Change to subsite 2 Subsite::changeSubsite($subsite2->ID); // saving in subsite2 (which already has a page with URLSegment 'contact-us'), // but linking to a page in subsite1 $subsite2Vp = new SubsitesVirtualPage(); $subsite2Vp->CopyContentFromID = $subsite1Page->ID; $subsite2Vp->SubsiteID = $subsite2->ID; $subsite2Vp->write(); $this->assertEquals($subsite2Vp->URLSegment, $subsite1Page->URLSegment, "Does allow explicit URLSegment overrides when only existing in a different subsite"); }
/** * Return an existing member with administrator privileges, or create one of necessary. * * Will create a default 'Administrators' group if no group is found * with an ADMIN permission. Will create a new 'Admin' member with administrative permissions * if no existing Member with these permissions is found. * * Important: Any newly created administrator accounts will NOT have valid * login credentials (Email/Password properties), which means they can't be used for login * purposes outside of any default credentials set through {@link Security::setDefaultAdmin()}. * * @return Member */ public static function findAnAdministrator() { // coupling to subsites module $origSubsite = null; if (is_callable('Subsite::changeSubsite')) { $origSubsite = Subsite::currentSubsiteID(); Subsite::changeSubsite(0); } $member = null; // find a group with ADMIN permission $adminGroup = Permission::get_groups_by_permission('ADMIN')->First(); if (is_callable('Subsite::changeSubsite')) { Subsite::changeSubsite($origSubsite); } if ($adminGroup) { $member = $adminGroup->Members()->First(); } if (!$adminGroup) { singleton('Group')->requireDefaultRecords(); $adminGroup = Permission::get_groups_by_permission('ADMIN')->First(); } if (!$member) { singleton('Member')->requireDefaultRecords(); $member = Permission::get_members_by_permission('ADMIN')->First(); } if (!$member) { $member = Member::default_admin(); } if (!$member) { // Failover to a blank admin $member = Member::create(); $member->FirstName = _t('Member.DefaultAdminFirstname', 'Default Admin'); $member->write(); // Add member to group instead of adding group to member // This bypasses the privilege escallation code in Member_GroupSet $adminGroup->DirectMembers()->add($member); } return $member; }
/** * Return an existing member with administrator privileges, or create one of necessary. * * Will create a default 'Administrators' group if no group is found * with an ADMIN permission. Will create a new 'Admin' member with administrative permissions * if no existing Member with these permissions is found. * * Important: Any newly created administrator accounts will NOT have valid * login credentials (Email/Password properties), which means they can't be used for login * purposes outside of any default credentials set through {@link Security::setDefaultAdmin()}. * * @return Member */ static function findAnAdministrator() { // coupling to subsites module $origSubsite = null; if (is_callable('Subsite::changeSubsite')) { $origSubsite = Subsite::currentSubsiteID(); Subsite::changeSubsite(0); } $member = null; // find a group with ADMIN permission $adminGroup = DataObject::get('Group', "\"Permission\".\"Code\" = 'ADMIN'", "\"Group\".\"ID\"", "JOIN \"Permission\" ON \"Group\".\"ID\"=\"Permission\".\"GroupID\"", '1')->First(); if (is_callable('Subsite::changeSubsite')) { Subsite::changeSubsite($origSubsite); } if ($adminGroup) { $member = $adminGroup->Members()->First(); } if (!$adminGroup) { singleton('Group')->requireDefaultRecords(); } if (!$member) { singleton('Member')->requireDefaultRecords(); $member = Permission::get_members_by_permission('ADMIN')->First(); } return $member; }
/** * Make this subsite the current one */ public function activate() { Subsite::changeSubsite($this); }
function testUnpublishingParentPageUnpublishesSubsiteVirtualPages() { StaticPublisher::$disable_realtime = true; // Go to main site, get parent page $subsite = $this->objFromFixture('Subsite_Template', 'main'); Subsite::changeSubsite($subsite->ID); $page = $this->objFromFixture('SiteTree', 'importantpage'); // Create two SVPs on other subsites $subsite = $this->objFromFixture('Subsite_Template', 'subsite1'); Subsite::changeSubsite($subsite->ID); $vp1 = new SubsitesVirtualPage(); $vp1->CopyContentFromID = $page->ID; $vp1->write(); $vp1->doPublish(); $subsite = $this->objFromFixture('Subsite_Template', 'subsite2'); Subsite::changeSubsite($subsite->ID); $vp2 = new SubsitesVirtualPage(); $vp2->CopyContentFromID = $page->ID; $vp2->write(); $vp2->doPublish(); // Switch back to main site, unpublish source $subsite = $this->objFromFixture('Subsite_Template', 'main'); Subsite::changeSubsite($subsite->ID); $page = $this->objFromFixture('SiteTree', 'importantpage'); $page->doUnpublish(); Subsite::changeSubsite($vp1->SubsiteID); $onLive = Versioned::get_one_by_stage('SubsitesVirtualPage', 'Live', "\"SiteTree_Live\".\"ID\" = " . $vp1->ID); $this->assertFalse($onLive, 'SVP has been removed from live'); $subsite = $this->objFromFixture('Subsite_Template', 'subsite2'); Subsite::changeSubsite($vp2->SubsiteID); $onLive = Versioned::get_one_by_stage('SubsitesVirtualPage', 'Live', "\"SiteTree_Live\".\"ID\" = " . $vp2->ID); $this->assertFalse($onLive, 'SVP has been removed from live'); }
/** * 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; }
/** * Return an existing member with administrator privileges, or create one of necessary. * * Will create a default 'Administrators' group if no group is found * with an ADMIN permission. Will create a new 'Admin' member with administrative permissions * if no existing Member with these permissions is found. * * Important: Any newly created administrator accounts will NOT have valid * login credentials (Email/Password properties), which means they can't be used for login * purposes outside of any default credentials set through {@link Security::setDefaultAdmin()}. * * @return Member */ public static function findAnAdministrator() { // coupling to subsites module $origSubsite = null; if (is_callable('Subsite::changeSubsite')) { $origSubsite = Subsite::currentSubsiteID(); Subsite::changeSubsite(0); } $member = null; // find a group with ADMIN permission $adminGroup = DataObject::get('Group')->where(array('"Permission"."Code"' => 'ADMIN'))->sort('"Group"."ID"')->innerJoin("Permission", '"Group"."ID" = "Permission"."GroupID"')->First(); if (is_callable('Subsite::changeSubsite')) { Subsite::changeSubsite($origSubsite); } if ($adminGroup) { $member = $adminGroup->Members()->First(); } if (!$adminGroup) { singleton('Group')->requireDefaultRecords(); } if (!$member) { singleton('Member')->requireDefaultRecords(); $member = Permission::get_members_by_permission('ADMIN')->First(); } return $member; }
/** * This function ensures the file table is correct with the files in the assets folder. * * If a Folder record ID is given, all of that folder's children will be synchronised. * If the given Folder ID isn't found, or not specified at all, then everything will * be synchronised from the root folder (singleton Folder). * * See {@link File->updateFilesystem()} to sync properties of a single database record * back to the equivalent filesystem record. * * @param int $folderID Folder ID to sync along with all it's children * @param Boolean $syncLinkTracking Determines if the link tracking data should also * be updated via {@link SiteTree->syncLinkTracking()}. Setting this to FALSE * means that broken links inside page content are not noticed, at least until the next * call to {@link SiteTree->write()} on this page. * @return string Localized status message */ public static function sync($folderID = null, $syncLinkTracking = true) { $folder = DataObject::get_by_id('Folder', (int) $folderID); if (!($folder && $folder->exists())) { $folder = singleton('Folder'); } $results = $folder->syncChildren(); $finished = false; while (!$finished) { $orphans = DB::query("SELECT \"C\".\"ID\" FROM \"File\" AS \"C\" \n\t\t\t\tLEFT JOIN \"File\" AS \"P\" ON \"C\".\"ParentID\" = \"P\".\"ID\" \n\t\t\t\tWHERE \"P\".\"ID\" IS NULL AND \"C\".\"ParentID\" > 0"); $finished = true; if ($orphans) { foreach ($orphans as $orphan) { $finished = false; // Delete the database record but leave the filesystem alone $file = DataObject::get_by_id("File", $orphan['ID']); $file->deleteDatabaseOnly(); unset($file); } } } // Update the image tracking of all pages if ($syncLinkTracking) { if (class_exists('SiteTree')) { // if subsites exist, go through each subsite and sync each subsite's pages. // disabling the filter doesn't work reliably, because writing pages that share // the same URLSegment between subsites will break, e.g. "home" between two // sites will modify one of them to "home-2", thinking it's a duplicate. The // check before a write is done in SiteTree::validURLSegment() if (class_exists('Subsite')) { // loop through each subsite ID, changing the subsite, then query it's pages foreach (Subsite::get()->getIDList() as $id) { Subsite::changeSubsite($id); foreach (SiteTree::get() as $page) { // syncLinkTracking is called by SiteTree::onBeforeWrite(). // Call it without affecting the page version, as this is an internal change. $page->writeWithoutVersion(); } } // change back to the main site so the foreach below works Subsite::changeSubsite(0); } foreach (SiteTree::get() as $page) { // syncLinkTracking is called by SiteTree::onBeforeWrite(). // Call it without affecting the page version, as this is an internal change. $page->writeWithoutVersion(); } } } return _t('Filesystem.SYNCRESULTS', 'Sync complete: {createdcount} items created, {deletedcount} items deleted', array('createdcount' => (int) $results['added'], 'deletedcount' => (int) $results['deleted'])); }
/** * Process all jobs from a given queue * * @param string $name The job queue to completely process */ public function processJobQueue($name) { // Start timer to measure lifetime $this->markStarted(); // Begin main loop do { if (class_exists('Subsite')) { // clear subsite back to default to prevent any subsite changes from leaking to // subsequent actions Subsite::changeSubsite(0); } if (Controller::has_curr()) { Session::clear('loggedInAs'); } else { unset($_SESSION['loggedInAs']); } if (class_exists('SecurityContext')) { singleton('SecurityContext')->setMember(null); } $job = $this->getNextPendingJob($name); if ($job) { $success = $this->runJob($job->ID); if (!$success) { // make sure job is null so it doesn't continue the current // processing loop. Next queue executor can pick up where // things left off $job = null; } } } while ($job); }
function testTwoPagesWithSameURLOnDifferentSubsites() { // Set up a couple of pages with the same URL on different subsites $s1 = $this->objFromFixture('Subsite', 'domaintest1'); $s2 = $this->objFromFixture('Subsite', 'domaintest2'); $p1 = new SiteTree(); $p1->Title = $p1->URLSegment = "test-page"; $p1->SubsiteID = $s1->ID; $p1->write(); $p2 = new SiteTree(); $p2->Title = $p1->URLSegment = "test-page"; $p2->SubsiteID = $s2->ID; $p2->write(); // Check that the URLs weren't modified in our set-up $this->assertEquals($p1->URLSegment, 'test-page'); $this->assertEquals($p2->URLSegment, 'test-page'); // Check that if we switch between the different subsites, we receive the correct pages Subsite::changeSubsite($s1); $this->assertEquals($p1->ID, SiteTree::get_by_link('test-page')->ID); Subsite::changeSubsite($s2); $this->assertEquals($p2->ID, SiteTree::get_by_link('test-page')->ID); }