mirror of
https://github.com/processwire/processwire.git
synced 2025-08-12 09:44:38 +02:00
Minor improvements and refactoring in PageArray and WireArray, plus this should also fix processwire/processwire-issues#1416
This commit is contained in:
@@ -28,7 +28,7 @@
|
|||||||
* ~~~~~
|
* ~~~~~
|
||||||
* #pw-body
|
* #pw-body
|
||||||
*
|
*
|
||||||
* ProcessWire 3.x, Copyright 2019 by Ryan Cramer
|
* ProcessWire 3.x, Copyright 2021 by Ryan Cramer
|
||||||
* https://processwire.com
|
* https://processwire.com
|
||||||
*
|
*
|
||||||
* @method string getMarkup($key = null) Render a simple/default markup value for each item #pw-internal
|
* @method string getMarkup($key = null) Render a simple/default markup value for each item #pw-internal
|
||||||
@@ -123,14 +123,14 @@ class PageArray extends PaginatedArray implements WirePaginatable {
|
|||||||
// given item exists in this PageArray (or at least has)
|
// given item exists in this PageArray (or at least has)
|
||||||
$key = $this->keyIndex[$id];
|
$key = $this->keyIndex[$id];
|
||||||
if(isset($this->data[$key])) {
|
if(isset($this->data[$key])) {
|
||||||
$page = $this->data[$key];
|
$page = $this->data[$key]; /** @var Page $page */
|
||||||
if($page->id === $id) {
|
if($page->id === $id) {
|
||||||
// found it
|
// found it
|
||||||
return $key;
|
return $key;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
// if this point is reached, then index needs to be rebuilt
|
// if this (maybe unreachable) point is reached, then index needs to
|
||||||
// because either item is no longer here, or has moved
|
// be rebuilt because either item is no longer here, or has moved
|
||||||
$this->keyIndex = array();
|
$this->keyIndex = array();
|
||||||
foreach($this->data as $key => $page) {
|
foreach($this->data as $key => $page) {
|
||||||
$this->keyIndex[$page->id] = $key;
|
$this->keyIndex[$page->id] = $key;
|
||||||
@@ -163,7 +163,7 @@ class PageArray extends PaginatedArray implements WirePaginatable {
|
|||||||
*
|
*
|
||||||
*/
|
*/
|
||||||
public function makeBlankItem() {
|
public function makeBlankItem() {
|
||||||
return $this->wire('pages')->newPage();
|
return $this->wire()->pages->newPage();
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -197,19 +197,13 @@ class PageArray extends PaginatedArray implements WirePaginatable {
|
|||||||
if(!self::iterable($pages)) return $this;
|
if(!self::iterable($pages)) return $this;
|
||||||
foreach($pages as $page) $this->add($page);
|
foreach($pages as $page) $this->add($page);
|
||||||
if($pages instanceof PageArray) {
|
if($pages instanceof PageArray) {
|
||||||
if(count($pages) < $pages->getTotal()) $this->setTotal($this->getTotal() + ($pages->getTotal() - count($pages)));
|
if(count($pages) < $pages->getTotal()) {
|
||||||
|
$this->setTotal($this->getTotal() + ($pages->getTotal() - count($pages)));
|
||||||
|
}
|
||||||
}
|
}
|
||||||
return $this;
|
return $this;
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
|
||||||
public function get($key) {
|
|
||||||
if(ctype_digit("$key")) return parent::get($key);
|
|
||||||
@todo check if selector, then call findOne(). If it returns null, return a NullPage instead.
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
*/
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Does this PageArray contain the given index or Page?
|
* Does this PageArray contain the given index or Page?
|
||||||
*
|
*
|
||||||
@@ -252,106 +246,17 @@ class PageArray extends PaginatedArray implements WirePaginatable {
|
|||||||
|
|
||||||
if($this->isValidItem($page)) {
|
if($this->isValidItem($page)) {
|
||||||
parent::add($page);
|
parent::add($page);
|
||||||
$this->numTotal++;
|
|
||||||
|
|
||||||
} else if($page instanceof PageArray || is_array($page)) {
|
} else if($page instanceof PageArray || is_array($page)) {
|
||||||
return $this->import($page);
|
return $this->import($page);
|
||||||
|
|
||||||
} else if(ctype_digit("$page")) {
|
} else if(ctype_digit("$page")) {
|
||||||
$page = $this->wire('pages')->get("id=$page");
|
$page = $this->wire()->pages->get("id=$page");
|
||||||
if($page->id) {
|
if($page->id) parent::add($page);
|
||||||
parent::add($page);
|
|
||||||
$this->numTotal++;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
return $this;
|
return $this;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Sets an index in the PageArray.
|
|
||||||
*
|
|
||||||
* #pw-internal
|
|
||||||
*
|
|
||||||
* @param int $key Key of item to set.
|
|
||||||
* @param Page $value Value of item.
|
|
||||||
* @return $this
|
|
||||||
*
|
|
||||||
*/
|
|
||||||
public function set($key, $value) {
|
|
||||||
$has = $this->has($key);
|
|
||||||
parent::set($key, $value);
|
|
||||||
if(!$has) $this->numTotal++;
|
|
||||||
return $this;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Prepend a Page to the beginning of the PageArray.
|
|
||||||
*
|
|
||||||
* #pw-internal
|
|
||||||
*
|
|
||||||
* @param Page|PageArray $item
|
|
||||||
* @return WireArray This instance.
|
|
||||||
*
|
|
||||||
*/
|
|
||||||
public function prepend($item) {
|
|
||||||
parent::prepend($item);
|
|
||||||
// note that WireArray::prepend does a recursive call to prepend with each item,
|
|
||||||
// so it's only necessary to increase numTotal if the given item is Page (vs. PageArray)
|
|
||||||
if($item instanceof Page) $this->numTotal++;
|
|
||||||
return $this;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Remove the given Page or key from the PageArray.
|
|
||||||
*
|
|
||||||
* #pw-internal
|
|
||||||
*
|
|
||||||
* @param int|Page $key
|
|
||||||
* @return $this This PageArray instance
|
|
||||||
*
|
|
||||||
*/
|
|
||||||
public function remove($key) {
|
|
||||||
|
|
||||||
// if a Page object has been passed, determine its key
|
|
||||||
if($this->isValidItem($key)) {
|
|
||||||
$key = $this->getItemKey($key);
|
|
||||||
}
|
|
||||||
if($this->has($key)) {
|
|
||||||
parent::remove($key);
|
|
||||||
$this->numTotal--;
|
|
||||||
}
|
|
||||||
|
|
||||||
return $this;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Shift the first Page off of the PageArray and return it.
|
|
||||||
*
|
|
||||||
* #pw-internal
|
|
||||||
*
|
|
||||||
* @return Page|NULL
|
|
||||||
*
|
|
||||||
*/
|
|
||||||
public function shift() {
|
|
||||||
if($this->numTotal) $this->numTotal--;
|
|
||||||
return parent::shift();
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Pop the last page off of the PageArray and return it.
|
|
||||||
*
|
|
||||||
* #pw-internal
|
|
||||||
*
|
|
||||||
* @return Page|NULL
|
|
||||||
*
|
|
||||||
*/
|
|
||||||
public function pop() {
|
|
||||||
if($this->numTotal) $this->numTotal--;
|
|
||||||
return parent::pop();
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Get one or more random pages from this PageArray.
|
* Get one or more random pages from this PageArray.
|
||||||
*
|
*
|
||||||
@@ -641,7 +546,12 @@ class PageArray extends PaginatedArray implements WirePaginatable {
|
|||||||
*
|
*
|
||||||
*/
|
*/
|
||||||
protected function filterDataSelectors(Selectors $selectors) {
|
protected function filterDataSelectors(Selectors $selectors) {
|
||||||
// @todo make it remove references to include= statements since not applicable in-memory
|
$disallowed = array('include', 'check_access', 'checkAccess');
|
||||||
|
foreach($selectors as $selector) {
|
||||||
|
if(in_array($selector->field(), $disallowed)) {
|
||||||
|
$selectors->remove($selector);
|
||||||
|
}
|
||||||
|
}
|
||||||
parent::filterDataSelectors($selectors);
|
parent::filterDataSelectors($selectors);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -786,6 +696,9 @@ class PageArray extends PaginatedArray implements WirePaginatable {
|
|||||||
*/
|
*/
|
||||||
protected function trackAdd($item, $key) {
|
protected function trackAdd($item, $key) {
|
||||||
parent::trackAdd($item, $key);
|
parent::trackAdd($item, $key);
|
||||||
|
if(!$item instanceof Page) return;
|
||||||
|
/** @var Page $item */
|
||||||
|
if(!isset($this->keyIndex[$item->id])) $this->numTotal++;
|
||||||
$this->keyIndex[$item->id] = $key;
|
$this->keyIndex[$item->id] = $key;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -798,8 +711,13 @@ class PageArray extends PaginatedArray implements WirePaginatable {
|
|||||||
*/
|
*/
|
||||||
protected function trackRemove($item, $key) {
|
protected function trackRemove($item, $key) {
|
||||||
parent::trackRemove($item, $key);
|
parent::trackRemove($item, $key);
|
||||||
|
if(!$item instanceof Page) return;
|
||||||
|
/** @var Page $item */
|
||||||
|
if(isset($this->keyIndex[$item->id])) {
|
||||||
|
if($this->numTotal) $this->numTotal--;
|
||||||
unset($this->keyIndex[$item->id]);
|
unset($this->keyIndex[$item->id]);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@@ -10,9 +10,8 @@
|
|||||||
* WireArray is the base of the PageArray (subclass) which is the most used instance.
|
* WireArray is the base of the PageArray (subclass) which is the most used instance.
|
||||||
*
|
*
|
||||||
* @todo can we implement next() and prev() like on Page, as alias to getNext() and getPrev()?
|
* @todo can we implement next() and prev() like on Page, as alias to getNext() and getPrev()?
|
||||||
* @todo narrow down to one method of addition and removal, especially for removal, i.e. make shift() run through remove()
|
|
||||||
*
|
*
|
||||||
* ProcessWire 3.x, Copyright 2016 by Ryan Cramer
|
* ProcessWire 3.x, Copyright 2021 by Ryan Cramer
|
||||||
* https://processwire.com
|
* https://processwire.com
|
||||||
*
|
*
|
||||||
* @method WireArray and($item)
|
* @method WireArray and($item)
|
||||||
@@ -405,7 +404,7 @@ class WireArray extends Wire implements \IteratorAggregate, \ArrayAccess, \Count
|
|||||||
$a = $this->get($itemA);
|
$a = $this->get($itemA);
|
||||||
$b = $this->get($itemB);
|
$b = $this->get($itemB);
|
||||||
if($a && $b) {
|
if($a && $b) {
|
||||||
// swap a and b
|
// swap a and b, both already present in this WireArray
|
||||||
$data = $this->data;
|
$data = $this->data;
|
||||||
foreach($data as $key => $value) {
|
foreach($data as $key => $value) {
|
||||||
$k = null;
|
$k = null;
|
||||||
@@ -455,8 +454,12 @@ class WireArray extends Wire implements \IteratorAggregate, \ArrayAccess, \Count
|
|||||||
*/
|
*/
|
||||||
public function set($key, $value) {
|
public function set($key, $value) {
|
||||||
|
|
||||||
if(!$this->isValidItem($value)) throw new WireException("Item '$key' set to " . get_class($this) . " is not an allowed type");
|
if(!$this->isValidItem($value)) {
|
||||||
if(!$this->isValidKey($key)) throw new WireException("Key '$key' is not an allowed key for " . get_class($this));
|
throw new WireException("Item '$key' set to " . get_class($this) . " is not an allowed type");
|
||||||
|
}
|
||||||
|
if(!$this->isValidKey($key)) {
|
||||||
|
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);
|
$this->trackChange($key, isset($this->data[$key]) ? $this->data[$key] : null, $value);
|
||||||
$this->data[$key] = $value;
|
$this->data[$key] = $value;
|
||||||
@@ -476,7 +479,9 @@ class WireArray extends Wire implements \IteratorAggregate, \ArrayAccess, \Count
|
|||||||
*
|
*
|
||||||
*/
|
*/
|
||||||
public function __set($property, $value) {
|
public function __set($property, $value) {
|
||||||
if($this->getProperty($property)) throw new WireException("Property '$property' is a reserved word and may not be set by direct reference.");
|
if($this->getProperty($property)) {
|
||||||
|
throw new WireException("Property '$property' is a reserved word and may not be set by direct reference.");
|
||||||
|
}
|
||||||
$this->set($property, $value);
|
$this->set($property, $value);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -941,8 +946,11 @@ class WireArray extends Wire implements \IteratorAggregate, \ArrayAccess, \Count
|
|||||||
*
|
*
|
||||||
*/
|
*/
|
||||||
public function slice($start, $limit = 0) {
|
public function slice($start, $limit = 0) {
|
||||||
if($limit) $slice = array_slice($this->data, $start, $limit);
|
if($limit) {
|
||||||
else $slice = array_slice($this->data, $start);
|
$slice = array_slice($this->data, $start, $limit);
|
||||||
|
} else {
|
||||||
|
$slice = array_slice($this->data, $start);
|
||||||
|
}
|
||||||
$items = $this->makeNew();
|
$items = $this->makeNew();
|
||||||
$items->import($slice);
|
$items->import($slice);
|
||||||
$items->setTrackChanges(true);
|
$items->setTrackChanges(true);
|
||||||
@@ -987,7 +995,6 @@ class WireArray extends Wire implements \IteratorAggregate, \ArrayAccess, \Count
|
|||||||
reset($this->data);
|
reset($this->data);
|
||||||
$key = key($this->data);
|
$key = key($this->data);
|
||||||
}
|
}
|
||||||
//if($item instanceof Wire) $item->setTrackChanges();
|
|
||||||
$this->trackChange('prepend', null, $item);
|
$this->trackChange('prepend', null, $item);
|
||||||
$this->trackAdd($item, $key);
|
$this->trackAdd($item, $key);
|
||||||
return $this;
|
return $this;
|
||||||
@@ -1206,12 +1213,11 @@ class WireArray extends Wire implements \IteratorAggregate, \ArrayAccess, \Count
|
|||||||
$key = $this->getItemKey($key);
|
$key = $this->getItemKey($key);
|
||||||
}
|
}
|
||||||
|
|
||||||
if($this->has($key)) {
|
if(array_key_exists($key, $this->data)) {
|
||||||
$item = $this->data[$key];
|
$item = $this->data[$key];
|
||||||
unset($this->data[$key]);
|
unset($this->data[$key]);
|
||||||
$this->trackChange("remove", $item, null);
|
$this->trackChange("remove", $item, null);
|
||||||
$this->trackRemove($item, $key);
|
$this->trackRemove($item, $key);
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
return $this;
|
return $this;
|
||||||
@@ -1475,7 +1481,7 @@ class WireArray extends Wire implements \IteratorAggregate, \ArrayAccess, \Count
|
|||||||
protected function filterData($selectors, $not = false) {
|
protected function filterData($selectors, $not = false) {
|
||||||
|
|
||||||
if(is_object($selectors) && $selectors instanceof Selectors) {
|
if(is_object($selectors) && $selectors instanceof Selectors) {
|
||||||
// fantastic
|
$selectors = clone $selectors;
|
||||||
} else {
|
} else {
|
||||||
if(!is_array($selectors) && ctype_digit("$selectors")) $selectors = "id=$selectors";
|
if(!is_array($selectors) && ctype_digit("$selectors")) $selectors = "id=$selectors";
|
||||||
$selector = $selectors;
|
$selector = $selectors;
|
||||||
@@ -1485,6 +1491,7 @@ class WireArray extends Wire implements \IteratorAggregate, \ArrayAccess, \Count
|
|||||||
|
|
||||||
$this->filterDataSelectors($selectors);
|
$this->filterDataSelectors($selectors);
|
||||||
|
|
||||||
|
$fields = $this->wire()->fields;
|
||||||
$sort = array();
|
$sort = array();
|
||||||
$start = 0;
|
$start = 0;
|
||||||
$limit = null;
|
$limit = null;
|
||||||
@@ -1509,7 +1516,7 @@ class WireArray extends Wire implements \IteratorAggregate, \ArrayAccess, \Count
|
|||||||
// use only the last limit selector
|
// use only the last limit selector
|
||||||
$limit = (int) $selector->value;
|
$limit = (int) $selector->value;
|
||||||
|
|
||||||
} else if(($field === 'index' || $field == 'eq') && !$this->wire('fields')->get($field)) {
|
} else if(($field === 'index' || $field == 'eq') && !$fields->get($field)) {
|
||||||
// eq or index properties
|
// eq or index properties
|
||||||
switch($selector->value) {
|
switch($selector->value) {
|
||||||
case 'first': $eq = 0; break;
|
case 'first': $eq = 0; break;
|
||||||
@@ -1533,7 +1540,9 @@ class WireArray extends Wire implements \IteratorAggregate, \ArrayAccess, \Count
|
|||||||
$qty++;
|
$qty++;
|
||||||
if(is_array($selector->field)) {
|
if(is_array($selector->field)) {
|
||||||
$value = array();
|
$value = array();
|
||||||
foreach($selector->field as $field) $value[] = (string) $this->getItemPropertyValue($item, $field);
|
foreach($selector->field as $field) {
|
||||||
|
$value[] = (string) $this->getItemPropertyValue($item, $field);
|
||||||
|
}
|
||||||
} else {
|
} else {
|
||||||
$value = (string) $this->getItemPropertyValue($item, $selector->field);
|
$value = (string) $this->getItemPropertyValue($item, $selector->field);
|
||||||
}
|
}
|
||||||
@@ -1588,7 +1597,7 @@ class WireArray extends Wire implements \IteratorAggregate, \ArrayAccess, \Count
|
|||||||
$this->data = array_slice($this->data, $start, $limit, true);
|
$this->data = array_slice($this->data, $start, $limit, true);
|
||||||
}
|
}
|
||||||
|
|
||||||
$this->trackChange("filterData:$selectors");
|
if($this->trackChanges()) $this->trackChange("filterData:$selectors");
|
||||||
return $this;
|
return $this;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Reference in New Issue
Block a user