1
0
mirror of https://github.com/processwire/processwire.git synced 2025-08-10 16:54:44 +02:00

Continued updates to new PagesParents class and update PagesEditor to use it

This commit is contained in:
Ryan Cramer
2020-05-14 12:05:30 -04:00
parent 851969c9e0
commit fd2a06d4b2
3 changed files with 312 additions and 302 deletions

View File

@@ -807,6 +807,7 @@ class Page extends WireData implements \Countable, WireMatchable {
$this->_meta = null;
foreach($this->template->fieldgroup as $field) {
$name = $field->name;
if(!$field->type) continue;
if(!$field->type->isAutoload() && !isset($this->data[$name])) continue; // important for draft loading
$value = $this->get($name);
// no need to clone non-objects, as they've already been cloned
@@ -966,14 +967,14 @@ class Page extends WireData implements \Countable, WireMatchable {
*
*/
public function setQuietly($key, $value) {
$this->quietMode = true;
if(isset($this->settings[$key]) && is_int($value)) {
// allow integer-only values in $this->settings to be set directly in quiet mode
$this->settings[$key] = $value;
} else {
$this->quietMode = true;
parent::setQuietly($key, $value);
$this->quietMode = false;
}
$this->quietMode = false;
return $this;
}

View File

@@ -28,6 +28,12 @@ class PagesEditor extends Wire {
*/
protected $pages;
/**
* Construct
*
* @param Pages $pages
*
*/
public function __construct(Pages $pages) {
$this->pages = $pages;
@@ -642,14 +648,18 @@ class PagesEditor extends Wire {
// update children counts for current/previous parent
if($isNew) {
// new page
$page->parent->numChildren++;
} else if($page->parentPrevious && $page->parentPrevious->id != $page->parent->id) {
// parent changed
$page->parentPrevious->numChildren--;
$page->parent->numChildren++;
} else {
if($page->parentPrevious && $page->parentPrevious->id != $page->parent->id) {
$page->parentPrevious->numChildren--;
$page->parent->numChildren++;
}
}
// save any needed updates to pages_parents table
$this->pages->parents()->save($page);
// if page hasn't changed, don't continue further
if(!$page->isChanged() && !$isNew) {
$this->pages->debugLog('save', '[not-changed]', true);
@@ -731,30 +741,6 @@ class PagesEditor extends Wire {
// operations can be access controlled.
if($isNew || $page->parentPrevious || $page->templatePrevious) $this->wire(new PagesAccess($page));
// lastly determine whether the pages_parents table needs to be updated for the find() cache
// and call upon $this->saveParents where appropriate.
if($page->parentPrevious && $page->numChildren > 0) {
// page is moved and it has children
$this->saveParents($page->id, $page->numChildren);
if($page->parent->numChildren == 1) $this->saveParents($page->parent_id, $page->parent->numChildren);
} else if(($page->parentPrevious && $page->parent->numChildren == 1) ||
($isNew && $page->parent->numChildren == 1) ||
($page->_forceSaveParents)) {
// page is moved and is the first child of it's new parent
// OR page is NEW and is the first child of it's parent
// OR $page->_forceSaveParents is set (debug/debug, can be removed later)
$this->saveParents($page->parent_id, $page->parent->numChildren);
} else if($page->parentPrevious && $page->parent->numChildren > 1 && $page->parent->parent_id > 1) {
$this->saveParents($page->parent->parent_id, $page->parent->parent->numChildren);
}
if($page->parentPrevious && $page->parentPrevious->numChildren == 0) {
// $page was moved and it's previous parent is now left with no children, this ensures the old entries get deleted
$this->saveParents($page->parentPrevious->id, 0);
}
// trigger hooks
if(empty($options['noHooks'])) {
$this->pages->saved($page, $changes, $changesValues);
@@ -771,6 +757,47 @@ class PagesEditor extends Wire {
return true;
}
/**
* TBD Identify if parent changed and call saveParentsTable() where appropriate
*
* @param Page $page Page to save parent(s) for
* @param bool $isNew If page is newly created during this save this should be true, otherwise false
*
protected function savePageParent(Page $page, $isNew) {
if($page->parentPrevious || $page->_forceSaveParents || $isNew) {
$this->pages->parents()->rebuild($page);
}
// saveParentsTable option is always true unless manually disabled from a hook
if($page->parentPrevious && !$isNew && $page->numChildren > 0) {
// existing page was moved and it has children
if($page->parent->numChildren == 1) {
// first child of new parent
$this->pages->parents()->rebuildPage($page->parent);
} else {
$this->pages->parents()->rebuildPage($page);
}
} else if(($page->parentPrevious && $page->parent->numChildren == 1) ||
($isNew && $page->parent->numChildren == 1) ||
($page->_forceSaveParents)) {
// page is moved and is the first child of its new parent
// OR page is NEW and is the first child of its parent
// OR $page->_forceSaveParents is set (debug/debug, can be removed later)
$this->pages->parents()->rebuildPage($page->parent);
} else if($page->parentPrevious && $page->parent->numChildren > 1 && $page->parent->parent_id > 1) {
$this->pages->parents()->rebuildPage($page->parent->parent);
}
if($page->parentPrevious && $page->parentPrevious->numChildren == 0) {
// $page was moved and its previous parent is now left with no children, this ensures the old entries get deleted
$this->pages->parents()->rebuild($page->parentPrevious->id);
}
}
*/
/**
* Save just a field from the given page as used by Page::save($field)
*
@@ -844,75 +871,6 @@ class PagesEditor extends Wire {
return $return;
}
/**
* Save references to the Page's parents in pages_parents table, as well as any other pages affected by a parent change
*
* Any pages_id passed into here are assumed to have children
*
* @param int $pages_id ID of page to save parents from
* @param int $numChildren Number of children this Page has
* @param int $level Recursion level, for debugging.
* @return bool
*
*/
protected function saveParents($pages_id, $numChildren, $level = 0) {
$pages_id = (int) $pages_id;
if(!$pages_id) return false;
$database = $this->wire('database');
$query = $database->prepare("DELETE FROM pages_parents WHERE pages_id=:pages_id");
$query->bindValue(':pages_id', $pages_id, \PDO::PARAM_INT);
$query->execute();
if(!$numChildren) return true;
$insertSql = '';
$id = $pages_id;
$cnt = 0;
$query = $database->prepare("SELECT parent_id FROM pages WHERE id=:id");
do {
if($id < 2) break; // home has no parent, so no need to do that query
$query->bindValue(":id", $id, \PDO::PARAM_INT);
$query->execute();
list($id) = $query->fetch(\PDO::FETCH_NUM);
$id = (int) $id;
if($id < 2) break; // no need to record 1 for every page, since it is assumed
$insertSql .= "($pages_id, $id),";
$cnt++;
} while(1);
if($insertSql) {
$sql =
'INSERT INTO pages_parents (pages_id, parents_id) ' .
'VALUES' . rtrim($insertSql, ',') . ' ' .
'ON DUPLICATE KEY UPDATE parents_id=VALUES(parents_id)';
$database->exec($sql);
}
// find all children of $pages_id that themselves have children
$sql =
"SELECT pages.id, COUNT(children.id) AS numChildren " .
"FROM pages " .
"JOIN pages AS children ON children.parent_id=pages.id " .
"WHERE pages.parent_id=:pages_id " .
"GROUP BY pages.id ";
$query = $database->prepare($sql);
$query->bindValue(':pages_id', $pages_id, \PDO::PARAM_INT);
$database->execute($query);
/** @noinspection PhpAssignmentInConditionInspection */
while($row = $query->fetch(\PDO::FETCH_ASSOC)) {
$this->saveParents($row['id'], $row['numChildren'], $level+1);
}
$query->closeCursor();
return true;
}
/**
* Silently add status flag to a Page and save
*
@@ -1137,13 +1095,11 @@ class PagesEditor extends Wire {
/** @var PagesAccess $access */
$access = $this->wire(new PagesAccess());
$access->deletePage($page);
// delete entirely from pages_parents table
$this->pages->parents()->delete($page);
$database = $this->wire('database');
$query = $database->prepare("DELETE FROM pages_parents WHERE pages_id=:page_id");
$query->bindValue(":page_id", $page->id, \PDO::PARAM_INT);
$query->execute();
$query = $database->prepare("DELETE FROM pages WHERE id=:page_id LIMIT 1"); // QA
$query->bindValue(":page_id", $page->id, \PDO::PARAM_INT);
$query->execute();
@@ -1174,12 +1130,18 @@ class PagesEditor extends Wire {
*
*/
public function _clone(Page $page, Page $parent = null, $recursive = true, $options = array()) {
$defaults = array(
'forceID' => 0,
'set' => array(),
'recursionLevel' => 0, // recursion level (internal use only)
);
if(is_string($options)) $options = Selectors::keyValueStringToArray($options);
if(!isset($options['recursionLevel'])) $options['recursionLevel'] = 0; // recursion level
$options = array_merge($defaults, $options);
if($parent === null) $parent = $page->parent;
if(isset($options['set']) && isset($options['set']['name']) && strlen($options['set']['name'])) {
if(count($options['set']) && !empty($options['set']['name'])) {
$name = $options['set']['name'];
} else {
$name = $this->pages->names()->uniquePageName(array(
@@ -1201,24 +1163,24 @@ class PagesEditor extends Wire {
// clone in memory
$copy = clone $page;
$copy->setQuietly('_cloning', $page);
$copy->id = isset($options['forceID']) ? (int) $options['forceID'] : 0;
$copy->setIsNew(true);
$copy->of(false);
$copy->setQuietly('_cloning', $page);
$copy->setQuietly('id', $options['forceID'] > 1 ? (int) $options['forceID'] : 0);
$copy->setQuietly('numChildren', 0);
$copy->setQuietly('created', time());
$copy->setQuietly('modified', time());
$copy->name = $name;
$copy->parent = $parent;
$copy->of(false);
$copy->set('numChildren', 0);
$copy->created = time();
$copy->modified = time();
if(!isset($options['quiet']) || $options['quiet']) {
$options['quiet'] = true;
$copy->created_users_id = $user->id;
$copy->modified_users_id = $user->id;
$copy->setQuietly('created_users_id', $user->id);
$copy->setQuietly('modified_users_id', $user->id);
}
// set any properties indicated in options
if(isset($options['set']) && is_array($options['set'])) {
if(count($options['set'])) {
foreach($options['set'] as $key => $value) {
$copy->set($key, $value);
// quiet option required for setting modified time or user
@@ -1261,32 +1223,39 @@ class PagesEditor extends Wire {
if($page->numChildren && $recursive) {
$start = 0;
$limit = 200;
$numChildrenCopied = 0;
do {
$children = $page->children("include=all, start=$start, limit=$limit");
$numChildren = $children->count();
foreach($children as $child) {
/** @var Page $child */
$this->pages->clone($child, $copy, true, array('recursionLevel' => $options['recursionLevel'] + 1));
$childCopy = $this->pages->clone($child, $copy, true, array(
'recursionLevel' => $options['recursionLevel'] + 1,
));
if($childCopy->id) $numChildrenCopied++;
}
$start += $limit;
$this->pages->uncacheAll();
} while($numChildren);
$copy->setQuietly('numChildren', $numChildrenCopied);
}
$copy->parentPrevious = null;
$copy->setQuietly('_cloning', null);
// update pages_parents table, only when at recursionLevel 0 since pagesParents is already recursive
if($recursive && $options['recursionLevel'] === 0) {
$this->saveParents($copy->id, $copy->numChildren);
}
if($options['recursionLevel'] === 0) {
// update pages_parents table, only when at recursionLevel 0 since parents()->rebuild() already descends
if($copy->numChildren) {
$copy->setIsNew(true);
$this->pages->parents()->rebuild($copy);
$copy->setIsNew(false);
}
// update sort
if($copy->parent()->sortfield() == 'sort') {
$this->sortPage($copy, $copy->sort, true);
}
}
$copy->setQuietly('_cloning', null);
$copy->of($of);
$page->of($of);
$page->meta()->copyTo($copy->id);

View File

@@ -12,7 +12,7 @@
*
* ~~~~~~
* // Rebuild the entire pages_parents table
* $numRows = $pages->parents()->rebuild();
* $numRows = $pages->parents()->rebuildAll();
* ~~~~~~
*
* ProcessWire 3.x, Copyright 2020 by Ryan Cramer
@@ -38,16 +38,6 @@ class PagesParents extends Wire {
*/
protected $debug = false;
/**
* Page parent IDs excluded from pages_parents table
*
* Set via $config->parentsTableExcludeIDs
*
* @var array
*
*/
protected $excludeIDs = array();
/**
* Construct
*
@@ -57,13 +47,6 @@ class PagesParents extends Wire {
public function __construct(Pages $pages) {
$this->pages = $pages;
$this->debug = $pages->debug();
$excludeIDs = $pages->wire('config')->parentsTableExcludeIDs;
if(is_array($excludeIDs)) {
foreach($excludeIDs as $id) {
$this->excludeIDs[$id] = $id;
}
}
}
/**
@@ -492,45 +475,134 @@ class PagesParents extends Wire {
return $a;
}
/**
* Rebuild pages_parents index for given page (and any children)
/**
* Check if saved page needs any pages_parents updates and perform them when applicable
*
* @param Page $page
* @return int Number of rows updated
*
*/
public function save(Page $page) {
$numRows = 0;
// homepage not maintained in pages_parents table
// pages being cloned are not maintained till clone operation finishes
if($page->id < 2 || $page->_cloning || !$page->parent) return 0;
// first check if page parents need any updates
if($page->isNew()) {
// newly added page
if($page->parent->numChildren === 1) {
// first time parent gets added to pages_parents
$numRows += $this->rebuild($page->parent);
}
} else if($page->parentPrevious && $page->parentPrevious->id != $page->parent->id) {
// existing page with parent changed
if($page->parentPrevious->numChildren === 0) {
// parent no longer has children and doesnt need entry
$numRows += $this->delete($page->parentPrevious);
}
if($page->parent->numChildren === 1) {
// first time parent gets added to pages_parents
$numRows += $this->rebuild($page->parent);
}
}
return $numRows;
}
/**
* Rebuild pages_parents table for given page
*
* This descends into both parents, and children that are themselves parents,
* and this method already calls the rebuildBranch() method when appropriate.
*
* @param Page $page
* @return int
* @since 3.0.156
*
*
*/
public function rebuildPage(Page $page) {
$pages_id = (int) $page->id;
public function rebuild(Page $page) {
$pages_id = (int) $page->id;
$database = $this->wire('database'); /** @var WireDatabasePDO $database */
$inserts = array();
$rowCount = 0;
$exclude = false;
if($page->id < 2) return 0;
if(!$page->_cloning && !$page->isNew()) $this->clearPage($page);
if(!$page->isNew()) $this->clear($page);
// if page has no children it does not need pages_parents entries
if(!$page->numChildren) return 0;
// identify parents to store for $page
foreach($page->parents() as $parent) {
$parents_id = (int) $parent->id;
if($parents_id < 2) break;
$inserts[] = "$pages_id,$parents_id";
$exclude = isset($this->excludeIDs[$parents_id]);
if($exclude) break;
}
if($exclude) return 0;
if(count($inserts)) {
// if parents found to insert, rebuild parents of $page
$inserts = implode('),(', $inserts);
$query = $database->prepare("INSERT INTO pages_parents (pages_id, parents_id) VALUES($inserts)");
$query->execute();
$rowCount += $query->rowCount();
}
// rebuild parents within pages children
$rowCount += $this->rebuildBranch($page->id);
return $rowCount;
}
/**
* Rebuild pages_parents branch starting at $fromParent and into all descendents
*
* @param Page|int $fromParent From parent Page or ID
* @return int Number of rows inserted
*
*/
public function rebuildBranch($fromParent) {
return $this->rebuildAll($fromParent);
}
/**
* Rebuild pages_parents table entirely or from branch starting with a parent branch
*
* @param int|Page $fromParent Specify parent ID or page to rebuild from that parent, or omit to rebuild all
* @return int Number of rows inserted
* @since 3.0.156
*
*/
public function rebuildAll($fromParent = null) {
$database = $this->wire('database'); /** @var WireDatabasePDO $database */
$inserts = array();
$parents = $this->findParentIDs($fromParent ? $fromParent : -2); // find parents within children
$rowCount = 0;
foreach($parents as $pages_id => $parents_id) {
if(isset($this->excludeIDs[$parents_id])) continue;
$inserts[] = "$pages_id,$parents_id";
while(isset($parents[$parents_id])) {
$parents_id = $parents[$parents_id];
$inserts[] = "$pages_id,$parents_id";
}
}
if(!isset($this->excludeIDs[$page->id])) {
$rowCount += $this->rebuild($page->id);
if(count($parents)) {
$where = $fromParent ? 'WHERE pages_id IN(' . implode(',', array_keys($parents)) . ')' : '';
$sql = "DELETE FROM pages_parents $where";
$database->exec($sql);
}
if(count($inserts)) {
$inserts = array_unique($inserts);
$inserts = implode('),(', $inserts);
$query = $database->prepare("INSERT INTO pages_parents (pages_id, parents_id) VALUES($inserts)");
$query->execute();
$rowCount = $query->rowCount();
}
return $rowCount;
@@ -538,13 +610,13 @@ class PagesParents extends Wire {
/**
* Clear page from pages_parents index
*
*
* @param Page|int $page
* @return int
* @since 3.0.156
*
*
*/
public function clearPage($page) {
public function clear($page) {
$pages_id = (int) "$page";
$database = $this->wire('database'); /** @var WireDatabasePDO $database */
$query = $database->prepare("DELETE FROM pages_parents WHERE pages_id=:id");
@@ -556,160 +628,128 @@ class PagesParents extends Wire {
}
/**
* Rebuild pages_parents table entirely or from branch starting with a parent
*
* @param int|Page $fromParent Specify parent ID or page to rebuild from that parent, or omit to rebuild all
* @return int Number of rows inserted
* Delete page entirely from pages_parents table (both as page and parent)
*
* @param Page|int $page
* @return int
* @since 3.0.156
*
*
*/
public function rebuild($fromParent = null) {
public function delete($page) {
$pages_id = (int) "$page";
$database = $this->wire('database'); /** @var WireDatabasePDO $database */
$inserts = array();
$parents = $this->findParentIDs($fromParent ? $fromParent : -2);
foreach($parents as $pages_id => $parents_id) {
if(isset($this->excludeIDs[$parents_id])) continue;
$inserts[] = "$pages_id,$parents_id";
while(isset($parents[$parents_id])) {
$parents_id = $parents[$parents_id];
$inserts[] = "$pages_id,$parents_id";
}
}
$inserts = array_unique($inserts);
$where = $fromParent ? 'WHERE pages_id IN(' . implode(',', array_keys($parents)) . ')' : '';
$database->exec("DELETE FROM pages_parents $where");
$inserts = implode('),(', $inserts);
$query = $database->prepare("INSERT INTO pages_parents (pages_id, parents_id) VALUES($inserts)");
$sql = "DELETE FROM pages_parents WHERE pages_id=:pages_id OR parents_id=:parents_id";
$query = $database->prepare($sql);
$query->bindValue(':pages_id', $pages_id, \PDO::PARAM_INT);
$query->bindValue(':parents_id', $pages_id, \PDO::PARAM_INT);
$query->execute();
$rowCount = $query->rowCount();
return $rowCount;
$cnt = $query->rowCount();
$query->closeCursor();
return $cnt;
}
/**
* Rebuild pages_parents table (deprecated original version replaced by rebuild method, here for reference only)
*
* Save references to the Page's parents in pages_parents table, as well as any other pages affected by a parent change
* Tests a page and returns verbose details about what was found
*
* For debugging/development purposes to make sure pages_parents
* is working as intended.
*
* #pw-internal
*
* @param int|Page $pages_id ID of page to save parents from
* @param int|bool $hasChildren Does this page have children? Specify true or quantity of children.
* @param array $options
* - `debug` (bool): Return debug info array? (default=false)
* - `skipIDs` (array): if pages_id has a parent matching any of these then do not save pages_parents table data for it.
* - `level` (int): Recursion level (internal use)
* @return int|array Returns number of records inserted or array when debug option specified
* @deprecated
*
*
* @param Page $page
* @return array
*
*/
private function saveParents($pages_id, $hasChildren, array $options = array()) {
$defaults = array(
'level' => 0, // recursion level
'skipIDs' => array(),
'parentsIDs' => array(), // internal recursive use only
'debug' => false,
);
$options = array_merge($defaults, $options);
$pages_id = (int) "$pages_id";
$config = $this->wire('config'); /** @var Config $config */
public function pageTests(Page $page) {
$id = (int) "$page";
$path = $page->path;
$database = $this->wire('database'); /** @var WireDatabasePDO $database */
$debug = $options['debug'] ? array() : false;
$parentsIDs = empty($options['parentsIDs']) ? array() : $options['parentsIDs'];
if($debug !== false && !$options['level']) $debug = array('debug' => "saveParentsTable($pages_id)");
if(!$pages_id) return $debug === false ? 0 : $debug;
$skipIDs = $config->parentsTableExcludeIDs;
$skipIDs = is_array($skipIDs) ? array_merge($skipIDs, $options['skipIDs']) : $options['skipIDs'];
$skipIDs = empty($skipIDs) ? array() : array_flip($skipIDs); // flip for isset() use
$sql = "DELETE FROM pages_parents WHERE pages_id=:pages_id ";
if(!$options['level'] && count($skipIDs)) {
$parentsIDs = array();
foreach($skipIDs as $id) $parentsIDs[] = (int) $id;
$sql .= 'OR (pages_id>0 AND parents_id IN(' . implode(',', $parentsIDs) . '))';
}
$query = $database->prepare($sql);
$query->bindValue(':pages_id', $pages_id, \PDO::PARAM_INT);
$query->execute();
$query->closeCursor();
// if page has no children, then there is nothing further to do
if(!$hasChildren) return $debug === false ? 0 : $debug;
$skip = false;
$inserts = array();
if(empty($parentsIDs)) {
$parentsIDs = $this->getParents($pages_id, array(
'column' => 'id', // get value of id column only
'noHome' => true // exclude homepage
));
}
foreach($parentsIDs as $parent_id) {
$parent_id = (int) $parent_id;
$skip = isset($skipIDs[$parent_id]);
if($skip) break;
$inserts[] = "$pages_id,$parent_id";
if($debug !== false) $debug[] = $parent_id;
}
if($skip) return $debug === false ? 0 : $debug;
$numInserts = count($inserts);
if($numInserts) {
$sql =
'INSERT INTO pages_parents (pages_id, parents_id) ' .
'VALUES(' . implode('),(', $inserts) . ') ' .
'ON DUPLICATE KEY UPDATE parents_id=VALUES(parents_id)';
$database->exec($sql);
}
// find all children of $pages_id that themselves have children
$sql =
"SELECT pages.id, pages.name, COUNT(children.id) AS numChildren " .
"FROM pages " .
"JOIN pages AS children ON children.parent_id=pages.id " .
"WHERE pages.parent_id=:pages_id " .
"GROUP BY pages.id ";
$query = $database->prepare($sql);
$query->bindValue(':pages_id', $pages_id, \PDO::PARAM_INT);
$database->execute($query);
$rows = array();
/** @noinspection PhpAssignmentInConditionInspection */
while($row = $query->fetch(\PDO::FETCH_ASSOC)) $rows[] = $row;
$query->closeCursor();
if(count($rows)) {
array_unshift($parentsIDs, $pages_id);
$options['parentsIDs'] = $parentsIDs;
$options['level']++;
foreach($rows as $row) {
$result = $this->saveParents($row['id'], $row['numChildren'], $options);
if($debug === false) {
$numInserts += $result;
} else {
$debug["parents-of-$row[id]"] = $result;
$tests = array(
'query-for-parents-of-page' => array(
'notes' => "Query DB for parents of $path. Result will exclude homepage.",
'query' => "SELECT parents_id FROM pages_parents WHERE pages_id=$id",
'timer' => '',
'count' => 0,
'pages' => array(),
'type' => 'database.query',
),
'query-for-pages-having-parent' => array(
'notes' => "Query DB for pages having parent $path. Result will exclude pages that are not themselves parents.",
'query' => "SELECT pages_id FROM pages_parents WHERE parents_id=$id",
'timer' => '',
'count' => 0,
'pages' => array(),
'type' => 'database.query',
),
'pages-find-descendents' => array(
'notes' => "Use \$pages->find() with selector to find all descendents of $path with no exclusions.",
'query' => "has_parent=$id, sort=parent_id, sort=id, include=all",
'timer' => '',
'count' => 0,
'pages' => array(),
'type' => 'pages.find',
),
'page-children-descendents' => array(
'notes' => "Use recursive \$page->children() to manually reproduce result from previous test (the two should match)",
'query' => "include=all, sort=id",
'timer' => '',
'count' => 0,
'pages' => array(),
'type' => 'descendents',
),
);
foreach($tests as $key => $test) {
$timer = Debug::timer();
if($test['type'] === 'database.query') {
$query = $database->prepare($test['query']);
$query->execute();
$test['count'] = $query->rowCount();
while($value = $query->fetchColumn()) {
$test['pages'][] = "$value: " . $this->pages->getPath($value);
}
$query->closeCursor();
} else if($test['type'] === 'pages.find') {
$this->pages->uncacheAll();
$items = $this->pages->find($test['query']);
$test['count'] = $items->count();
$test['pages'] = $items->explode("{id}: {path}");
} else if($test['type'] === 'descendents') {
$this->pages->uncacheAll();
$items = $this->descendents($page, $test['query']);
$test['count'] = $items->count();
$test['pages'] = $items->explode("{id}: {path}");
}
$options['level']--;
$test['timer'] = Debug::timer($timer);
$tests[$key] = $test;
}
return $debug === false ? $numInserts : $debug;
return $tests;
}
/**
* Find descendents of $page by going recursive rather than using pages_parents table (for testing)
*
* @param Page $page
* @param string $selector
* @return PageArray
*
*/
protected function descendents(Page $page, $selector = 'include=all') {
$children = new PageArray();
foreach($page->children($selector) as $child) {
$children->add($child);
if(!$child->numChildren) continue;
foreach($this->descendents($child, $selector) as $item) {
$children->add($item);
}
}
return $children;
}
}