浏览代码

Fix up inclusive search using contain.

mscherer 4 年之前
父节点
当前提交
4e2323bd6f

+ 2 - 2
docs/Behavior/Bitmasked.md

@@ -117,11 +117,11 @@ $this->Comments->find('bits', ['bits' => $statuses, 'type' => 'contain])->toArra
 If you build more complex finders or queries for your data, you might find the following info useful:
 
 "contains" (looking for any that contains this type) is translated to `field & {type} = {type}` in the ORM, e.g. `status & 1 = 1`.
-Once you are looking for a combination of types, it will be the bitmask of those integers, e.g. `1 + 2 = 3`, so `status & 3 = 3`.
+Once you are looking for a combination of types, it will be an `OR` of those elements, e.g. `status & 1 = 1 OR status & 2 = 2`.
 
 Using the finder you do not have to care about the SQL details here, as it will translate to this automatically.
 
-"exact" (default) only looks at the values exclusivly. If you are looking for multiple ones at once that are exclusive, this will need to be translated to `IN (...)` using only the type integers directly (not the bitmasked combinations), e.g. `IN (1, 2, 4`).
+"exact" (default) only looks at the values exclusively. If you are looking for multiple ones at once that are exclusive, this will need to be translated to `IN (...)` using only the type integers directly (not the bitmasked combinations), e.g. `IN (1, 2, 4`).
 
 
 ### Configuration

+ 13 - 1
src/Model/Behavior/BitmaskedBehavior.php

@@ -61,7 +61,19 @@ class BitmaskedBehavior extends Behavior {
 		$options += ['type' => 'exact'];
 
 		if ($options['type'] === 'contain') {
-			return $query->where($this->containsBit($options['bits']));
+			$bits = (array)$options['bits'];
+			if (!$bits) {
+				$field = $this->_config['field'];
+
+				return $query->where([$this->_table->getAlias() . '.' . $field  => $this->_getDefaultValue($field)]);
+			}
+
+			$conditions = [];
+			foreach ($bits as $bit) {
+				$conditions[] = $this->containsBit($bit);
+			}
+
+			return $query->where(['OR' => $conditions]);
 		}
 
 		$bits = $this->encodeBitmask($options['bits']);

+ 9 - 8
tests/Fixture/BitmaskedCommentsFixture.php

@@ -3,6 +3,7 @@
 namespace Tools\Test\Fixture;
 
 use Cake\TestSuite\Fixture\TestFixture;
+use TestApp\Model\Entity\BitmaskedComment;
 
 /**
  * For BitmaskedBehaviorTest
@@ -19,7 +20,7 @@ class BitmaskedCommentsFixture extends TestFixture {
 		'article_id' => ['type' => 'integer', 'null' => true],
 		'user_id' => ['type' => 'integer', 'null' => true],
 		'comment' => 'text',
-		'status' => ['type' => 'integer', 'null' => false, 'length' => 2, 'default' => '0'],
+		'status' => ['type' => 'integer', 'null' => false, 'length' => 2, 'default' => 0],
 		'created' => 'datetime',
 		'updated' => 'datetime',
 		'_constraints' => ['primary' => ['type' => 'primary', 'columns' => ['id']]],
@@ -31,13 +32,13 @@ class BitmaskedCommentsFixture extends TestFixture {
 	 * @var array
 	 */
 	public $records = [
-		['article_id' => 1, 'user_id' => 2, 'comment' => 'First Comment for First Article', 'status' => '0', 'created' => '2007-03-18 10:45:23', 'updated' => '2007-03-18 10:47:31'],
-		['article_id' => 1, 'user_id' => 4, 'comment' => 'Second Comment for First Article', 'status' => '1', 'created' => '2007-03-18 10:47:23', 'updated' => '2007-03-18 10:49:31'],
-		['article_id' => 1, 'user_id' => 1, 'comment' => 'Third Comment for First Article', 'status' => '2', 'created' => '2007-03-18 10:49:23', 'updated' => '2007-03-18 10:51:31'],
-		['article_id' => 1, 'user_id' => 1, 'comment' => 'Fourth Comment for First Article', 'status' => '3', 'created' => '2007-03-18 10:51:23', 'updated' => '2007-03-18 10:53:31'],
-		['article_id' => 2, 'user_id' => 1, 'comment' => 'First Comment for Second Article', 'status' => '4', 'created' => '2007-03-18 10:53:23', 'updated' => '2007-03-18 10:55:31'],
-		['article_id' => 2, 'user_id' => 2, 'comment' => 'Second Comment for Second Article', 'status' => '5', 'created' => '2007-03-18 10:55:23', 'updated' => '2007-03-18 10:57:31'],
-		['article_id' => 2, 'user_id' => 3, 'comment' => 'Comment With All Bits set', 'status' => '15', 'created' => '2007-03-18 10:55:23', 'updated' => '2007-03-18 10:57:31'],
+		['article_id' => 1, 'user_id' => 2, 'comment' => 'First Comment for First Article', 'status' => 0, 'created' => '2007-03-18 10:45:23', 'updated' => '2007-03-18 10:47:31'],
+		['article_id' => 1, 'user_id' => 4, 'comment' => 'Second Comment for First Article', 'status' => BitmaskedComment::STATUS_ACTIVE, 'created' => '2007-03-18 10:47:23', 'updated' => '2007-03-18 10:49:31'],
+		['article_id' => 1, 'user_id' => 1, 'comment' => 'Third Comment for First Article', 'status' => BitmaskedComment::STATUS_PUBLISHED, 'created' => '2007-03-18 10:49:23', 'updated' => '2007-03-18 10:51:31'],
+		['article_id' => 1, 'user_id' => 1, 'comment' => 'Fourth Comment for First Article', 'status' => 3, 'created' => '2007-03-18 10:51:23', 'updated' => '2007-03-18 10:53:31'],
+		['article_id' => 2, 'user_id' => 1, 'comment' => 'First Comment for Second Article', 'status' => BitmaskedComment::STATUS_APPROVED, 'created' => '2007-03-18 10:53:23', 'updated' => '2007-03-18 10:55:31'],
+		['article_id' => 2, 'user_id' => 2, 'comment' => 'Second Comment for Second Article', 'status' => 5, 'created' => '2007-03-18 10:55:23', 'updated' => '2007-03-18 10:57:31'],
+		['article_id' => 2, 'user_id' => 3, 'comment' => 'Comment With All Bits set', 'status' => 15, 'created' => '2007-03-18 10:55:23', 'updated' => '2007-03-18 10:57:31'],
 	];
 
 }

+ 7 - 0
tests/TestCase/Model/Behavior/BitmaskedBehaviorTest.php

@@ -112,6 +112,13 @@ class BitmaskedBehaviorTest extends TestCase {
 		];
 		$res = $this->Comments->find('bits', $options)->toArray();
 		$this->assertCount(3, $res);
+
+		$options = [
+			'bits' => [BitmaskedComment::STATUS_APPROVED, BitmaskedComment::STATUS_PUBLISHED],
+			'type' => 'contain',
+		];
+		$res = $this->Comments->find('bits', $options)->toArray();
+		$this->assertCount(5, $res);
 	}
 
 	/**