HashTest.php 51 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798991001011021031041051061071081091101111121131141151161171181191201211221231241251261271281291301311321331341351361371381391401411421431441451461471481491501511521531541551561571581591601611621631641651661671681691701711721731741751761771781791801811821831841851861871881891901911921931941951961971981992002012022032042052062072082092102112122132142152162172182192202212222232242252262272282292302312322332342352362372382392402412422432442452462472482492502512522532542552562572582592602612622632642652662672682692702712722732742752762772782792802812822832842852862872882892902912922932942952962972982993003013023033043053063073083093103113123133143153163173183193203213223233243253263273283293303313323333343353363373383393403413423433443453463473483493503513523533543553563573583593603613623633643653663673683693703713723733743753763773783793803813823833843853863873883893903913923933943953963973983994004014024034044054064074084094104114124134144154164174184194204214224234244254264274284294304314324334344354364374384394404414424434444454464474484494504514524534544554564574584594604614624634644654664674684694704714724734744754764774784794804814824834844854864874884894904914924934944954964974984995005015025035045055065075085095105115125135145155165175185195205215225235245255265275285295305315325335345355365375385395405415425435445455465475485495505515525535545555565575585595605615625635645655665675685695705715725735745755765775785795805815825835845855865875885895905915925935945955965975985996006016026036046056066076086096106116126136146156166176186196206216226236246256266276286296306316326336346356366376386396406416426436446456466476486496506516526536546556566576586596606616626636646656666676686696706716726736746756766776786796806816826836846856866876886896906916926936946956966976986997007017027037047057067077087097107117127137147157167177187197207217227237247257267277287297307317327337347357367377387397407417427437447457467477487497507517527537547557567577587597607617627637647657667677687697707717727737747757767777787797807817827837847857867877887897907917927937947957967977987998008018028038048058068078088098108118128138148158168178188198208218228238248258268278288298308318328338348358368378388398408418428438448458468478488498508518528538548558568578588598608618628638648658668678688698708718728738748758768778788798808818828838848858868878888898908918928938948958968978988999009019029039049059069079089099109119129139149159169179189199209219229239249259269279289299309319329339349359369379389399409419429439449459469479489499509519529539549559569579589599609619629639649659669679689699709719729739749759769779789799809819829839849859869879889899909919929939949959969979989991000100110021003100410051006100710081009101010111012101310141015101610171018101910201021102210231024102510261027102810291030103110321033103410351036103710381039104010411042104310441045104610471048104910501051105210531054105510561057105810591060106110621063106410651066106710681069107010711072107310741075107610771078107910801081108210831084108510861087108810891090109110921093109410951096109710981099110011011102110311041105110611071108110911101111111211131114111511161117111811191120112111221123112411251126112711281129113011311132113311341135113611371138113911401141114211431144114511461147114811491150115111521153115411551156115711581159116011611162116311641165116611671168116911701171117211731174117511761177117811791180118111821183118411851186118711881189119011911192119311941195119611971198119912001201120212031204120512061207120812091210121112121213121412151216121712181219122012211222122312241225122612271228122912301231123212331234123512361237123812391240124112421243124412451246124712481249125012511252125312541255125612571258125912601261126212631264126512661267126812691270127112721273127412751276127712781279128012811282128312841285128612871288128912901291129212931294129512961297129812991300130113021303130413051306130713081309131013111312131313141315131613171318131913201321132213231324132513261327132813291330133113321333133413351336133713381339134013411342134313441345134613471348134913501351135213531354135513561357135813591360136113621363136413651366136713681369137013711372137313741375137613771378137913801381138213831384138513861387138813891390139113921393139413951396139713981399140014011402140314041405140614071408140914101411141214131414141514161417141814191420142114221423142414251426142714281429143014311432143314341435143614371438143914401441144214431444144514461447144814491450145114521453145414551456145714581459146014611462146314641465146614671468146914701471147214731474147514761477147814791480148114821483148414851486148714881489149014911492149314941495149614971498149915001501150215031504150515061507150815091510151115121513151415151516151715181519152015211522152315241525152615271528152915301531153215331534153515361537153815391540154115421543154415451546154715481549155015511552155315541555155615571558155915601561156215631564156515661567156815691570157115721573157415751576157715781579158015811582158315841585158615871588158915901591159215931594159515961597159815991600160116021603160416051606160716081609161016111612161316141615161616171618161916201621162216231624162516261627162816291630163116321633163416351636163716381639164016411642164316441645164616471648164916501651165216531654165516561657165816591660166116621663166416651666166716681669167016711672167316741675167616771678167916801681168216831684168516861687168816891690169116921693169416951696169716981699170017011702170317041705170617071708170917101711171217131714171517161717171817191720172117221723172417251726172717281729173017311732173317341735173617371738173917401741174217431744174517461747174817491750175117521753175417551756175717581759176017611762176317641765176617671768176917701771177217731774177517761777177817791780178117821783178417851786178717881789179017911792179317941795179617971798179918001801180218031804180518061807180818091810181118121813181418151816181718181819182018211822182318241825182618271828182918301831183218331834183518361837183818391840184118421843184418451846184718481849185018511852185318541855185618571858185918601861186218631864186518661867186818691870187118721873187418751876187718781879188018811882188318841885188618871888188918901891189218931894189518961897189818991900190119021903190419051906190719081909191019111912191319141915191619171918191919201921192219231924192519261927192819291930193119321933193419351936193719381939194019411942194319441945194619471948194919501951195219531954195519561957195819591960196119621963196419651966196719681969197019711972197319741975197619771978197919801981198219831984198519861987198819891990199119921993199419951996199719981999200020012002200320042005200620072008200920102011201220132014201520162017201820192020202120222023202420252026202720282029203020312032203320342035203620372038203920402041204220432044204520462047204820492050205120522053205420552056205720582059206020612062206320642065206620672068206920702071207220732074207520762077207820792080208120822083208420852086208720882089209020912092209320942095209620972098209921002101210221032104210521062107210821092110211121122113211421152116211721182119212021212122212321242125212621272128
  1. <?php
  2. /**
  3. * CakePHP(tm) : Rapid Development Framework (http://cakephp.org)
  4. * Copyright 2005-2011, Cake Software Foundation, Inc. (http://cakefoundation.org)
  5. *
  6. * Licensed under The MIT License
  7. * Redistributions of files must retain the above copyright notice.
  8. *
  9. * @copyright Copyright 2005-2011, Cake Software Foundation, Inc. (http://cakefoundation.org)
  10. * @link http://cakephp.org CakePHP(tm) Project
  11. * @package Cake.Utility
  12. * @since CakePHP(tm) v 2.2.0
  13. * @license MIT License (http://www.opensource.org/licenses/mit-license.php)
  14. */
  15. App::uses('Hash', 'Utility');
  16. class HashTest extends CakeTestCase {
  17. public static function articleData() {
  18. return array(
  19. array(
  20. 'Article' => array(
  21. 'id' => '1',
  22. 'user_id' => '1',
  23. 'title' => 'First Article',
  24. 'body' => 'First Article Body'
  25. ),
  26. 'User' => array(
  27. 'id' => '1',
  28. 'user' => 'mariano',
  29. 'password' => '5f4dcc3b5aa765d61d8327deb882cf99',
  30. ),
  31. 'Comment' => array(
  32. array(
  33. 'id' => '1',
  34. 'article_id' => '1',
  35. 'user_id' => '2',
  36. 'comment' => 'First Comment for First Article',
  37. ),
  38. array(
  39. 'id' => '2',
  40. 'article_id' => '1',
  41. 'user_id' => '4',
  42. 'comment' => 'Second Comment for First Article',
  43. ),
  44. ),
  45. 'Tag' => array(
  46. array(
  47. 'id' => '1',
  48. 'tag' => 'tag1',
  49. ),
  50. array(
  51. 'id' => '2',
  52. 'tag' => 'tag2',
  53. )
  54. ),
  55. 'Deep' => array(
  56. 'Nesting' => array(
  57. 'test' => array(
  58. 1 => 'foo',
  59. 2 => array(
  60. 'and' => array('more' => 'stuff')
  61. )
  62. )
  63. )
  64. )
  65. ),
  66. array(
  67. 'Article' => array(
  68. 'id' => '2',
  69. 'user_id' => '1',
  70. 'title' => 'Second Article',
  71. 'body' => 'Second Article Body',
  72. 'published' => 'Y',
  73. ),
  74. 'User' => array(
  75. 'id' => '2',
  76. 'user' => 'mariano',
  77. 'password' => '5f4dcc3b5aa765d61d8327deb882cf99',
  78. ),
  79. 'Comment' => array(),
  80. 'Tag' => array()
  81. ),
  82. array(
  83. 'Article' => array(
  84. 'id' => '3',
  85. 'user_id' => '1',
  86. 'title' => 'Third Article',
  87. 'body' => 'Third Article Body',
  88. ),
  89. 'User' => array(
  90. 'id' => '3',
  91. 'user' => 'mariano',
  92. 'password' => '5f4dcc3b5aa765d61d8327deb882cf99',
  93. ),
  94. 'Comment' => array(),
  95. 'Tag' => array()
  96. ),
  97. array(
  98. 'Article' => array(
  99. 'id' => '4',
  100. 'user_id' => '1',
  101. 'title' => 'Fourth Article',
  102. 'body' => 'Fourth Article Body',
  103. ),
  104. 'User' => array(
  105. 'id' => '4',
  106. 'user' => 'mariano',
  107. 'password' => '5f4dcc3b5aa765d61d8327deb882cf99',
  108. ),
  109. 'Comment' => array(),
  110. 'Tag' => array()
  111. ),
  112. array(
  113. 'Article' => array(
  114. 'id' => '5',
  115. 'user_id' => '1',
  116. 'title' => 'Fifth Article',
  117. 'body' => 'Fifth Article Body',
  118. ),
  119. 'User' => array(
  120. 'id' => '5',
  121. 'user' => 'mariano',
  122. 'password' => '5f4dcc3b5aa765d61d8327deb882cf99',
  123. ),
  124. 'Comment' => array(),
  125. 'Tag' => array()
  126. )
  127. );
  128. }
  129. public static function userData() {
  130. return array(
  131. array(
  132. 'User' => array(
  133. 'id' => 2,
  134. 'group_id' => 1,
  135. 'Data' => array(
  136. 'user' => 'mariano.iglesias',
  137. 'name' => 'Mariano Iglesias'
  138. )
  139. )
  140. ),
  141. array(
  142. 'User' => array(
  143. 'id' => 14,
  144. 'group_id' => 2,
  145. 'Data' => array(
  146. 'user' => 'phpnut',
  147. 'name' => 'Larry E. Masters'
  148. )
  149. )
  150. ),
  151. array(
  152. 'User' => array(
  153. 'id' => 25,
  154. 'group_id' => 1,
  155. 'Data' => array(
  156. 'user' => 'gwoo',
  157. 'name' => 'The Gwoo'
  158. )
  159. )
  160. )
  161. );
  162. }
  163. /**
  164. * Test get()
  165. *
  166. * return void
  167. */
  168. public function testGet() {
  169. $data = self::articleData();
  170. $result = Hash::get(array(), '1.Article.title');
  171. $this->assertNull($result);
  172. $result = Hash::get($data, '');
  173. $this->assertNull($result);
  174. $result = Hash::get($data, '0.Article.title');
  175. $this->assertEquals('First Article', $result);
  176. $result = Hash::get($data, '1.Article.title');
  177. $this->assertEquals('Second Article', $result);
  178. $result = Hash::get($data, '5.Article.title');
  179. $this->assertNull($result);
  180. $result = Hash::get($data, '1.Article.title.not_there');
  181. $this->assertNull($result);
  182. $result = Hash::get($data, '1.Article');
  183. $this->assertEquals($data[1]['Article'], $result);
  184. $result = Hash::get($data, array('1', 'Article'));
  185. $this->assertEquals($data[1]['Article'], $result);
  186. }
  187. /**
  188. * Test dimensions.
  189. *
  190. * @return void
  191. */
  192. public function testDimensions() {
  193. $result = Hash::dimensions(array());
  194. $this->assertEquals($result, 0);
  195. $data = array('one', '2', 'three');
  196. $result = Hash::dimensions($data);
  197. $this->assertEquals($result, 1);
  198. $data = array('1' => '1.1', '2', '3');
  199. $result = Hash::dimensions($data);
  200. $this->assertEquals($result, 1);
  201. $data = array('1' => array('1.1' => '1.1.1'), '2', '3' => array('3.1' => '3.1.1'));
  202. $result = Hash::dimensions($data);
  203. $this->assertEquals($result, 2);
  204. $data = array('1' => '1.1', '2', '3' => array('3.1' => '3.1.1'));
  205. $result = Hash::dimensions($data);
  206. $this->assertEquals($result, 1);
  207. $data = array('1' => array('1.1' => '1.1.1'), '2', '3' => array('3.1' => array('3.1.1' => '3.1.1.1')));
  208. $result = Hash::dimensions($data);
  209. $this->assertEquals($result, 2);
  210. }
  211. /**
  212. * Test maxDimensions
  213. *
  214. * @return void
  215. */
  216. public function testMaxDimensions() {
  217. $data = array('1' => '1.1', '2', '3' => array('3.1' => '3.1.1'));
  218. $result = Hash::maxDimensions($data);
  219. $this->assertEquals($result, 2);
  220. $data = array('1' => array('1.1' => '1.1.1'), '2', '3' => array('3.1' => array('3.1.1' => '3.1.1.1')));
  221. $result = Hash::maxDimensions($data);
  222. $this->assertEquals($result, 3);
  223. $data = array(
  224. '1' => array('1.1' => '1.1.1'),
  225. array('2' => array('2.1' => array('2.1.1' => '2.1.1.1'))),
  226. '3' => array('3.1' => array('3.1.1' => '3.1.1.1'))
  227. );
  228. $result = Hash::maxDimensions($data);
  229. $this->assertEquals($result, 4);
  230. $data = array(
  231. '1' => array('1.1' => '1.1.1'),
  232. array('2' => array('2.1' => array('2.1.1' => array('2.1.1.1')))),
  233. '3' => array('3.1' => array('3.1.1' => '3.1.1.1'))
  234. );
  235. $result = Hash::maxDimensions($data);
  236. $this->assertEquals($result, 5);
  237. $data = array(
  238. '1' => array('1.1' => '1.1.1'),
  239. array('2' => array('2.1' => array('2.1.1' => array('2.1.1.1' => '2.1.1.1.1')))),
  240. '3' => array('3.1' => array('3.1.1' => '3.1.1.1'))
  241. );
  242. $result = Hash::maxDimensions($data);
  243. $this->assertEquals($result, 5);
  244. $data = array(
  245. '1' => array('1.1' => '1.1.1'),
  246. array('2' => array('2.1' => array('2.1.1' => array('2.1.1.1' => '2.1.1.1.1')))),
  247. '3' => array('3.1' => array('3.1.1' => '3.1.1.1'))
  248. );
  249. $result = Hash::maxDimensions($data);
  250. $this->assertEquals($result, 5);
  251. }
  252. /**
  253. * Tests Hash::flatten
  254. *
  255. * @return void
  256. */
  257. public function testFlatten() {
  258. $data = array('Larry', 'Curly', 'Moe');
  259. $result = Hash::flatten($data);
  260. $this->assertEquals($result, $data);
  261. $data[9] = 'Shemp';
  262. $result = Hash::flatten($data);
  263. $this->assertEquals($result, $data);
  264. $data = array(
  265. array(
  266. 'Post' => array('id' => '1', 'author_id' => '1', 'title' => 'First Post'),
  267. 'Author' => array('id' => '1', 'user' => 'nate', 'password' => 'foo'),
  268. ),
  269. array(
  270. 'Post' => array('id' => '2', 'author_id' => '3', 'title' => 'Second Post', 'body' => 'Second Post Body'),
  271. 'Author' => array('id' => '3', 'user' => 'larry', 'password' => null),
  272. )
  273. );
  274. $result = Hash::flatten($data);
  275. $expected = array(
  276. '0.Post.id' => '1',
  277. '0.Post.author_id' => '1',
  278. '0.Post.title' => 'First Post',
  279. '0.Author.id' => '1',
  280. '0.Author.user' => 'nate',
  281. '0.Author.password' => 'foo',
  282. '1.Post.id' => '2',
  283. '1.Post.author_id' => '3',
  284. '1.Post.title' => 'Second Post',
  285. '1.Post.body' => 'Second Post Body',
  286. '1.Author.id' => '3',
  287. '1.Author.user' => 'larry',
  288. '1.Author.password' => null
  289. );
  290. $this->assertEquals($expected, $result);
  291. $data = array(
  292. array('Post' => array('id' => 1)),
  293. array('Post' => array('id' => 2)),
  294. );
  295. $result = Hash::flatten($data, '/');
  296. $expected = array(
  297. '0/Post/id' => '1',
  298. '1/Post/id' => '2',
  299. );
  300. $this->assertEquals($expected, $result);
  301. }
  302. /**
  303. * Test diff();
  304. *
  305. * @return void
  306. */
  307. public function testDiff() {
  308. $a = array(
  309. 0 => array('name' => 'main'),
  310. 1 => array('name' => 'about')
  311. );
  312. $b = array(
  313. 0 => array('name' => 'main'),
  314. 1 => array('name' => 'about'),
  315. 2 => array('name' => 'contact')
  316. );
  317. $result = Hash::diff($a, array());
  318. $expected = $a;
  319. $this->assertEquals($expected, $result);
  320. $result = Hash::diff(array(), $b);
  321. $expected = $b;
  322. $this->assertEquals($expected, $result);
  323. $result = Hash::diff($a, $b);
  324. $expected = array(
  325. 2 => array('name' => 'contact')
  326. );
  327. $this->assertEquals($expected, $result);
  328. $b = array(
  329. 0 => array('name' => 'me'),
  330. 1 => array('name' => 'about')
  331. );
  332. $result = Hash::diff($a, $b);
  333. $expected = array(
  334. 0 => array('name' => 'main')
  335. );
  336. $this->assertEquals($expected, $result);
  337. $a = array();
  338. $b = array('name' => 'bob', 'address' => 'home');
  339. $result = Hash::diff($a, $b);
  340. $this->assertEquals($result, $b);
  341. $a = array('name' => 'bob', 'address' => 'home');
  342. $b = array();
  343. $result = Hash::diff($a, $b);
  344. $this->assertEquals($result, $a);
  345. $a = array('key' => true, 'another' => false, 'name' => 'me');
  346. $b = array('key' => 1, 'another' => 0);
  347. $expected = array('name' => 'me');
  348. $result = Hash::diff($a, $b);
  349. $this->assertEquals($expected, $result);
  350. $a = array('key' => 'value', 'another' => null, 'name' => 'me');
  351. $b = array('key' => 'differentValue', 'another' => null);
  352. $expected = array('key' => 'value', 'name' => 'me');
  353. $result = Hash::diff($a, $b);
  354. $this->assertEquals($expected, $result);
  355. $a = array('key' => 'value', 'another' => null, 'name' => 'me');
  356. $b = array('key' => 'differentValue', 'another' => 'value');
  357. $expected = array('key' => 'value', 'another' => null, 'name' => 'me');
  358. $result = Hash::diff($a, $b);
  359. $this->assertEquals($expected, $result);
  360. $a = array('key' => 'value', 'another' => null, 'name' => 'me');
  361. $b = array('key' => 'differentValue', 'another' => 'value');
  362. $expected = array('key' => 'differentValue', 'another' => 'value', 'name' => 'me');
  363. $result = Hash::diff($b, $a);
  364. $this->assertEquals($expected, $result);
  365. $a = array('key' => 'value', 'another' => null, 'name' => 'me');
  366. $b = array(0 => 'differentValue', 1 => 'value');
  367. $expected = $a + $b;
  368. $result = Hash::diff($a, $b);
  369. $this->assertEquals($expected, $result);
  370. }
  371. /**
  372. * Test merge()
  373. *
  374. * @return void
  375. */
  376. public function testMerge() {
  377. $result = Hash::merge(array('foo'), array('bar'));
  378. $this->assertEquals($result, array('foo', 'bar'));
  379. $result = Hash::merge(array('foo'), array('user' => 'bob', 'no-bar'), 'bar');
  380. $this->assertEquals($result, array('foo', 'user' => 'bob', 'no-bar', 'bar'));
  381. $a = array('foo', 'foo2');
  382. $b = array('bar', 'bar2');
  383. $expected = array('foo', 'foo2', 'bar', 'bar2');
  384. $this->assertEquals($expected, Hash::merge($a, $b));
  385. $a = array('foo' => 'bar', 'bar' => 'foo');
  386. $b = array('foo' => 'no-bar', 'bar' => 'no-foo');
  387. $expected = array('foo' => 'no-bar', 'bar' => 'no-foo');
  388. $this->assertEquals($expected, Hash::merge($a, $b));
  389. $a = array('users' => array('bob', 'jim'));
  390. $b = array('users' => array('lisa', 'tina'));
  391. $expected = array('users' => array('bob', 'jim', 'lisa', 'tina'));
  392. $this->assertEquals($expected, Hash::merge($a, $b));
  393. $a = array('users' => array('jim', 'bob'));
  394. $b = array('users' => 'none');
  395. $expected = array('users' => 'none');
  396. $this->assertEquals($expected, Hash::merge($a, $b));
  397. $a = array('users' => array('lisa' => array('id' => 5, 'pw' => 'secret')), 'cakephp');
  398. $b = array('users' => array('lisa' => array('pw' => 'new-pass', 'age' => 23)), 'ice-cream');
  399. $expected = array(
  400. 'users' => array('lisa' => array('id' => 5, 'pw' => 'new-pass', 'age' => 23)),
  401. 'cakephp',
  402. 'ice-cream'
  403. );
  404. $result = Hash::merge($a, $b);
  405. $this->assertEquals($expected, $result);
  406. $c = array(
  407. 'users' => array('lisa' => array('pw' => 'you-will-never-guess', 'age' => 25, 'pet' => 'dog')),
  408. 'chocolate'
  409. );
  410. $expected = array(
  411. 'users' => array('lisa' => array('id' => 5, 'pw' => 'you-will-never-guess', 'age' => 25, 'pet' => 'dog')),
  412. 'cakephp',
  413. 'ice-cream',
  414. 'chocolate'
  415. );
  416. $this->assertEquals($expected, Hash::merge($a, $b, $c));
  417. $this->assertEquals($expected, Hash::merge($a, $b, array(), $c));
  418. $a = array(
  419. 'Tree',
  420. 'CounterCache',
  421. 'Upload' => array(
  422. 'folder' => 'products',
  423. 'fields' => array('image_1_id', 'image_2_id', 'image_3_id', 'image_4_id', 'image_5_id')
  424. )
  425. );
  426. $b = array(
  427. 'Cacheable' => array('enabled' => false),
  428. 'Limit',
  429. 'Bindable',
  430. 'Validator',
  431. 'Transactional'
  432. );
  433. $expected = array(
  434. 'Tree',
  435. 'CounterCache',
  436. 'Upload' => array(
  437. 'folder' => 'products',
  438. 'fields' => array('image_1_id', 'image_2_id', 'image_3_id', 'image_4_id', 'image_5_id')
  439. ),
  440. 'Cacheable' => array('enabled' => false),
  441. 'Limit',
  442. 'Bindable',
  443. 'Validator',
  444. 'Transactional'
  445. );
  446. $this->assertEquals(Hash::merge($a, $b), $expected);
  447. }
  448. /**
  449. * test normalizing arrays
  450. *
  451. * @return void
  452. */
  453. public function testNormalize() {
  454. $result = Hash::normalize(array('one', 'two', 'three'));
  455. $expected = array('one' => null, 'two' => null, 'three' => null);
  456. $this->assertEquals($expected, $result);
  457. $result = Hash::normalize(array('one', 'two', 'three'), false);
  458. $expected = array('one', 'two', 'three');
  459. $this->assertEquals($expected, $result);
  460. $result = Hash::normalize(array('one' => 1, 'two' => 2, 'three' => 3, 'four'), false);
  461. $expected = array('one' => 1, 'two' => 2, 'three' => 3, 'four' => null);
  462. $this->assertEquals($expected, $result);
  463. $result = Hash::normalize(array('one' => 1, 'two' => 2, 'three' => 3, 'four'));
  464. $expected = array('one' => 1, 'two' => 2, 'three' => 3, 'four' => null);
  465. $this->assertEquals($expected, $result);
  466. $result = Hash::normalize(array('one' => array('a', 'b', 'c' => 'cee'), 'two' => 2, 'three'));
  467. $expected = array('one' => array('a', 'b', 'c' => 'cee'), 'two' => 2, 'three' => null);
  468. $this->assertEquals($expected, $result);
  469. }
  470. /**
  471. * testContains method
  472. *
  473. * @return void
  474. */
  475. public function testContains() {
  476. $data = array('apple', 'bee', 'cyclops');
  477. $this->assertTrue(Hash::contains($data, array('apple')));
  478. $this->assertFalse(Hash::contains($data, array('data')));
  479. $a = array(
  480. 0 => array('name' => 'main'),
  481. 1 => array('name' => 'about')
  482. );
  483. $b = array(
  484. 0 => array('name' => 'main'),
  485. 1 => array('name' => 'about'),
  486. 2 => array('name' => 'contact'),
  487. 'a' => 'b'
  488. );
  489. $this->assertTrue(Hash::contains($a, $a));
  490. $this->assertFalse(Hash::contains($a, $b));
  491. $this->assertTrue(Hash::contains($b, $a));
  492. $a = array(
  493. array('User' => array('id' => 1)),
  494. array('User' => array('id' => 2)),
  495. );
  496. $b = array(
  497. array('User' => array('id' => 1)),
  498. array('User' => array('id' => 2)),
  499. array('User' => array('id' => 3))
  500. );
  501. $this->assertTrue(Hash::contains($b, $a));
  502. $this->assertFalse(Hash::contains($a, $b));
  503. }
  504. /**
  505. * testFilter method
  506. *
  507. * @return void
  508. */
  509. public function testFilter() {
  510. $result = Hash::filter(array('0', false, true, 0, array('one thing', 'I can tell you', 'is you got to be', false)));
  511. $expected = array('0', 2 => true, 3 => 0, 4 => array('one thing', 'I can tell you', 'is you got to be'));
  512. $this->assertSame($expected, $result);
  513. $result = Hash::filter(array(1, array(false)));
  514. $expected = array(1);
  515. $this->assertEquals($expected, $result);
  516. $result = Hash::filter(array(1, array(false, false)));
  517. $expected = array(1);
  518. $this->assertEquals($expected, $result);
  519. $result = Hash::filter(array(1, array('empty', false)));
  520. $expected = array(1, array('empty'));
  521. $this->assertEquals($expected, $result);
  522. $result = Hash::filter(array(1, array('2', false, array(3, null))));
  523. $expected = array(1, array('2', 2 => array(3)));
  524. $this->assertEquals($expected, $result);
  525. $this->assertSame(array(), Hash::filter(array()));
  526. }
  527. /**
  528. * testNumericArrayCheck method
  529. *
  530. * @return void
  531. */
  532. public function testNumeric() {
  533. $data = array('one');
  534. $this->assertTrue(Hash::numeric(array_keys($data)));
  535. $data = array(1 => 'one');
  536. $this->assertFalse(Hash::numeric($data));
  537. $data = array('one');
  538. $this->assertFalse(Hash::numeric($data));
  539. $data = array('one' => 'two');
  540. $this->assertFalse(Hash::numeric($data));
  541. $data = array('one' => 1);
  542. $this->assertTrue(Hash::numeric($data));
  543. $data = array(0);
  544. $this->assertTrue(Hash::numeric($data));
  545. $data = array('one', 'two', 'three', 'four', 'five');
  546. $this->assertTrue(Hash::numeric(array_keys($data)));
  547. $data = array(1 => 'one', 2 => 'two', 3 => 'three', 4 => 'four', 5 => 'five');
  548. $this->assertTrue(Hash::numeric(array_keys($data)));
  549. $data = array('1' => 'one', 2 => 'two', 3 => 'three', 4 => 'four', 5 => 'five');
  550. $this->assertTrue(Hash::numeric(array_keys($data)));
  551. $data = array('one', 2 => 'two', 3 => 'three', 4 => 'four', 'a' => 'five');
  552. $this->assertFalse(Hash::numeric(array_keys($data)));
  553. }
  554. /**
  555. * Test simple paths.
  556. *
  557. * @return void
  558. */
  559. public function testExtractBasic() {
  560. $data = self::articleData();
  561. $result = Hash::extract($data, '');
  562. $this->assertEquals($data, $result);
  563. $result = Hash::extract($data, '0.Article.title');
  564. $this->assertEquals(array('First Article'), $result);
  565. $result = Hash::extract($data, '1.Article.title');
  566. $this->assertEquals(array('Second Article'), $result);
  567. }
  568. /**
  569. * Test the {n} selector
  570. *
  571. * @return void
  572. */
  573. public function testExtractNumericKey() {
  574. $data = self::articleData();
  575. $result = Hash::extract($data, '{n}.Article.title');
  576. $expected = array(
  577. 'First Article', 'Second Article',
  578. 'Third Article', 'Fourth Article',
  579. 'Fifth Article'
  580. );
  581. $this->assertEquals($expected, $result);
  582. $result = Hash::extract($data, '0.Comment.{n}.user_id');
  583. $expected = array(
  584. '2', '4'
  585. );
  586. $this->assertEquals($expected, $result);
  587. }
  588. /**
  589. * Test the {n} selector with inconsistent arrays
  590. *
  591. * @return void
  592. */
  593. public function testExtractNumericMixedKeys() {
  594. $data = array(
  595. 'User' => array(
  596. 0 => array(
  597. 'id' => 4,
  598. 'name' => 'Neo'
  599. ),
  600. 1 => array(
  601. 'id' => 5,
  602. 'name' => 'Morpheus'
  603. ),
  604. 'stringKey' => array(
  605. 'name' => 'Fail'
  606. )
  607. )
  608. );
  609. $result = Hash::extract($data, 'User.{n}.name');
  610. $expected = array('Neo', 'Morpheus');
  611. $this->assertEquals($expected, $result);
  612. }
  613. /**
  614. * Test the {n} selector with non-zero based arrays
  615. *
  616. * @return void
  617. */
  618. public function testExtractNumericNonZero() {
  619. $data = array(
  620. 1 => array(
  621. 'User' => array(
  622. 'id' => 1,
  623. 'name' => 'John',
  624. )
  625. ),
  626. 2 => array(
  627. 'User' => array(
  628. 'id' => 2,
  629. 'name' => 'Bob',
  630. )
  631. ),
  632. 3 => array(
  633. 'User' => array(
  634. 'id' => 3,
  635. 'name' => 'Tony',
  636. )
  637. )
  638. );
  639. $result = Hash::extract($data, '{n}.User.name');
  640. $expected = array('John', 'Bob', 'Tony');
  641. $this->assertEquals($expected, $result);
  642. }
  643. /**
  644. * Test the {s} selector.
  645. *
  646. * @return void
  647. */
  648. public function testExtractStringKey() {
  649. $data = self::articleData();
  650. $result = Hash::extract($data, '{n}.{s}.user');
  651. $expected = array(
  652. 'mariano',
  653. 'mariano',
  654. 'mariano',
  655. 'mariano',
  656. 'mariano'
  657. );
  658. $this->assertEquals($expected, $result);
  659. $result = Hash::extract($data, '{n}.{s}.Nesting.test.1');
  660. $this->assertEquals(array('foo'), $result);
  661. }
  662. /**
  663. * Test the attribute presense selector.
  664. *
  665. * @return void
  666. */
  667. public function testExtractAttributePresence() {
  668. $data = self::articleData();
  669. $result = Hash::extract($data, '{n}.Article[published]');
  670. $expected = array($data[1]['Article']);
  671. $this->assertEquals($expected, $result);
  672. $result = Hash::extract($data, '{n}.Article[id][published]');
  673. $expected = array($data[1]['Article']);
  674. $this->assertEquals($expected, $result);
  675. }
  676. /**
  677. * Test = and != operators.
  678. *
  679. * @return void
  680. */
  681. public function testExtractAttributeEquality() {
  682. $data = self::articleData();
  683. $result = Hash::extract($data, '{n}.Article[id=3]');
  684. $expected = array($data[2]['Article']);
  685. $this->assertEquals($expected, $result);
  686. $result = Hash::extract($data, '{n}.Article[id = 3]');
  687. $expected = array($data[2]['Article']);
  688. $this->assertEquals($expected, $result, 'Whitespace should not matter.');
  689. $result = Hash::extract($data, '{n}.Article[id!=3]');
  690. $this->assertEquals(1, $result[0]['id']);
  691. $this->assertEquals(2, $result[1]['id']);
  692. $this->assertEquals(4, $result[2]['id']);
  693. $this->assertEquals(5, $result[3]['id']);
  694. }
  695. /**
  696. * Test comparison operators.
  697. *
  698. * @return void
  699. */
  700. public function testExtractAttributeComparison() {
  701. $data = self::articleData();
  702. $result = Hash::extract($data, '{n}.Comment.{n}[user_id > 2]');
  703. $expected = array($data[0]['Comment'][1]);
  704. $this->assertEquals($expected, $result);
  705. $this->assertEquals(4, $expected[0]['user_id']);
  706. $result = Hash::extract($data, '{n}.Comment.{n}[user_id >= 4]');
  707. $expected = array($data[0]['Comment'][1]);
  708. $this->assertEquals($expected, $result);
  709. $this->assertEquals(4, $expected[0]['user_id']);
  710. $result = Hash::extract($data, '{n}.Comment.{n}[user_id < 3]');
  711. $expected = array($data[0]['Comment'][0]);
  712. $this->assertEquals($expected, $result);
  713. $this->assertEquals(2, $expected[0]['user_id']);
  714. $result = Hash::extract($data, '{n}.Comment.{n}[user_id <= 2]');
  715. $expected = array($data[0]['Comment'][0]);
  716. $this->assertEquals($expected, $result);
  717. $this->assertEquals(2, $expected[0]['user_id']);
  718. }
  719. /**
  720. * Test multiple attributes with conditions.
  721. *
  722. * @return void
  723. */
  724. public function testExtractAttributeMultiple() {
  725. $data = self::articleData();
  726. $result = Hash::extract($data, '{n}.Comment.{n}[user_id > 2][id=1]');
  727. $this->assertEmpty($result);
  728. $result = Hash::extract($data, '{n}.Comment.{n}[user_id > 2][id=2]');
  729. $expected = array($data[0]['Comment'][1]);
  730. $this->assertEquals($expected, $result);
  731. $this->assertEquals(4, $expected[0]['user_id']);
  732. }
  733. /**
  734. * Test attribute pattern matching.
  735. *
  736. * @return void
  737. */
  738. public function testExtractAttributePattern() {
  739. $data = self::articleData();
  740. $result = Hash::extract($data, '{n}.Article[title=/^First/]');
  741. $expected = array($data[0]['Article']);
  742. $this->assertEquals($expected, $result);
  743. }
  744. /**
  745. * Test that uneven keys are handled correctly.
  746. *
  747. * @return void
  748. */
  749. public function testExtractUnevenKeys() {
  750. $data = array(
  751. 'Level1' => array(
  752. 'Level2' => array('test1', 'test2'),
  753. 'Level2bis' => array('test3', 'test4')
  754. )
  755. );
  756. $this->assertEquals(
  757. array('test1', 'test2'),
  758. Hash::extract($data, 'Level1.Level2')
  759. );
  760. $this->assertEquals(
  761. array('test3', 'test4'),
  762. Hash::extract($data, 'Level1.Level2bis')
  763. );
  764. $data = array(
  765. 'Level1' => array(
  766. 'Level2bis' => array(
  767. array('test3', 'test4'),
  768. array('test5', 'test6')
  769. )
  770. )
  771. );
  772. $expected = array(
  773. array('test3', 'test4'),
  774. array('test5', 'test6')
  775. );
  776. $this->assertEquals($expected, Hash::extract($data, 'Level1.Level2bis'));
  777. $data['Level1']['Level2'] = array('test1', 'test2');
  778. $this->assertEquals($expected, Hash::extract($data, 'Level1.Level2bis'));
  779. }
  780. /**
  781. * testSort method
  782. *
  783. * @return void
  784. */
  785. public function testSort() {
  786. $a = array(
  787. 0 => array(
  788. 'Person' => array('name' => 'Jeff'),
  789. 'Friend' => array(array('name' => 'Nate'))
  790. ),
  791. 1 => array(
  792. 'Person' => array('name' => 'Tracy'),
  793. 'Friend' => array(array('name' => 'Lindsay'))
  794. )
  795. );
  796. $b = array(
  797. 0 => array(
  798. 'Person' => array('name' => 'Tracy'),
  799. 'Friend' => array(array('name' => 'Lindsay'))
  800. ),
  801. 1 => array(
  802. 'Person' => array('name' => 'Jeff'),
  803. 'Friend' => array(array('name' => 'Nate'))
  804. )
  805. );
  806. $a = Hash::sort($a, '{n}.Friend.{n}.name', 'asc');
  807. $this->assertEquals($a, $b);
  808. $b = array(
  809. 0 => array(
  810. 'Person' => array('name' => 'Jeff'),
  811. 'Friend' => array(array('name' => 'Nate'))
  812. ),
  813. 1 => array(
  814. 'Person' => array('name' => 'Tracy'),
  815. 'Friend' => array(array('name' => 'Lindsay'))
  816. )
  817. );
  818. $a = array(
  819. 0 => array(
  820. 'Person' => array('name' => 'Tracy'),
  821. 'Friend' => array(array('name' => 'Lindsay'))
  822. ),
  823. 1 => array(
  824. 'Person' => array('name' => 'Jeff'),
  825. 'Friend' => array(array('name' => 'Nate'))
  826. )
  827. );
  828. $a = Hash::sort($a, '{n}.Friend.{n}.name', 'desc');
  829. $this->assertEquals($a, $b);
  830. $a = array(
  831. 0 => array(
  832. 'Person' => array('name' => 'Jeff'),
  833. 'Friend' => array(array('name' => 'Nate'))
  834. ),
  835. 1 => array(
  836. 'Person' => array('name' => 'Tracy'),
  837. 'Friend' => array(array('name' => 'Lindsay'))
  838. ),
  839. 2 => array(
  840. 'Person' => array('name' => 'Adam'),
  841. 'Friend' => array(array('name' => 'Bob'))
  842. )
  843. );
  844. $b = array(
  845. 0 => array(
  846. 'Person' => array('name' => 'Adam'),
  847. 'Friend' => array(array('name' => 'Bob'))
  848. ),
  849. 1 => array(
  850. 'Person' => array('name' => 'Jeff'),
  851. 'Friend' => array(array('name' => 'Nate'))
  852. ),
  853. 2 => array(
  854. 'Person' => array('name' => 'Tracy'),
  855. 'Friend' => array(array('name' => 'Lindsay'))
  856. )
  857. );
  858. $a = Hash::sort($a, '{n}.Person.name', 'asc');
  859. $this->assertEquals($a, $b);
  860. $a = array(
  861. 0 => array('Person' => array('name' => 'Jeff')),
  862. 1 => array('Shirt' => array('color' => 'black'))
  863. );
  864. $b = array(
  865. 0 => array('Shirt' => array('color' => 'black')),
  866. 1 => array('Person' => array('name' => 'Jeff')),
  867. );
  868. $a = Hash::sort($a, '{n}.Person.name', 'ASC', 'STRING');
  869. $this->assertEquals($a, $b);
  870. $names = array(
  871. array('employees' => array(
  872. array('name' => array('first' => 'John', 'last' => 'Doe')))
  873. ),
  874. array('employees' => array(
  875. array('name' => array('first' => 'Jane', 'last' => 'Doe')))
  876. ),
  877. array('employees' => array(array('name' => array()))),
  878. array('employees' => array(array('name' => array())))
  879. );
  880. $result = Hash::sort($names, '{n}.employees.0.name', 'asc');
  881. $expected = array(
  882. array('employees' => array(
  883. array('name' => array('first' => 'John', 'last' => 'Doe')))
  884. ),
  885. array('employees' => array(
  886. array('name' => array('first' => 'Jane', 'last' => 'Doe')))
  887. ),
  888. array('employees' => array(array('name' => array()))),
  889. array('employees' => array(array('name' => array())))
  890. );
  891. $this->assertEquals($expected, $result);
  892. }
  893. /**
  894. * Test sort() with numeric option.
  895. *
  896. * @return void
  897. */
  898. public function testSortNumeric() {
  899. $items = array(
  900. array('Item' => array('price' => '155,000')),
  901. array('Item' => array('price' => '139,000')),
  902. array('Item' => array('price' => '275,622')),
  903. array('Item' => array('price' => '230,888')),
  904. array('Item' => array('price' => '66,000')),
  905. );
  906. $result = Hash::sort($items, '{n}.Item.price', 'asc', 'numeric');
  907. $expected = array(
  908. array('Item' => array('price' => '66,000')),
  909. array('Item' => array('price' => '139,000')),
  910. array('Item' => array('price' => '155,000')),
  911. array('Item' => array('price' => '230,888')),
  912. array('Item' => array('price' => '275,622')),
  913. );
  914. $this->assertEquals($expected, $result);
  915. $result = Hash::sort($items, '{n}.Item.price', 'desc', 'numeric');
  916. $expected = array(
  917. array('Item' => array('price' => '275,622')),
  918. array('Item' => array('price' => '230,888')),
  919. array('Item' => array('price' => '155,000')),
  920. array('Item' => array('price' => '139,000')),
  921. array('Item' => array('price' => '66,000')),
  922. );
  923. $this->assertEquals($expected, $result);
  924. }
  925. /**
  926. * Test natural sorting.
  927. *
  928. * @return void
  929. */
  930. public function testSortNatural() {
  931. if (version_compare(PHP_VERSION, '5.4.0', '<')) {
  932. $this->markTestSkipped('SORT_NATURAL is available since PHP 5.4.');
  933. }
  934. $items = array(
  935. array('Item' => array('image' => 'img1.jpg')),
  936. array('Item' => array('image' => 'img99.jpg')),
  937. array('Item' => array('image' => 'img12.jpg')),
  938. array('Item' => array('image' => 'img10.jpg')),
  939. array('Item' => array('image' => 'img2.jpg')),
  940. );
  941. $result = Hash::sort($items, '{n}.Item.image', 'desc', 'natural');
  942. $expected = array(
  943. array('Item' => array('image' => 'img99.jpg')),
  944. array('Item' => array('image' => 'img12.jpg')),
  945. array('Item' => array('image' => 'img10.jpg')),
  946. array('Item' => array('image' => 'img2.jpg')),
  947. array('Item' => array('image' => 'img1.jpg')),
  948. );
  949. $this->assertEquals($expected, $result);
  950. $result = Hash::sort($items, '{n}.Item.image', 'asc', 'natural');
  951. $expected = array(
  952. array('Item' => array('image' => 'img1.jpg')),
  953. array('Item' => array('image' => 'img2.jpg')),
  954. array('Item' => array('image' => 'img10.jpg')),
  955. array('Item' => array('image' => 'img12.jpg')),
  956. array('Item' => array('image' => 'img99.jpg')),
  957. );
  958. $this->assertEquals($expected, $result);
  959. }
  960. /**
  961. * test sorting with out of order keys.
  962. *
  963. * @return void
  964. */
  965. public function testSortWithOutOfOrderKeys() {
  966. $data = array(
  967. 9 => array('class' => 510, 'test2' => 2),
  968. 1 => array('class' => 500, 'test2' => 1),
  969. 2 => array('class' => 600, 'test2' => 2),
  970. 5 => array('class' => 625, 'test2' => 4),
  971. 0 => array('class' => 605, 'test2' => 3),
  972. );
  973. $expected = array(
  974. array('class' => 500, 'test2' => 1),
  975. array('class' => 510, 'test2' => 2),
  976. array('class' => 600, 'test2' => 2),
  977. array('class' => 605, 'test2' => 3),
  978. array('class' => 625, 'test2' => 4),
  979. );
  980. $result = Hash::sort($data, '{n}.class', 'asc');
  981. $this->assertEquals($expected, $result);
  982. $result = Hash::sort($data, '{n}.test2', 'asc');
  983. $this->assertEquals($expected, $result);
  984. }
  985. /**
  986. * test sorting with string keys.
  987. *
  988. * @return void
  989. */
  990. public function testSortString() {
  991. $toSort = array(
  992. 'four' => array('number' => 4, 'some' => 'foursome'),
  993. 'six' => array('number' => 6, 'some' => 'sixsome'),
  994. 'five' => array('number' => 5, 'some' => 'fivesome'),
  995. 'two' => array('number' => 2, 'some' => 'twosome'),
  996. 'three' => array('number' => 3, 'some' => 'threesome')
  997. );
  998. $sorted = Hash::sort($toSort, '{s}.number', 'asc');
  999. $expected = array(
  1000. 'two' => array('number' => 2, 'some' => 'twosome'),
  1001. 'three' => array('number' => 3, 'some' => 'threesome'),
  1002. 'four' => array('number' => 4, 'some' => 'foursome'),
  1003. 'five' => array('number' => 5, 'some' => 'fivesome'),
  1004. 'six' => array('number' => 6, 'some' => 'sixsome')
  1005. );
  1006. $this->assertEquals($expected, $sorted);
  1007. $menus = array(
  1008. 'blogs' => array('title' => 'Blogs', 'weight' => 3),
  1009. 'comments' => array('title' => 'Comments', 'weight' => 2),
  1010. 'users' => array('title' => 'Users', 'weight' => 1),
  1011. );
  1012. $expected = array(
  1013. 'users' => array('title' => 'Users', 'weight' => 1),
  1014. 'comments' => array('title' => 'Comments', 'weight' => 2),
  1015. 'blogs' => array('title' => 'Blogs', 'weight' => 3),
  1016. );
  1017. $result = Hash::sort($menus, '{s}.weight', 'ASC');
  1018. $this->assertEquals($expected, $result);
  1019. }
  1020. /**
  1021. * Test insert()
  1022. *
  1023. * @return void
  1024. */
  1025. public function testInsertSimple() {
  1026. $a = array(
  1027. 'pages' => array('name' => 'page')
  1028. );
  1029. $result = Hash::insert($a, 'files', array('name' => 'files'));
  1030. $expected = array(
  1031. 'pages' => array('name' => 'page'),
  1032. 'files' => array('name' => 'files')
  1033. );
  1034. $this->assertEquals($expected, $result);
  1035. $a = array(
  1036. 'pages' => array('name' => 'page')
  1037. );
  1038. $result = Hash::insert($a, 'pages.name', array());
  1039. $expected = array(
  1040. 'pages' => array('name' => array()),
  1041. );
  1042. $this->assertEquals($expected, $result);
  1043. }
  1044. /**
  1045. * Test inserting with multiple values.
  1046. *
  1047. * @return void
  1048. */
  1049. public function testInsertMulti() {
  1050. $data = self::articleData();
  1051. $result = Hash::insert($data, '{n}.Article.insert', 'value');
  1052. $this->assertEquals('value', $result[0]['Article']['insert']);
  1053. $this->assertEquals('value', $result[1]['Article']['insert']);
  1054. $result = Hash::insert($data, '{n}.Comment.{n}.insert', 'value');
  1055. $this->assertEquals('value', $result[0]['Comment'][0]['insert']);
  1056. $this->assertEquals('value', $result[0]['Comment'][1]['insert']);
  1057. }
  1058. /**
  1059. * Test that insert() can insert data over a string value.
  1060. *
  1061. * @return void
  1062. */
  1063. public function testInsertOverwriteStringValue() {
  1064. $data = array(
  1065. 'Some' => array(
  1066. 'string' => 'value'
  1067. )
  1068. );
  1069. $result = Hash::insert($data, 'Some.string.value', array('values'));
  1070. $expected = array(
  1071. 'Some' => array(
  1072. 'string' => array(
  1073. 'value' => array( 'values')
  1074. )
  1075. )
  1076. );
  1077. $this->assertEquals($expected, $result);
  1078. }
  1079. /**
  1080. * Test remove() method.
  1081. *
  1082. * @return void
  1083. */
  1084. public function testRemove() {
  1085. $a = array(
  1086. 'pages' => array('name' => 'page'),
  1087. 'files' => array('name' => 'files')
  1088. );
  1089. $result = Hash::remove($a, 'files');
  1090. $expected = array(
  1091. 'pages' => array('name' => 'page')
  1092. );
  1093. $this->assertEquals($expected, $result);
  1094. $a = array(
  1095. 'pages' => array(
  1096. 0 => array('name' => 'main'),
  1097. 1 => array(
  1098. 'name' => 'about',
  1099. 'vars' => array('title' => 'page title')
  1100. )
  1101. )
  1102. );
  1103. $result = Hash::remove($a, 'pages.1.vars');
  1104. $expected = array(
  1105. 'pages' => array(
  1106. 0 => array('name' => 'main'),
  1107. 1 => array('name' => 'about')
  1108. )
  1109. );
  1110. $this->assertEquals($expected, $result);
  1111. $result = Hash::remove($a, 'pages.2.vars');
  1112. $expected = $a;
  1113. $this->assertEquals($expected, $result);
  1114. }
  1115. /**
  1116. * Test removing multiple values.
  1117. *
  1118. * @return void
  1119. */
  1120. public function testRemoveMulti() {
  1121. $data = self::articleData();
  1122. $result = Hash::remove($data, '{n}.Article.title');
  1123. $this->assertFalse(isset($result[0]['Article']['title']));
  1124. $this->assertFalse(isset($result[1]['Article']['title']));
  1125. $result = Hash::remove($data, '{n}.Article.{s}');
  1126. $this->assertFalse(isset($result[0]['Article']['id']));
  1127. $this->assertFalse(isset($result[0]['Article']['user_id']));
  1128. $this->assertFalse(isset($result[0]['Article']['title']));
  1129. $this->assertFalse(isset($result[0]['Article']['body']));
  1130. }
  1131. /**
  1132. * testCheck method
  1133. *
  1134. * @return void
  1135. */
  1136. public function testCheck() {
  1137. $set = array(
  1138. 'My Index 1' => array('First' => 'The first item')
  1139. );
  1140. $this->assertTrue(Hash::check($set, 'My Index 1.First'));
  1141. $this->assertTrue(Hash::check($set, 'My Index 1'));
  1142. $set = array(
  1143. 'My Index 1' => array(
  1144. 'First' => array(
  1145. 'Second' => array(
  1146. 'Third' => array(
  1147. 'Fourth' => 'Heavy. Nesting.'
  1148. )
  1149. )
  1150. )
  1151. )
  1152. );
  1153. $this->assertTrue(Hash::check($set, 'My Index 1.First.Second'));
  1154. $this->assertTrue(Hash::check($set, 'My Index 1.First.Second.Third'));
  1155. $this->assertTrue(Hash::check($set, 'My Index 1.First.Second.Third.Fourth'));
  1156. $this->assertFalse(Hash::check($set, 'My Index 1.First.Seconds.Third.Fourth'));
  1157. }
  1158. /**
  1159. * testCombine method
  1160. *
  1161. * @return void
  1162. */
  1163. public function testCombine() {
  1164. $result = Hash::combine(array(), '{n}.User.id', '{n}.User.Data');
  1165. $this->assertTrue(empty($result));
  1166. $a = self::userData();
  1167. $result = Hash::combine($a, '{n}.User.id');
  1168. $expected = array(2 => null, 14 => null, 25 => null);
  1169. $this->assertEquals($expected, $result);
  1170. $result = Hash::combine($a, '{n}.User.id', '{n}.User.non-existant');
  1171. $expected = array(2 => null, 14 => null, 25 => null);
  1172. $this->assertEquals($expected, $result);
  1173. $result = Hash::combine($a, '{n}.User.id', '{n}.User.Data');
  1174. $expected = array(
  1175. 2 => array('user' => 'mariano.iglesias', 'name' => 'Mariano Iglesias'),
  1176. 14 => array('user' => 'phpnut', 'name' => 'Larry E. Masters'),
  1177. 25 => array('user' => 'gwoo', 'name' => 'The Gwoo'));
  1178. $this->assertEquals($expected, $result);
  1179. $result = Hash::combine($a, '{n}.User.id', '{n}.User.Data.name');
  1180. $expected = array(
  1181. 2 => 'Mariano Iglesias',
  1182. 14 => 'Larry E. Masters',
  1183. 25 => 'The Gwoo');
  1184. $this->assertEquals($expected, $result);
  1185. }
  1186. /**
  1187. * test combine() with a group path.
  1188. *
  1189. * @return void
  1190. */
  1191. public function testCombineWithGroupPath() {
  1192. $a = self::userData();
  1193. $result = Hash::combine($a, '{n}.User.id', '{n}.User.Data', '{n}.User.group_id');
  1194. $expected = array(
  1195. 1 => array(
  1196. 2 => array('user' => 'mariano.iglesias', 'name' => 'Mariano Iglesias'),
  1197. 25 => array('user' => 'gwoo', 'name' => 'The Gwoo')
  1198. ),
  1199. 2 => array(
  1200. 14 => array('user' => 'phpnut', 'name' => 'Larry E. Masters')
  1201. )
  1202. );
  1203. $this->assertEquals($expected, $result);
  1204. $result = Hash::combine($a, '{n}.User.id', '{n}.User.Data.name', '{n}.User.group_id');
  1205. $expected = array(
  1206. 1 => array(
  1207. 2 => 'Mariano Iglesias',
  1208. 25 => 'The Gwoo'
  1209. ),
  1210. 2 => array(
  1211. 14 => 'Larry E. Masters'
  1212. )
  1213. );
  1214. $this->assertEquals($expected, $result);
  1215. $result = Hash::combine($a, '{n}.User.id', '{n}.User.Data', '{n}.User.group_id');
  1216. $expected = array(
  1217. 1 => array(
  1218. 2 => array('user' => 'mariano.iglesias', 'name' => 'Mariano Iglesias'),
  1219. 25 => array('user' => 'gwoo', 'name' => 'The Gwoo')
  1220. ),
  1221. 2 => array(
  1222. 14 => array('user' => 'phpnut', 'name' => 'Larry E. Masters')
  1223. )
  1224. );
  1225. $this->assertEquals($expected, $result);
  1226. $result = Hash::combine($a, '{n}.User.id', '{n}.User.Data.name', '{n}.User.group_id');
  1227. $expected = array(
  1228. 1 => array(
  1229. 2 => 'Mariano Iglesias',
  1230. 25 => 'The Gwoo'
  1231. ),
  1232. 2 => array(
  1233. 14 => 'Larry E. Masters'
  1234. )
  1235. );
  1236. $this->assertEquals($expected, $result);
  1237. }
  1238. /**
  1239. * Test combine with formatting rules.
  1240. *
  1241. * @return void
  1242. */
  1243. public function testCombineWithFormatting() {
  1244. $a = self::userData();
  1245. $result = Hash::combine(
  1246. $a,
  1247. '{n}.User.id',
  1248. array('%1$s: %2$s', '{n}.User.Data.user', '{n}.User.Data.name'),
  1249. '{n}.User.group_id'
  1250. );
  1251. $expected = array(
  1252. 1 => array(
  1253. 2 => 'mariano.iglesias: Mariano Iglesias',
  1254. 25 => 'gwoo: The Gwoo'
  1255. ),
  1256. 2 => array(
  1257. 14 => 'phpnut: Larry E. Masters'
  1258. )
  1259. );
  1260. $this->assertEquals($expected, $result);
  1261. $result = Hash::combine(
  1262. $a,
  1263. array(
  1264. '%s: %s',
  1265. '{n}.User.Data.user',
  1266. '{n}.User.Data.name'
  1267. ),
  1268. '{n}.User.id'
  1269. );
  1270. $expected = array(
  1271. 'mariano.iglesias: Mariano Iglesias' => 2,
  1272. 'phpnut: Larry E. Masters' => 14,
  1273. 'gwoo: The Gwoo' => 25
  1274. );
  1275. $this->assertEquals($expected, $result);
  1276. $result = Hash::combine(
  1277. $a,
  1278. array('%1$s: %2$d', '{n}.User.Data.user', '{n}.User.id'),
  1279. '{n}.User.Data.name'
  1280. );
  1281. $expected = array(
  1282. 'mariano.iglesias: 2' => 'Mariano Iglesias',
  1283. 'phpnut: 14' => 'Larry E. Masters',
  1284. 'gwoo: 25' => 'The Gwoo'
  1285. );
  1286. $this->assertEquals($expected, $result);
  1287. $result = Hash::combine(
  1288. $a,
  1289. array('%2$d: %1$s', '{n}.User.Data.user', '{n}.User.id'),
  1290. '{n}.User.Data.name'
  1291. );
  1292. $expected = array(
  1293. '2: mariano.iglesias' => 'Mariano Iglesias',
  1294. '14: phpnut' => 'Larry E. Masters',
  1295. '25: gwoo' => 'The Gwoo'
  1296. );
  1297. $this->assertEquals($expected, $result);
  1298. }
  1299. /**
  1300. * testFormat method
  1301. *
  1302. * @return void
  1303. */
  1304. public function testFormat() {
  1305. $data = self::userData();
  1306. $result = Hash::format(
  1307. $data,
  1308. array('{n}.User.Data.user', '{n}.User.id'),
  1309. '%s, %s'
  1310. );
  1311. $expected = array(
  1312. 'mariano.iglesias, 2',
  1313. 'phpnut, 14',
  1314. 'gwoo, 25'
  1315. );
  1316. $this->assertEquals($expected, $result);
  1317. $result = Hash::format(
  1318. $data,
  1319. array('{n}.User.Data.user', '{n}.User.id'),
  1320. '%2$s, %1$s'
  1321. );
  1322. $expected = array(
  1323. '2, mariano.iglesias',
  1324. '14, phpnut',
  1325. '25, gwoo'
  1326. );
  1327. $this->assertEquals($expected, $result);
  1328. }
  1329. /**
  1330. * testFormattingNullValues method
  1331. *
  1332. * @return void
  1333. */
  1334. public function testFormatNullValues() {
  1335. $data = array(
  1336. array('Person' => array(
  1337. 'first_name' => 'Nate', 'last_name' => 'Abele', 'city' => 'Boston', 'state' => 'MA', 'something' => '42'
  1338. )),
  1339. array('Person' => array(
  1340. 'first_name' => 'Larry', 'last_name' => 'Masters', 'city' => 'Boondock', 'state' => 'TN', 'something' => null
  1341. )),
  1342. array('Person' => array(
  1343. 'first_name' => 'Garrett', 'last_name' => 'Woodworth', 'city' => 'Venice Beach', 'state' => 'CA', 'something' => null
  1344. ))
  1345. );
  1346. $result = Hash::format($data, array('{n}.Person.something'), '%s');
  1347. $expected = array('42', '', '');
  1348. $this->assertEquals($expected, $result);
  1349. $result = Hash::format($data, array('{n}.Person.city', '{n}.Person.something'), '%s, %s');
  1350. $expected = array('Boston, 42', 'Boondock, ', 'Venice Beach, ');
  1351. $this->assertEquals($expected, $result);
  1352. }
  1353. /**
  1354. * Test map()
  1355. *
  1356. * @return void
  1357. */
  1358. public function testMap() {
  1359. $data = self::articleData();
  1360. $result = Hash::map($data, '{n}.Article.id', array($this, 'mapCallback'));
  1361. $expected = array(2, 4, 6, 8, 10);
  1362. $this->assertEquals($expected, $result);
  1363. }
  1364. public function testApply() {
  1365. $data = self::articleData();
  1366. $result = Hash::apply($data, '{n}.Article.id', 'array_sum');
  1367. $this->assertEquals(15, $result);
  1368. }
  1369. /**
  1370. * Test reduce()
  1371. *
  1372. * @return void
  1373. */
  1374. public function testReduce() {
  1375. $data = self::articleData();
  1376. $result = Hash::reduce($data, '{n}.Article.id', array($this, 'reduceCallback'));
  1377. $this->assertEquals(15, $result);
  1378. }
  1379. /**
  1380. * testing method for map callbacks.
  1381. *
  1382. * @param mixed $value
  1383. * @return mixed.
  1384. */
  1385. public function mapCallback($value) {
  1386. return $value * 2;
  1387. }
  1388. /**
  1389. * testing method for reduce callbacks.
  1390. *
  1391. * @param mixed $one
  1392. * @param mixed $two
  1393. * @return mixed.
  1394. */
  1395. public function reduceCallback($one, $two) {
  1396. return $one + $two;
  1397. }
  1398. /**
  1399. * test Hash nest with a normal model result set. For kicks rely on Hash nest detecting the key names
  1400. * automatically
  1401. *
  1402. * @return void
  1403. */
  1404. public function testNestModel() {
  1405. $input = array(
  1406. array(
  1407. 'ModelName' => array(
  1408. 'id' => 1,
  1409. 'parent_id' => null
  1410. ),
  1411. ),
  1412. array(
  1413. 'ModelName' => array(
  1414. 'id' => 2,
  1415. 'parent_id' => 1
  1416. ),
  1417. ),
  1418. array(
  1419. 'ModelName' => array(
  1420. 'id' => 3,
  1421. 'parent_id' => 1
  1422. ),
  1423. ),
  1424. array(
  1425. 'ModelName' => array(
  1426. 'id' => 4,
  1427. 'parent_id' => 1
  1428. ),
  1429. ),
  1430. array(
  1431. 'ModelName' => array(
  1432. 'id' => 5,
  1433. 'parent_id' => 1
  1434. ),
  1435. ),
  1436. array(
  1437. 'ModelName' => array(
  1438. 'id' => 6,
  1439. 'parent_id' => null
  1440. ),
  1441. ),
  1442. array(
  1443. 'ModelName' => array(
  1444. 'id' => 7,
  1445. 'parent_id' => 6
  1446. ),
  1447. ),
  1448. array(
  1449. 'ModelName' => array(
  1450. 'id' => 8,
  1451. 'parent_id' => 6
  1452. ),
  1453. ),
  1454. array(
  1455. 'ModelName' => array(
  1456. 'id' => 9,
  1457. 'parent_id' => 6
  1458. ),
  1459. ),
  1460. array(
  1461. 'ModelName' => array(
  1462. 'id' => 10,
  1463. 'parent_id' => 6
  1464. )
  1465. )
  1466. );
  1467. $expected = array(
  1468. array(
  1469. 'ModelName' => array(
  1470. 'id' => 1,
  1471. 'parent_id' => null
  1472. ),
  1473. 'children' => array(
  1474. array(
  1475. 'ModelName' => array(
  1476. 'id' => 2,
  1477. 'parent_id' => 1
  1478. ),
  1479. 'children' => array()
  1480. ),
  1481. array(
  1482. 'ModelName' => array(
  1483. 'id' => 3,
  1484. 'parent_id' => 1
  1485. ),
  1486. 'children' => array()
  1487. ),
  1488. array(
  1489. 'ModelName' => array(
  1490. 'id' => 4,
  1491. 'parent_id' => 1
  1492. ),
  1493. 'children' => array()
  1494. ),
  1495. array(
  1496. 'ModelName' => array(
  1497. 'id' => 5,
  1498. 'parent_id' => 1
  1499. ),
  1500. 'children' => array()
  1501. ),
  1502. )
  1503. ),
  1504. array(
  1505. 'ModelName' => array(
  1506. 'id' => 6,
  1507. 'parent_id' => null
  1508. ),
  1509. 'children' => array(
  1510. array(
  1511. 'ModelName' => array(
  1512. 'id' => 7,
  1513. 'parent_id' => 6
  1514. ),
  1515. 'children' => array()
  1516. ),
  1517. array(
  1518. 'ModelName' => array(
  1519. 'id' => 8,
  1520. 'parent_id' => 6
  1521. ),
  1522. 'children' => array()
  1523. ),
  1524. array(
  1525. 'ModelName' => array(
  1526. 'id' => 9,
  1527. 'parent_id' => 6
  1528. ),
  1529. 'children' => array()
  1530. ),
  1531. array(
  1532. 'ModelName' => array(
  1533. 'id' => 10,
  1534. 'parent_id' => 6
  1535. ),
  1536. 'children' => array()
  1537. )
  1538. )
  1539. )
  1540. );
  1541. $result = Hash::nest($input);
  1542. $this->assertEquals($expected, $result);
  1543. }
  1544. /**
  1545. * test Hash nest with a normal model result set, and a nominated root id
  1546. *
  1547. * @return void
  1548. */
  1549. public function testNestModelExplicitRoot() {
  1550. $input = array(
  1551. array(
  1552. 'ModelName' => array(
  1553. 'id' => 1,
  1554. 'parent_id' => null
  1555. ),
  1556. ),
  1557. array(
  1558. 'ModelName' => array(
  1559. 'id' => 2,
  1560. 'parent_id' => 1
  1561. ),
  1562. ),
  1563. array(
  1564. 'ModelName' => array(
  1565. 'id' => 3,
  1566. 'parent_id' => 1
  1567. ),
  1568. ),
  1569. array(
  1570. 'ModelName' => array(
  1571. 'id' => 4,
  1572. 'parent_id' => 1
  1573. ),
  1574. ),
  1575. array(
  1576. 'ModelName' => array(
  1577. 'id' => 5,
  1578. 'parent_id' => 1
  1579. ),
  1580. ),
  1581. array(
  1582. 'ModelName' => array(
  1583. 'id' => 6,
  1584. 'parent_id' => null
  1585. ),
  1586. ),
  1587. array(
  1588. 'ModelName' => array(
  1589. 'id' => 7,
  1590. 'parent_id' => 6
  1591. ),
  1592. ),
  1593. array(
  1594. 'ModelName' => array(
  1595. 'id' => 8,
  1596. 'parent_id' => 6
  1597. ),
  1598. ),
  1599. array(
  1600. 'ModelName' => array(
  1601. 'id' => 9,
  1602. 'parent_id' => 6
  1603. ),
  1604. ),
  1605. array(
  1606. 'ModelName' => array(
  1607. 'id' => 10,
  1608. 'parent_id' => 6
  1609. )
  1610. )
  1611. );
  1612. $expected = array(
  1613. array(
  1614. 'ModelName' => array(
  1615. 'id' => 6,
  1616. 'parent_id' => null
  1617. ),
  1618. 'children' => array(
  1619. array(
  1620. 'ModelName' => array(
  1621. 'id' => 7,
  1622. 'parent_id' => 6
  1623. ),
  1624. 'children' => array()
  1625. ),
  1626. array(
  1627. 'ModelName' => array(
  1628. 'id' => 8,
  1629. 'parent_id' => 6
  1630. ),
  1631. 'children' => array()
  1632. ),
  1633. array(
  1634. 'ModelName' => array(
  1635. 'id' => 9,
  1636. 'parent_id' => 6
  1637. ),
  1638. 'children' => array()
  1639. ),
  1640. array(
  1641. 'ModelName' => array(
  1642. 'id' => 10,
  1643. 'parent_id' => 6
  1644. ),
  1645. 'children' => array()
  1646. )
  1647. )
  1648. )
  1649. );
  1650. $result = Hash::nest($input, array('root' => 6));
  1651. $this->assertEquals($expected, $result);
  1652. }
  1653. /**
  1654. * test Hash nest with a 1d array - this method should be able to handle any type of array input
  1655. *
  1656. * @return void
  1657. */
  1658. public function testNest1Dimensional() {
  1659. $input = array(
  1660. array(
  1661. 'id' => 1,
  1662. 'parent_id' => null
  1663. ),
  1664. array(
  1665. 'id' => 2,
  1666. 'parent_id' => 1
  1667. ),
  1668. array(
  1669. 'id' => 3,
  1670. 'parent_id' => 1
  1671. ),
  1672. array(
  1673. 'id' => 4,
  1674. 'parent_id' => 1
  1675. ),
  1676. array(
  1677. 'id' => 5,
  1678. 'parent_id' => 1
  1679. ),
  1680. array(
  1681. 'id' => 6,
  1682. 'parent_id' => null
  1683. ),
  1684. array(
  1685. 'id' => 7,
  1686. 'parent_id' => 6
  1687. ),
  1688. array(
  1689. 'id' => 8,
  1690. 'parent_id' => 6
  1691. ),
  1692. array(
  1693. 'id' => 9,
  1694. 'parent_id' => 6
  1695. ),
  1696. array(
  1697. 'id' => 10,
  1698. 'parent_id' => 6
  1699. )
  1700. );
  1701. $expected = array(
  1702. array(
  1703. 'id' => 1,
  1704. 'parent_id' => null,
  1705. 'children' => array(
  1706. array(
  1707. 'id' => 2,
  1708. 'parent_id' => 1,
  1709. 'children' => array()
  1710. ),
  1711. array(
  1712. 'id' => 3,
  1713. 'parent_id' => 1,
  1714. 'children' => array()
  1715. ),
  1716. array(
  1717. 'id' => 4,
  1718. 'parent_id' => 1,
  1719. 'children' => array()
  1720. ),
  1721. array(
  1722. 'id' => 5,
  1723. 'parent_id' => 1,
  1724. 'children' => array()
  1725. ),
  1726. )
  1727. ),
  1728. array(
  1729. 'id' => 6,
  1730. 'parent_id' => null,
  1731. 'children' => array(
  1732. array(
  1733. 'id' => 7,
  1734. 'parent_id' => 6,
  1735. 'children' => array()
  1736. ),
  1737. array(
  1738. 'id' => 8,
  1739. 'parent_id' => 6,
  1740. 'children' => array()
  1741. ),
  1742. array(
  1743. 'id' => 9,
  1744. 'parent_id' => 6,
  1745. 'children' => array()
  1746. ),
  1747. array(
  1748. 'id' => 10,
  1749. 'parent_id' => 6,
  1750. 'children' => array()
  1751. )
  1752. )
  1753. )
  1754. );
  1755. $result = Hash::nest($input, array('idPath' => '{n}.id', 'parentPath' => '{n}.parent_id'));
  1756. $this->assertEquals($expected, $result);
  1757. }
  1758. /**
  1759. * test Hash nest with no specified parent data.
  1760. *
  1761. * The result should be the same as the input.
  1762. * For an easier comparison, unset all the empty children arrays from the result
  1763. *
  1764. * @return void
  1765. */
  1766. public function testMissingParent() {
  1767. $input = array(
  1768. array(
  1769. 'id' => 1,
  1770. ),
  1771. array(
  1772. 'id' => 2,
  1773. ),
  1774. array(
  1775. 'id' => 3,
  1776. ),
  1777. array(
  1778. 'id' => 4,
  1779. ),
  1780. array(
  1781. 'id' => 5,
  1782. ),
  1783. array(
  1784. 'id' => 6,
  1785. ),
  1786. array(
  1787. 'id' => 7,
  1788. ),
  1789. array(
  1790. 'id' => 8,
  1791. ),
  1792. array(
  1793. 'id' => 9,
  1794. ),
  1795. array(
  1796. 'id' => 10,
  1797. )
  1798. );
  1799. $result = Hash::nest($input, array('idPath' => '{n}.id', 'parentPath' => '{n}.parent_id'));
  1800. foreach ($result as &$row) {
  1801. if (empty($row['children'])) {
  1802. unset($row['children']);
  1803. }
  1804. }
  1805. $this->assertEquals($input, $result);
  1806. }
  1807. /**
  1808. * testMergeDiff method
  1809. *
  1810. * @return void
  1811. */
  1812. public function testMergeDiff() {
  1813. $first = array(
  1814. 'ModelOne' => array(
  1815. 'id' => 1001,
  1816. 'field_one' => 'a1.m1.f1',
  1817. 'field_two' => 'a1.m1.f2'
  1818. )
  1819. );
  1820. $second = array(
  1821. 'ModelTwo' => array(
  1822. 'id' => 1002,
  1823. 'field_one' => 'a2.m2.f1',
  1824. 'field_two' => 'a2.m2.f2'
  1825. )
  1826. );
  1827. $result = Hash::mergeDiff($first, $second);
  1828. $this->assertEquals($result, $first + $second);
  1829. $result = Hash::mergeDiff($first, array());
  1830. $this->assertEquals($result, $first);
  1831. $result = Hash::mergeDiff(array(), $first);
  1832. $this->assertEquals($result, $first);
  1833. $third = array(
  1834. 'ModelOne' => array(
  1835. 'id' => 1003,
  1836. 'field_one' => 'a3.m1.f1',
  1837. 'field_two' => 'a3.m1.f2',
  1838. 'field_three' => 'a3.m1.f3'
  1839. )
  1840. );
  1841. $result = Hash::mergeDiff($first, $third);
  1842. $expected = array(
  1843. 'ModelOne' => array(
  1844. 'id' => 1001,
  1845. 'field_one' => 'a1.m1.f1',
  1846. 'field_two' => 'a1.m1.f2',
  1847. 'field_three' => 'a3.m1.f3'
  1848. )
  1849. );
  1850. $this->assertEquals($expected, $result);
  1851. $first = array(
  1852. 0 => array('ModelOne' => array('id' => 1001, 'field_one' => 's1.0.m1.f1', 'field_two' => 's1.0.m1.f2')),
  1853. 1 => array('ModelTwo' => array('id' => 1002, 'field_one' => 's1.1.m2.f2', 'field_two' => 's1.1.m2.f2'))
  1854. );
  1855. $second = array(
  1856. 0 => array('ModelOne' => array('id' => 1001, 'field_one' => 's2.0.m1.f1', 'field_two' => 's2.0.m1.f2')),
  1857. 1 => array('ModelTwo' => array('id' => 1002, 'field_one' => 's2.1.m2.f2', 'field_two' => 's2.1.m2.f2'))
  1858. );
  1859. $result = Hash::mergeDiff($first, $second);
  1860. $this->assertEquals($result, $first);
  1861. $third = array(
  1862. 0 => array(
  1863. 'ModelThree' => array(
  1864. 'id' => 1003,
  1865. 'field_one' => 's3.0.m3.f1',
  1866. 'field_two' => 's3.0.m3.f2'
  1867. )
  1868. )
  1869. );
  1870. $result = Hash::mergeDiff($first, $third);
  1871. $expected = array(
  1872. 0 => array(
  1873. 'ModelOne' => array(
  1874. 'id' => 1001,
  1875. 'field_one' => 's1.0.m1.f1',
  1876. 'field_two' => 's1.0.m1.f2'
  1877. ),
  1878. 'ModelThree' => array(
  1879. 'id' => 1003,
  1880. 'field_one' => 's3.0.m3.f1',
  1881. 'field_two' => 's3.0.m3.f2'
  1882. )
  1883. ),
  1884. 1 => array(
  1885. 'ModelTwo' => array(
  1886. 'id' => 1002,
  1887. 'field_one' => 's1.1.m2.f2',
  1888. 'field_two' => 's1.1.m2.f2'
  1889. )
  1890. )
  1891. );
  1892. $this->assertEquals($expected, $result);
  1893. $result = Hash::mergeDiff($first, null);
  1894. $this->assertEquals($result, $first);
  1895. $result = Hash::mergeDiff($first, $second);
  1896. $this->assertEquals($result, $first + $second);
  1897. }
  1898. /**
  1899. * Tests Hash::expand
  1900. *
  1901. * @return void
  1902. */
  1903. public function testExpand() {
  1904. $data = array('My', 'Array', 'To', 'Flatten');
  1905. $flat = Hash::flatten($data);
  1906. $result = Hash::expand($flat);
  1907. $this->assertEquals($data, $result);
  1908. $data = array(
  1909. '0.Post.id' => '1', '0.Post.author_id' => '1', '0.Post.title' => 'First Post', '0.Author.id' => '1',
  1910. '0.Author.user' => 'nate', '0.Author.password' => 'foo', '1.Post.id' => '2', '1.Post.author_id' => '3',
  1911. '1.Post.title' => 'Second Post', '1.Post.body' => 'Second Post Body', '1.Author.id' => '3',
  1912. '1.Author.user' => 'larry', '1.Author.password' => null
  1913. );
  1914. $result = Hash::expand($data);
  1915. $expected = array(
  1916. array(
  1917. 'Post' => array('id' => '1', 'author_id' => '1', 'title' => 'First Post'),
  1918. 'Author' => array('id' => '1', 'user' => 'nate', 'password' => 'foo'),
  1919. ),
  1920. array(
  1921. 'Post' => array('id' => '2', 'author_id' => '3', 'title' => 'Second Post', 'body' => 'Second Post Body'),
  1922. 'Author' => array('id' => '3', 'user' => 'larry', 'password' => null),
  1923. )
  1924. );
  1925. $this->assertEquals($result, $expected);
  1926. $data = array(
  1927. '0/Post/id' => 1,
  1928. '0/Post/name' => 'test post'
  1929. );
  1930. $result = Hash::expand($data, '/');
  1931. $expected = array(
  1932. array(
  1933. 'Post' => array(
  1934. 'id' => 1,
  1935. 'name' => 'test post'
  1936. )
  1937. )
  1938. );
  1939. $this->assertEquals($result, $expected);
  1940. }
  1941. }