1
0
mirror of https://github.com/processwire/processwire.git synced 2025-08-09 08:17:12 +02:00

Updated $pages->findRaw() to have new 'objects' and 'entities' options. The objects option makes it return StdClass objects to represent pages and other data rather than associative arrays (requested by @adrianbj). The entities option makes it entity-encode string values in case you are using findRaw() values for HTML output purposes.

This commit is contained in:
Ryan Cramer
2021-03-11 13:10:45 -05:00
parent 7cb11850e8
commit a24d09b8d0
2 changed files with 134 additions and 5 deletions

View File

@@ -520,6 +520,20 @@ class Pages extends Wire {
* // If you prefer, you can specify the field name(s) in the selector (3.0.173+):
* $a = $pages->findRaw("template=blog, field=title");
* $a = $pages->findRaw("template=blog, field=title|categories.title");
*
* // Specify “objects=1” in selector to use objects rather than associative arrays
* // for pages and fields (3.0.174+):
* $a = $pages->findRaw("template=blog, field=title|categories.title, objects=1");
*
* // Specify “entities=1” to entity encode all string values:
* $a = $pages->findRaw("template=blog, field=title|summary, entities=1");
*
* // Specify “entities=field” or “entities=field1|field2” to entity encode just
* // the specific fields that you name (3.0.174+):
* $a = $pages->findRaw("template=blog, entities=title|summary");
*
* // If you prefer, options can also be enabled this way (3.0.174+):
* $a = $pages->findRaw("template=blog, options=objects|entities");
* ~~~~~
*
* #pw-advanced
@@ -528,7 +542,9 @@ class Pages extends Wire {
* @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 array $options
* @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+
* @return array
* @since 3.0.172
*

View File

@@ -32,7 +32,9 @@ class PagesRaw extends Wire {
* @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 array $options See options for Pages::find
* - `indexed` (bool): Index by page ID? (default=false)
* - `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)
* @return array
* @since 3.0.172
*
@@ -49,7 +51,9 @@ class PagesRaw extends Wire {
*
* @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 array $options See options for Pages::find
* @param array|bool $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=false)
* @return array
* @since 3.0.172
@@ -89,6 +93,8 @@ class PagesRawFinder extends Wire {
*/
protected $defaults = array(
'indexed' => true,
'objects' => false,
'entities' => false,
'findOne' => false,
);
@@ -98,6 +104,12 @@ class PagesRawFinder extends Wire {
*/
protected $selector = '';
/**
* @var bool
*
*/
protected $selectorIsPageIDs = false;
/**
* @var array
*
@@ -207,6 +219,9 @@ class PagesRawFinder extends Wire {
*
*/
protected function init($selector, $field, $options) {
$fields = $this->wire()->fields;
$selectorString = '';
$this->selector = $selector;
$this->options = array_merge($this->defaults, $options);
@@ -218,17 +233,25 @@ class PagesRawFinder extends Wire {
$this->getMultiple = true;
$this->getAll = false;
$this->ids = null;
if(is_array($selector)) {
$val = reset($selector);
$key = key($selector);
if(ctype_digit("$key") && ctype_digit("$val")) $this->selectorIsPageIDs = true;
} else {
$selectorString = (string) $selector;
}
if(empty($field)) {
if(empty($field) && !$this->selectorIsPageIDs) {
// check if field specified in selector instead
$field = array();
$multi = false;
$fields = $this->wire()->fields;
if(!$selector instanceof Selectors) {
$selector = new Selectors($selector);
$this->wire($selector);
}
foreach($selector as $item) {
if(!$item instanceof SelectorEqual) continue;
$name = $item->field();
if($name !== 'field' && $name !== 'join' && $name !== 'fields') continue;
if($name !== 'fields' && $fields->get($name)) continue;
@@ -274,6 +297,37 @@ class PagesRawFinder extends Wire {
// split request fields into nativeFields and customFields
$this->splitFields();
}
// detect 'objects' and 'entities' options in selector
$optionsValues = array();
foreach(array('objects', 'entities', '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
$result = Selectors::selectorHasField($this->selector, $name, array(
'operator' => '=',
'verbose' => true,
'remove' => true,
));
$value = $result['value'];
if($result['result'] && $value && !isset($options[$name])) {
if($name === 'options') {
if(is_string($value)) $optionsValues[] = $value;
if(is_array($value)) $optionsValues = array_merge($optionsValues, $value);
} else if(is_array($value)) {
$this->options[$name] = array();
foreach($value as $v) $this->options[$name][$v] = $v;
} else if(!ctype_digit("$value")) {
$this->options[$name] = $value;
} else {
$this->options[$name] = (bool) ((int) $value);
}
}
if(!empty($result['selectors'])) $this->selector = $result['selectors'];
}
foreach(array('objects', 'entities') as $name) {
if(in_array($name, $optionsValues)) $this->options[$name] = true;
}
}
/**
@@ -300,6 +354,9 @@ class PagesRawFinder extends Wire {
*
*/
public function find($selector, $field = '', $options = array()) {
static $level = 0;
$level++;
$this->init($selector, $field, $options);
@@ -324,6 +381,18 @@ class PagesRawFinder extends Wire {
if(!$this->options['indexed']) {
$this->values = array_values($this->values);
}
if($this->options['entities']) {
if($this->options['objects'] || $level === 1) {
$this->entities($this->values);
}
}
if($this->options['objects']) {
$this->objects($this->values);
}
$level--;
return $this->values;
}
@@ -841,6 +910,50 @@ class PagesRawFinder extends Wire {
return $rows;
}
/**
* Convert associative arrays to objects
*
* @param array $values
*
*/
protected function objects(&$values) {
foreach(array_keys($values) as $key) {
$value = $values[$key];
if(!is_array($value)) continue;
reset($value);
if(is_int(key($value))) continue;
$this->objects($value);
$values[$key] = (object) $value;
}
}
/**
* Apply entity encoding to all strings in given value, recursively
*
* @param mixed $value
*
*/
protected function entities(&$value) {
$prefix = ''; // populate for testing only
if(is_string($value)) {
// entity-encode
$value = $prefix . htmlentities($value, ENT_QUOTES, 'UTF-8');
} else if(is_array($value)) {
// iterate and go recursive
foreach(array_keys($value) as $key) {
if(is_array($value[$key])) {
$this->entities($value[$key]);
} else if(is_string($value[$key])) {
if($this->options['entities'] === true || $this->options['entities'] === $key || isset($this->options['entities'][$key])) {
$value[$key] = $prefix . htmlentities($value[$key], ENT_QUOTES, 'UTF-8');
}
}
}
} else {
// leave as-is
}
}
/**
* Get or convert $this->ids to/from CSV
*