mirror of
https://github.com/processwire/processwire.git
synced 2025-08-09 16:26:59 +02:00
Improvements to $pages->findRaw() based on requests. Added support getting "parent.field" and "parent.parent.field", etc. Added support for "references" and "references.field", etc. which returns matches from pages referencing the found pages via page reference fields (optionally include 'references.field' in requested fields list to index references by field name). Added support for FieldtypeOptions fields so that they can now return label, value, id or any of them by adding "your_options_field.label" (for example) in your requested $fields. Added new "flat" option which makes it returned flattened arrays for each page match... when used results are indexed in the same way they are requested, for example a result like [ 'page_field' => [ 'title' => 'Some title' ]] becomes [ 'page_field.title' => 'Some title' ]. Added support for requesting field 'meta' and 'meta.name' which returns Page meta data that you would usually access from $page->meta('name'). A few of these requests came from processwire/processwire-requests#427
This commit is contained in:
@@ -2699,8 +2699,9 @@ class PageFinder extends Wire {
|
||||
}
|
||||
$this->parent_id = null;
|
||||
if($isParent) {
|
||||
if($operator === '=') $IDs = $values;
|
||||
$field = 'parent_id';
|
||||
if(count($values) == 1 && count($fields) == 1 && $selector->operator() === '=') {
|
||||
if(count($values) == 1 && count($fields) == 1 && $operator === '=') {
|
||||
$this->parent_id = reset($values);
|
||||
}
|
||||
}
|
||||
@@ -2747,7 +2748,7 @@ class PageFinder extends Wire {
|
||||
$field = $subfield;
|
||||
}
|
||||
}
|
||||
} else if($field === 'id' && count($values) > 1 && $selector->operator === '=' && !$selector->not) {
|
||||
} else if($field === 'id' && count($values) > 1 && $operator === '=' && !$selector->not) {
|
||||
$IDs = $values;
|
||||
|
||||
} else {
|
||||
@@ -2776,7 +2777,7 @@ class PageFinder extends Wire {
|
||||
// convert templates specified as a name to the numeric template ID
|
||||
// allows selectors like 'template=my_template_name'
|
||||
$field = 'templates_id';
|
||||
if(count($values) == 1 && $selector->operator() === '=') $this->templates_id = reset($values);
|
||||
if(count($values) == 1 && $operator === '=') $this->templates_id = reset($values);
|
||||
if(!ctype_digit("$value")) $value = (($template = $this->templates->get($value)) ? $template->id : 0);
|
||||
|
||||
} else if(in_array($field, array('created', 'modified', 'published'))) {
|
||||
|
@@ -565,15 +565,25 @@ class Pages extends Wire {
|
||||
* $a = $pages->findRaw("template=blog, options=objects|entities");
|
||||
* ~~~~~
|
||||
*
|
||||
* In 3.0.193 the following additional options were added for the `$field` argument:
|
||||
*
|
||||
* - Specify `parent.field_name` or `parent.parent.field_name`, etc. to return values from parent(s).
|
||||
* - Specify `references` or `references.field_name`, etc. to also return values from pages referencing found pages.
|
||||
* - Specify `meta` or `meta.name` to also return values from page meta data.
|
||||
*
|
||||
* #pw-advanced
|
||||
* #pw-group-retrieval
|
||||
*
|
||||
* @param string|array|Selectors|int $selector Page matching selector or page ID
|
||||
* @param string|array|Field $field Name of field/property to get, or array of them, or omit to get all (default='')
|
||||
* Note: this argument may also be specified in the $selector argument as "field=foo" or "field=foo|bar|baz" (3.0.173+).
|
||||
* @param string|array|Field $field Name of field/property to get, or array of them, CSV string, or omit to get all (default='')
|
||||
* - Optionally use associative array to rename fields in returned value, i.e. `['title' => 'label']` returns 'title' as 'label' in return value.
|
||||
* - Note: this argument may also be specified in the $selector argument as "field=foo" or "field=foo|bar|baz" (3.0.173+).
|
||||
* @param array $options Options to adjust behavior (may also be specified in selector, i.e. “objects=1, entities=foo|bar”)
|
||||
* - `objects` (bool): Use objects rather than associative arrays? (default=false) 3.0.174+
|
||||
* - `entities` (bool|array): Entity encode string values? True or 1 to enable, or specify array of field names. (default=false) 3.0.174+
|
||||
* - `flat` (bool|string): Flatten return value as `["field.subfield" => "value"]` rather than `["field" => ["subfield" => "value"]]`?
|
||||
* Optionally specify field delimiter for the value, otherwise a period `.` will be used as the delimiter. (default=false) 3.0.193+
|
||||
* - Note the `objects` and `flat` options are not meant to be used together.
|
||||
* @return array
|
||||
* @since 3.0.172
|
||||
*
|
||||
|
@@ -30,12 +30,18 @@ class PagesRaw extends Wire {
|
||||
* Find pages and return raw data from them in a PHP array
|
||||
*
|
||||
* @param string|array|Selectors $selector
|
||||
* @param string|Field|int|array $field Field/property name to get or array of them (or omit to get all)
|
||||
* @param string|array|Field $field Name of field/property to get, or array of them, CSV string, or omit to get all (default='')
|
||||
* - Optionally use associative array to rename fields in returned value, i.e. `['title' => 'label']` returns 'title' as 'label' in return value.
|
||||
* - Specify `parent.field_name` or `parent.parent.field_name`, etc. to return values from parent(s). 3.0.193+
|
||||
* - Specify `references` or `references.field_name`, etc. to also return values from pages referencing found pages. 3.0.193+
|
||||
* - Specify `meta` or `meta.name` to also return values from page meta data. 3.0.193+
|
||||
* @param array $options See options for Pages::find
|
||||
* - `objects` (bool): Use objects rather than associative arrays? (default=false)
|
||||
* - `entities` (bool|array): Entity encode string values? True, or specify array of field names. (default=false)
|
||||
* - `indexed` (bool): Index by page ID? (default=true)
|
||||
* - `flat` (bool|string): Flatten return value as `["field.subfield" => "value"]` rather than `["field" => ["subfield" => "value"]]`?
|
||||
* Optionally specify field delimiter, otherwise a period `.` will be used as the delimiter. (default=false) 3.0.193+
|
||||
* - Note the `objects` and `flat` options are not meant to be used together.
|
||||
* @return array
|
||||
* @since 3.0.172
|
||||
*
|
||||
@@ -56,6 +62,8 @@ class PagesRaw extends Wire {
|
||||
* - `objects` (bool): Use objects rather than associative arrays? (default=false)
|
||||
* - `entities` (bool|array): Entity encode string values? True, or specify array of field names. (default=false)
|
||||
* - `indexed` (bool): Index by page ID? (default=false)
|
||||
* - `flat` (bool|string): Flatten return value as `["field.subfield" => "value"]` rather than `["field" => ["subfield" => "value"]]`?
|
||||
* Optionally specify field delimiter, otherwise a period `.` will be used as the delimiter. (default=false) 3.0.193+
|
||||
* @return array
|
||||
* @since 3.0.172
|
||||
*
|
||||
@@ -256,6 +264,7 @@ class PagesRawFinder extends Wire {
|
||||
'objects' => false,
|
||||
'entities' => false,
|
||||
'findOne' => false,
|
||||
'flat' => false,
|
||||
);
|
||||
|
||||
/**
|
||||
@@ -314,6 +323,14 @@ class PagesRawFinder extends Wire {
|
||||
*/
|
||||
protected $renameFields = array();
|
||||
|
||||
/**
|
||||
* Temporary fields set to $this->value that should be unset from return value
|
||||
*
|
||||
* @var array
|
||||
*
|
||||
*/
|
||||
protected $unsetFields = array();
|
||||
|
||||
/**
|
||||
* @var array
|
||||
*
|
||||
@@ -479,7 +496,7 @@ class PagesRawFinder extends Wire {
|
||||
|
||||
// detect 'objects' and 'entities' options in selector
|
||||
$optionsValues = array();
|
||||
foreach(array('objects', 'entities', 'options') as $name) {
|
||||
foreach(array('objects', 'entities', 'flat', 'options') as $name) {
|
||||
if($this->selectorIsPageIDs) continue;
|
||||
if($selectorString && strpos($selectorString, "$name=") === false) continue;
|
||||
if($fields->get($name)) continue; // if maps to a real field then ignore
|
||||
@@ -504,7 +521,7 @@ class PagesRawFinder extends Wire {
|
||||
}
|
||||
if(!empty($result['selectors'])) $this->selector = $result['selectors'];
|
||||
}
|
||||
foreach(array('objects', 'entities') as $name) {
|
||||
foreach(array('objects', 'entities', 'flat') as $name) {
|
||||
if(in_array($name, $optionsValues)) $this->options[$name] = true;
|
||||
}
|
||||
}
|
||||
@@ -544,6 +561,12 @@ class PagesRawFinder extends Wire {
|
||||
|
||||
$this->init($selector, $field, $options);
|
||||
|
||||
if(count($this->parentFields) && !isset($this->nativeFields['parent_id'])) {
|
||||
// we need parent_id if finding any parent fields
|
||||
$this->nativeFields['parent_id'] = 'parent_id';
|
||||
$this->unsetFields['parent_id'] = 'parent_id';
|
||||
}
|
||||
|
||||
// requested native pages table fields/properties
|
||||
if(count($this->nativeFields) || $this->getAll || $this->getPaths) {
|
||||
// one or more native pages table column(s) requested
|
||||
@@ -555,6 +578,25 @@ class PagesRawFinder extends Wire {
|
||||
$this->findCustom();
|
||||
}
|
||||
|
||||
// requested runtime fields
|
||||
if(count($this->runtimeFields)) {
|
||||
$this->findRuntime();
|
||||
}
|
||||
|
||||
// requested parent fields
|
||||
if(count($this->parentFields)) {
|
||||
$this->findParent();
|
||||
}
|
||||
|
||||
// remove runtime only fields
|
||||
if(count($this->unsetFields)) {
|
||||
foreach($this->unsetFields as $name) {
|
||||
foreach($this->values as $key => $value) {
|
||||
unset($this->values[$key][$name]);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// reduce return value when expected
|
||||
if(!$this->getMultiple) {
|
||||
foreach($this->values as $id => $row) {
|
||||
@@ -576,6 +618,13 @@ class PagesRawFinder extends Wire {
|
||||
}
|
||||
}
|
||||
|
||||
if($this->options['flat']) {
|
||||
$delimiter = is_string($this->options['flat']) ? $this->options['flat'] : '.';
|
||||
foreach($this->values as $key => $value) {
|
||||
$this->values[$key] = $this->flattenValues($value, '', $delimiter);
|
||||
}
|
||||
}
|
||||
|
||||
if($this->options['objects']) {
|
||||
$this->objects($this->values);
|
||||
}
|
||||
@@ -595,6 +644,7 @@ class PagesRawFinder extends Wire {
|
||||
|
||||
$fields = $this->wire()->fields;
|
||||
$fails = array();
|
||||
$runtimeNames = array('meta', 'references');
|
||||
|
||||
// split request fields into custom fields and native (pages table) fields
|
||||
foreach($this->requestFields as $key => $fieldName) {
|
||||
@@ -620,6 +670,10 @@ class PagesRawFinder extends Wire {
|
||||
$fieldName = $key;
|
||||
if($fieldName === 'parent' || $fieldName === 'children') {
|
||||
// passthru
|
||||
} else if(in_array($fieldName, $runtimeNames) && !$fields->get($fieldName)) {
|
||||
// passthru
|
||||
$this->runtimeFields[$fullName] = $fullName;
|
||||
continue;
|
||||
} else {
|
||||
$fieldObject = isset($this->customFields[$fieldName]) ? $this->customFields[$fieldName] : null;
|
||||
if(!$fieldObject) $fieldObject = $fields->get($fieldName);
|
||||
@@ -641,6 +695,10 @@ class PagesRawFinder extends Wire {
|
||||
}
|
||||
if($fieldName === 'parent' || $fieldName === 'children') {
|
||||
// passthru
|
||||
} else if(in_array($fieldName, $runtimeNames) && !$fields->get($fieldName)) {
|
||||
// passthru
|
||||
$this->runtimeFields[$fullName] = $fullName;
|
||||
continue;
|
||||
} else {
|
||||
$fieldObject = isset($this->customFields[$fieldName]) ? $this->customFields[$fieldName] : null;
|
||||
if(!$fieldObject) $fieldObject = $fields->get($fieldName);
|
||||
@@ -653,12 +711,11 @@ class PagesRawFinder extends Wire {
|
||||
}
|
||||
|
||||
if($fieldName === 'parent') {
|
||||
// @todo not yet supported
|
||||
$this->parentFields[$fullName] = array($fieldName, $colName);
|
||||
$this->parentFields[$fullName] = $colName;
|
||||
|
||||
} else if($fieldName === 'children') {
|
||||
// @todo not yet supported
|
||||
$this->childrenFields[$fullName] = array($fieldName, $colName);
|
||||
$this->childrenFields[$fullName] = $colName;
|
||||
|
||||
} else if($fullName === 'url' || $fullName === 'path') {
|
||||
if($this->wire()->modules->isInstalled('PagePaths')) {
|
||||
@@ -783,7 +840,7 @@ class PagesRawFinder extends Wire {
|
||||
// one or more custom fields requested
|
||||
if($this->ids === null) {
|
||||
// only find IDs if we didn’t already in the nativeFields section
|
||||
$this->ids = $this->findIDs($this->selector, false);
|
||||
$this->setIds($this->findIDs($this->selector, false));
|
||||
}
|
||||
if(!count($this->ids)) return;
|
||||
foreach($this->customFields as $fieldName => $field) {
|
||||
@@ -812,7 +869,9 @@ class PagesRawFinder extends Wire {
|
||||
$getCols = array();
|
||||
$skipCols = array();
|
||||
$getAllCols = false;
|
||||
$getExternal = false; // true when request includes columns not in field’s DB schema
|
||||
$pageRefCols = array();
|
||||
$externalCols = array(); // columns that are external from field’s DB schema
|
||||
|
||||
/** @var FieldtypeMulti $fieldtypeMulti */
|
||||
$fieldtype = $field->type;
|
||||
@@ -848,6 +907,7 @@ class PagesRawFinder extends Wire {
|
||||
|
||||
} else if(reset($cols) === '*') {
|
||||
$getAllCols = true;
|
||||
if(wireInstanceOf($field->type, 'FieldtypeOptions')) $getExternal = true;
|
||||
|
||||
} else {
|
||||
foreach($cols as $key => $col) {
|
||||
@@ -858,14 +918,17 @@ class PagesRawFinder extends Wire {
|
||||
} else if($fieldtypePage || $fieldtypeRepeater) {
|
||||
$pageRefCols[$col] = $col;
|
||||
} else {
|
||||
// unknown column
|
||||
// unknown or external column
|
||||
$getCols['data'] = 'data';
|
||||
$externalCols[$col] = $col;
|
||||
$getExternal = true;
|
||||
}
|
||||
}
|
||||
if(count($pageRefCols)) {
|
||||
// get just the data column when a field within a Page reference is asked for
|
||||
$getCols['data'] = 'data';
|
||||
}
|
||||
if(count($getCols) === 1 && !$this->getMultiple) {
|
||||
if(count($getCols) === 1 && !$this->getMultiple && count($externalCols) < 2) {
|
||||
// if only getting single field we will populate its value rather than
|
||||
// its value in an associative array
|
||||
$getArray = false;
|
||||
@@ -966,10 +1029,82 @@ class PagesRawFinder extends Wire {
|
||||
$this->findCustomFieldtypePage($field, $fieldName, $pageRefCols);
|
||||
}
|
||||
}
|
||||
|
||||
if($getExternal) {
|
||||
if(wireInstanceOf($fieldtype, 'FieldtypeOptions')) {
|
||||
$this->findCustomFieldtypeOptions($field, $externalCols, $getArray, $getAllCols);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Find custom Options fieldtype columns
|
||||
*
|
||||
* Options field stores its values/titles in separate table.
|
||||
*
|
||||
* To use, specify one of the following in the fields to get (where field_name is an options field name):
|
||||
*
|
||||
* - `field_name` to just include the IDs of the selected options for each page.
|
||||
* - `field_name.*` to include all available properties for selected options for each page.
|
||||
* - `field_name.title` to include the selected option titles.
|
||||
* - `field_name.value` to include the selected option values.
|
||||
*
|
||||
* @param Field $field
|
||||
* @param array $cols
|
||||
* @param bool $getArray
|
||||
* @param bool $getAllCols
|
||||
* @since 3.0.193
|
||||
*
|
||||
*/
|
||||
protected function findCustomFieldtypeOptions(Field $field, $cols, $getArray, $getAllCols) {
|
||||
/** @var FieldtypeOptions $fieldtype */
|
||||
$fieldtype = $field->type;
|
||||
$fieldName = $field->name;
|
||||
$options = $fieldtype->getOptions($field);
|
||||
$firstColName = reset($cols);
|
||||
|
||||
foreach($this->values as $pageId => $data) {
|
||||
if(!isset($data[$fieldName])) continue;
|
||||
foreach($data[$fieldName] as $key => $optionValue) {
|
||||
if(is_array($optionValue)) {
|
||||
$optionId = (int) $optionValue['data'];
|
||||
} else if(ctype_digit("$optionValue")) {
|
||||
$optionId = (int) $optionValue;
|
||||
} else {
|
||||
continue; // not likely
|
||||
}
|
||||
/** @var SelectableOption $option */
|
||||
$option = $options->get((int) $optionId);
|
||||
if(!$option) {
|
||||
// unknown option
|
||||
} else if($getAllCols) {
|
||||
$a = $option->getArray();
|
||||
unset($a['sort']);
|
||||
$this->values[$pageId][$fieldName][$key] = $a;
|
||||
} else if($getArray) {
|
||||
$this->values[$pageId][$fieldName][$key] = array();
|
||||
foreach($cols as $colName) {
|
||||
$value = $option->get($colName);
|
||||
if(!is_string($value) && !is_int($value)) $value = null;
|
||||
$this->values[$pageId][$fieldName][$key][$colName] = $option->get($colName);
|
||||
}
|
||||
} else {
|
||||
$value = $option->get($firstColName); // i.e. title, value, id, title1234, etc.
|
||||
$this->values[$pageId][$fieldName][$key] = (is_string($value) || is_int($value) ? $value : null);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Find and apply values for Page reference fields
|
||||
*
|
||||
* @param Field $field
|
||||
* @param string $fieldName
|
||||
* @param array $pageRefCols
|
||||
*
|
||||
*/
|
||||
protected function findCustomFieldtypePage(Field $field, $fieldName, array $pageRefCols) {
|
||||
// print_r($values);
|
||||
$pageRefIds = array();
|
||||
foreach($this->values as $pageId => $row) {
|
||||
if(!isset($row[$fieldName])) continue;
|
||||
@@ -1025,6 +1160,213 @@ class PagesRawFinder extends Wire {
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Find and apply values for parent.[field]
|
||||
*
|
||||
* @since 3.0.193
|
||||
*
|
||||
*/
|
||||
protected function findParent() {
|
||||
|
||||
$ids = array();
|
||||
|
||||
foreach($this->values as $pageId => $data) {
|
||||
$parentId = $data['parent_id'];
|
||||
if(!isset($ids[$parentId])) $ids[$parentId] = array();
|
||||
$ids[$parentId][] = $pageId;
|
||||
}
|
||||
|
||||
$finder = new PagesRawFinder($this->pages);
|
||||
$this->wire($finder);
|
||||
$options = $this->options;
|
||||
$options['indexed'] = true;
|
||||
$parentFields = array_values($this->parentFields);
|
||||
|
||||
if(!$this->getMultiple && count($parentFields) < 2) {
|
||||
$parentFields = reset($parentFields);
|
||||
}
|
||||
|
||||
$rows = $finder->find(array_keys($ids), $parentFields, $options);
|
||||
|
||||
foreach($rows as $parentId => $row) {
|
||||
foreach($ids[$parentId] as $pageId) {
|
||||
$this->values[$pageId]['parent'] = $row;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Find runtime generated fields
|
||||
*
|
||||
* @since 3.0.193
|
||||
*
|
||||
*/
|
||||
protected function findRuntime() {
|
||||
|
||||
$runtimeFields = array();
|
||||
$fieldNames = $this->runtimeFields;
|
||||
|
||||
unset($fieldNames['url'], $fieldNames['path']);
|
||||
|
||||
if(empty($fieldNames)) return;
|
||||
|
||||
if($this->ids === null) {
|
||||
$this->setIds($this->findIDs($this->selector, false));
|
||||
}
|
||||
|
||||
foreach($fieldNames as $fieldName) {
|
||||
$colName = '';
|
||||
if(strpos($fieldName, '.')) list($fieldName, $colName) = explode('.', $fieldName, 2);
|
||||
if(!isset($runtimeFields[$fieldName])) $runtimeFields[$fieldName] = array();
|
||||
if($colName) $runtimeFields[$fieldName][] = $colName;
|
||||
}
|
||||
|
||||
if(isset($runtimeFields['meta'])) {
|
||||
$this->findMeta($runtimeFields['meta']);
|
||||
}
|
||||
|
||||
if(isset($runtimeFields['references'])) {
|
||||
$this->findReferences($runtimeFields['references']);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Populate 'meta' to (form pages_meta table) to the result values
|
||||
*
|
||||
* @param array $names
|
||||
* @since 3.0.193
|
||||
*
|
||||
*/
|
||||
protected function findMeta(array $names) {
|
||||
|
||||
if(empty($this->ids)) return;
|
||||
$this->ids(true);
|
||||
|
||||
$getAll = $this->getAll || in_array('*', $names, true) || empty($names);
|
||||
if($getAll) $names = array();
|
||||
|
||||
$sql = "SELECT source_id, name, data FROM pages_meta WHERE source_id IN($this->ids)";
|
||||
$query = $this->wire()->database->prepare($sql);
|
||||
$query->execute();
|
||||
|
||||
while($row = $query->fetch(\PDO::FETCH_ASSOC)) {
|
||||
$id = (int) $row['source_id'];
|
||||
$name = $row['name'];
|
||||
$data = json_decode($row['data'], true);
|
||||
if(!isset($this->values[$id]['meta'])) $this->values[$id]['meta'] = array();
|
||||
if($getAll || in_array($name, $names, true)) $this->values[$id]['meta'][$name] = $data;
|
||||
}
|
||||
|
||||
foreach(array_keys($this->values) as $id) {
|
||||
if(!isset($this->values[$id]['meta'])) $this->values[$id]['meta'] = array();
|
||||
}
|
||||
|
||||
$query->closeCursor();
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Populate a 'references' to the raw results that includes other pages referencing the found ones
|
||||
*
|
||||
* To use this specify `references` in the fields to return. Or, to get page references that are
|
||||
* indexed by field name, specify `references.field` instead. To get something more than the id
|
||||
* of page references, specify properties or fields as `references.field_name` replacing `field_name`
|
||||
* with a page property or field name, i.e. `references.title`.
|
||||
*
|
||||
* @param array $colNames
|
||||
* @since 3.0.193
|
||||
*
|
||||
*/
|
||||
protected function findReferences(array $colNames) {
|
||||
|
||||
$database = $this->wire()->database;
|
||||
$pageFields = array();
|
||||
|
||||
foreach($this->wire()->fields as $field) {
|
||||
if($field->type instanceof FieldtypePage) $pageFields[$field->name] = $field;
|
||||
}
|
||||
|
||||
foreach($this->values as $id => $data) {
|
||||
$this->values[$id]['references'] = array();
|
||||
}
|
||||
|
||||
$showField = array_search('field', $colNames);
|
||||
if($showField !== false) {
|
||||
unset($colNames[$showField]);
|
||||
$showField = true;
|
||||
}
|
||||
|
||||
$this->ids(true);
|
||||
$fromPageIds = array();
|
||||
$findPageIds = array();
|
||||
|
||||
foreach($pageFields as $pageField) {
|
||||
$fieldName = $pageField->name;
|
||||
|
||||
/** @var Field $pageField */
|
||||
$table = $pageField->getTable();
|
||||
$sql = "SELECT pages_id, data FROM $table WHERE data IN($this->ids)";
|
||||
$query = $database->prepare($sql);
|
||||
$query->execute();
|
||||
|
||||
while($row = $query->fetch(\PDO::FETCH_NUM)) {
|
||||
$fromPageId = (int) $row[0]; // pages_id
|
||||
$toPageId = (int) $row[1]; // data
|
||||
if(!isset($fromPageIds[$toPageId])) $fromPageIds[$toPageId] = array();
|
||||
if(!isset($fromPageIds[$toPageId][$fieldName])) $fromPageIds[$toPageId][$fieldName] = array();
|
||||
$fromPageIds[$toPageId][$fieldName][] = $fromPageId;
|
||||
$findPageIds[] = $fromPageId;
|
||||
}
|
||||
|
||||
$query->closeCursor();
|
||||
}
|
||||
|
||||
if(!count($findPageIds)) return;
|
||||
|
||||
if(empty($colNames)) {
|
||||
// shortcut: we only need to include the ids
|
||||
foreach($this->values as $toPageId => $data) {
|
||||
if(!isset($fromPageIds[$toPageId])) continue;
|
||||
if($showField) {
|
||||
$references = $fromPageIds[$toPageId];
|
||||
} else {
|
||||
$references = array();
|
||||
foreach($fromPageIds[$toPageId] as $fieldName => $ids) {
|
||||
$references = array_merge($references, $ids);
|
||||
}
|
||||
}
|
||||
$this->values[$toPageId]['references'] = $references;
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
// load properties/fields from found references
|
||||
$finder = new PagesRawFinder($this->pages);
|
||||
$this->wire($finder);
|
||||
$options = $this->options;
|
||||
$options['indexed'] = true;
|
||||
$colNames = $this->getMultiple || count($colNames) > 1 ? $colNames : reset($colNames);
|
||||
$rows = $finder->find($findPageIds, $colNames, $options);
|
||||
|
||||
foreach($this->values as $toPageId => $data) {
|
||||
if(!isset($fromPageIds[$toPageId])) continue;
|
||||
foreach($fromPageIds[$toPageId] as $fieldName => $fromIds) {
|
||||
foreach($fromIds as $fromId) {
|
||||
if(!isset($rows[$fromId])) continue;
|
||||
$row = $rows[$fromId];
|
||||
if($showField) {
|
||||
if(!isset($this->values[$toPageId]['references'][$fieldName])) {
|
||||
$this->values[$toPageId]['references'][$fieldName] = array();
|
||||
}
|
||||
$this->values[$toPageId]['references'][$fieldName][$fromId] = $row;
|
||||
} else {
|
||||
$this->values[$toPageId]['references'][$fromId] = $row;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Front-end to pages.findIDs that optionally accepts array of page IDs
|
||||
*
|
||||
@@ -1191,6 +1533,67 @@ class PagesRawFinder extends Wire {
|
||||
return $this->ids;
|
||||
}
|
||||
|
||||
/**
|
||||
* Set the found IDs and init the $this->values array
|
||||
*
|
||||
* @param array $ids
|
||||
* @since 3.0.193
|
||||
*
|
||||
*/
|
||||
protected function setIds(array $ids) {
|
||||
$this->ids = $ids;
|
||||
foreach($ids as $id) {
|
||||
$this->values[$id] = array();
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Flatten multidimensional values from array['a']['b']['c'] to array['a.b.c']
|
||||
*
|
||||
* @param array $values
|
||||
* @param string $prefix Prefix for recursive use
|
||||
* @param string $delimiter
|
||||
* @return array
|
||||
* @since 3.0.193
|
||||
*
|
||||
*/
|
||||
protected function flattenValues(array $values, $prefix = '', $delimiter = '.') {
|
||||
|
||||
$flat = array();
|
||||
|
||||
foreach($values as $key => $value) {
|
||||
|
||||
if(!is_array($value)) {
|
||||
$flat["$prefix$key"] = $value;
|
||||
continue;
|
||||
}
|
||||
|
||||
$a = $this->flattenValues($value, "$prefix$key$delimiter", $delimiter);
|
||||
|
||||
if(!is_int($key)) {
|
||||
$flat = $flat + $a;
|
||||
continue;
|
||||
}
|
||||
|
||||
$converted = false;
|
||||
|
||||
// convert categories.1234.title => categories.title = array(1234 => 'title', ...);
|
||||
foreach($a as $k => $v) {
|
||||
if(strpos($k, "$delimiter$key$delimiter") === false) continue;
|
||||
list($k1, $k2) = explode("$delimiter$key$delimiter", $k);
|
||||
unset($a[$k]);
|
||||
$kk = "$k1$delimiter$k2";
|
||||
if(!isset($flat[$kk])) $flat[$kk] = array();
|
||||
$flat[$kk][$key] = $v;
|
||||
$converted = true;
|
||||
}
|
||||
|
||||
if(!$converted) $flat = $flat + $a;
|
||||
}
|
||||
return $flat;
|
||||
}
|
||||
|
||||
|
||||
protected function unknownFieldsException(array $fieldNames, $context = '') {
|
||||
if($context) $context = " $context";
|
||||
$s = "Unknown$context name(s) for findRaw: " . implode(', ', $fieldNames);
|
||||
|
Reference in New Issue
Block a user