allFixtureIDs(SiteConfig::class); if ($ids) { foreach (SiteConfig::get()->exclude('ID', $ids) as $config) { $config->delete(); } } } public function testSiteTreeHints() { $cache = Injector::inst()->get(CacheInterface::class . '.CMSMain_SiteTreeHints'); // Login as user with root creation privileges $user = $this->objFromFixture(Member::class, 'rootedituser'); Security::setCurrentUser($user); $cache->clear(); $rawHints = singleton(CMSMain::class)->SiteTreeHints(); $this->assertNotNull($rawHints); $rawHints = preg_replace('/^"(.*)"$/', '$1', Convert::xml2raw($rawHints) ?? ''); $hints = json_decode($rawHints ?? '', true); $this->assertArrayHasKey('Root', $hints); $this->assertArrayHasKey('Page', $hints); $this->assertArrayHasKey('All', $hints); $this->assertArrayHasKey( CMSMainTest_ClassA::class, $hints['All'], 'Global list shows allowed classes' ); $this->assertArrayNotHasKey( CMSMainTest_HiddenClass::class, $hints['All'], 'Global list does not list hidden classes' ); $this->assertNotContains( CMSMainTest_ClassA::class, $hints['Root']['disallowedChildren'], 'Limits root classes' ); $this->assertContains( CMSMainTest_NotRoot::class, $hints['Root']['disallowedChildren'], 'Limits root classes' ); } public function testChildFilter() { $this->logInWithPermission('ADMIN'); // Check page A $pageA = new CMSMainTest_ClassA(); $pageA->write(); $pageB = new CMSMainTest_ClassB(); $pageB->write(); // Check query $response = $this->get('admin/pages/childfilter?ParentID=' . $pageA->ID); $children = json_decode($response->getBody() ?? ''); $this->assertFalse($response->isError()); // Page A can't have unrelated children $this->assertContains( 'Page', $children, 'Limited parent lists disallowed classes' ); // But it can create a ClassB $this->assertNotContains( CMSMainTest_ClassB::class, $children, 'Limited parent omits explicitly allowed classes in disallowedChildren' ); } /** * @todo Test the results of a publication better */ public function testPublish() { if (Deprecation::isEnabled()) { $this->markTestSkipped('Test calls deprecated code'); } $page1 = $this->objFromFixture(Page::class, "page1"); $page2 = $this->objFromFixture(Page::class, "page2"); $this->logInAs('admin'); $response = $this->get('admin/pages/publishall?confirm=1'); $this->assertStringContainsString( 'Done: Published 30 pages', $response->getBody() ); // Some modules (e.g., cmsworkflow) will remove this action $actions = CMSBatchActionHandler::config()->batch_actions; if (isset($actions['publish'])) { $response = $this->get('admin/pages/batchactions/publish?ajax=1&csvIDs=' . implode(',', [$page1->ID, $page2->ID])); $responseData = json_decode($response->getBody() ?? '', true); $this->assertArrayHasKey($page1->ID, $responseData['modified']); $this->assertArrayHasKey($page2->ID, $responseData['modified']); } // Get the latest version of the redirector page $pageID = $this->idFromFixture(RedirectorPage::class, 'page5'); $latestID = DB::prepared_query('select max("Version") from "RedirectorPage_Versions" where "RecordID" = ?', [$pageID])->value(); $dsCount = DB::prepared_query('select count("Version") from "RedirectorPage_Versions" where "RecordID" = ? and "Version"= ?', [$pageID, $latestID])->value(); $this->assertEquals(1, $dsCount, "Published page has no duplicate version records: it has " . $dsCount . " for version " . $latestID); } /** * Test that getCMSFields works on each page type. * Mostly, this is just checking that the method doesn't return an error */ public function testThatGetCMSFieldsWorksOnEveryPageType() { $classes = ClassInfo::subclassesFor(SiteTree::class); array_shift($classes); foreach ($classes as $class) { $page = new $class(); if ($page instanceof TestOnly) { continue; } if (!$page->config()->get('can_be_root')) { continue; } $page->Title = "Test $class page"; $page->write(); $page->flushCache(); $page = DataObject::get_by_id(SiteTree::class, $page->ID); $this->assertTrue($page->getCMSFields() instanceof FieldList); } } public function testCanPublishPageWithUnpublishedParentWithStrictHierarchyOff() { $this->logInWithPermission('ADMIN'); Config::modify()->set(SiteTree::class, 'enforce_strict_hierarchy', true); $parentPage = $this->objFromFixture(Page::class, 'page3'); $childPage = $this->objFromFixture(Page::class, 'page1'); $parentPage->doUnpublish(); $childPage->doUnpublish(); $actions = $childPage->getCMSActions()->dataFields(); $this->assertArrayHasKey( 'action_publish', $actions, 'Can publish a page with an unpublished parent with strict hierarchy off' ); Config::modify()->set(SiteTree::class, 'enforce_strict_hierarchy', false); } /** * Test that a draft-deleted page can still be opened in the CMS */ public function testDraftDeletedPageCanBeOpenedInCMS() { $this->logInWithPermission('ADMIN'); // Set up a page that is delete from live $page = $this->objFromFixture(Page::class, 'page1'); $pageID = $page->ID; $page->publishRecursive(); $page->delete(); $response = $this->get('admin/pages/edit/show/' . $pageID); $livePage = Versioned::get_one_by_stage(SiteTree::class, Versioned::LIVE, [ '"SiteTree"."ID"' => $pageID ]); $this->assertInstanceOf(SiteTree::class, $livePage); $this->assertTrue($livePage->canDelete()); // Check that the 'restore' button exists as a simple way of checking that the correct page is returned. $this->assertMatchesRegularExpression('/