Skip to content

Commit

Permalink
Bugfix, re-selecting a field will now update other fields correctly
Browse files Browse the repository at this point in the history
  • Loading branch information
Phillaf committed Nov 27, 2015
1 parent 51747e9 commit 33d47ef
Show file tree
Hide file tree
Showing 4 changed files with 87 additions and 22 deletions.
2 changes: 1 addition & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -39,7 +39,7 @@ CREATE table songs(
Load the behavior in your model ```SongsTable.php```:

```
$this->addBehavior('Multiselect.Multiselect', ['field' => 'playing']);
$this->addBehavior('Multiselect.Multiselect', ['playing']);
```

The field must be a boolean.
Expand Down
38 changes: 25 additions & 13 deletions src/Model/Behavior/MultiselectBehavior.php
Original file line number Diff line number Diff line change
Expand Up @@ -21,9 +21,10 @@ class MultiselectBehavior extends Behavior
protected $_fieldConfig = [
'state' => true,
'limit' => 1,
'order' => ['modified' => 'ASC'],
'order' => [],
'scope' => [],
];

/**
* Constructor
*
Expand All @@ -37,6 +38,11 @@ class MultiselectBehavior extends Behavior
public function __construct(Table $table, array $config = [])
{
foreach ($config as $field => $fieldConfig) {
if (is_string($fieldConfig)) {
unset($config[$field]);
$field = $fieldConfig;
$fieldConfig = [];
}
$config[$field] = array_merge($this->_fieldConfig, $fieldConfig);
}
$config = $this->_resolveMethodAliases(
Expand Down Expand Up @@ -65,41 +71,42 @@ public function beforeSave(Event $event, Entity $entity)
{
$fields = $this->config();
foreach ($fields as $field => $config) {

if ($entity->get($field) !== $config['state']) {
continue;
}

$conditions = $this->getConditions($entity, $field, $config);
$count = $this->getCount($conditions, $entity);

if ($count < $config['limit']) {
continue;
}
if ($entity->get($field) !== $config['state']) {
continue;
}

$this->unselect($count, $conditions, $field, $config);
}
return true;
}

/**
* Find the number of entries matching the given expression
* We don't want to take into account the currently saved record
* Find the number of selected entries excluding currently saved entity
*
* @param array $conditions ORM conditions to be used
* @param \Cake\ORM\Entity $entity the entity to be saved
* @return int
*/
public function getCount(array $conditions, Entity $entity)
{
if (!$entity->isNew()) {
$primaryKey = $this->_table->schema()->primaryKey();
$primaryKey = is_string($primaryKey) ?: $primaryKey[0];
$conditions[$primaryKey . ' NOT IN'] = $entity->get($primaryKey);
}
return $this->_table->find()
$count = $this->_table->find()
->where($conditions)
->count();

return $count;
}

/**
* Find the number of entries matching the given expression
* Find the number of entries matching the given expression excluding
* current entity
*
* @param \Cake\ORM\Entity $entity the entity to match conditions against
* @param string $field name of the field to be configured
Expand All @@ -114,6 +121,11 @@ public function getConditions(Entity $entity, $field, $config)
$field => $entity->get($field)
]);
}
if (!$entity->isNew()) {
$primaryKey = $this->_table->schema()->primaryKey();
$primaryKey = is_string($primaryKey) ?: $primaryKey[0];
$conditions[$primaryKey . ' NOT IN'] = $entity->get($primaryKey);
}
return $conditions;
}

Expand Down
26 changes: 26 additions & 0 deletions tests/Fixture/ArticlesFixture.php
Original file line number Diff line number Diff line change
Expand Up @@ -39,34 +39,60 @@ class ArticlesFixture extends TestFixture
*/
public $records = [
[
// 1
'featured' => true,
'approved' => true,
'author_id' => 1,
'published' => '2015-09-01 00:00:00',
],
[
// 2
'featured' => false,
'approved' => false,
'author_id' => 1,
'published' => '2015-09-02 00:00:00',
],
[
// 3
'featured' => false,
'approved' => true,
'author_id' => 1,
'published' => '2015-09-03 00:00:00',
],
[
// 4
'featured' => true,
'approved' => true,
'author_id' => 2,
'published' => '2015-09-03 00:00:00',
],
[
// 5
'featured' => true,
'approved' => true,
'author_id' => 1,
'published' => '2015-09-04 00:00:00',
],
[
// 6
'featured' => true,
'approved' => true,
'author_id' => 3,
'published' => '2015-09-04 00:00:00',
],
[
// 7
'featured' => true,
'approved' => true,
'author_id' => 3,
'published' => '2015-09-05 00:00:00',
],
[
// 8
'featured' => true,
'approved' => true,
'author_id' => 3,
'published' => '2015-09-06 00:00:00',
],
];
}
43 changes: 35 additions & 8 deletions tests/TestCase/Model/Behavior/MultiselectBehaviorTest.php
Original file line number Diff line number Diff line change
Expand Up @@ -50,14 +50,18 @@ public function testUnselectedSave()
$this->Articles->save($article);

$result = $this->Articles
->find('list', ['valuefield' => 'id'])
->find()
->where(['featured' => true, 'author_id' => 1])
->extract('id')
->toarray();

$expected = [1 => 1, 5 => 5];
$expected = [1, 5];
$this->assertequals($expected, $result);
}

/**
* 1 and 5 are selected, insert new selected record
*/
public function testSelectedSave()
{
$data = [
Expand All @@ -70,11 +74,12 @@ public function testSelectedSave()
$this->Articles->save($article);

$result = $this->Articles
->find('list', ['valuefield' => 'id'])
->find()
->where(['featured' => true, 'author_id' => 1])
->extract('id')
->toarray();

$expected = [5 => 5, 6 => 6];
$expected = [5, 9];
$this->assertequals($expected, $result);
}

Expand Down Expand Up @@ -113,14 +118,19 @@ public function testScope()


$result = $this->Articles
->find('list', ['valuefield' => 'id'])
->find()
->where(['featured' => true, 'author_id' => 1])
->extract('id')
->toarray();

$expected = [5 => 5, 6 => 6];
$expected = [5, 9];
$this->assertequals($expected, $result);
}

/**
* Articles 1 and 5 featured
* Change article 5 for unapproved so that it's the first to be unselected
*/
public function testOrder()
{
$article = $this->Articles->get(5);
Expand All @@ -137,11 +147,28 @@ public function testOrder()
$this->Articles->save($article);

$result = $this->Articles
->find('list', ['valuefield' => 'id'])
->find()
->where(['featured' => true, 'author_id' => 1])
->extract('id')
->toarray();

$expected = [1 => 1, 6 => 6];
$expected = [1, 9];
$this->assertequals($expected, $result);
}

public function testCorrection()
{
$article = $this->Articles->get(6);
$article->dirty('id', true);
$this->Articles->save($article);

$result = $this->Articles
->find()
->where(['featured' => true, 'author_id' => 3])
->extract('id')
->toarray();

$expected = [6, 8];
$this->assertequals($expected, $result);
}
}

0 comments on commit 33d47ef

Please # to comment.