mirror of
https://github.com/processwire/processwire.git
synced 2025-08-08 15:57:01 +02:00
Update PagesLoader.preloadPage() method to support a loadPageRefs option which loads page references separately and as a group. Not yet certain this will remain though, as it seems like the FieldtypePage loader is already fast enough
This commit is contained in:
@@ -2052,9 +2052,10 @@ class PagesLoader extends Wire {
|
|||||||
* @param Page $page Page to preload fields for
|
* @param Page $page Page to preload fields for
|
||||||
* @param array $fieldNames Names of fields to preload
|
* @param array $fieldNames Names of fields to preload
|
||||||
* @param array $options
|
* @param array $options
|
||||||
* - `debug` (bool): Specify true to return array of debug info (default=false).
|
* - `debug` (bool): Specify true to include additional debug info in return value (default=false).
|
||||||
* - `useFieldtypeMulti` (bool): Enable FieldtypeMulti for testing purposes (default=false).
|
* - `useFieldtypeMulti` (bool): Enable FieldtypeMulti for testing purposes (default=false).
|
||||||
* @return int|array Number of fields preloaded, or array of details (if debug)
|
* - `loadPageRefs` (bool): Optimization to early load pages in page reference fields? (default=true)
|
||||||
|
* @return array Array containing what was loaded and skipped
|
||||||
* @since 3.0.243
|
* @since 3.0.243
|
||||||
*
|
*
|
||||||
*/
|
*/
|
||||||
@@ -2063,13 +2064,14 @@ class PagesLoader extends Wire {
|
|||||||
$defaults = [
|
$defaults = [
|
||||||
'debug' => is_bool($options) ? $options : false,
|
'debug' => is_bool($options) ? $options : false,
|
||||||
'useFieldtypeMulti' => false,
|
'useFieldtypeMulti' => false,
|
||||||
|
'loadPageRefs' => true,
|
||||||
];
|
];
|
||||||
|
|
||||||
static $level = 0;
|
static $level = 0;
|
||||||
|
|
||||||
$options = is_array($options) ? array_merge($defaults, $options) : $defaults;
|
$options = is_array($options) ? array_merge($defaults, $options) : $defaults;
|
||||||
$debug = $options['debug'];
|
$debug = $options['debug'];
|
||||||
$database = $page->wire()->database;
|
$database = $this->wire()->database;
|
||||||
$fieldNames = array_unique($fieldNames);
|
$fieldNames = array_unique($fieldNames);
|
||||||
$fields = $page->wire()->fields;
|
$fields = $page->wire()->fields;
|
||||||
$loadFields = [];
|
$loadFields = [];
|
||||||
@@ -2084,10 +2086,9 @@ class PagesLoader extends Wire {
|
|||||||
'skipped' => [],
|
'skipped' => [],
|
||||||
'blank' => [],
|
'blank' => [],
|
||||||
'queries' => 1,
|
'queries' => 1,
|
||||||
'timer' => 0.0,
|
|
||||||
];
|
];
|
||||||
|
|
||||||
if(!$page->id || !$page->template) return $debug ? $log : 0;
|
if(!$page->id || !$page->template) return $log;
|
||||||
|
|
||||||
foreach($fieldNames as $fieldKey => $fieldName) {
|
foreach($fieldNames as $fieldKey => $fieldName) {
|
||||||
|
|
||||||
@@ -2099,7 +2100,7 @@ class PagesLoader extends Wire {
|
|||||||
|
|
||||||
if($error) {
|
if($error) {
|
||||||
unset($fieldNames[$fieldKey]);
|
unset($fieldNames[$fieldKey]);
|
||||||
if($debug) $log['skipped'][$fieldName] = $error;
|
if($fieldName) $log['skipped'][] = "$fieldName ($error)";
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -2127,7 +2128,7 @@ class PagesLoader extends Wire {
|
|||||||
unset($fieldNames[$fieldKey]);
|
unset($fieldNames[$fieldKey]);
|
||||||
}
|
}
|
||||||
|
|
||||||
if(!count($selects)) return $debug ? $log : 0;
|
if(!count($selects)) return $log;
|
||||||
|
|
||||||
$level++;
|
$level++;
|
||||||
$timer = $debug ? Debug::timer() : false;
|
$timer = $debug ? Debug::timer() : false;
|
||||||
@@ -2158,58 +2159,90 @@ class PagesLoader extends Wire {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// wake up loaded values and populate to $page
|
// wake up loaded values and populate to $page
|
||||||
|
$pageIds = [];
|
||||||
|
|
||||||
foreach($data as $fieldName => $sleepValue) {
|
foreach($data as $fieldName => $sleepValue) {
|
||||||
if(!isset($loadFields[$fieldName])) continue;
|
if(!isset($loadFields[$fieldName])) {
|
||||||
|
unset($data[$fieldName]);
|
||||||
|
continue;
|
||||||
|
}
|
||||||
$field = $loadFields[$fieldName];
|
$field = $loadFields[$fieldName];
|
||||||
$fieldtype = $field->type;
|
$fieldtype = $field->type;
|
||||||
$cols = array_keys($sleepValue);
|
$cols = array_keys($sleepValue);
|
||||||
if(count($cols) === 1 && array_key_exists('data', $sleepValue)) {
|
if(count($cols) === 1 && array_key_exists('data', $sleepValue)) {
|
||||||
$sleepValue = $sleepValue['data'];
|
$sleepValue = $sleepValue['data'];
|
||||||
}
|
}
|
||||||
if($sleepValue === null) continue; // force to getBlankValue in loop below this
|
if($sleepValue === null) {
|
||||||
|
unset($data[$fieldName]);
|
||||||
|
continue; // force to getBlankValue in loop below this
|
||||||
|
}
|
||||||
if($options['useFieldtypeMulti'] && $fieldtype instanceof FieldtypeMulti) {
|
if($options['useFieldtypeMulti'] && $fieldtype instanceof FieldtypeMulti) {
|
||||||
if(strrpos($sleepValue, FieldtypeMulti::multiValueSeparator)) {
|
if(strrpos($sleepValue, FieldtypeMulti::multiValueSeparator)) {
|
||||||
$sleepValue = explode(FieldtypeMulti::multiValueSeparator, $sleepValue);
|
$sleepValue = explode(FieldtypeMulti::multiValueSeparator, $sleepValue);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
if($fieldtype instanceof FieldtypePage && $sleepValue && $options['loadPageRefs']) {
|
||||||
|
if(!is_array($sleepValue)) $sleepValue = [ $sleepValue ];
|
||||||
|
foreach($sleepValue as $pageId) {
|
||||||
|
$pageId = (int) $pageId;
|
||||||
|
if(!$pageId) continue;
|
||||||
|
if($this->pages->cacher()->hasCache($pageId)) continue;
|
||||||
|
$parentId = $field->get('parent_id');
|
||||||
|
$templateId = FieldtypePage::getTemplateIDs($field, true);
|
||||||
|
if(!ctype_digit("$parentId")) $parentId = 0;
|
||||||
|
if(!ctype_digit("$templateId")) $templateId = 0;
|
||||||
|
$groupKey = "$parentId,$templateId";
|
||||||
|
if(!isset($pageIds[$groupKey])) $pageIds[$groupKey] = [];
|
||||||
|
$pageIds[$groupKey][$pageId] = $pageId;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
$data[$fieldName] = $sleepValue;
|
||||||
|
}
|
||||||
|
|
||||||
|
// preload all pages in template or parent groups
|
||||||
|
if(count($pageIds)) {
|
||||||
|
foreach($pageIds as $groupKey => $ids) {
|
||||||
|
list($parentId, $templateId) = explode(',', $groupKey);
|
||||||
|
$this->pages->getByID($ids, [ 'template' => $templateId, 'parent_id' => $parentId ]);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
foreach($data as $fieldName => $sleepValue) {
|
||||||
|
$field = $loadFields[$fieldName];
|
||||||
|
$fieldtype = $field->type;
|
||||||
$value = $fieldtype->wakeupValue($page, $field, $sleepValue);
|
$value = $fieldtype->wakeupValue($page, $field, $sleepValue);
|
||||||
$page->_parentSet($field->name, $value);
|
$page->_parentSet($field->name, $value);
|
||||||
$loadedFields[$field->name] = $fieldName;
|
$loadedFields[$field->name] = $fieldName;
|
||||||
unset($loadFields[$field->name]);
|
unset($loadFields[$field->name]);
|
||||||
if($debug) {
|
$log['loaded'][] = $fieldName;
|
||||||
$log['loaded'][$fieldName] = "$fieldtype->shortName: " . implode(',', $cols);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// any remaining loadFields not present in DB should get blank value
|
// any remaining loadFields not present in DB should get blank value
|
||||||
foreach($loadFields as $field) {
|
foreach($loadFields as $field) {
|
||||||
$value = $field->type->getBlankValue($page, $field);
|
$value = $field->type->getBlankValue($page, $field);
|
||||||
$page->_parentSet($field->name, $value);
|
$fieldName = $field->name;
|
||||||
if($debug) $log['blank'][$field->name] = $field->type->shortName;
|
$page->_parentSet($fieldName, $value);
|
||||||
|
$log['blank'][] = $fieldName;
|
||||||
}
|
}
|
||||||
|
|
||||||
$numLoaded = count($loadedFields);
|
|
||||||
|
|
||||||
// go recursive for any remaining fields
|
// go recursive for any remaining fields
|
||||||
if(count($fieldNames)) {
|
if(count($fieldNames)) {
|
||||||
$result = $this->preloadFields($page, $fieldNames, $debug);
|
$result = $this->preloadFields($page, $fieldNames, $options);
|
||||||
if($debug) {
|
foreach($log as $key => $value) {
|
||||||
foreach($log as $key => $value) {
|
if(is_array($value)) {
|
||||||
if(is_array($value)) {
|
$log[$key] = array_merge($value, $result[$key]);
|
||||||
$log[$key] = array_merge($value, $result[$key]);
|
} else if(is_int($value)) {
|
||||||
} else if(is_int($value)) {
|
$log[$key] += $result[$key];
|
||||||
$log[$key] += $result[$key];
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
} else {
|
|
||||||
$numLoaded += $result;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
$level--;
|
$level--;
|
||||||
|
|
||||||
if($debug && $timer && !$level) $log['timer'] = Debug::timer($timer);
|
if($debug && $timer && !$level) $log['timer'] = Debug::timer($timer);
|
||||||
|
|
||||||
return $debug ? $log : $numLoaded;
|
return $log;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -2285,7 +2318,7 @@ class PagesLoader extends Wire {
|
|||||||
} else if($fieldtype instanceof FieldtypePage && $field->get('derefAsPage') > 0) {
|
} else if($fieldtype instanceof FieldtypePage && $field->get('derefAsPage') > 0) {
|
||||||
// allow single-page matches
|
// allow single-page matches
|
||||||
} else {
|
} else {
|
||||||
$error = "$shortName: Unsupported";
|
$error = "$shortName: Unsupported without useFieldtypeMulti=true";
|
||||||
}
|
}
|
||||||
} else if($fieldtype instanceof FieldtypeFieldsetOpen) {
|
} else if($fieldtype instanceof FieldtypeFieldsetOpen) {
|
||||||
$error = 'Fieldset: Unsupported';
|
$error = 'Fieldset: Unsupported';
|
||||||
|
Reference in New Issue
Block a user