ソースを参照

Merge pull request #200 from dereuromark/feature/bitmask

Bitmask custom finder.
Mark Sch 8 年 前
コミット
11829c5626

+ 23 - 2
docs/Behavior/Bitmasked.md

@@ -63,20 +63,41 @@ Obviously you could also just use four or more boolean fields to achieve the sam
 
 So now, in the add/edit form we can:
 ```php
-echo $this->Form->input('statuses', ['options' => Comment::statuses(), 'multiple' => 'checkbox']);
+echo $this->Form->control('statuses', ['options' => Comment::statuses(), 'multiple' => 'checkbox']);
 ```
 
 Tip: Usually, you have passed down the current entity for the form building anyway, then you don't need static access:
 ```php
 echo $this->Form->create($comment);
-echo $this->Form->input('statuses', ['options' => $comment->statuses(), 'multiple' => 'checkbox']);
+echo $this->Form->control('statuses', ['options' => $comment->statuses(), 'multiple' => 'checkbox']);
 ...
 ```
 
 It will save the final bitmask to the database field `status` as integer. For example "active and approved" would become `9`.
 
+### Custom finder
+You can use the built in custom finder `findBitmasked`:
+```php
+$statuses = [Comment::STATUS_ACTIVE, STATUS_ACTIVE::STATUS_FEATURED];
+$comments = $this->Comments->find('bits', ['bits' => $statuses])->toArray();
+```
+
+#### Using Search plugin
+If you use [Search](https://github.com/FriendsOfCake/search/) plugin, you can easily make a filter as multi-checkbox:
+```php
+echo $this->Form->control('status', ['options' => Comment::statuses(), 'multiple' => 'checkbox', 'empty' => ' - no filter - ']);
+```
+
+And in your Table searchManager() setup:
+```php
+$searchManager
+	// We need to map the posted "status" key to the finder required "bits" key
+	->finder('status', ['finder' => 'bits', 'map' => ['bits' => 'status']])
+```
 
+This way the array of checkboxes selected will be turned into the integer bitmask needed for the query to work.
 
+Note: This requires Search ^4.3.0!
 
 ### Outview
 

+ 20 - 0
src/Model/Behavior/BitmaskedBehavior.php

@@ -9,6 +9,7 @@ use Cake\Event\Event;
 use Cake\ORM\Behavior;
 use Cake\ORM\Query;
 use Cake\Utility\Inflector;
+use InvalidArgumentException;
 use RuntimeException;
 use Tools\Utility\Text;
 
@@ -42,9 +43,28 @@ class BitmaskedBehavior extends Behavior {
 		'bits' => null, // Method or callback to get the bits data
 		'on' => 'beforeMarshal', // or beforeRules or beforeSave
 		'defaultValue' => null, // NULL = auto (use empty string to trigger "notEmpty" rule for "default NOT NULL" db fields)
+		'implementedFinders' => [
+			'bits' => 'findBitmasked'
+		],
 	];
 
 	/**
+	 * @param \Cake\ORM\Query $query
+	 * @param array $options
+	 * @return \Cake\ORM\Query
+	 * @throws \InvalidArgumentException If the 'slug' key is missing in options
+	 */
+	public function findBitmasked(Query $query, array $options) {
+		if (!isset($options['bits'])) {
+			throw new InvalidArgumentException("The 'bits' key is required for find('bits')");
+		}
+
+		$bits = $this->encodeBitmask($options['bits']);
+
+		return $query->where([$this->_config['field'] => $bits]);
+	}
+
+	/**
 	 * Behavior configuration
 	 *
 	 * @param array $config

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

@@ -82,6 +82,17 @@ class BitmaskedBehaviorTest extends TestCase {
 	/**
 	 * @return void
 	 */
+	public function testFindBitmasked() {
+		$res = $this->Comments->find('bits', ['bits' => []])->toArray();
+		$this->assertSame([], $res);
+
+		$res = $this->Comments->find('bits', ['bits' => [BitmaskedComment::STATUS_ACTIVE, BitmaskedComment::STATUS_APPROVED]])->toArray();
+		$this->assertCount(1, $res);
+	}
+
+	/**
+	 * @return void
+	 */
 	public function testSaveBasic() {
 		$data = [
 			'comment' => 'test save',