Skip to content
Permalink
Browse files

Add an option which enables ignoring counter cache fields from being …

…updated
  • Loading branch information...
cleptric committed Jan 3, 2017
1 parent 1a250ac commit c24eba6d4e7ba518f40aa48343ba345c451726e2
@@ -18,6 +18,8 @@
use Cake\Event\Event;
use Cake\ORM\Association;
use Cake\ORM\Behavior;
use Cake\Utility\Hash;
use Cake\Utility\Inflector;
/**
* CounterCache behavior
@@ -74,10 +76,60 @@
* ]
* ]
* ```
*
* Ignore updating the field if it is dirty
* ```
* [
* 'Users' => [
* 'posts_published' => [
* 'ignoreDirty' => true
* ]
* ]
* ]
* ```
*/
class CounterCacheBehavior extends Behavior
{
/**
* Store the fields which should be ignored
*
* @var array
*/
protected $_ignoreDirty = [];
/**
* beforeSave callback.
*
* Check if a field, which should be ignored, is dirty
*
* @param \Cake\Event\Event $event The beforeSave event that was fired
* @param \Cake\Datasource\EntityInterface $entity The entity that is going to be saved
* @return void
*/
public function beforeSave(Event $event, EntityInterface $entity)
{
foreach ($this->_config as $assoc => $settings) {
$assoc = $this->_table->association($assoc);
foreach ($settings as $field => $config) {
if (is_int($field)) {
continue;
}
$registryAlias = $assoc->target()->registryAlias();
$entityAlias = $assoc->property();
if (!is_callable($config) &&
isset($config['ignoreDirty']) &&
$config['ignoreDirty'] === true &&
$entity->$entityAlias->dirty($field)
) {
$this->_ignoreDirty[$registryAlias][$field] = true;
}
}
}
}
/**
* afterSave callback.
*
@@ -90,6 +142,7 @@ class CounterCacheBehavior extends Behavior
public function afterSave(Event $event, EntityInterface $entity)
{
$this->_processAssociations($event, $entity);
$this->_ignoreDirty = [];
}
/**
@@ -148,6 +201,12 @@ protected function _processAssociation(Event $event, EntityInterface $entity, As
$config = [];
}
if (isset($this->_ignoreDirty[$assoc->target()->registryAlias()][$field]) &&
$this->_ignoreDirty[$assoc->target()->registryAlias()][$field] === true
) {
continue;
}
if (!is_string($config) && is_callable($config)) {
$count = $config($event, $entity, $this->_table, false);
} else {
@@ -0,0 +1,37 @@
<?php
/**
* CakePHP(tm) : Rapid Development Framework (http://cakephp.org)
* Copyright (c) Cake Software Foundation, Inc. (http://cakefoundation.org)
*
* Licensed under The MIT License
* For full copyright and license information, please see the LICENSE.txt
* Redistributions of files must retain the above copyright notice
*
* @copyright Copyright (c) Cake Software Foundation, Inc. (http://cakefoundation.org)
* @link http://cakephp.org CakePHP(tm) Project
* @since 1.2.0
* @license http://www.opensource.org/licenses/mit-license.php MIT License
*/
namespace Cake\Test\Fixture;
use Cake\TestSuite\Fixture\TestFixture;
/**
* Counter Cache Test Fixtures
*/
class CounterCacheCommentsFixture extends TestFixture
{
public $fields = [
'id' => ['type' => 'integer'],
'title' => ['type' => 'string', 'length' => 255],
'user_id' => ['type' => 'integer', 'null' => true],
'_constraints' => ['primary' => ['type' => 'primary', 'columns' => ['id']]]
];
public $records = [
['title' => 'First Comment', 'user_id' => 1],
['title' => 'Second Comment', 'user_id' => 1],
['title' => 'Third Comment', 'user_id' => 2],
];
}
@@ -26,12 +26,13 @@ class CounterCacheUsersFixture extends TestFixture
'id' => ['type' => 'integer'],
'name' => ['type' => 'string', 'length' => 255, 'null' => false],
'post_count' => ['type' => 'integer', 'null' => true],
'comment_count' => ['type' => 'integer', 'null' => true],
'posts_published' => ['type' => 'integer', 'null' => true],
'_constraints' => ['primary' => ['type' => 'primary', 'columns' => ['id']]]
];
public $records = [
['name' => 'Alexander', 'post_count' => 2, 'posts_published' => 1],
['name' => 'Steven', 'post_count' => 1, 'posts_published' => 1],
['name' => 'Alexander', 'post_count' => 2, 'comment_count' => 2, 'posts_published' => 1],
['name' => 'Steven', 'post_count' => 1, 'comment_count' => 1, 'posts_published' => 1],
];
}
@@ -49,6 +49,7 @@ class CounterCacheBehaviorTest extends TestCase
public $fixtures = [
'core.counter_cache_categories',
'core.counter_cache_posts',
'core.counter_cache_comments',
'core.counter_cache_users',
'core.counter_cache_user_category_posts'
];
@@ -73,6 +74,12 @@ public function setUp()
'connection' => $this->connection
]);
$this->comment = TableRegistry::get('Comments', [
'alias' => 'Comment',
'table' => 'counter_cache_comments',
'connection' => $this->connection
]);
$this->post = new PostTable([
'alias' => 'Post',
'table' => 'counter_cache_posts',
@@ -402,6 +409,94 @@ public function testBindingKey()
$this->assertEquals(2, $after->get('post_count'));
}
/**
* Testing the ignore if dirty option
*
* @return void
*/
public function testIgnoreDirty()
{
$this->post->belongsTo('Users');
$this->comment->belongsTo('Users');
$this->post->addBehavior('CounterCache', [
'Users' => [
'post_count' => [
'ignoreDirty' => true
],
'comment_count' => [
'ignoreDirty' => true
],
]
]);
$user = $this->_getUser(1);
$this->assertSame(2, $user->get('post_count'));
$this->assertSame(2, $user->get('comment_count'));
$this->assertSame(1, $user->get('posts_published'));
$post = $this->post->find('all')
->contain('Users')
->where(['title' => 'Rock and Roll'])
->first();
$post = $this->post->patchEntity($post, [
'posts_published' => true,
'user' => [
'id' => 1,
'post_count' => 10,
'comment_count' => 10
]
]);
$save = $this->post->save($post);
$user = $this->_getUser(1);
$this->assertSame(10, $user->get('post_count'));
$this->assertSame(10, $user->get('comment_count'));
$this->assertSame(1, $user->get('posts_published'));
}
/**
* Testing the ignore if dirty option with just one field set to ignoreDirty
*
* @return void
*/
public function testIgnoreDirtyMixed()
{
$this->post->belongsTo('Users');
$this->comment->belongsTo('Users');
$this->post->addBehavior('CounterCache', [
'Users' => [
'post_count' => [
'ignoreDirty' => true
]
]
]);
$user = $this->_getUser(1);
$this->assertSame(2, $user->get('post_count'));
$this->assertSame(2, $user->get('comment_count'));
$this->assertSame(1, $user->get('posts_published'));
$post = $this->post->find('all')
->contain('Users')
->where(['title' => 'Rock and Roll'])
->first();
$post = $this->post->patchEntity($post, [
'posts_published' => true,
'user' => [
'id' => 1,
'post_count' => 10
]
]);
$save = $this->post->save($post);
$user = $this->_getUser(1);
$this->assertSame(10, $user->get('post_count'));
$this->assertSame(2, $user->get('comment_count'));
$this->assertSame(1, $user->get('posts_published'));
}
/**
* Get a new Entity
*

0 comments on commit c24eba6

Please sign in to comment.
You can’t perform that action at this time.
You signed in with another tab or window. Reload to refresh your session. You signed out in another tab or window. Reload to refresh your session.