From d81e04e9a3c1909020aa9f2a23ce1bf9d3c2eecc Mon Sep 17 00:00:00 2001 From: mscherer Date: Thu, 2 Dec 2021 02:02:27 +0100 Subject: [PATCH] Add contain mode AND. --- src/Model/Behavior/BitmaskedBehavior.php | 13 +++++++- .../Model/Behavior/BitmaskedBehaviorTest.php | 30 +++++++++++++++++++ 2 files changed, 42 insertions(+), 1 deletion(-) diff --git a/src/Model/Behavior/BitmaskedBehavior.php b/src/Model/Behavior/BitmaskedBehavior.php index 74035163..e06abd54 100644 --- a/src/Model/Behavior/BitmaskedBehavior.php +++ b/src/Model/Behavior/BitmaskedBehavior.php @@ -46,6 +46,8 @@ class BitmaskedBehavior extends Behavior { 'implementedFinders' => [ 'bits' => 'findBitmasked', ], + 'type' => null, // Auto-defaults to current default "exact", set to "contain" for contain mode + 'containMode' => 'or', // Use "and" when a record must match all bits ]; /** @@ -58,7 +60,10 @@ public function findBitmasked(Query $query, array $options) { if (!isset($options['bits'])) { throw new InvalidArgumentException("The 'bits' key is required for find('bits')"); } - $options += ['type' => 'exact']; + $options += [ + 'type' => $this->_config['type'] ?? 'exact', + 'containMode' => $this->_config['containMode'], + ]; if ($options['type'] === 'contain') { $bits = (array)$options['bits']; @@ -68,6 +73,12 @@ public function findBitmasked(Query $query, array $options) { return $query->where([$this->_table->getAlias() . '.' . $field => $this->_getDefaultValue($field)]); } + if ($options['containMode'] === 'and') { + $bits = $this->encodeBitmask($options['bits']); + + return $query->where($this->containsBit($bits)); + } + $conditions = []; foreach ($bits as $bit) { $conditions[] = $this->containsBit($bit); diff --git a/tests/TestCase/Model/Behavior/BitmaskedBehaviorTest.php b/tests/TestCase/Model/Behavior/BitmaskedBehaviorTest.php index 9aa9423b..301c1a02 100644 --- a/tests/TestCase/Model/Behavior/BitmaskedBehaviorTest.php +++ b/tests/TestCase/Model/Behavior/BitmaskedBehaviorTest.php @@ -121,6 +121,36 @@ public function testFindBitmaskedContain() { $this->assertCount(5, $res); } + /** + * @return void + */ + public function testFindBitmaskedContainAnd() { + $options = [ + 'bits' => [], + 'type' => 'contain', + 'containMode' => 'and', + ]; + $res = $this->Comments->find('bits', $options)->toArray(); + $this->assertCount(1, $res); + $this->assertSame([], $res[0]->statuses); + + $options = [ + 'bits' => [BitmaskedComment::STATUS_APPROVED], + 'type' => 'contain', + 'containMode' => 'and', + ]; + $res = $this->Comments->find('bits', $options)->toArray(); + $this->assertCount(3, $res); + + $options = [ + 'bits' => [BitmaskedComment::STATUS_APPROVED, BitmaskedComment::STATUS_PUBLISHED], + 'type' => 'contain', + 'containMode' => 'and', + ]; + $res = $this->Comments->find('bits', $options)->toArray(); + $this->assertCount(1, $res); + } + /** * @return void */