protected function getQueryHasParent(DatabaseQuerySelect $query, $selector)
{
static $cnt = 0;
$wheres = array();
$parent_ids = $selector->value;
if (!is_array($parent_ids)) {
$parent_ids = array($parent_ids);
}
foreach ($parent_ids as $parent_id) {
if (!ctype_digit("{$parent_id}")) {
// parent_id is a path, convert a path to a parent
$parent = new NullPage();
$path = $this->wire('sanitizer')->path($parent_id);
if ($path) {
$parent = $this->wire('pages')->get('/' . trim($path, '/') . '/');
}
$parent_id = $parent->id;
if (!$parent_id) {
$query->where("1>2");
// force the query to fail
return;
}
}
$parent_id = (int) $parent_id;
$cnt++;
if ($parent_id == 1) {
// homepage
if ($selector->operator == '!=') {
// homepage is only page that can match not having a has_parent of 1
$query->where("pages.id=1");
} else {
// no different from not having a has_parent, so we ignore it
}
return;
}
// the subquery performs faster than the old method (further below) on sites with tens of thousands of pages
$in = $selector->operator == '!=' ? 'NOT IN' : 'IN';
$wheres[] = "pages.parent_id {$in} (SELECT pages_id FROM pages_parents WHERE parents_id={$parent_id} OR pages_id={$parent_id})";
}
$andor = $selector->operator == '!=' ? ' AND ' : ' OR ';
$query->where(implode($andor, $wheres));
/*
// OLD method kept for reference
$joinType = 'join';
$table = "pages_has_parent$cnt";
if($selector->operator == '!=') {
$joinType = 'leftjoin';
$query->where("$table.pages_id IS NULL");
}
$query->$joinType(
"pages_parents AS $table ON (" .
"($table.pages_id=pages.id OR $table.pages_id=pages.parent_id) " .
"AND ($table.parents_id=$parent_id OR $table.pages_id=$parent_id) " .
")"
);
*/
}