Skip to content

Commit

Permalink
Merge pull request #161 from ndm2/multi-field-search-support
Browse files Browse the repository at this point in the history
Add multi-field search support to value filter.
  • Loading branch information
dereuromark authored Apr 26, 2017
2 parents 88e4dd3 + 3ba9321 commit 9ed0e68
Show file tree
Hide file tree
Showing 3 changed files with 120 additions and 18 deletions.
4 changes: 2 additions & 2 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -319,8 +319,8 @@ The following options are supported by all filters except `Callback` and `Finder
multiple values. If disabled, and multiple values are being passed, the filter
will fall back to using the default value defined by the `defaultValue` option.

- `mode` (`string`, defaults to `OR`) The conditional mode to use when searching for
multiple values. Valid values are `OR` and `AND`.
- `mode` (`string`, defaults to `OR`) The conditional mode to use when matching
against multiple fields. Valid values are `OR` and `AND`.

#### `Finder`

Expand Down
30 changes: 15 additions & 15 deletions src/Model/Filter/Value.php
Original file line number Diff line number Diff line change
@@ -1,6 +1,8 @@
<?php
namespace Search\Model\Filter;

use Cake\Database\Expression\QueryExpression;

class Value extends Base
{

Expand All @@ -10,7 +12,7 @@ class Value extends Base
* @var array
*/
protected $_defaultConfig = [
'mode' => 'OR',
'mode' => 'OR'
];

/**
Expand All @@ -36,21 +38,19 @@ public function process()
return;
}

$this->query()->andWhere(function ($e) use ($value, $isMultiValue) {
/* @var $e \Cake\Database\Expression\QueryExpression */
$field = $this->field();

if (strtoupper($this->config('mode')) === 'OR' &&
$isMultiValue
) {
return $e->in($field, $value);
}
$expressions = [];
foreach ($this->fields() as $field) {
$expressions[] = function (QueryExpression $e) use ($field, $value, $isMultiValue) {
if ($isMultiValue) {
return $e->in($field, $value);
}

foreach ((array)$value as $val) {
$e->eq($field, $val);
}
return $e->eq($field, $value);
};
}

return $e;
});
if (!empty($expressions)) {
$this->query()->andWhere([$this->config('mode') => $expressions]);
}
}
}
104 changes: 103 additions & 1 deletion tests/TestCase/Model/Filter/ValueTest.php
Original file line number Diff line number Diff line change
Expand Up @@ -87,6 +87,55 @@ public function testProcessSingleValueWithAndMode()
);
}

/**
* @return void
*/
public function testProcessSingleValueAndMultiField()
{
$articles = TableRegistry::get('Articles');
$manager = new Manager($articles);
$filter = new Value('title', $manager, [
'field' => ['title', 'other']
]);
$filter->args(['title' => 'foo']);
$filter->query($articles->find());
$filter->process();

$this->assertRegExp(
'/WHERE \(Articles\.title = :c0 OR Articles\.other = :c1\)$/',
$filter->query()->sql()
);
$this->assertEquals(
['foo', 'foo'],
Hash::extract($filter->query()->valueBinder()->bindings(), '{s}.value')
);
}

/**
* @return void
*/
public function testProcessSingleValueAndMultiFieldWithAndMode()
{
$articles = TableRegistry::get('Articles');
$manager = new Manager($articles);
$filter = new Value('title', $manager, [
'field' => ['title', 'other'],
'mode' => 'and'
]);
$filter->args(['title' => 'foo']);
$filter->query($articles->find());
$filter->process();

$this->assertRegExp(
'/WHERE \(Articles\.title = :c0 AND Articles\.other = :c1\)$/',
$filter->query()->sql()
);
$this->assertEquals(
['foo', 'foo'],
Hash::extract($filter->query()->valueBinder()->bindings(), '{s}.value')
);
}

/**
* @return void
*/
Expand Down Expand Up @@ -125,7 +174,7 @@ public function testProcessMultiValueWithAndMode()
$filter->process();

$this->assertRegExp(
'/WHERE \(Articles\.title = :c0 AND Articles\.title = :c1\)$/',
'/WHERE Articles\.title IN \(:c0,:c1\)$/',
$filter->query()->sql()
);
$this->assertEquals(
Expand All @@ -134,6 +183,59 @@ public function testProcessMultiValueWithAndMode()
);
}

/**
* @return void
*/
public function testProcessMultiValueAndMultiField()
{
$articles = TableRegistry::get('Articles');
$manager = new Manager($articles);
$filter = new Value('title', $manager, [
'multiValue' => true,
'field' => ['title', 'other']
]);
$filter->args(['title' => ['foo', 'bar']]);
$filter->query($articles->find());
$filter->process();

$this->assertRegExp(
'/WHERE \(Articles\.title IN \(:c0,:c1\) ' .
'OR Articles\.other IN \(:c2,:c3\)\)$/',
$filter->query()->sql()
);
$this->assertEquals(
['foo', 'bar', 'foo', 'bar'],
Hash::extract($filter->query()->valueBinder()->bindings(), '{s}.value')
);
}

/**
* @return void
*/
public function testProcessMultiValueAndMultiFieldWithAndMode()
{
$articles = TableRegistry::get('Articles');
$manager = new Manager($articles);
$filter = new Value('title', $manager, [
'multiValue' => true,
'field' => ['title', 'other'],
'mode' => 'and'
]);
$filter->args(['title' => ['foo', 'bar']]);
$filter->query($articles->find());
$filter->process();

$this->assertRegExp(
'/WHERE \(Articles\.title IN \(:c0,:c1\) ' .
'AND Articles\.other IN \(:c2,:c3\)\)$/',
$filter->query()->sql()
);
$this->assertEquals(
['foo', 'bar', 'foo', 'bar'],
Hash::extract($filter->query()->valueBinder()->bindings(), '{s}.value')
);
}

/**
* @return void
*/
Expand Down

0 comments on commit 9ed0e68

Please sign in to comment.