From 848b7805e272a2774303f936fecf4a83136703b8 Mon Sep 17 00:00:00 2001 From: Ingo Schommer Date: Mon, 12 Apr 2010 02:33:46 +0000 Subject: [PATCH] API CHANGE: Added Hierarchy::numHistoricalChildren() and Versioned::get_including_deleted_query() API CHANGE: Added numChildrenMethod arg to getChildrenAsUL, markPartialTree, markChildren, markingFinished BUGFIX: Clear the bypassStaticCache cookie when you return to the live site. (from r91165) (from r96739) git-svn-id: svn://svn.silverstripe.com/silverstripe/open/modules/sapphire/trunk@102365 467b73ca-7a2a-4603-9d3b-597d59a354a9 --- core/model/Hierarchy.php | 28 +++++++++++++++++++--------- core/model/SiteTree.php | 3 ++- core/model/Versioned.php | 26 +++++++++++++++++++++----- tests/model/HierarchyTest.php | 10 ++++++++++ 4 files changed, 52 insertions(+), 15 deletions(-) diff --git a/core/model/Hierarchy.php b/core/model/Hierarchy.php index 4e5b8a444..1a15f8dee 100755 --- a/core/model/Hierarchy.php +++ b/core/model/Hierarchy.php @@ -37,9 +37,9 @@ class Hierarchy extends DataObjectDecorator { * @param int $minNodeCount * @return string */ - public function getChildrenAsUL($attributes = "", $titleEval = '"
  • " . $child->Title', $extraArg = null, $limitToMarked = false, $childrenMethod = "AllChildrenIncludingDeleted", $rootCall = true, $minNodeCount = 30) { + public function getChildrenAsUL($attributes = "", $titleEval = '"
  • " . $child->Title', $extraArg = null, $limitToMarked = false, $childrenMethod = "AllChildrenIncludingDeleted", $numChildrenMethod = "numChildren", $rootCall = true, $minNodeCount = 30) { if($limitToMarked && $rootCall) { - $this->markingFinished(); + $this->markingFinished($numChildrenMethod); } if($this->owner->hasMethod($childrenMethod)) { @@ -60,7 +60,7 @@ class Hierarchy extends DataObjectDecorator { if(!$limitToMarked || $child->isMarked()) { $foundAChild = true; $output .= eval("return $titleEval;") . "\n" . - $child->getChildrenAsUL("", $titleEval, $extraArg, $limitToMarked, $childrenMethod, false, $minNodeCount) . "
  • \n"; + $child->getChildrenAsUL("", $titleEval, $extraArg, $limitToMarked, $childrenMethod, $numChildrenMethod, false, $minNodeCount) . "\n"; } } @@ -83,7 +83,7 @@ class Hierarchy extends DataObjectDecorator { * @param int $minNodeCount The minimum amount of nodes to mark. * @return int The actual number of nodes marked. */ - public function markPartialTree($minNodeCount = 30, $context = null, $childrenMethod = "AllChildrenIncludingDeleted") { + public function markPartialTree($minNodeCount = 30, $context = null, $childrenMethod = "AllChildrenIncludingDeleted", $numChildrenMethod = "numChildren") { if(!is_numeric($minNodeCount)) $minNodeCount = 30; $this->markedNodes = array($this->owner->ID => $this->owner); @@ -91,7 +91,7 @@ class Hierarchy extends DataObjectDecorator { // foreach can't handle an ever-growing $nodes list while(list($id, $node) = each($this->markedNodes)) { - $this->markChildren($node, $context, $childrenMethod); + $this->markChildren($node, $context, $childrenMethod, $numChildrenMethod); if($minNodeCount && sizeof($this->markedNodes) >= $minNodeCount) { break; } @@ -154,7 +154,7 @@ class Hierarchy extends DataObjectDecorator { * Mark all children of the given node that match the marking filter. * @param DataObject $node Parent node. */ - public function markChildren($node, $context = null, $childrenMethod = "AllChildrenIncludingDeleted") { + public function markChildren($node, $context = null, $childrenMethod = "AllChildrenIncludingDeleted", $numChildrenMethod = "numChildren") { if($node->hasMethod($childrenMethod)) { $children = $node->$childrenMethod($context); } else { @@ -166,7 +166,7 @@ class Hierarchy extends DataObjectDecorator { if($children) { foreach($children as $child) { if(!$this->markingFilter || $this->markingFilterMatches($child)) { - if($child->numChildren()) { + if($child->$numChildrenMethod()) { $child->markUnexpanded(); } else { $child->markExpanded(); @@ -181,11 +181,11 @@ class Hierarchy extends DataObjectDecorator { * Ensure marked nodes that have children are also marked expanded. * Call this after marking but before iterating over the tree. */ - protected function markingFinished() { + protected function markingFinished($numChildrenMethod = "numChildren") { // Mark childless nodes as expanded. if($this->markedNodes) { foreach($this->markedNodes as $id => $node) { - if(!$node->isExpanded() && !$node->numChildren()) { + if(!$node->isExpanded() && !$node->$numChildrenMethod()) { $node->markExpanded(); } } @@ -482,6 +482,16 @@ class Hierarchy extends DataObjectDecorator { "\"ParentID\" = " . (int)$this->owner->ID, "\"$baseClass\".\"ID\" ASC"); } + /** + * Return the number of children that this page ever had, including pages that were deleted + */ + public function numHistoricalChildren() { + $query = Versioned::get_including_deleted_query(ClassInfo::baseDataClass($this->owner->class), + "ParentID = " . (int)$this->owner->ID); + + return $query->unlimitedRowCount(); + } + /** * Return the number of direct children. * By default, values are cached after the first invocation. diff --git a/core/model/SiteTree.php b/core/model/SiteTree.php index cea439468..178055f74 100755 --- a/core/model/SiteTree.php +++ b/core/model/SiteTree.php @@ -1375,7 +1375,8 @@ class SiteTree extends DataObject implements PermissionProvider,i18nEntityProvid // Also write all VPs pointing here $suffix = Versioned::current_stage() == 'Live' ? '_Live' : ''; - foreach(DataObject::get('VirtualPage', "SiteTree$suffix.ID = SiteTree$suffix.ID AND CopyContentFromID = {$this->ID}") as $page) { + $virtualPages = DataObject::get('VirtualPage', "SiteTree$suffix.ID = SiteTree$suffix.ID AND CopyContentFromID = {$this->ID}"); + if($virtualPages) foreach($virtualPages as $page) { // $page->write() calls syncLinkTracking, which does all the hard work for us. $page->write(); } diff --git a/core/model/Versioned.php b/core/model/Versioned.php index 28ee75f6a..e61c536b9 100755 --- a/core/model/Versioned.php +++ b/core/model/Versioned.php @@ -579,7 +579,6 @@ class Versioned extends DataObjectDecorator { $_GET['stage'] = ucfirst(strtolower($_GET['stage'])); Session::set('currentStage', $_GET['stage']); Session::clear('archiveDate'); - Cookie::set('bypassStaticCache', '1', 0); } if(isset($_GET['archiveDate'])) { Session::set('archiveDate', $_GET['archiveDate']); @@ -592,6 +591,12 @@ class Versioned extends DataObjectDecorator { } else { Versioned::reading_stage("Live"); } + + if(Versioned::current_stage() == 'Live') { + Cookie::set('bypassStaticCache', null, 0); + } else { + Cookie::set('bypassStaticCache', '1', 0); + } } /** @@ -815,6 +820,20 @@ class Versioned extends DataObjectDecorator { * In particular, this will query deleted records as well as active ones. */ static function get_including_deleted($class, $filter = "", $sort = "") { + $query = self::get_including_deleted_query($class, $filter, $sort); + + // Process into a DataObjectSet + $SNG = singleton($class); + return $SNG->buildDataObjectSet($query->execute(), 'DataObjectSet', null, $class); + } + + /** + * Return the query for the equivalent of a DataObject::get() call, querying the latest + * version of each page stored in the (class)_versions tables. + * + * In particular, this will query deleted records as well as active ones. + */ + static function get_including_deleted_query($class, $filter = "", $sort = "") { $oldStage = Versioned::$reading_stage; Versioned::$reading_stage = null; @@ -827,12 +846,9 @@ class Versioned extends DataObjectDecorator { $query->from[$archiveTable] = "INNER JOIN \"$archiveTable\" ON \"$archiveTable\".\"ID\" = \"{$baseTable}_versions\".\"RecordID\" AND \"$archiveTable\".\"Version\" = \"{$baseTable}_versions\".\"Version\""; - - // Process into a DataObjectSet - $result = $SNG->buildDataObjectSet($query->execute(), 'DataObjectSet', null, $class); Versioned::$reading_stage = $oldStage; - return $result; + return $query; } /** diff --git a/tests/model/HierarchyTest.php b/tests/model/HierarchyTest.php index 10897a539..891263750 100644 --- a/tests/model/HierarchyTest.php +++ b/tests/model/HierarchyTest.php @@ -16,10 +16,17 @@ class HierarchyTest extends SapphireTest { $this->assertEquals(array("Page 1", "Page 2", "Page 3"), singleton('Page')->AllHistoricalChildren()->column('Title')); + // Check numHistoricalChildren + $this->assertEquals(3, singleton('Page')->numHistoricalChildren()); + // Check that both page 2 children are returned $page2 = $this->objFromFixture('Page', 'page2'); $this->assertEquals(array("Page 2a", "Page 2b"), $page2->AllHistoricalChildren()->column('Title')); + + // Check numHistoricalChildren + $this->assertEquals(2, $page2->numHistoricalChildren()); + // Page 3 has been deleted; let's bring it back from the grave $page3 = Versioned::get_including_deleted("SiteTree", "\"Title\" = 'Page 3'")->First(); @@ -27,6 +34,9 @@ class HierarchyTest extends SapphireTest { // Check that both page 3 children are returned $this->assertEquals(array("Page 3a", "Page 3b"), $page3->AllHistoricalChildren()->column('Title')); + + // Check numHistoricalChildren + $this->assertEquals(2, $page3->numHistoricalChildren()); }