PageRenderTime 47ms CodeModel.GetById 18ms RepoModel.GetById 1ms app.codeStats 0ms

/Test/Case/Model/Behavior/SearchableBehaviorTest.php

https://github.com/dkullmann/search
PHP | 425 lines | 227 code | 48 blank | 150 comment | 11 complexity | 529cf480815ab69fc3d889b62d6feb44 MD5 | raw file
  1. <?php
  2. /**
  3. * Copyright 2009-2010, Cake Development Corporation (http://cakedc.com)
  4. *
  5. * Licensed under The MIT License
  6. * Redistributions of files must retain the above copyright notice.
  7. *
  8. * @copyright Copyright 2009-2010, Cake Development Corporation (http://cakedc.com)
  9. * @license MIT License (http://www.opensource.org/licenses/mit-license.php)
  10. */
  11. App::import('Core', 'Model');
  12. App::import('Model', 'ModelBehavior');
  13. /**
  14. * Searchable behavior tests
  15. *
  16. * @package search
  17. * @subpackage search.tests.cases.behaviors
  18. */
  19. class FilterBehavior extends ModelBehavior {
  20. /**
  21. * mostFilterConditions
  22. *
  23. * @param Model $Model
  24. * @param string $data
  25. * @return array
  26. */
  27. public function mostFilterConditions(Model $Model, $data = array()) {
  28. $filter = $data['filter'];
  29. if (!in_array($filter, array('views', 'comments'))) {
  30. return array();
  31. }
  32. switch ($filter) {
  33. case 'views':
  34. $cond = $Model->alias . '.views > 10';
  35. break;
  36. case 'comments':
  37. $cond = $Model->alias . '.comments > 10';
  38. break;
  39. }
  40. return (array)$cond;
  41. }
  42. }
  43. /**
  44. * Tag model
  45. *
  46. * @package search
  47. * @subpackage search.tests.cases.behaviors
  48. */
  49. class Tag extends CakeTestModel {
  50. }
  51. /**
  52. * Tagged model
  53. *
  54. * @package search
  55. * @subpackage search.tests.cases.behaviors
  56. */
  57. class Tagged extends CakeTestModel {
  58. /**
  59. * Table to use
  60. *
  61. * @var string
  62. */
  63. public $useTable = 'tagged';
  64. /**
  65. * Belongs To Assocaitions
  66. *
  67. * @var array
  68. */
  69. public $belongsTo = array('Tag');
  70. }
  71. /**
  72. * Article model
  73. *
  74. * @package search
  75. * @subpackage search.tests.cases.behaviors
  76. */
  77. class Article extends CakeTestModel {
  78. /**
  79. * Behaviors
  80. *
  81. * @var array
  82. */
  83. public $actsAs = array('Search.Searchable');
  84. /**
  85. * HABTM associations
  86. *
  87. * @var array
  88. */
  89. public $hasAndBelongsToMany = array('Tag' => array('with' => 'Tagged'));
  90. /**
  91. * Find by tags
  92. *
  93. * @param string $data
  94. * @return array
  95. */
  96. public function findByTags($data = array()) {
  97. $this->Tagged->Behaviors->attach('Containable', array('autoFields' => false));
  98. $this->Tagged->Behaviors->attach('Search.Searchable');
  99. $query = $this->Tagged->getQuery('all', array(
  100. 'conditions' => array('Tag.name' => $data['tags']),
  101. 'fields' => array('foreign_key'),
  102. 'contain' => array('Tag')
  103. ));
  104. return $query;
  105. }
  106. /**
  107. * Makes an array of range numbers that matches the ones on the interface.
  108. *
  109. * @return array
  110. */
  111. public function makeRangeCondition($data, $field = null) {
  112. if (is_string($data)) {
  113. $input = $data;
  114. }
  115. if (is_array($data)) {
  116. if (!empty($field['name'])) {
  117. $input = $data[$field['name']];
  118. } else {
  119. $input = $data['range'];
  120. }
  121. }
  122. switch ($input) {
  123. case '10':
  124. return array(0, 10);
  125. case '100':
  126. return array(11, 100);
  127. case '1000':
  128. return array(101, 1000);
  129. default:
  130. return array(0, 0);
  131. }
  132. }
  133. /**
  134. * orConditions
  135. *
  136. * @param array $data
  137. * @return array
  138. */
  139. public function orConditions($data = array()) {
  140. $filter = $data['filter'];
  141. $cond = array(
  142. 'OR' => array(
  143. $this->alias . '.title LIKE' => '%' . $filter . '%',
  144. $this->alias . '.body LIKE' => '%' . $filter . '%',
  145. ));
  146. return $cond;
  147. }
  148. }
  149. /**
  150. * SearchableTestCase
  151. *
  152. * @package search
  153. * @subpackage search.tests.cases.behaviors
  154. */
  155. class SearchableTestCase extends CakeTestCase {
  156. /**
  157. * Fixtures used in the SessionTest
  158. *
  159. * @var array
  160. */
  161. var $fixtures = array('plugin.search.article', 'plugin.search.tag', 'plugin.search.tagged');
  162. /**
  163. * startTest
  164. *
  165. * @return void
  166. */
  167. public function startTest() {
  168. $this->Article = ClassRegistry::init('Article');
  169. }
  170. /**
  171. * endTest
  172. *
  173. * @return void
  174. */
  175. public function endTest() {
  176. unset($this->Article);
  177. }
  178. /**
  179. * testValueCondition
  180. *
  181. * @return void
  182. * @link http://github.com/CakeDC/Search/issues#issue/3
  183. */
  184. public function testValueCondition() {
  185. $this->Article->filterArgs = array(
  186. array('name' => 'slug', 'type' => 'value'));
  187. $data = array();
  188. $result = $this->Article->parseCriteria($data);
  189. $this->assertEqual($result, array());
  190. $data = array('slug' => 'first_article');
  191. $result = $this->Article->parseCriteria($data);
  192. $expected = array('Article.slug' => 'first_article');
  193. $this->assertEqual($result, $expected);
  194. $this->Article->filterArgs = array(
  195. array('name' => 'fakeslug', 'type' => 'value', 'field' => 'Article2.slug'));
  196. $data = array('fakeslug' => 'first_article');
  197. $result = $this->Article->parseCriteria($data);
  198. $expected = array('Article2.slug' => 'first_article');
  199. $this->assertEqual($result, $expected);
  200. // Testing http://github.com/CakeDC/Search/issues#issue/3
  201. $this->Article->filterArgs = array(
  202. array('name' => 'views', 'type' => 'value'));
  203. $data = array('views' => '0');
  204. $result = $this->Article->parseCriteria($data);
  205. $this->assertEqual($result, array('Article.views' => 0));
  206. $this->Article->filterArgs = array(
  207. array('name' => 'views', 'type' => 'value'));
  208. $data = array('views' => 0);
  209. $result = $this->Article->parseCriteria($data);
  210. $this->assertEqual($result, array('Article.views' => 0));
  211. $this->Article->filterArgs = array(
  212. array('name' => 'views', 'type' => 'value'));
  213. $data = array('views' => '');
  214. $result = $this->Article->parseCriteria($data);
  215. $this->assertEqual($result, array());
  216. }
  217. /**
  218. * testLikeCondition
  219. *
  220. * @return void
  221. */
  222. public function testLikeCondition() {
  223. $this->Article->filterArgs = array(
  224. array('name' => 'title', 'type' => 'like'));
  225. $data = array();
  226. $result = $this->Article->parseCriteria($data);
  227. $this->assertEqual($result, array());
  228. $data = array('title' => 'First');
  229. $result = $this->Article->parseCriteria($data);
  230. $expected = array('Article.title LIKE' => '%First%');
  231. $this->assertEqual($result, $expected);
  232. $this->Article->filterArgs = array(
  233. array('name' => 'faketitle', 'type' => 'like', 'field' => 'Article.title'));
  234. $data = array('faketitle' => 'First');
  235. $result = $this->Article->parseCriteria($data);
  236. $expected = array('Article.title LIKE' => '%First%');
  237. $this->assertEqual($result, $expected);
  238. }
  239. /**
  240. * testSubQueryCondition
  241. *
  242. * @return void
  243. */
  244. public function testSubQueryCondition() {
  245. $this->Article->filterArgs = array(
  246. array('name' => 'tags', 'type' => 'subquery', 'method' => 'findByTags', 'field' => 'Article.id'));
  247. $data = array();
  248. $result = $this->Article->parseCriteria($data);
  249. $this->assertEqual($result, array());
  250. if ($this->skipIf($this->db->config['datasource'] != 'Database/Mysql', 'Test requires mysql db. %s')) {
  251. return;
  252. }
  253. $data = array('tags' => 'Cake');
  254. $result = $this->Article->parseCriteria($data);
  255. $expected = array(array("Article.id in (SELECT `Tagged`.`foreign_key` FROM `tagged` AS `Tagged` LEFT JOIN `tags` AS `Tag` ON (`Tagged`.`tag_id` = `Tag`.`id`) WHERE `Tag`.`name` = 'Cake')"));
  256. $this->assertEqual($result, $expected);
  257. }
  258. /**
  259. * testQueryOrExample
  260. *
  261. * @return void
  262. */
  263. public function testQueryOrExample() {
  264. $this->Article->filterArgs = array(
  265. array('name' => 'filter', 'type' => 'query', 'method' => 'orConditions'));
  266. $data = array();
  267. $result = $this->Article->parseCriteria($data);
  268. $this->assertEqual($result, array());
  269. $data = array('filter' => 'ticl');
  270. $result = $this->Article->parseCriteria($data);
  271. $expected = array('OR' => array(
  272. 'Article.title LIKE' => '%ticl%',
  273. 'Article.body LIKE' => '%ticl%'));
  274. $this->assertEqual($result, $expected);
  275. }
  276. /**
  277. * testQueryWithBehaviorCallCondition
  278. *
  279. * @return void
  280. */
  281. public function testQueryWithBehaviorCallCondition() {
  282. $this->Article->Behaviors->attach('Filter');
  283. $this->Article->filterArgs = array(
  284. array('name' => 'filter', 'type' => 'query', 'method' => 'mostFilterConditions'));
  285. $data = array();
  286. $result = $this->Article->parseCriteria($data);
  287. $this->assertEqual($result, array());
  288. $data = array('filter' => 'views');
  289. $result = $this->Article->parseCriteria($data);
  290. $expected = array('Article.views > 10');
  291. $this->assertEqual($result, $expected);
  292. }
  293. /**
  294. * testExpressionCallCondition
  295. *
  296. * @return void
  297. */
  298. public function testExpressionCallCondition() {
  299. $this->Article->filterArgs = array(
  300. array('name' => 'range', 'type' => 'expression', 'method' => 'makeRangeCondition', 'field' => 'Article.views BETWEEN ? AND ?'));
  301. $data = array();
  302. $result = $this->Article->parseCriteria($data);
  303. $this->assertEqual($result, array());
  304. $data = array('range' => '10');
  305. $result = $this->Article->parseCriteria($data);
  306. $expected = array('Article.views BETWEEN ? AND ?' => array(0, 10));
  307. $this->assertEqual($result, $expected);
  308. $this->Article->filterArgs = array(
  309. array('name' => 'range', 'type' => 'expression', 'method' => 'testThatInBehaviorMethodNotDefined', 'field' => 'Article.views BETWEEN ? AND ?'));
  310. $data = array('range' => '10');
  311. $result = $this->Article->parseCriteria($data);
  312. $this->assertEqual($result, array());
  313. }
  314. /**
  315. * testUnbindAll
  316. *
  317. * @return void
  318. */
  319. public function testUnbindAll() {
  320. $this->Article->unbindAllModels();
  321. $this->assertEqual($this->Article->belongsTo, array());
  322. $this->assertEqual($this->Article->hasMany, array());
  323. $this->assertEqual($this->Article->hasAndBelongsToMany, array());
  324. $this->assertEqual($this->Article->hasOne, array());
  325. }
  326. /**
  327. * testValidateSearch
  328. *
  329. * @return void
  330. */
  331. public function testValidateSearch() {
  332. $this->Article->filterArgs = array();
  333. $data = array('Article' => array('title' => 'Last Article'));
  334. $this->Article->set($data);
  335. $this->Article->validateSearch();
  336. $this->assertEqual($this->Article->data, $data);
  337. $this->Article->validateSearch($data);
  338. $this->assertEqual($this->Article->data, $data);
  339. $data = array('Article' => array('title' => ''));
  340. $this->Article->validateSearch($data);
  341. $expected = array('Article' => array());
  342. $this->assertEqual($this->Article->data, $expected);
  343. }
  344. /**
  345. * testPassedArgs
  346. *
  347. * @return void
  348. */
  349. public function testPassedArgs() {
  350. $this->Article->filterArgs = array(
  351. array('name' => 'slug', 'type' => 'value'));
  352. $data = array('slug' => 'first_article', 'filter' => 'myfilter');
  353. $result = $this->Article->passedArgs($data);
  354. $expected = array('slug' => 'first_article');
  355. $this->assertEqual($result, $expected);
  356. }
  357. /**
  358. * testGetQuery
  359. *
  360. * @return void
  361. */
  362. public function testGetQuery() {
  363. if ($this->skipIf($this->db->config['datasource'] != 'Database/Mysql', 'Test requires mysql db. %s')) {
  364. return;
  365. }
  366. $conditions = array('Article.id' => 1);
  367. $result = $this->Article->getQuery('all', array('conditions' => $conditions, 'order' => 'title', 'page' => 2, 'limit' => 2, 'fields' => array('id', 'title')));
  368. $expected = 'SELECT `Article`.`id`, `Article`.`title` FROM `articles` AS `Article` WHERE `Article`.`id` = 1 ORDER BY `title` ASC LIMIT 2, 2';
  369. $this->assertEqual($result, $expected);
  370. $this->Article->Tagged->Behaviors->attach('Search.Searchable');
  371. $conditions = array('Tagged.tag_id' => 1);
  372. $result = $this->Article->Tagged->recursive = -1;
  373. $result = $this->Article->Tagged->getQuery('first', compact('conditions'));
  374. $expected = "SELECT `Tagged`.`id`, `Tagged`.`foreign_key`, `Tagged`.`tag_id`, `Tagged`.`model`, `Tagged`.`language`, `Tagged`.`created`, `Tagged`.`modified` FROM `tagged` AS `Tagged` WHERE `Tagged`.`tag_id` = '1' LIMIT 1";
  375. $this->assertEqual($result, $expected);
  376. }
  377. }