From e0b1c5c1bd0ddca1f8e3c350de4ee98eff733473 Mon Sep 17 00:00:00 2001 From: Ryan Cramer Date: Fri, 5 Apr 2019 12:06:08 -0400 Subject: [PATCH] Add update to accommodate different "not" logic in a new notAll() method for WireArray/PageArray per processwire/processwire-issues#383 --- wire/core/PageArray.php | 2 +- wire/core/WireArray.php | 27 ++++++++++++++++++++++++++- 2 files changed, 27 insertions(+), 2 deletions(-) diff --git a/wire/core/PageArray.php b/wire/core/PageArray.php index a467e0b7..5dbeca48 100644 --- a/wire/core/PageArray.php +++ b/wire/core/PageArray.php @@ -453,7 +453,7 @@ class PageArray extends PaginatedArray implements WirePaginatable { * This is applicable to and destructive to the WireArray. * * @param string|Selectors|array $selectors AttributeSelector string to use as the filter. - * @param bool $not Make this a "not" filter? (default is false) + * @param bool|int $not Make this a "not" filter? Use int 1 for "not all". (default is false) * @return PageArray|WireArray reference to current [filtered] PageArray * */ diff --git a/wire/core/WireArray.php b/wire/core/WireArray.php index 43debbbb..d3f2677a 100644 --- a/wire/core/WireArray.php +++ b/wire/core/WireArray.php @@ -1449,7 +1449,7 @@ class WireArray extends Wire implements \IteratorAggregate, \ArrayAccess, \Count * This function contains additions and modifications by @niklaka. * * @param string|array|Selectors $selectors Selector string|array to use as the filter. - * @param bool $not Make this a "not" filter? (default is false) + * @param bool|int $not Make this a "not" filter? Use int 1 for “not all” mode as if selectors had brackets around it. (default is false) * @return $this reference to current [filtered] instance * */ @@ -1470,6 +1470,8 @@ class WireArray extends Wire implements \IteratorAggregate, \ArrayAccess, \Count $start = 0; $limit = null; $eq = null; + $notAll = $not === 1; + if($notAll) $not = true; // leave sort, limit and start away from filtering selectors foreach($selectors as $selector) { @@ -1506,7 +1508,10 @@ class WireArray extends Wire implements \IteratorAggregate, \ArrayAccess, \Count // now filter the data according to the selectors that remain foreach($this->data as $key => $item) { + $qty = 0; + $qtyMatch = 0; foreach($selectors as $selector) { + $qty++; if(is_array($selector->field)) { $value = array(); foreach($selector->field as $field) $value[] = (string) $this->getItemPropertyValue($item, $field); @@ -1514,10 +1519,16 @@ class WireArray extends Wire implements \IteratorAggregate, \ArrayAccess, \Count $value = (string) $this->getItemPropertyValue($item, $selector->field); } if($not === $selector->matches($value) && isset($this->data[$key])) { + $qtyMatch++; + if($notAll) continue; // will do this outside the loop of all in $selectors match $this->trackRemove($this->data[$key], $key); unset($this->data[$key]); } } + if($notAll && $qty && $qty === $qtyMatch) { + $this->trackRemove($this->data[$key], $key); + unset($this->data[$key]); + } } if(!is_null($eq)) { @@ -1612,6 +1623,20 @@ class WireArray extends Wire implements \IteratorAggregate, \ArrayAccess, \Count return $this->filterData($selector, true); } + /** + * Like the not() method but $selector evaluated as if it had (brackets) around it + * + * #pw-internal Until we've got a better description for what this does + * + * @param string|array|Selectors $selector + * @return $this reference to current instance. + * @see filterData + * + */ + public function notAll($selector) { + return $this->filterData($selector, 1); + } + /** * Find all items in this WireArray that match the given selector. *