CounterCacheBehaviorTest.php 11 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401
  1. <?php
  2. /**
  3. * CakePHP(tm) : Rapid Development Framework (http://cakephp.org)
  4. * Copyright (c) Cake Software Foundation, Inc. (http://cakefoundation.org)
  5. *
  6. * Licensed under The MIT License
  7. * For full copyright and license information, please see the LICENSE.txt
  8. * Redistributions of files must retain the above copyright notice.
  9. *
  10. * @copyright Copyright (c) Cake Software Foundation, Inc. (http://cakefoundation.org)
  11. * @link http://cakephp.org CakePHP(tm) Project
  12. * @since 3.0.0
  13. * @license http://www.opensource.org/licenses/mit-license.php MIT License
  14. */
  15. namespace Cake\Test\TestCase\ORM\Behavior;
  16. use Cake\Database\Query;
  17. use Cake\Datasource\ConnectionManager;
  18. use Cake\Datasource\EntityInterface;
  19. use Cake\Event\Event;
  20. use Cake\ORM\Behavior\CounterCacheBehavior;
  21. use Cake\ORM\Entity;
  22. use Cake\ORM\Table;
  23. use Cake\ORM\TableRegistry;
  24. use Cake\TestSuite\TestCase;
  25. /**
  26. * Used for testing counter cache with custom finder
  27. */
  28. class PostTable extends Table
  29. {
  30. public function findPublished(Query $query, array $options)
  31. {
  32. return $query->where(['published' => true]);
  33. }
  34. }
  35. /**
  36. * CounterCacheBehavior test case
  37. */
  38. class CounterCacheBehaviorTest extends TestCase
  39. {
  40. /**
  41. * Fixture
  42. *
  43. * @var array
  44. */
  45. public $fixtures = [
  46. 'core.counter_cache_categories',
  47. 'core.counter_cache_posts',
  48. 'core.counter_cache_users'
  49. ];
  50. /**
  51. * setup
  52. *
  53. * @return void
  54. */
  55. public function setUp()
  56. {
  57. parent::setUp();
  58. $this->connection = ConnectionManager::get('test');
  59. $this->user = TableRegistry::get('Users', [
  60. 'table' => 'counter_cache_users',
  61. 'connection' => $this->connection
  62. ]);
  63. $this->category = TableRegistry::get('Categories', [
  64. 'table' => 'counter_cache_categories',
  65. 'connection' => $this->connection
  66. ]);
  67. $this->post = new PostTable([
  68. 'alias' => 'Post',
  69. 'table' => 'counter_cache_posts',
  70. 'connection' => $this->connection
  71. ]);
  72. }
  73. /**
  74. * teardown
  75. *
  76. * @return void
  77. */
  78. public function tearDown()
  79. {
  80. parent::tearDown();
  81. unset($this->user, $this->post);
  82. TableRegistry::clear();
  83. }
  84. /**
  85. * Testing simple counter caching when adding a record
  86. *
  87. * @return void
  88. */
  89. public function testAdd()
  90. {
  91. $this->post->belongsTo('Users');
  92. $this->post->addBehavior('CounterCache', [
  93. 'Users' => [
  94. 'post_count'
  95. ]
  96. ]);
  97. $before = $this->_getUser();
  98. $entity = $this->_getEntity();
  99. $this->post->save($entity);
  100. $after = $this->_getUser();
  101. $this->assertEquals(2, $before->get('post_count'));
  102. $this->assertEquals(3, $after->get('post_count'));
  103. }
  104. /**
  105. * Testing simple counter caching when adding a record
  106. *
  107. * @return void
  108. */
  109. public function testAddScope()
  110. {
  111. $this->post->belongsTo('Users');
  112. $this->post->addBehavior('CounterCache', [
  113. 'Users' => [
  114. 'posts_published' => [
  115. 'conditions' => [
  116. 'published' => true
  117. ]
  118. ]
  119. ]
  120. ]);
  121. $before = $this->_getUser();
  122. $entity = $this->_getEntity()->set('published', true);
  123. $this->post->save($entity);
  124. $after = $this->_getUser();
  125. $this->assertEquals(1, $before->get('posts_published'));
  126. $this->assertEquals(2, $after->get('posts_published'));
  127. }
  128. /**
  129. * Testing simple counter caching when deleting a record
  130. *
  131. * @return void
  132. */
  133. public function testDelete()
  134. {
  135. $this->post->belongsTo('Users');
  136. $this->post->addBehavior('CounterCache', [
  137. 'Users' => [
  138. 'post_count'
  139. ]
  140. ]);
  141. $before = $this->_getUser();
  142. $post = $this->post->find('all')->first();
  143. $this->post->delete($post);
  144. $after = $this->_getUser();
  145. $this->assertEquals(2, $before->get('post_count'));
  146. $this->assertEquals(1, $after->get('post_count'));
  147. }
  148. /**
  149. * Testing update simple counter caching when updating a record association
  150. *
  151. * @return void
  152. */
  153. public function testUpdate()
  154. {
  155. $this->post->belongsTo('Users');
  156. $this->post->belongsTo('Categories');
  157. $this->post->addBehavior('CounterCache', [
  158. 'Users' => [
  159. 'post_count'
  160. ],
  161. 'Categories' => [
  162. 'post_count'
  163. ],
  164. ]);
  165. $user1 = $this->_getUser(1);
  166. $user2 = $this->_getUser(2);
  167. $category1 = $this->_getCategory(1);
  168. $category2 = $this->_getCategory(2);
  169. $post = $this->post->find('all')->first();
  170. $this->assertEquals(2, $user1->get('post_count'));
  171. $this->assertEquals(1, $user2->get('post_count'));
  172. $this->assertEquals(1, $category1->get('post_count'));
  173. $this->assertEquals(2, $category2->get('post_count'));
  174. $entity = $this->post->patchEntity($post, ['user_id' => 2, 'category_id' => 2]);
  175. $this->post->save($entity);
  176. $user1 = $this->_getUser(1);
  177. $user2 = $this->_getUser(2);
  178. $category1 = $this->_getCategory(1);
  179. $category2 = $this->_getCategory(2);
  180. $this->assertEquals(1, $user1->get('post_count'));
  181. $this->assertEquals(2, $user2->get('post_count'));
  182. $this->assertEquals(0, $category1->get('post_count'));
  183. $this->assertEquals(3, $category2->get('post_count'));
  184. }
  185. /**
  186. * Testing counter cache with custom find
  187. *
  188. * @return void
  189. */
  190. public function testCustomFind()
  191. {
  192. $this->post->belongsTo('Users');
  193. $this->post->addBehavior('CounterCache', [
  194. 'Users' => [
  195. 'posts_published' => [
  196. 'finder' => 'published'
  197. ]
  198. ]
  199. ]);
  200. $before = $this->_getUser();
  201. $entity = $this->_getEntity()->set('published', true);
  202. $this->post->save($entity);
  203. $after = $this->_getUser();
  204. $this->assertEquals(1, $before->get('posts_published'));
  205. $this->assertEquals(2, $after->get('posts_published'));
  206. }
  207. /**
  208. * Testing counter cache with lambda returning number
  209. *
  210. * @return void
  211. */
  212. public function testLambdaNumber()
  213. {
  214. $this->post->belongsTo('Users');
  215. $table = $this->post;
  216. $entity = $this->_getEntity();
  217. $this->post->addBehavior('CounterCache', [
  218. 'Users' => [
  219. 'posts_published' => function (Event $orgEvent, EntityInterface $orgEntity, Table $orgTable) use ($entity, $table) {
  220. $this->assertSame($orgTable, $table);
  221. $this->assertSame($orgEntity, $entity);
  222. return 2;
  223. }
  224. ]
  225. ]);
  226. $before = $this->_getUser();
  227. $this->post->save($entity);
  228. $after = $this->_getUser();
  229. $this->assertEquals(1, $before->get('posts_published'));
  230. $this->assertEquals(2, $after->get('posts_published'));
  231. }
  232. /**
  233. * Testing counter cache with lambda returning number and changing of related ID
  234. *
  235. * @return void
  236. */
  237. public function testLambdaNumberUpdate()
  238. {
  239. $this->post->belongsTo('Users');
  240. $table = $this->post;
  241. $entity = $this->_getEntity();
  242. $this->post->addBehavior('CounterCache', [
  243. 'Users' => [
  244. 'posts_published' => function (Event $orgEvent, EntityInterface $orgEntity, Table $orgTable, $original) use ($entity, $table) {
  245. $this->assertSame($orgTable, $table);
  246. $this->assertSame($orgEntity, $entity);
  247. if (!$original) {
  248. return 2;
  249. } else {
  250. return 1;
  251. }
  252. }
  253. ]
  254. ]);
  255. $this->post->save($entity);
  256. $between = $this->_getUser();
  257. $entity->user_id = 2;
  258. $this->post->save($entity);
  259. $afterUser1 = $this->_getUser(1);
  260. $afterUser2 = $this->_getUser(2);
  261. $this->assertEquals(2, $between->get('posts_published'));
  262. $this->assertEquals(1, $afterUser1->get('posts_published'));
  263. $this->assertEquals(2, $afterUser2->get('posts_published'));
  264. }
  265. /**
  266. * Testing counter cache with lambda returning subqueryn
  267. *
  268. * @return void
  269. */
  270. public function testLambdaSubquery()
  271. {
  272. $this->post->belongsTo('Users');
  273. $this->post->addBehavior('CounterCache', [
  274. 'Users' => [
  275. 'posts_published' => function (Event $event, EntityInterface $entity, Table $table) {
  276. $query = new Query($this->connection);
  277. return $query->select(4);
  278. }
  279. ]
  280. ]);
  281. $before = $this->_getUser();
  282. $entity = $this->_getEntity();
  283. $this->post->save($entity);
  284. $after = $this->_getUser();
  285. $this->assertEquals(1, $before->get('posts_published'));
  286. $this->assertEquals(4, $after->get('posts_published'));
  287. }
  288. /**
  289. * Testing multiple counter cache when adding a record
  290. *
  291. * @return void
  292. */
  293. public function testMultiple()
  294. {
  295. $this->post->belongsTo('Users');
  296. $this->post->addBehavior('CounterCache', [
  297. 'Users' => [
  298. 'post_count',
  299. 'posts_published' => [
  300. 'conditions' => [
  301. 'published' => true
  302. ]
  303. ]
  304. ]
  305. ]);
  306. $before = $this->_getUser();
  307. $entity = $this->_getEntity()->set('published', true);
  308. $this->post->save($entity);
  309. $after = $this->_getUser();
  310. $this->assertEquals(1, $before->get('posts_published'));
  311. $this->assertEquals(2, $after->get('posts_published'));
  312. $this->assertEquals(2, $before->get('post_count'));
  313. $this->assertEquals(3, $after->get('post_count'));
  314. }
  315. /**
  316. * Get a new Entity
  317. *
  318. * @return Entity
  319. */
  320. protected function _getEntity()
  321. {
  322. return new Entity([
  323. 'title' => 'Test 123',
  324. 'user_id' => 1
  325. ]);
  326. }
  327. /**
  328. * Returns entity for user
  329. *
  330. * @return Entity
  331. */
  332. protected function _getUser($id = 1)
  333. {
  334. return $this->user->get($id);
  335. }
  336. /**
  337. * Returns entity for category
  338. *
  339. * @return Entity
  340. */
  341. protected function _getCategory($id = 1)
  342. {
  343. return $this->category->find('all')->where(['id' => $id])->first();
  344. }
  345. }