Skip to content
This repository
Browse code

FIX Hierarchy#liveChildren couldnt handle lots of pages

Hierarchy#liveChildren was generating a list of all IDs of all pages
on staging. When a site had lots of pages, this basically killed the
tree.

Fix by adding new versioned mode, stage_unique, which uses a
subselect to only return items from a stage that are in no
other stage.
  • Loading branch information...
commit d0bc9c6d233a0a64aab7569ce0e42b70bc9a36ac 1 parent 4916b36
Hamish Friedlander authored August 21, 2012
17  model/Hierarchy.php
@@ -575,22 +575,9 @@ public function liveChildren($showAll = false, $onlyDeletedFromStage = false) {
575 575
 		if(!$showAll) $children = $children->where('"ShowInMenus" = 1');
576 576
 
577 577
 		// Query the live site
578  
-		$children->dataQuery()->setQueryParam('Versioned.mode', 'stage');
  578
+		$children->dataQuery()->setQueryParam('Versioned.mode', $onlyDeletedFromStage ? 'stage_unique' : 'stage');
579 579
 		$children->dataQuery()->setQueryParam('Versioned.stage', 'Live');
580  
-		
581  
-		if($onlyDeletedFromStage) {
582  
-			// Note that this makes a second query, and could be optimised to be a join
583  
-			$stageChildren = DataObject::get($baseClass)
584  
-				->where("\"{$baseClass}\".\"ID\" != $id");
585  
-			$stageChildren->dataQuery()->setQueryParam('Versioned.mode', 'stage');
586  
-			$stageChildren->dataQuery()->setQueryParam('Versioned.stage', '');
587  
-			
588  
-			$ids = $stageChildren->column("ID");
589  
-			if($ids) {
590  
-				$children = $children->where("\"$baseClass\".\"ID\" NOT IN (" . implode(',',$ids) . ")");
591  
-			}
592  
-		}
593  
-		
  580
+
594 581
 		return $children;
595 582
 	}
596 583
 	
24  model/Versioned.php
@@ -181,8 +181,28 @@ function augmentSQL(SQLQuery &$query, DataQuery &$dataQuery = null) {
181 181
 				}
182 182
 			}
183 183
 			break;
184  
-			
185  
-		
  184
+
  185
+		// Reading a specific stage, but only return items that aren't in any other stage
  186
+		case 'stage_unique':
  187
+			$stage = $dataQuery->getQueryParam('Versioned.stage');
  188
+
  189
+			// Recurse to do the default stage behavior (must be first, we rely on stage renaming happening before below)
  190
+			$dataQuery->setQueryParam('Versioned.mode', 'stage');
  191
+			$this->augmentSQL($query, $dataQuery);
  192
+
  193
+			// Now exclude any ID from any other stage. Note that we double rename to avoid the regular stage rename
  194
+			// renaming all subquery references to be Versioned.stage
  195
+			foreach($this->stages as $excluding) {
  196
+				if ($excluding == $stage) continue;
  197
+
  198
+				$tempName = 'ExclusionarySource_'.$excluding;
  199
+				$excludingTable = $baseTable . ($excluding && $excluding != $this->defaultStage ? "_$excluding" : '');
  200
+
  201
+				$query->addWhere('"'.$baseTable.'"."ID" NOT IN (SELECT ID FROM "'.$tempName.'")');
  202
+				$query->renameTable($tempName, $excludingTable);
  203
+			}
  204
+			break;
  205
+
186 206
 		// Return all version instances	
187 207
 		case 'all_versions':
188 208
 		case 'latest_versions':

0 notes on commit d0bc9c6

Please sign in to comment.
Something went wrong with that request. Please try again.