mirror of
https://github.com/processwire/processwire.git
synced 2025-08-07 15:26:54 +02:00
Optimizations to WireArray and some descending classes
This commit is contained in:
@@ -5,7 +5,7 @@
|
||||
*
|
||||
* WireArray of Fieldgroup instances as used by Fieldgroups class.
|
||||
*
|
||||
* ProcessWire 3.x, Copyright 2016 by Ryan Cramer
|
||||
* ProcessWire 3.x, Copyright 2024 by Ryan Cramer
|
||||
* https://processwire.com
|
||||
*
|
||||
*
|
||||
@@ -25,6 +25,7 @@ class FieldgroupsArray extends WireArray {
|
||||
*
|
||||
*/
|
||||
public function getItemKey($item) {
|
||||
/** @var Fieldgroup $item */
|
||||
return $item->id;
|
||||
}
|
||||
|
||||
|
@@ -6,7 +6,7 @@
|
||||
* #pw-summary Maintains a collection of Fieldtype modules.
|
||||
* #pw-var $fieldtypes
|
||||
*
|
||||
* ProcessWire 3.x, Copyright 2020 by Ryan Cramer
|
||||
* ProcessWire 3.x, Copyright 2024 by Ryan Cramer
|
||||
* https://processwire.com
|
||||
*
|
||||
* @property FieldtypeCheckbox $FieldtypeCheckbox
|
||||
@@ -88,13 +88,24 @@ class Fieldtypes extends WireArray {
|
||||
*/
|
||||
protected $isAPI = false;
|
||||
|
||||
/**
|
||||
* Construct
|
||||
*
|
||||
*/
|
||||
public function __construct() {
|
||||
parent::__construct();
|
||||
$this->usesNumericKeys = false;
|
||||
$this->indexedByName = true;
|
||||
$this->nameProperty = 'className';
|
||||
}
|
||||
|
||||
/**
|
||||
* Construct the $fieldtypes API var (load all Fieldtype modules into it)
|
||||
*
|
||||
*/
|
||||
public function init() {
|
||||
$this->isAPI = true;
|
||||
foreach($this->wire()->modules->findByPrefix('Fieldtype', 3) as $name => $module) {
|
||||
foreach($this->wire()->modules->findByPrefix('Fieldtype', 3) as /* $name => */ $module) {
|
||||
$this->add($module);
|
||||
}
|
||||
}
|
||||
@@ -153,16 +164,6 @@ class Fieldtypes extends WireArray {
|
||||
return $item->className();
|
||||
}
|
||||
|
||||
/**
|
||||
* Does this WireArray use numeric keys only?
|
||||
*
|
||||
* @return bool
|
||||
*
|
||||
*/
|
||||
protected function usesNumericKeys() {
|
||||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
* Per the WireArray interface, return a blank copy
|
||||
*
|
||||
@@ -229,5 +230,3 @@ class Fieldtypes extends WireArray {
|
||||
public function getNext($item, $strict = true) { $this->preload(); return parent::getNext($item, $strict); }
|
||||
public function getPrev($item, $strict = true) { $this->preload(); return parent::getPrev($item, $strict); }
|
||||
}
|
||||
|
||||
|
||||
|
@@ -5,13 +5,19 @@
|
||||
*
|
||||
* The default numeric indexing of a WireArray is not overridden.
|
||||
*
|
||||
* ProcessWire 3.x, Copyright 2016 by Ryan Cramer
|
||||
* ProcessWire 3.x, Copyright 2024 by Ryan Cramer
|
||||
* https://processwire.com
|
||||
*
|
||||
*/
|
||||
|
||||
class InputfieldsArray extends WireArray {
|
||||
|
||||
public function __construct() {
|
||||
parent::__construct();
|
||||
$this->usesNumericKeys = true;
|
||||
$this->indexedByName = false;
|
||||
}
|
||||
|
||||
/**
|
||||
* Per WireArray interface, only Inputfield instances are accepted.
|
||||
*
|
||||
@@ -31,6 +37,7 @@ class InputfieldsArray extends WireArray {
|
||||
*
|
||||
*/
|
||||
public function find($selector) {
|
||||
/** @var WireArray|InputfieldsArray $a */
|
||||
$a = parent::find($selector);
|
||||
foreach($this as $item) {
|
||||
if(!$item instanceof InputfieldWrapper) continue;
|
||||
@@ -44,8 +51,4 @@ class InputfieldsArray extends WireArray {
|
||||
return null; // Inputfield is abstract, so there is nothing to return here
|
||||
}
|
||||
|
||||
public function usesNumericKeys() {
|
||||
return true;
|
||||
}
|
||||
|
||||
}
|
||||
|
@@ -508,6 +508,12 @@ class Notices extends WireArray {
|
||||
|
||||
const logAllNotices = false; // for debugging/dev purposes
|
||||
|
||||
public function __construct() {
|
||||
parent::__construct();
|
||||
$this->usesNumericKeys = true;
|
||||
$this->indexedByName = false;
|
||||
}
|
||||
|
||||
/**
|
||||
* Initialize Notices API var
|
||||
*
|
||||
@@ -549,7 +555,8 @@ class Notices extends WireArray {
|
||||
*/
|
||||
protected function allowNotice(Notice $item) {
|
||||
|
||||
$user = $this->wire()->user;
|
||||
// intentionally not using $this->wire()->user; in case this gets called early in boot
|
||||
$user = $this->wire('user');
|
||||
|
||||
if($item->flags & Notice::debug) {
|
||||
if(!$this->wire()->config->debug) return false;
|
||||
|
@@ -74,6 +74,16 @@ class PageArray extends PaginatedArray implements WirePaginatable {
|
||||
*/
|
||||
protected $keyIndex = array();
|
||||
|
||||
/**
|
||||
* Construct
|
||||
*
|
||||
*/
|
||||
public function __construct() {
|
||||
parent::__construct();
|
||||
$this->indexedByName = false;
|
||||
$this->usesNumericKeys = true;
|
||||
}
|
||||
|
||||
/**
|
||||
* Template method that descendant classes may use to validate items added to this WireArray
|
||||
*
|
||||
@@ -142,18 +152,6 @@ class PageArray extends PaginatedArray implements WirePaginatable {
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Does this PageArray use numeric keys only? (yes it does)
|
||||
*
|
||||
* Defined here to override the slower check in WireArray
|
||||
*
|
||||
* @return bool
|
||||
*
|
||||
*/
|
||||
protected function usesNumericKeys() {
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* Per WireArray interface, return a blank Page
|
||||
*
|
||||
|
@@ -124,6 +124,8 @@ class Pagefiles extends WireArray implements PageFieldValueInterface {
|
||||
public function __construct(Page $page) {
|
||||
$this->setPage($page);
|
||||
parent::__construct();
|
||||
$this->usesNumericKeys = false;
|
||||
$this->indexedByName = true;
|
||||
}
|
||||
|
||||
/**
|
||||
|
@@ -109,6 +109,8 @@ class Selectors extends WireArray {
|
||||
*/
|
||||
public function __construct($selector = null) {
|
||||
parent::__construct();
|
||||
$this->usesNumericKeys = false;
|
||||
$this->indexedByName = false;
|
||||
if(!is_null($selector)) $this->init($selector);
|
||||
}
|
||||
|
||||
|
@@ -5,7 +5,7 @@
|
||||
*
|
||||
* WireArray of Template instances as used by Templates class.
|
||||
*
|
||||
* ProcessWire 3.x, Copyright 2016 by Ryan Cramer
|
||||
* ProcessWire 3.x, Copyright 2024 by Ryan Cramer
|
||||
* https://processwire.com
|
||||
*
|
||||
*/
|
||||
@@ -21,6 +21,7 @@ class TemplatesArray extends WireArray {
|
||||
}
|
||||
|
||||
public function getItemKey($item) {
|
||||
/** @var Template $item */
|
||||
return $item->id;
|
||||
}
|
||||
|
||||
|
@@ -11,7 +11,7 @@
|
||||
*
|
||||
* @todo can we implement next() and prev() like on Page, as alias to getNext() and getPrev()?
|
||||
*
|
||||
* ProcessWire 3.x, Copyright 2022 by Ryan Cramer
|
||||
* ProcessWire 3.x, Copyright 2024 by Ryan Cramer
|
||||
* https://processwire.com
|
||||
*
|
||||
* @method WireArray and($item)
|
||||
@@ -88,12 +88,47 @@ class WireArray extends Wire implements \IteratorAggregate, \ArrayAccess, \Count
|
||||
*/
|
||||
protected $sortFlags = 0; // 0 == SORT_REGULAR
|
||||
|
||||
/**
|
||||
* For WireArray that holds WireData objects, property that contains the item’s name
|
||||
*
|
||||
* @var string
|
||||
* @since 3.0.240
|
||||
*
|
||||
*/
|
||||
protected $nameProperty = 'name';
|
||||
|
||||
/**
|
||||
* Is this WireArray indexed by the name property?
|
||||
*
|
||||
* This will be auto-detected at runtime unless specifically set in the constructor.
|
||||
*
|
||||
* @var bool|null Bool once known, null if not yet known
|
||||
* @since 3.0.240
|
||||
*
|
||||
*/
|
||||
protected $indexedByName = null;
|
||||
|
||||
/**
|
||||
* Does this WireArray use numeric keys?
|
||||
*
|
||||
* This will be auto-detected at runtime unless specifically set in the constructor.
|
||||
*
|
||||
* @var bool|null
|
||||
* @since 3.0.240
|
||||
*
|
||||
*/
|
||||
protected $usesNumericKeys = null;
|
||||
|
||||
/**
|
||||
* Construct
|
||||
*
|
||||
*/
|
||||
public function __construct() {
|
||||
if($this->className() === 'WireArray') $this->duplicateChecking = false;
|
||||
if($this->className() === 'WireArray') {
|
||||
$this->duplicateChecking = false;
|
||||
$this->indexedByName = false;
|
||||
$this->usesNumericKeys = true;
|
||||
}
|
||||
parent::__construct();
|
||||
}
|
||||
|
||||
@@ -296,7 +331,7 @@ class WireArray extends Wire implements \IteratorAggregate, \ArrayAccess, \Count
|
||||
$key = key($this->data);
|
||||
}
|
||||
|
||||
$this->trackChange("add", null, $item);
|
||||
if($this->trackChanges) $this->trackChange("add", null, $item);
|
||||
$this->trackAdd($item, $key);
|
||||
|
||||
return $this;
|
||||
@@ -461,7 +496,7 @@ class WireArray extends Wire implements \IteratorAggregate, \ArrayAccess, \Count
|
||||
throw new WireException("Key '$key' is not an allowed key for " . get_class($this));
|
||||
}
|
||||
|
||||
$this->trackChange($key, isset($this->data[$key]) ? $this->data[$key] : null, $value);
|
||||
if($this->trackChanges) $this->trackChange($key, isset($this->data[$key]) ? $this->data[$key] : null, $value);
|
||||
$this->data[$key] = $value;
|
||||
$this->trackAdd($value, $key);
|
||||
return $this;
|
||||
@@ -602,7 +637,7 @@ class WireArray extends Wire implements \IteratorAggregate, \ArrayAccess, \Count
|
||||
if(isset($this->data[$k])) {
|
||||
$match = $this->data[$k];
|
||||
} else if($numericKeys) {
|
||||
$match = $this->getItemThatMatches('name', $k);
|
||||
$match = $this->getItemThatMatches($this->nameProperty, $k);
|
||||
}
|
||||
if($match) break;
|
||||
}
|
||||
@@ -613,7 +648,7 @@ class WireArray extends Wire implements \IteratorAggregate, \ArrayAccess, \Count
|
||||
// if the WireArray uses numeric keys, then it's okay to
|
||||
// match a 'name' field if the provided key is a string
|
||||
if($this->usesNumericKeys()) {
|
||||
$match = $this->getItemThatMatches('name', $key);
|
||||
$match = $this->getItemThatMatches($this->nameProperty, $key);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -760,7 +795,7 @@ class WireArray extends Wire implements \IteratorAggregate, \ArrayAccess, \Count
|
||||
$match = $this->findOne($key);
|
||||
|
||||
} else if($this->usesNumericKeys()) {
|
||||
$match = $this->getItemThatMatches('name', $key);
|
||||
$match = $this->getItemThatMatches($this->nameProperty, $key);
|
||||
}
|
||||
|
||||
}
|
||||
@@ -997,7 +1032,7 @@ class WireArray extends Wire implements \IteratorAggregate, \ArrayAccess, \Count
|
||||
reset($this->data);
|
||||
$key = key($this->data);
|
||||
}
|
||||
$this->trackChange('prepend', null, $item);
|
||||
if($this->trackChanges) $this->trackChange('prepend', null, $item);
|
||||
$this->trackAdd($item, $key);
|
||||
return $this;
|
||||
}
|
||||
@@ -1058,7 +1093,7 @@ class WireArray extends Wire implements \IteratorAggregate, \ArrayAccess, \Count
|
||||
$key = key($this->data);
|
||||
$item = array_shift($this->data);
|
||||
if(is_null($item)) return null;
|
||||
$this->trackChange('shift', $item, null);
|
||||
if($this->trackChanges) $this->trackChange('shift', $item, null);
|
||||
$this->trackRemove($item, $key);
|
||||
return $item;
|
||||
}
|
||||
@@ -1094,7 +1129,7 @@ class WireArray extends Wire implements \IteratorAggregate, \ArrayAccess, \Count
|
||||
$key = key($this->data);
|
||||
$item = array_pop($this->data);
|
||||
if(is_null($item)) return null;
|
||||
$this->trackChange('pop', $item, null);
|
||||
if($this->trackChanges) $this->trackChange('pop', $item, null);
|
||||
$this->trackRemove($item, $key);
|
||||
return $item;
|
||||
}
|
||||
@@ -1119,7 +1154,7 @@ class WireArray extends Wire implements \IteratorAggregate, \ArrayAccess, \Count
|
||||
$data[$key] = $this->data[$key];
|
||||
}
|
||||
|
||||
$this->trackChange('shuffle', $this->data, $data);
|
||||
if($this->trackChanges) $this->trackChange('shuffle', $this->data, $data);
|
||||
|
||||
$this->data = $data;
|
||||
|
||||
@@ -1219,7 +1254,7 @@ class WireArray extends Wire implements \IteratorAggregate, \ArrayAccess, \Count
|
||||
if(array_key_exists($key, $this->data)) {
|
||||
$item = $this->data[$key];
|
||||
unset($this->data[$key]);
|
||||
$this->trackChange("remove", $item, null);
|
||||
if($this->trackChanges) $this->trackChange("remove", $item, null);
|
||||
$this->trackRemove($item, $key);
|
||||
} else if(!$obj && is_string($key) && Selectors::stringHasSelector($key)) {
|
||||
foreach($this->find($key) as $item) {
|
||||
@@ -1330,6 +1365,13 @@ class WireArray extends Wire implements \IteratorAggregate, \ArrayAccess, \Count
|
||||
|
||||
if(empty($properties)) return $this;
|
||||
|
||||
if($propertiesStr === $this->nameProperty && $this->indexedByName) {
|
||||
// optimization when it's a very simple sort by name
|
||||
ksort($this->data, $this->sortFlags);
|
||||
if($this->trackChanges) $this->trackChange("sort:$propertiesStr");
|
||||
return $this;
|
||||
}
|
||||
|
||||
// shortcut for random (only allowed as the sole sort property)
|
||||
// no warning/error for issuing more properties though
|
||||
// TODO: warning for random+more properties (and trackChange() too)
|
||||
@@ -2000,7 +2042,20 @@ class WireArray extends Wire implements \IteratorAggregate, \ArrayAccess, \Count
|
||||
*
|
||||
*/
|
||||
protected function trackAdd($item, $key) {
|
||||
if($key) {}
|
||||
if($key !== null && $key !== false) {
|
||||
if($this->usesNumericKeys === null) {
|
||||
$this->usesNumericKeys = is_int($key);
|
||||
}
|
||||
if($this->indexedByName === null) {
|
||||
$this->indexedByName = false;
|
||||
if($item instanceof WireData) {
|
||||
$name = $item->get($this->nameProperty);
|
||||
if($name === $key && isset($this->data[$name]) && $this->data[$name] === $item) {
|
||||
$this->indexedByName = true;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
if($this->trackChanges()) $this->itemsAdded[] = $item;
|
||||
// wire this WireArray to the same instance of $item, if it isn’t already wired
|
||||
if($this->_wire === null && $item instanceof Wire && $item->isWired()) $item->wire($this);
|
||||
@@ -2118,16 +2173,29 @@ class WireArray extends Wire implements \IteratorAggregate, \ArrayAccess, \Count
|
||||
*/
|
||||
protected function usesNumericKeys() {
|
||||
|
||||
static $testItem = null;
|
||||
static $usesNumericKeys = null;
|
||||
if($this->usesNumericKeys !== null) {
|
||||
return $this->usesNumericKeys;
|
||||
}
|
||||
|
||||
if(!is_null($usesNumericKeys)) return $usesNumericKeys;
|
||||
if(is_null($testItem)) $testItem = $this->makeBlankItem();
|
||||
if(is_null($testItem)) return true;
|
||||
if(!empty($this->data)) {
|
||||
reset($this->data);
|
||||
$key = key($this->data);
|
||||
if($key !== null) {
|
||||
$this->usesNumericKeys = is_int($key);
|
||||
return $this->usesNumericKeys;
|
||||
}
|
||||
}
|
||||
|
||||
$testItem = $this->makeBlankItem();
|
||||
|
||||
if($testItem === null) {
|
||||
$this->usesNumericKeys = true;
|
||||
} else {
|
||||
$key = $this->getItemKey($testItem);
|
||||
$usesNumericKeys = is_int($key) ? true : false;
|
||||
return $usesNumericKeys;
|
||||
$this->usesNumericKeys = is_int($key);
|
||||
}
|
||||
|
||||
return $this->usesNumericKeys;
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -2552,7 +2620,7 @@ class WireArray extends Wire implements \IteratorAggregate, \ArrayAccess, \Count
|
||||
}
|
||||
} else {
|
||||
// array or string or null
|
||||
if(is_null($func)) $func = 'name';
|
||||
if(is_null($func)) $func = $this->nameProperty;
|
||||
$result = $this->explode($func);
|
||||
}
|
||||
|
||||
@@ -2658,7 +2726,7 @@ class WireArray extends Wire implements \IteratorAggregate, \ArrayAccess, \Count
|
||||
$item = $item->debugInfoSmall();
|
||||
} else if($item instanceof WireData) {
|
||||
$_item = $item;
|
||||
$item = $item->get('name');
|
||||
$item = $item->get($this->nameProperty);
|
||||
if(!$item) $item = $_item->get('id');
|
||||
if(!$item) $item = $_item->className();
|
||||
} else {
|
||||
|
Reference in New Issue
Block a user