統計
| ブランチ: | リビジョン:

pictcode / lib / Cake / Test / Case / Utility / HashTest.php @ 635eef61

履歴 | 表示 | アノテート | ダウンロード (66.541 KB)

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
 * @package       Cake.Utility
13
 * @since         CakePHP(tm) v 2.2.0
14
 * @license       http://www.opensource.org/licenses/mit-license.php MIT License
15
 */
16

    
17
App::uses('Hash', 'Utility');
18

    
19
/**
20
 * Class HashTest
21
 *
22
 * @package       Cake.Utility
23
 */
24
class HashTest extends CakeTestCase {
25

    
26
/**
27
 * Data provider
28
 *
29
 * @return array
30
 */
31
        public static function articleData() {
32
                return array(
33
                        array(
34
                                'Article' => array(
35
                                        'id' => '1',
36
                                        'user_id' => '1',
37
                                        'title' => 'First Article',
38
                                        'body' => 'First Article Body'
39
                                ),
40
                                'User' => array(
41
                                        'id' => '1',
42
                                        'user' => 'mariano',
43
                                        'password' => '5f4dcc3b5aa765d61d8327deb882cf99',
44
                                ),
45
                                'Comment' => array(
46
                                        array(
47
                                                'id' => '1',
48
                                                'article_id' => '1',
49
                                                'user_id' => '2',
50
                                                'comment' => 'First Comment for First Article',
51
                                        ),
52
                                        array(
53
                                                'id' => '2',
54
                                                'article_id' => '1',
55
                                                'user_id' => '4',
56
                                                'comment' => 'Second Comment for First Article',
57
                                        ),
58
                                ),
59
                                'Tag' => array(
60
                                        array(
61
                                                'id' => '1',
62
                                                'tag' => 'tag1',
63
                                        ),
64
                                        array(
65
                                                'id' => '2',
66
                                                'tag' => 'tag2',
67
                                        )
68
                                ),
69
                                'Deep' => array(
70
                                        'Nesting' => array(
71
                                                'test' => array(
72
                                                        1 => 'foo',
73
                                                        2 => array(
74
                                                                'and' => array('more' => 'stuff')
75
                                                        )
76
                                                )
77
                                        )
78
                                )
79
                        ),
80
                        array(
81
                                'Article' => array(
82
                                        'id' => '2',
83
                                        'user_id' => '1',
84
                                        'title' => 'Second Article',
85
                                        'body' => 'Second Article Body',
86
                                        'published' => 'Y',
87
                                ),
88
                                'User' => array(
89
                                        'id' => '2',
90
                                        'user' => 'mariano',
91
                                        'password' => '5f4dcc3b5aa765d61d8327deb882cf99',
92
                                ),
93
                                'Comment' => array(),
94
                                'Tag' => array()
95
                        ),
96
                        array(
97
                                'Article' => array(
98
                                        'id' => '3',
99
                                        'user_id' => '1',
100
                                        'title' => 'Third Article',
101
                                        'body' => 'Third Article Body',
102
                                ),
103
                                'User' => array(
104
                                        'id' => '3',
105
                                        'user' => 'mariano',
106
                                        'password' => '5f4dcc3b5aa765d61d8327deb882cf99',
107
                                ),
108
                                'Comment' => array(),
109
                                'Tag' => array()
110
                        ),
111
                        array(
112
                                'Article' => array(
113
                                        'id' => '4',
114
                                        'user_id' => '1',
115
                                        'title' => 'Fourth Article',
116
                                        'body' => 'Fourth Article Body',
117
                                ),
118
                                'User' => array(
119
                                        'id' => '4',
120
                                        'user' => 'mariano',
121
                                        'password' => '5f4dcc3b5aa765d61d8327deb882cf99',
122
                                ),
123
                                'Comment' => array(),
124
                                'Tag' => array()
125
                        ),
126
                        array(
127
                                'Article' => array(
128
                                        'id' => '5',
129
                                        'user_id' => '1',
130
                                        'title' => 'Fifth Article',
131
                                        'body' => 'Fifth Article Body',
132
                                ),
133
                                'User' => array(
134
                                        'id' => '5',
135
                                        'user' => 'mariano',
136
                                        'password' => '5f4dcc3b5aa765d61d8327deb882cf99',
137
                                        ),
138
                                'Comment' => array(),
139
                                'Tag' => array()
140
                        )
141
                );
142
        }
143

    
144
/**
145
 * Data provider
146
 *
147
 * @return array
148
 */
149
        public static function userData() {
150
                return array(
151
                        array(
152
                                'User' => array(
153
                                        'id' => 2,
154
                                        'group_id' => 1,
155
                                        'Data' => array(
156
                                                'user' => 'mariano.iglesias',
157
                                                'name' => 'Mariano Iglesias'
158
                                        )
159
                                )
160
                        ),
161
                        array(
162
                                'User' => array(
163
                                        'id' => 14,
164
                                        'group_id' => 2,
165
                                        'Data' => array(
166
                                                'user' => 'phpnut',
167
                                                'name' => 'Larry E. Masters'
168
                                        )
169
                                )
170
                        ),
171
                        array(
172
                                'User' => array(
173
                                        'id' => 25,
174
                                        'group_id' => 1,
175
                                        'Data' => array(
176
                                                'user' => 'gwoo',
177
                                                'name' => 'The Gwoo'
178
                                        )
179
                                )
180
                        )
181
                );
182
        }
183

    
184
/**
185
 * Test get()
186
 *
187
 * @return void
188
 */
189
        public function testGet() {
190
                $data = array('abc', 'def');
191

    
192
                $result = Hash::get($data, '0');
193
                $this->assertEquals('abc', $result);
194

    
195
                $result = Hash::get($data, 0);
196
                $this->assertEquals('abc', $result);
197

    
198
                $result = Hash::get($data, '1');
199
                $this->assertEquals('def', $result);
200

    
201
                $data = static::articleData();
202

    
203
                $result = Hash::get(array(), '1.Article.title');
204
                $this->assertNull($result);
205

    
206
                $result = Hash::get($data, '');
207
                $this->assertNull($result);
208

    
209
                $result = Hash::get($data, '0.Article.title');
210
                $this->assertEquals('First Article', $result);
211

    
212
                $result = Hash::get($data, '1.Article.title');
213
                $this->assertEquals('Second Article', $result);
214

    
215
                $result = Hash::get($data, '5.Article.title');
216
                $this->assertNull($result);
217

    
218
                $default = array('empty');
219
                $this->assertEquals($default, Hash::get($data, '5.Article.title', $default));
220
                $this->assertEquals($default, Hash::get(array(), '5.Article.title', $default));
221

    
222
                $result = Hash::get($data, '1.Article.title.not_there');
223
                $this->assertNull($result);
224

    
225
                $result = Hash::get($data, '1.Article');
226
                $this->assertEquals($data[1]['Article'], $result);
227

    
228
                $result = Hash::get($data, array('1', 'Article'));
229
                $this->assertEquals($data[1]['Article'], $result);
230
        }
231

    
232
/**
233
 * Test get() with an invalid path
234
 *
235
 * @expectedException InvalidArgumentException
236
 * @return void
237
 */
238
        public function testGetInvalidPath() {
239
                Hash::get(array('one' => 'two'), true);
240
        }
241

    
242
/**
243
 * Test testGetNullPath()
244
 *
245
 * @return void
246
 */
247
        public function testGetNullPath() {
248
                $result = Hash::get(array('one' => 'two'), null, '-');
249
                $this->assertEquals('-', $result);
250

    
251
                $result = Hash::get(array('one' => 'two'), '', '-');
252
                $this->assertEquals('-', $result);
253
        }
254

    
255
/**
256
 * Test dimensions.
257
 *
258
 * @return void
259
 */
260
        public function testDimensions() {
261
                $result = Hash::dimensions(array());
262
                $this->assertEquals($result, 0);
263

    
264
                $data = array('one', '2', 'three');
265
                $result = Hash::dimensions($data);
266
                $this->assertEquals($result, 1);
267

    
268
                $data = array('1' => '1.1', '2', '3');
269
                $result = Hash::dimensions($data);
270
                $this->assertEquals($result, 1);
271

    
272
                $data = array('1' => array('1.1' => '1.1.1'), '2', '3' => array('3.1' => '3.1.1'));
273
                $result = Hash::dimensions($data);
274
                $this->assertEquals($result, 2);
275

    
276
                $data = array('1' => '1.1', '2', '3' => array('3.1' => '3.1.1'));
277
                $result = Hash::dimensions($data);
278
                $this->assertEquals($result, 1);
279

    
280
                $data = array('1' => array('1.1' => '1.1.1'), '2', '3' => array('3.1' => array('3.1.1' => '3.1.1.1')));
281
                $result = Hash::dimensions($data);
282
                $this->assertEquals($result, 2);
283
        }
284

    
285
/**
286
 * Test maxDimensions
287
 *
288
 * @return void
289
 */
290
        public function testMaxDimensions() {
291
                $data = array();
292
                $result = Hash::maxDimensions($data);
293
                $this->assertEquals(0, $result);
294

    
295
                $data = array('a', 'b');
296
                $result = Hash::maxDimensions($data);
297
                $this->assertEquals(1, $result);
298

    
299
                $data = array('1' => '1.1', '2', '3' => array('3.1' => '3.1.1'));
300
                $result = Hash::maxDimensions($data);
301
                $this->assertEquals($result, 2);
302

    
303
                $data = array(
304
                        '1' => array('1.1' => '1.1.1'),
305
                        '2',
306
                        '3' => array('3.1' => array('3.1.1' => '3.1.1.1'))
307
                );
308
                $result = Hash::maxDimensions($data);
309
                $this->assertEquals($result, 3);
310

    
311
                $data = array(
312
                        '1' => array(
313
                                '1.1' => '1.1.1',
314
                                '1.2' => array(
315
                                        '1.2.1' => array(
316
                                                '1.2.1.1',
317
                                                array('1.2.2.1')
318
                                        )
319
                                )
320
                        ),
321
                        '2' => array('2.1' => '2.1.1')
322
                );
323
                $result = Hash::maxDimensions($data);
324
                $this->assertEquals($result, 5);
325
        }
326

    
327
/**
328
 * Tests Hash::flatten
329
 *
330
 * @return void
331
 */
332
        public function testFlatten() {
333
                $data = array('Larry', 'Curly', 'Moe');
334
                $result = Hash::flatten($data);
335
                $this->assertEquals($result, $data);
336

    
337
                $data[9] = 'Shemp';
338
                $result = Hash::flatten($data);
339
                $this->assertEquals($result, $data);
340

    
341
                $data = array(
342
                        array(
343
                                'Post' => array('id' => '1', 'author_id' => '1', 'title' => 'First Post'),
344
                                'Author' => array('id' => '1', 'user' => 'nate', 'password' => 'foo'),
345
                        ),
346
                        array(
347
                                'Post' => array('id' => '2', 'author_id' => '3', 'title' => 'Second Post', 'body' => 'Second Post Body'),
348
                                'Author' => array('id' => '3', 'user' => 'larry', 'password' => null),
349
                        )
350
                );
351
                $result = Hash::flatten($data);
352
                $expected = array(
353
                        '0.Post.id' => '1',
354
                        '0.Post.author_id' => '1',
355
                        '0.Post.title' => 'First Post',
356
                        '0.Author.id' => '1',
357
                        '0.Author.user' => 'nate',
358
                        '0.Author.password' => 'foo',
359
                        '1.Post.id' => '2',
360
                        '1.Post.author_id' => '3',
361
                        '1.Post.title' => 'Second Post',
362
                        '1.Post.body' => 'Second Post Body',
363
                        '1.Author.id' => '3',
364
                        '1.Author.user' => 'larry',
365
                        '1.Author.password' => null
366
                );
367
                $this->assertEquals($expected, $result);
368

    
369
                $data = array(
370
                        array(
371
                                'Post' => array('id' => '1', 'author_id' => null, 'title' => 'First Post'),
372
                                'Author' => array(),
373
                        )
374
                );
375
                $result = Hash::flatten($data);
376
                $expected = array(
377
                        '0.Post.id' => '1',
378
                        '0.Post.author_id' => null,
379
                        '0.Post.title' => 'First Post',
380
                        '0.Author' => array()
381
                );
382
                $this->assertEquals($expected, $result);
383

    
384
                $data = array(
385
                        array('Post' => array('id' => 1)),
386
                        array('Post' => array('id' => 2)),
387
                );
388
                $result = Hash::flatten($data, '/');
389
                $expected = array(
390
                        '0/Post/id' => '1',
391
                        '1/Post/id' => '2',
392
                );
393
                $this->assertEquals($expected, $result);
394
        }
395

    
396
/**
397
 * Test diff();
398
 *
399
 * @return void
400
 */
401
        public function testDiff() {
402
                $a = array(
403
                        0 => array('name' => 'main'),
404
                        1 => array('name' => 'about')
405
                );
406
                $b = array(
407
                        0 => array('name' => 'main'),
408
                        1 => array('name' => 'about'),
409
                        2 => array('name' => 'contact')
410
                );
411

    
412
                $result = Hash::diff($a, array());
413
                $expected = $a;
414
                $this->assertEquals($expected, $result);
415

    
416
                $result = Hash::diff(array(), $b);
417
                $expected = $b;
418
                $this->assertEquals($expected, $result);
419

    
420
                $result = Hash::diff($a, $b);
421
                $expected = array(
422
                        2 => array('name' => 'contact')
423
                );
424
                $this->assertEquals($expected, $result);
425

    
426
                $b = array(
427
                        0 => array('name' => 'me'),
428
                        1 => array('name' => 'about')
429
                );
430

    
431
                $result = Hash::diff($a, $b);
432
                $expected = array(
433
                        0 => array('name' => 'main')
434
                );
435
                $this->assertEquals($expected, $result);
436

    
437
                $a = array();
438
                $b = array('name' => 'bob', 'address' => 'home');
439
                $result = Hash::diff($a, $b);
440
                $this->assertEquals($result, $b);
441

    
442
                $a = array('name' => 'bob', 'address' => 'home');
443
                $b = array();
444
                $result = Hash::diff($a, $b);
445
                $this->assertEquals($result, $a);
446

    
447
                $a = array('key' => true, 'another' => false, 'name' => 'me');
448
                $b = array('key' => 1, 'another' => 0);
449
                $expected = array('name' => 'me');
450
                $result = Hash::diff($a, $b);
451
                $this->assertEquals($expected, $result);
452

    
453
                $a = array('key' => 'value', 'another' => null, 'name' => 'me');
454
                $b = array('key' => 'differentValue', 'another' => null);
455
                $expected = array('key' => 'value', 'name' => 'me');
456
                $result = Hash::diff($a, $b);
457
                $this->assertEquals($expected, $result);
458

    
459
                $a = array('key' => 'value', 'another' => null, 'name' => 'me');
460
                $b = array('key' => 'differentValue', 'another' => 'value');
461
                $expected = array('key' => 'value', 'another' => null, 'name' => 'me');
462
                $result = Hash::diff($a, $b);
463
                $this->assertEquals($expected, $result);
464

    
465
                $a = array('key' => 'value', 'another' => null, 'name' => 'me');
466
                $b = array('key' => 'differentValue', 'another' => 'value');
467
                $expected = array('key' => 'differentValue', 'another' => 'value', 'name' => 'me');
468
                $result = Hash::diff($b, $a);
469
                $this->assertEquals($expected, $result);
470

    
471
                $a = array('key' => 'value', 'another' => null, 'name' => 'me');
472
                $b = array(0 => 'differentValue', 1 => 'value');
473
                $expected = $a + $b;
474
                $result = Hash::diff($a, $b);
475
                $this->assertEquals($expected, $result);
476
        }
477

    
478
/**
479
 * Test merge()
480
 *
481
 * @return void
482
 */
483
        public function testMerge() {
484
                $result = Hash::merge(array('foo'), array('bar'));
485
                $this->assertEquals($result, array('foo', 'bar'));
486

    
487
                $result = Hash::merge(array('foo'), array('user' => 'bob', 'no-bar'), 'bar');
488
                $this->assertEquals($result, array('foo', 'user' => 'bob', 'no-bar', 'bar'));
489

    
490
                $a = array('foo', 'foo2');
491
                $b = array('bar', 'bar2');
492
                $expected = array('foo', 'foo2', 'bar', 'bar2');
493
                $this->assertEquals($expected, Hash::merge($a, $b));
494

    
495
                $a = array('foo' => 'bar', 'bar' => 'foo');
496
                $b = array('foo' => 'no-bar', 'bar' => 'no-foo');
497
                $expected = array('foo' => 'no-bar', 'bar' => 'no-foo');
498
                $this->assertEquals($expected, Hash::merge($a, $b));
499

    
500
                $a = array('users' => array('bob', 'jim'));
501
                $b = array('users' => array('lisa', 'tina'));
502
                $expected = array('users' => array('bob', 'jim', 'lisa', 'tina'));
503
                $this->assertEquals($expected, Hash::merge($a, $b));
504

    
505
                $a = array('users' => array('jim', 'bob'));
506
                $b = array('users' => 'none');
507
                $expected = array('users' => 'none');
508
                $this->assertEquals($expected, Hash::merge($a, $b));
509

    
510
                $a = array('users' => array('lisa' => array('id' => 5, 'pw' => 'secret')), 'cakephp');
511
                $b = array('users' => array('lisa' => array('pw' => 'new-pass', 'age' => 23)), 'ice-cream');
512
                $expected = array(
513
                        'users' => array('lisa' => array('id' => 5, 'pw' => 'new-pass', 'age' => 23)),
514
                        'cakephp',
515
                        'ice-cream'
516
                );
517
                $result = Hash::merge($a, $b);
518
                $this->assertEquals($expected, $result);
519

    
520
                $c = array(
521
                        'users' => array('lisa' => array('pw' => 'you-will-never-guess', 'age' => 25, 'pet' => 'dog')),
522
                        'chocolate'
523
                );
524
                $expected = array(
525
                        'users' => array('lisa' => array('id' => 5, 'pw' => 'you-will-never-guess', 'age' => 25, 'pet' => 'dog')),
526
                        'cakephp',
527
                        'ice-cream',
528
                        'chocolate'
529
                );
530
                $this->assertEquals($expected, Hash::merge($a, $b, $c));
531

    
532
                $this->assertEquals($expected, Hash::merge($a, $b, array(), $c));
533

    
534
                $a = array(
535
                        'Tree',
536
                        'CounterCache',
537
                        'Upload' => array(
538
                                'folder' => 'products',
539
                                'fields' => array('image_1_id', 'image_2_id', 'image_3_id', 'image_4_id', 'image_5_id')
540
                        )
541
                );
542
                $b = array(
543
                        'Cacheable' => array('enabled' => false),
544
                        'Limit',
545
                        'Bindable',
546
                        'Validator',
547
                        'Transactional'
548
                );
549
                $expected = array(
550
                        'Tree',
551
                        'CounterCache',
552
                        'Upload' => array(
553
                                'folder' => 'products',
554
                                'fields' => array('image_1_id', 'image_2_id', 'image_3_id', 'image_4_id', 'image_5_id')
555
                        ),
556
                        'Cacheable' => array('enabled' => false),
557
                        'Limit',
558
                        'Bindable',
559
                        'Validator',
560
                        'Transactional'
561
                );
562
                $this->assertEquals($expected, Hash::merge($a, $b));
563
        }
564

    
565
/**
566
 * test normalizing arrays
567
 *
568
 * @return void
569
 */
570
        public function testNormalize() {
571
                $result = Hash::normalize(array('one', 'two', 'three'));
572
                $expected = array('one' => null, 'two' => null, 'three' => null);
573
                $this->assertEquals($expected, $result);
574

    
575
                $result = Hash::normalize(array('one', 'two', 'three'), false);
576
                $expected = array('one', 'two', 'three');
577
                $this->assertEquals($expected, $result);
578

    
579
                $result = Hash::normalize(array('one' => 1, 'two' => 2, 'three' => 3, 'four'), false);
580
                $expected = array('one' => 1, 'two' => 2, 'three' => 3, 'four' => null);
581
                $this->assertEquals($expected, $result);
582

    
583
                $result = Hash::normalize(array('one' => 1, 'two' => 2, 'three' => 3, 'four'));
584
                $expected = array('one' => 1, 'two' => 2, 'three' => 3, 'four' => null);
585
                $this->assertEquals($expected, $result);
586

    
587
                $result = Hash::normalize(array('one' => array('a', 'b', 'c' => 'cee'), 'two' => 2, 'three'));
588
                $expected = array('one' => array('a', 'b', 'c' => 'cee'), 'two' => 2, 'three' => null);
589
                $this->assertEquals($expected, $result);
590
        }
591

    
592
/**
593
 * testContains method
594
 *
595
 * @return void
596
 */
597
        public function testContains() {
598
                $data = array('apple', 'bee', 'cyclops');
599
                $this->assertTrue(Hash::contains($data, array('apple')));
600
                $this->assertFalse(Hash::contains($data, array('data')));
601

    
602
                $a = array(
603
                        0 => array('name' => 'main'),
604
                        1 => array('name' => 'about')
605
                );
606
                $b = array(
607
                        0 => array('name' => 'main'),
608
                        1 => array('name' => 'about'),
609
                        2 => array('name' => 'contact'),
610
                        'a' => 'b'
611
                );
612

    
613
                $this->assertTrue(Hash::contains($a, $a));
614
                $this->assertFalse(Hash::contains($a, $b));
615
                $this->assertTrue(Hash::contains($b, $a));
616

    
617
                $a = array(
618
                        array('User' => array('id' => 1)),
619
                        array('User' => array('id' => 2)),
620
                );
621
                $b = array(
622
                        array('User' => array('id' => 1)),
623
                        array('User' => array('id' => 2)),
624
                        array('User' => array('id' => 3))
625
                );
626
                $this->assertTrue(Hash::contains($b, $a));
627
                $this->assertFalse(Hash::contains($a, $b));
628

    
629
                $a = array(0 => 'test', 'string' => null);
630
                $this->assertTrue(Hash::contains($a, array('string' => null)));
631

    
632
                $a = array(0 => 'test', 'string' => null);
633
                $this->assertTrue(Hash::contains($a, array('test')));
634
        }
635

    
636
/**
637
 * testFilter method
638
 *
639
 * @return void
640
 */
641
        public function testFilter() {
642
                $result = Hash::filter(array('0', false, true, 0, array('one thing', 'I can tell you', 'is you got to be', false)));
643
                $expected = array('0', 2 => true, 3 => 0, 4 => array('one thing', 'I can tell you', 'is you got to be'));
644
                $this->assertSame($expected, $result);
645

    
646
                $result = Hash::filter(array(1, array(false)));
647
                $expected = array(1);
648
                $this->assertEquals($expected, $result);
649

    
650
                $result = Hash::filter(array(1, array(false, false)));
651
                $expected = array(1);
652
                $this->assertEquals($expected, $result);
653

    
654
                $result = Hash::filter(array(1, array('empty', false)));
655
                $expected = array(1, array('empty'));
656
                $this->assertEquals($expected, $result);
657

    
658
                $result = Hash::filter(array(1, array('2', false, array(3, null))));
659
                $expected = array(1, array('2', 2 => array(3)));
660
                $this->assertEquals($expected, $result);
661

    
662
                $this->assertSame(array(), Hash::filter(array()));
663
        }
664

    
665
/**
666
 * testNumericArrayCheck method
667
 *
668
 * @return void
669
 */
670
        public function testNumeric() {
671
                $data = array('one');
672
                $this->assertTrue(Hash::numeric(array_keys($data)));
673

    
674
                $data = array(1 => 'one');
675
                $this->assertFalse(Hash::numeric($data));
676

    
677
                $data = array('one');
678
                $this->assertFalse(Hash::numeric($data));
679

    
680
                $data = array('one' => 'two');
681
                $this->assertFalse(Hash::numeric($data));
682

    
683
                $data = array('one' => 1);
684
                $this->assertTrue(Hash::numeric($data));
685

    
686
                $data = array(0);
687
                $this->assertTrue(Hash::numeric($data));
688

    
689
                $data = array('one', 'two', 'three', 'four', 'five');
690
                $this->assertTrue(Hash::numeric(array_keys($data)));
691

    
692
                $data = array(1 => 'one', 2 => 'two', 3 => 'three', 4 => 'four', 5 => 'five');
693
                $this->assertTrue(Hash::numeric(array_keys($data)));
694

    
695
                $data = array('1' => 'one', 2 => 'two', 3 => 'three', 4 => 'four', 5 => 'five');
696
                $this->assertTrue(Hash::numeric(array_keys($data)));
697

    
698
                $data = array('one', 2 => 'two', 3 => 'three', 4 => 'four', 'a' => 'five');
699
                $this->assertFalse(Hash::numeric(array_keys($data)));
700

    
701
                $data = array(2.4, 1, 0, -1, -2);
702
                $this->assertTrue(Hash::numeric($data));
703
        }
704

    
705
/**
706
 * Test simple paths.
707
 *
708
 * @return void
709
 */
710
        public function testExtractBasic() {
711
                $data = static::articleData();
712

    
713
                $result = Hash::extract($data, '');
714
                $this->assertEquals($data, $result);
715

    
716
                $result = Hash::extract($data, '0.Article.title');
717
                $this->assertEquals(array('First Article'), $result);
718

    
719
                $result = Hash::extract($data, '1.Article.title');
720
                $this->assertEquals(array('Second Article'), $result);
721

    
722
                $result = Hash::extract(array(false), '{n}.Something.another_thing');
723
                $this->assertEquals(array(), $result);
724
        }
725

    
726
/**
727
 * Test the {n} selector
728
 *
729
 * @return void
730
 */
731
        public function testExtractNumericKey() {
732
                $data = static::articleData();
733
                $result = Hash::extract($data, '{n}.Article.title');
734
                $expected = array(
735
                        'First Article', 'Second Article',
736
                        'Third Article', 'Fourth Article',
737
                        'Fifth Article'
738
                );
739
                $this->assertEquals($expected, $result);
740

    
741
                $result = Hash::extract($data, '0.Comment.{n}.user_id');
742
                $expected = array(
743
                        '2', '4'
744
                );
745
                $this->assertEquals($expected, $result);
746
        }
747

    
748
/**
749
 * Test the {n} selector with inconsistent arrays
750
 *
751
 * @return void
752
 */
753
        public function testExtractNumericMixedKeys() {
754
                $data = array(
755
                        'User' => array(
756
                                0 => array(
757
                                        'id' => 4,
758
                                        'name' => 'Neo'
759
                                ),
760
                                1 => array(
761
                                        'id' => 5,
762
                                        'name' => 'Morpheus'
763
                                ),
764
                                'stringKey' => array(
765
                                        'name' => 'Fail'
766
                                )
767
                        )
768
                );
769
                $result = Hash::extract($data, 'User.{n}.name');
770
                $expected = array('Neo', 'Morpheus');
771
                $this->assertEquals($expected, $result);
772
        }
773

    
774
/**
775
 * Test the {n} selector with non-zero based arrays
776
 *
777
 * @return void
778
 */
779
        public function testExtractNumericNonZero() {
780
                $data = array(
781
                        1 => array(
782
                                'User' => array(
783
                                        'id' => 1,
784
                                        'name' => 'John',
785
                                )
786
                        ),
787
                        2 => array(
788
                                'User' => array(
789
                                        'id' => 2,
790
                                        'name' => 'Bob',
791
                                )
792
                        ),
793
                        3 => array(
794
                                'User' => array(
795
                                        'id' => 3,
796
                                        'name' => 'Tony',
797
                                )
798
                        )
799
                );
800
                $result = Hash::extract($data, '{n}.User.name');
801
                $expected = array('John', 'Bob', 'Tony');
802
                $this->assertEquals($expected, $result);
803
        }
804

    
805
/**
806
 * Test the {s} selector.
807
 *
808
 * @return void
809
 */
810
        public function testExtractStringKey() {
811
                $data = static::articleData();
812
                $result = Hash::extract($data, '{n}.{s}.user');
813
                $expected = array(
814
                        'mariano',
815
                        'mariano',
816
                        'mariano',
817
                        'mariano',
818
                        'mariano'
819
                );
820
                $this->assertEquals($expected, $result);
821

    
822
                $result = Hash::extract($data, '{n}.{s}.Nesting.test.1');
823
                $this->assertEquals(array('foo'), $result);
824
        }
825

    
826
/**
827
 * Test wildcard matcher
828
 *
829
 * @return void
830
 */
831
        public function testExtractWildcard() {
832
                $data = array(
833
                        '02000009C5560001' => array('name' => 'Mr. Alphanumeric'),
834
                        '2300000918020101' => array('name' => 'Mr. Numeric'),
835
                        '390000096AB30001' => array('name' => 'Mrs. Alphanumeric'),
836
                        'stuff' => array('name' => 'Ms. Word'),
837
                        123 => array('name' => 'Mr. Number'),
838
                        true => array('name' => 'Ms. Bool'),
839
                );
840
                $result = Hash::extract($data, '{*}.name');
841
                $expected = array(
842
                        'Mr. Alphanumeric',
843
                        'Mr. Numeric',
844
                        'Mrs. Alphanumeric',
845
                        'Ms. Word',
846
                        'Mr. Number',
847
                        'Ms. Bool',
848
                );
849
                $this->assertEquals($expected, $result);
850
        }
851

    
852
/**
853
 * Test the attribute presense selector.
854
 *
855
 * @return void
856
 */
857
        public function testExtractAttributePresence() {
858
                $data = static::articleData();
859

    
860
                $result = Hash::extract($data, '{n}.Article[published]');
861
                $expected = array($data[1]['Article']);
862
                $this->assertEquals($expected, $result);
863

    
864
                $result = Hash::extract($data, '{n}.Article[id][published]');
865
                $expected = array($data[1]['Article']);
866
                $this->assertEquals($expected, $result);
867
        }
868

    
869
/**
870
 * Test = and != operators.
871
 *
872
 * @return void
873
 */
874
        public function testExtractAttributeEquality() {
875
                $data = static::articleData();
876

    
877
                $result = Hash::extract($data, '{n}.Article[id=3]');
878
                $expected = array($data[2]['Article']);
879
                $this->assertEquals($expected, $result);
880

    
881
                $result = Hash::extract($data, '{n}.Article[id = 3]');
882
                $expected = array($data[2]['Article']);
883
                $this->assertEquals($expected, $result, 'Whitespace should not matter.');
884

    
885
                $result = Hash::extract($data, '{n}.Article[id!=3]');
886
                $this->assertEquals(1, $result[0]['id']);
887
                $this->assertEquals(2, $result[1]['id']);
888
                $this->assertEquals(4, $result[2]['id']);
889
                $this->assertEquals(5, $result[3]['id']);
890
        }
891

    
892
/**
893
 * Test extracting based on attributes with boolean values.
894
 *
895
 * @return void
896
 */
897
        public function testExtractAttributeBoolean() {
898
                $users = array(
899
                        array(
900
                                'id' => 2,
901
                                'username' => 'johndoe',
902
                                'active' => true
903
                        ),
904
                        array(
905
                                'id' => 5,
906
                                'username' => 'kevin',
907
                                'active' => true
908
                        ),
909
                        array(
910
                                'id' => 9,
911
                                'username' => 'samantha',
912
                                'active' => false
913
                        ),
914
                );
915
                $result = Hash::extract($users, '{n}[active=0]');
916
                $this->assertCount(1, $result);
917
                $this->assertEquals($users[2], $result[0]);
918

    
919
                $result = Hash::extract($users, '{n}[active=false]');
920
                $this->assertCount(1, $result);
921
                $this->assertEquals($users[2], $result[0]);
922

    
923
                $result = Hash::extract($users, '{n}[active=1]');
924
                $this->assertCount(2, $result);
925
                $this->assertEquals($users[0], $result[0]);
926
                $this->assertEquals($users[1], $result[1]);
927

    
928
                $result = Hash::extract($users, '{n}[active=true]');
929
                $this->assertCount(2, $result);
930
                $this->assertEquals($users[0], $result[0]);
931
                $this->assertEquals($users[1], $result[1]);
932
        }
933

    
934
/**
935
 * Test that attribute matchers don't cause errors on scalar data.
936
 *
937
 * @return void
938
 */
939
        public function testExtractAttributeEqualityOnScalarValue() {
940
                $data = array(
941
                        'Entity' => array(
942
                                'id' => 1,
943
                                'data1' => 'value',
944
                        )
945
                );
946
                $result = Hash::extract($data, 'Entity[id=1].data1');
947
                $this->assertEquals(array('value'), $result);
948

    
949
                $data = array('Entity' => false );
950
                $result = Hash::extract($data, 'Entity[id=1].data1');
951
                $this->assertEquals(array(), $result);
952
        }
953

    
954
/**
955
 * Test comparison operators.
956
 *
957
 * @return void
958
 */
959
        public function testExtractAttributeComparison() {
960
                $data = static::articleData();
961

    
962
                $result = Hash::extract($data, '{n}.Comment.{n}[user_id > 2]');
963
                $expected = array($data[0]['Comment'][1]);
964
                $this->assertEquals($expected, $result);
965
                $this->assertEquals(4, $expected[0]['user_id']);
966

    
967
                $result = Hash::extract($data, '{n}.Comment.{n}[user_id >= 4]');
968
                $expected = array($data[0]['Comment'][1]);
969
                $this->assertEquals($expected, $result);
970
                $this->assertEquals(4, $expected[0]['user_id']);
971

    
972
                $result = Hash::extract($data, '{n}.Comment.{n}[user_id < 3]');
973
                $expected = array($data[0]['Comment'][0]);
974
                $this->assertEquals($expected, $result);
975
                $this->assertEquals(2, $expected[0]['user_id']);
976

    
977
                $result = Hash::extract($data, '{n}.Comment.{n}[user_id <= 2]');
978
                $expected = array($data[0]['Comment'][0]);
979
                $this->assertEquals($expected, $result);
980
                $this->assertEquals(2, $expected[0]['user_id']);
981
        }
982

    
983
/**
984
 * Test multiple attributes with conditions.
985
 *
986
 * @return void
987
 */
988
        public function testExtractAttributeMultiple() {
989
                $data = static::articleData();
990

    
991
                $result = Hash::extract($data, '{n}.Comment.{n}[user_id > 2][id=1]');
992
                $this->assertEmpty($result);
993

    
994
                $result = Hash::extract($data, '{n}.Comment.{n}[user_id > 2][id=2]');
995
                $expected = array($data[0]['Comment'][1]);
996
                $this->assertEquals($expected, $result);
997
                $this->assertEquals(4, $expected[0]['user_id']);
998
        }
999

    
1000
/**
1001
 * Test attribute pattern matching.
1002
 *
1003
 * @return void
1004
 */
1005
        public function testExtractAttributePattern() {
1006
                $data = static::articleData();
1007

    
1008
                $result = Hash::extract($data, '{n}.Article[title=/^First/]');
1009
                $expected = array($data[0]['Article']);
1010
                $this->assertEquals($expected, $result);
1011

    
1012
                $result = Hash::extract($data, '{n}.Article[title=/^Fir[a-z]+/]');
1013
                $expected = array($data[0]['Article']);
1014
                $this->assertEquals($expected, $result);
1015
        }
1016

    
1017
/**
1018
 * Test that extract() + matching can hit null things.
1019
 *
1020
 * @return void
1021
 */
1022
        public function testExtractMatchesNull() {
1023
                $data = array(
1024
                        'Country' => array(
1025
                                array('name' => 'Canada'),
1026
                                array('name' => 'Australia'),
1027
                                array('name' => null),
1028
                        )
1029
                );
1030
                $result = Hash::extract($data, 'Country.{n}[name=/Canada|^$/]');
1031
                $expected = array(
1032
                        array(
1033
                                'name' => 'Canada',
1034
                        ),
1035
                        array(
1036
                                'name' => null,
1037
                        ),
1038
                );
1039
                $this->assertEquals($expected, $result);
1040
        }
1041

    
1042
/**
1043
 * Test that uneven keys are handled correctly.
1044
 *
1045
 * @return void
1046
 */
1047
        public function testExtractUnevenKeys() {
1048
                $data = array(
1049
                        'Level1' => array(
1050
                                'Level2' => array('test1', 'test2'),
1051
                                'Level2bis' => array('test3', 'test4')
1052
                        )
1053
                );
1054
                $this->assertEquals(
1055
                        array('test1', 'test2'),
1056
                        Hash::extract($data, 'Level1.Level2')
1057
                );
1058
                $this->assertEquals(
1059
                        array('test3', 'test4'),
1060
                        Hash::extract($data, 'Level1.Level2bis')
1061
                );
1062

    
1063
                $data = array(
1064
                        'Level1' => array(
1065
                                'Level2bis' => array(
1066
                                        array('test3', 'test4'),
1067
                                        array('test5', 'test6')
1068
                                )
1069
                        )
1070
                );
1071
                $expected = array(
1072
                        array('test3', 'test4'),
1073
                        array('test5', 'test6')
1074
                );
1075
                $this->assertEquals($expected, Hash::extract($data, 'Level1.Level2bis'));
1076

    
1077
                $data['Level1']['Level2'] = array('test1', 'test2');
1078
                $this->assertEquals($expected, Hash::extract($data, 'Level1.Level2bis'));
1079
        }
1080

    
1081
/**
1082
 * testSort method
1083
 *
1084
 * @return void
1085
 */
1086
        public function testSort() {
1087
                $result = Hash::sort(array(), '{n}.name');
1088
                $this->assertEquals(array(), $result);
1089

    
1090
                $a = array(
1091
                        0 => array(
1092
                                'Person' => array('name' => 'Jeff'),
1093
                                'Friend' => array(array('name' => 'Nate'))
1094
                        ),
1095
                        1 => array(
1096
                                'Person' => array('name' => 'Tracy'),
1097
                                'Friend' => array(array('name' => 'Lindsay'))
1098
                        )
1099
                );
1100
                $b = array(
1101
                        0 => array(
1102
                                'Person' => array('name' => 'Tracy'),
1103
                                'Friend' => array(array('name' => 'Lindsay'))
1104
                        ),
1105
                        1 => array(
1106
                                'Person' => array('name' => 'Jeff'),
1107
                                'Friend' => array(array('name' => 'Nate'))
1108
                        )
1109
                );
1110
                $a = Hash::sort($a, '{n}.Friend.{n}.name');
1111
                $this->assertEquals($a, $b);
1112

    
1113
                $b = array(
1114
                        0 => array(
1115
                                'Person' => array('name' => 'Jeff'),
1116
                                'Friend' => array(array('name' => 'Nate'))
1117
                        ),
1118
                        1 => array(
1119
                                'Person' => array('name' => 'Tracy'),
1120
                                'Friend' => array(array('name' => 'Lindsay'))
1121
                        )
1122
                );
1123
                $a = array(
1124
                        0 => array(
1125
                                'Person' => array('name' => 'Tracy'),
1126
                                'Friend' => array(array('name' => 'Lindsay'))
1127
                        ),
1128
                        1 => array(
1129
                                'Person' => array('name' => 'Jeff'),
1130
                                'Friend' => array(array('name' => 'Nate'))
1131
                        )
1132
                );
1133
                $a = Hash::sort($a, '{n}.Friend.{n}.name', 'desc');
1134
                $this->assertEquals($a, $b);
1135

    
1136
                $a = array(
1137
                        0 => array(
1138
                                'Person' => array('name' => 'Jeff'),
1139
                                'Friend' => array(array('name' => 'Nate'))
1140
                        ),
1141
                        1 => array(
1142
                                'Person' => array('name' => 'Tracy'),
1143
                                'Friend' => array(array('name' => 'Lindsay'))
1144
                        ),
1145
                        2 => array(
1146
                                'Person' => array('name' => 'Adam'),
1147
                                'Friend' => array(array('name' => 'Bob'))
1148
                        )
1149
                );
1150
                $b = array(
1151
                        0 => array(
1152
                                'Person' => array('name' => 'Adam'),
1153
                                'Friend' => array(array('name' => 'Bob'))
1154
                        ),
1155
                        1 => array(
1156
                                'Person' => array('name' => 'Jeff'),
1157
                                'Friend' => array(array('name' => 'Nate'))
1158
                        ),
1159
                        2 => array(
1160
                                'Person' => array('name' => 'Tracy'),
1161
                                'Friend' => array(array('name' => 'Lindsay'))
1162
                        )
1163
                );
1164
                $a = Hash::sort($a, '{n}.Person.name', 'asc');
1165
                $this->assertEquals($a, $b);
1166

    
1167
                $a = array(
1168
                        0 => array('Person' => array('name' => 'Jeff')),
1169
                        1 => array('Shirt' => array('color' => 'black'))
1170
                );
1171
                $b = array(
1172
                        0 => array('Shirt' => array('color' => 'black')),
1173
                        1 => array('Person' => array('name' => 'Jeff')),
1174
                );
1175
                $a = Hash::sort($a, '{n}.Person.name', 'ASC', 'STRING');
1176
                $this->assertSame($a, $b);
1177

    
1178
                $names = array(
1179
                        array('employees' => array(
1180
                                array('name' => array('first' => 'John', 'last' => 'Doe')))
1181
                        ),
1182
                        array('employees' => array(
1183
                                array('name' => array('first' => 'Jane', 'last' => 'Doe')))
1184
                        ),
1185
                        array('employees' => array(array('name' => array()))),
1186
                        array('employees' => array(array('name' => array())))
1187
                );
1188
                $result = Hash::sort($names, '{n}.employees.0.name', 'asc');
1189
                $expected = array(
1190
                        array('employees' => array(
1191
                                array('name' => array('first' => 'John', 'last' => 'Doe')))
1192
                        ),
1193
                        array('employees' => array(
1194
                                array('name' => array('first' => 'Jane', 'last' => 'Doe')))
1195
                        ),
1196
                        array('employees' => array(array('name' => array()))),
1197
                        array('employees' => array(array('name' => array())))
1198
                );
1199
                $this->assertSame($expected, $result);
1200

    
1201
                $a = array(
1202
                        'SU' => array(
1203
                                'total_fulfillable' => 2
1204
                        ),
1205
                        'AA' => array(
1206
                                'total_fulfillable' => 1
1207
                        ),
1208
                        'LX' => array(
1209
                                'total_fulfillable' => 0
1210
                        ),
1211
                        'BL' => array(
1212
                                'total_fulfillable' => 3
1213
                        ),
1214
                );
1215
                $expected = array(
1216
                        'LX' => array(
1217
                                'total_fulfillable' => 0
1218
                        ),
1219
                        'AA' => array(
1220
                                'total_fulfillable' => 1
1221
                        ),
1222
                        'SU' => array(
1223
                                'total_fulfillable' => 2
1224
                        ),
1225
                        'BL' => array(
1226
                                'total_fulfillable' => 3
1227
                        ),
1228
                );
1229
                $result = Hash::sort($a, '{s}.total_fulfillable', 'asc');
1230
                $this->assertSame($expected, $result);
1231
        }
1232

    
1233
/**
1234
 * Test sort() with numeric option.
1235
 *
1236
 * @return void
1237
 */
1238
        public function testSortNumeric() {
1239
                $items = array(
1240
                        array('Item' => array('price' => '155,000')),
1241
                        array('Item' => array('price' => '139,000')),
1242
                        array('Item' => array('price' => '275,622')),
1243
                        array('Item' => array('price' => '230,888')),
1244
                        array('Item' => array('price' => '66,000')),
1245
                );
1246
                $result = Hash::sort($items, '{n}.Item.price', 'asc', 'numeric');
1247
                $expected = array(
1248
                        array('Item' => array('price' => '66,000')),
1249
                        array('Item' => array('price' => '139,000')),
1250
                        array('Item' => array('price' => '155,000')),
1251
                        array('Item' => array('price' => '230,888')),
1252
                        array('Item' => array('price' => '275,622')),
1253
                );
1254
                $this->assertEquals($expected, $result);
1255

    
1256
                $result = Hash::sort($items, '{n}.Item.price', 'desc', 'numeric');
1257
                $expected = array(
1258
                        array('Item' => array('price' => '275,622')),
1259
                        array('Item' => array('price' => '230,888')),
1260
                        array('Item' => array('price' => '155,000')),
1261
                        array('Item' => array('price' => '139,000')),
1262
                        array('Item' => array('price' => '66,000')),
1263
                );
1264
                $this->assertEquals($expected, $result);
1265
        }
1266

    
1267
/**
1268
 * Test natural sorting.
1269
 *
1270
 * @return void
1271
 */
1272
        public function testSortNatural() {
1273
                if (version_compare(PHP_VERSION, '5.4.0', '<')) {
1274
                        $this->markTestSkipped('SORT_NATURAL is available since PHP 5.4.');
1275
                }
1276
                $items = array(
1277
                        array('Item' => array('image' => 'img1.jpg')),
1278
                        array('Item' => array('image' => 'img99.jpg')),
1279
                        array('Item' => array('image' => 'img12.jpg')),
1280
                        array('Item' => array('image' => 'img10.jpg')),
1281
                        array('Item' => array('image' => 'img2.jpg')),
1282
                );
1283
                $result = Hash::sort($items, '{n}.Item.image', 'desc', 'natural');
1284
                $expected = array(
1285
                        array('Item' => array('image' => 'img99.jpg')),
1286
                        array('Item' => array('image' => 'img12.jpg')),
1287
                        array('Item' => array('image' => 'img10.jpg')),
1288
                        array('Item' => array('image' => 'img2.jpg')),
1289
                        array('Item' => array('image' => 'img1.jpg')),
1290
                );
1291
                $this->assertEquals($expected, $result);
1292

    
1293
                $result = Hash::sort($items, '{n}.Item.image', 'asc', 'natural');
1294
                $expected = array(
1295
                        array('Item' => array('image' => 'img1.jpg')),
1296
                        array('Item' => array('image' => 'img2.jpg')),
1297
                        array('Item' => array('image' => 'img10.jpg')),
1298
                        array('Item' => array('image' => 'img12.jpg')),
1299
                        array('Item' => array('image' => 'img99.jpg')),
1300
                );
1301
                $this->assertEquals($expected, $result);
1302
        }
1303

    
1304
/**
1305
 * Test that sort() with 'natural' type will fallback to 'regular' as SORT_NATURAL is introduced in PHP 5.4
1306
 *
1307
 * @return void
1308
 */
1309
        public function testSortNaturalFallbackToRegular() {
1310
                if (version_compare(PHP_VERSION, '5.4.0', '>=')) {
1311
                        $this->markTestSkipped('Skipping SORT_NATURAL fallback test on PHP >= 5.4');
1312
                }
1313

    
1314
                $a = array(
1315
                        0 => array('Person' => array('name' => 'Jeff')),
1316
                        1 => array('Shirt' => array('color' => 'black'))
1317
                );
1318
                $b = array(
1319
                        0 => array('Shirt' => array('color' => 'black')),
1320
                        1 => array('Person' => array('name' => 'Jeff')),
1321
                );
1322
                $sorted = Hash::sort($a, '{n}.Person.name', 'asc', 'natural');
1323
                $this->assertEquals($sorted, $b);
1324
        }
1325

    
1326
/**
1327
 * test sorting with out of order keys.
1328
 *
1329
 * @return void
1330
 */
1331
        public function testSortWithOutOfOrderKeys() {
1332
                $data = array(
1333
                        9 => array('class' => 510, 'test2' => 2),
1334
                        1 => array('class' => 500, 'test2' => 1),
1335
                        2 => array('class' => 600, 'test2' => 2),
1336
                        5 => array('class' => 625, 'test2' => 4),
1337
                        0 => array('class' => 605, 'test2' => 3),
1338
                );
1339
                $expected = array(
1340
                        array('class' => 500, 'test2' => 1),
1341
                        array('class' => 510, 'test2' => 2),
1342
                        array('class' => 600, 'test2' => 2),
1343
                        array('class' => 605, 'test2' => 3),
1344
                        array('class' => 625, 'test2' => 4),
1345
                );
1346
                $result = Hash::sort($data, '{n}.class', 'asc');
1347
                $this->assertEquals($expected, $result);
1348

    
1349
                $result = Hash::sort($data, '{n}.test2', 'asc');
1350
                $this->assertEquals($expected, $result);
1351
        }
1352

    
1353
/**
1354
 * test sorting with string keys.
1355
 *
1356
 * @return void
1357
 */
1358
        public function testSortString() {
1359
                $toSort = array(
1360
                        'four' => array('number' => 4, 'some' => 'foursome'),
1361
                        'six' => array('number' => 6, 'some' => 'sixsome'),
1362
                        'five' => array('number' => 5, 'some' => 'fivesome'),
1363
                        'two' => array('number' => 2, 'some' => 'twosome'),
1364
                        'three' => array('number' => 3, 'some' => 'threesome')
1365
                );
1366
                $sorted = Hash::sort($toSort, '{s}.number', 'asc');
1367
                $expected = array(
1368
                        'two' => array('number' => 2, 'some' => 'twosome'),
1369
                        'three' => array('number' => 3, 'some' => 'threesome'),
1370
                        'four' => array('number' => 4, 'some' => 'foursome'),
1371
                        'five' => array('number' => 5, 'some' => 'fivesome'),
1372
                        'six' => array('number' => 6, 'some' => 'sixsome')
1373
                );
1374
                $this->assertEquals($expected, $sorted);
1375

    
1376
                $menus = array(
1377
                        'blogs' => array('title' => 'Blogs', 'weight' => 3),
1378
                        'comments' => array('title' => 'Comments', 'weight' => 2),
1379
                        'users' => array('title' => 'Users', 'weight' => 1),
1380
                );
1381
                $expected = array(
1382
                        'users' => array('title' => 'Users', 'weight' => 1),
1383
                        'comments' => array('title' => 'Comments', 'weight' => 2),
1384
                        'blogs' => array('title' => 'Blogs', 'weight' => 3),
1385
                );
1386
                $result = Hash::sort($menus, '{s}.weight', 'ASC');
1387
                $this->assertEquals($expected, $result);
1388
        }
1389

    
1390
/**
1391
 * Test insert()
1392
 *
1393
 * @return void
1394
 */
1395
        public function testInsertSimple() {
1396
                $a = array(
1397
                        'pages' => array('name' => 'page')
1398
                );
1399
                $result = Hash::insert($a, 'files', array('name' => 'files'));
1400
                $expected = array(
1401
                        'pages' => array('name' => 'page'),
1402
                        'files' => array('name' => 'files')
1403
                );
1404
                $this->assertEquals($expected, $result);
1405

    
1406
                $a = array(
1407
                        'pages' => array('name' => 'page')
1408
                );
1409
                $result = Hash::insert($a, 'pages.name', array());
1410
                $expected = array(
1411
                        'pages' => array('name' => array()),
1412
                );
1413
                $this->assertEquals($expected, $result);
1414

    
1415
                $a = array(
1416
                        'foo' => array('bar' => 'baz')
1417
                );
1418
                $result = Hash::insert($a, 'some.0123.path', array('foo' => array('bar' => 'baz')));
1419
                $expected = array('foo' => array('bar' => 'baz'));
1420
                $this->assertEquals($expected, Hash::get($result, 'some.0123.path'));
1421
        }
1422

    
1423
/**
1424
 * Test inserting with multiple values.
1425
 *
1426
 * @return void
1427
 */
1428
        public function testInsertMulti() {
1429
                $data = static::articleData();
1430

    
1431
                $result = Hash::insert($data, '{n}.Article.insert', 'value');
1432
                $this->assertEquals('value', $result[0]['Article']['insert']);
1433
                $this->assertEquals('value', $result[1]['Article']['insert']);
1434

    
1435
                $result = Hash::insert($data, '{n}.Comment.{n}.insert', 'value');
1436
                $this->assertEquals('value', $result[0]['Comment'][0]['insert']);
1437
                $this->assertEquals('value', $result[0]['Comment'][1]['insert']);
1438

    
1439
                $data = array(
1440
                        0 => array('Item' => array('id' => 1, 'title' => 'first')),
1441
                        1 => array('Item' => array('id' => 2, 'title' => 'second')),
1442
                        2 => array('Item' => array('id' => 3, 'title' => 'third')),
1443
                        3 => array('Item' => array('id' => 4, 'title' => 'fourth')),
1444
                        4 => array('Item' => array('id' => 5, 'title' => 'fifth')),
1445
                );
1446
                $result = Hash::insert($data, '{n}.Item[id=/\b2|\b4/]', array('test' => 2));
1447
                $expected = array(
1448
                        0 => array('Item' => array('id' => 1, 'title' => 'first')),
1449
                        1 => array('Item' => array('id' => 2, 'title' => 'second', 'test' => 2)),
1450
                        2 => array('Item' => array('id' => 3, 'title' => 'third')),
1451
                        3 => array('Item' => array('id' => 4, 'title' => 'fourth', 'test' => 2)),
1452
                        4 => array('Item' => array('id' => 5, 'title' => 'fifth')),
1453
                );
1454
                $this->assertEquals($expected, $result);
1455
        }
1456

    
1457
/**
1458
 * Test that insert() can insert data over a string value.
1459
 *
1460
 * @return void
1461
 */
1462
        public function testInsertOverwriteStringValue() {
1463
                $data = array(
1464
                        'Some' => array(
1465
                                'string' => 'value'
1466
                        )
1467
                );
1468
                $result = Hash::insert($data, 'Some.string.value', array('values'));
1469
                $expected = array(
1470
                        'Some' => array(
1471
                                'string' => array(
1472
                                        'value' => array('values')
1473
                                )
1474
                        )
1475
                );
1476
                $this->assertEquals($expected, $result);
1477
        }
1478

    
1479
/**
1480
 * Test remove() method.
1481
 *
1482
 * @return void
1483
 */
1484
        public function testRemove() {
1485
                $a = array(
1486
                        'pages' => array('name' => 'page'),
1487
                        'files' => array('name' => 'files')
1488
                );
1489

    
1490
                $result = Hash::remove($a, 'files');
1491
                $expected = array(
1492
                        'pages' => array('name' => 'page')
1493
                );
1494
                $this->assertEquals($expected, $result);
1495

    
1496
                $a = array(
1497
                        'pages' => array(
1498
                                0 => array('name' => 'main'),
1499
                                1 => array(
1500
                                        'name' => 'about',
1501
                                        'vars' => array('title' => 'page title')
1502
                                )
1503
                        )
1504
                );
1505

    
1506
                $result = Hash::remove($a, 'pages.1.vars');
1507
                $expected = array(
1508
                        'pages' => array(
1509
                                0 => array('name' => 'main'),
1510
                                1 => array('name' => 'about')
1511
                        )
1512
                );
1513
                $this->assertEquals($expected, $result);
1514

    
1515
                $result = Hash::remove($a, 'pages.2.vars');
1516
                $expected = $a;
1517
                $this->assertEquals($expected, $result);
1518

    
1519
                $a = array(
1520
                        0 => array(
1521
                                'name' => 'pages'
1522
                        ),
1523
                        1 => array(
1524
                                'name' => 'files'
1525
                        )
1526
                );
1527

    
1528
                $result = Hash::remove($a, '{n}[name=files]');
1529
                $expected = array(
1530
                        0 => array(
1531
                                'name' => 'pages'
1532
                        )
1533
                );
1534
                $this->assertEquals($expected, $result);
1535

    
1536
                $array = array(
1537
                        0 => 'foo',
1538
                        1 => array(
1539
                                0 => 'baz'
1540
                        )
1541
                );
1542
                $expected = $array;
1543
                $result = Hash::remove($array, '{n}.part');
1544
                $this->assertEquals($expected, $result);
1545
                $result = Hash::remove($array, '{n}.{n}.part');
1546
                $this->assertEquals($expected, $result);
1547
        }
1548

    
1549
/**
1550
 * Test removing multiple values.
1551
 *
1552
 * @return void
1553
 */
1554
        public function testRemoveMulti() {
1555
                $data = static::articleData();
1556

    
1557
                $result = Hash::remove($data, '{n}.Article.title');
1558
                $this->assertFalse(isset($result[0]['Article']['title']));
1559
                $this->assertFalse(isset($result[1]['Article']['title']));
1560

    
1561
                $result = Hash::remove($data, '{n}.Article.{s}');
1562
                $this->assertFalse(isset($result[0]['Article']['id']));
1563
                $this->assertFalse(isset($result[0]['Article']['user_id']));
1564
                $this->assertFalse(isset($result[0]['Article']['title']));
1565
                $this->assertFalse(isset($result[0]['Article']['body']));
1566

    
1567
                $data = array(
1568
                        0 => array('Item' => array('id' => 1, 'title' => 'first')),
1569
                        1 => array('Item' => array('id' => 2, 'title' => 'second')),
1570
                        2 => array('Item' => array('id' => 3, 'title' => 'third')),
1571
                        3 => array('Item' => array('id' => 4, 'title' => 'fourth')),
1572
                        4 => array('Item' => array('id' => 5, 'title' => 'fifth')),
1573
                );
1574

    
1575
                $result = Hash::remove($data, '{n}.Item[id=/\b2|\b4/]');
1576
                $expected = array(
1577
                        0 => array('Item' => array('id' => 1, 'title' => 'first')),
1578
                        2 => array('Item' => array('id' => 3, 'title' => 'third')),
1579
                        4 => array('Item' => array('id' => 5, 'title' => 'fifth')),
1580
                );
1581
                $this->assertEquals($expected, $result);
1582
        }
1583

    
1584
/**
1585
 * testCheck method
1586
 *
1587
 * @return void
1588
 */
1589
        public function testCheck() {
1590
                $set = array(
1591
                        'My Index 1' => array('First' => 'The first item')
1592
                );
1593
                $this->assertTrue(Hash::check($set, 'My Index 1.First'));
1594
                $this->assertTrue(Hash::check($set, 'My Index 1'));
1595

    
1596
                $set = array(
1597
                        'My Index 1' => array(
1598
                                'First' => array(
1599
                                        'Second' => array(
1600
                                                'Third' => array(
1601
                                                        'Fourth' => 'Heavy. Nesting.'
1602
                                                )
1603
                                        )
1604
                                )
1605
                        )
1606
                );
1607
                $this->assertTrue(Hash::check($set, 'My Index 1.First.Second'));
1608
                $this->assertTrue(Hash::check($set, 'My Index 1.First.Second.Third'));
1609
                $this->assertTrue(Hash::check($set, 'My Index 1.First.Second.Third.Fourth'));
1610
                $this->assertFalse(Hash::check($set, 'My Index 1.First.Seconds.Third.Fourth'));
1611
        }
1612

    
1613
/**
1614
 * testCombine method
1615
 *
1616
 * @return void
1617
 */
1618
        public function testCombine() {
1619
                $result = Hash::combine(array(), '{n}.User.id', '{n}.User.Data');
1620
                $this->assertTrue(empty($result));
1621

    
1622
                $a = static::userData();
1623

    
1624
                $result = Hash::combine($a, '{n}.User.id');
1625
                $expected = array(2 => null, 14 => null, 25 => null);
1626
                $this->assertEquals($expected, $result);
1627

    
1628
                $result = Hash::combine($a, '{n}.User.id', '{n}.User.non-existant');
1629
                $expected = array(2 => null, 14 => null, 25 => null);
1630
                $this->assertEquals($expected, $result);
1631

    
1632
                $result = Hash::combine($a, '{n}.User.id', '{n}.User.Data');
1633
                $expected = array(
1634
                        2 => array('user' => 'mariano.iglesias', 'name' => 'Mariano Iglesias'),
1635
                        14 => array('user' => 'phpnut', 'name' => 'Larry E. Masters'),
1636
                        25 => array('user' => 'gwoo', 'name' => 'The Gwoo'));
1637
                $this->assertEquals($expected, $result);
1638

    
1639
                $result = Hash::combine($a, '{n}.User.id', '{n}.User.Data.name');
1640
                $expected = array(
1641
                        2 => 'Mariano Iglesias',
1642
                        14 => 'Larry E. Masters',
1643
                        25 => 'The Gwoo');
1644
                $this->assertEquals($expected, $result);
1645
        }
1646

    
1647
/**
1648
 * test combine() giving errors on key/value length mismatches.
1649
 *
1650
 * @expectedException CakeException
1651
 * @return void
1652
 */
1653
        public function testCombineErrorMissingValue() {
1654
                $data = array(
1655
                        array('User' => array('id' => 1, 'name' => 'mark')),
1656
                        array('User' => array('name' => 'jose')),
1657
                );
1658
                Hash::combine($data, '{n}.User.id', '{n}.User.name');
1659
        }
1660

    
1661
/**
1662
 * test combine() giving errors on key/value length mismatches.
1663
 *
1664
 * @expectedException CakeException
1665
 * @return void
1666
 */
1667
        public function testCombineErrorMissingKey() {
1668
                $data = array(
1669
                        array('User' => array('id' => 1, 'name' => 'mark')),
1670
                        array('User' => array('id' => 2)),
1671
                );
1672
                Hash::combine($data, '{n}.User.id', '{n}.User.name');
1673
        }
1674

    
1675
/**
1676
 * test combine() with a group path.
1677
 *
1678
 * @return void
1679
 */
1680
        public function testCombineWithGroupPath() {
1681
                $a = static::userData();
1682

    
1683
                $result = Hash::combine($a, '{n}.User.id', '{n}.User.Data', '{n}.User.group_id');
1684
                $expected = array(
1685
                        1 => array(
1686
                                2 => array('user' => 'mariano.iglesias', 'name' => 'Mariano Iglesias'),
1687
                                25 => array('user' => 'gwoo', 'name' => 'The Gwoo')
1688
                        ),
1689
                        2 => array(
1690
                                14 => array('user' => 'phpnut', 'name' => 'Larry E. Masters')
1691
                        )
1692
                );
1693
                $this->assertEquals($expected, $result);
1694

    
1695
                $result = Hash::combine($a, '{n}.User.id', '{n}.User.Data.name', '{n}.User.group_id');
1696
                $expected = array(
1697
                        1 => array(
1698
                                2 => 'Mariano Iglesias',
1699
                                25 => 'The Gwoo'
1700
                        ),
1701
                        2 => array(
1702
                                14 => 'Larry E. Masters'
1703
                        )
1704
                );
1705
                $this->assertEquals($expected, $result);
1706

    
1707
                $result = Hash::combine($a, '{n}.User.id', '{n}.User.Data', '{n}.User.group_id');
1708
                $expected = array(
1709
                        1 => array(
1710
                                2 => array('user' => 'mariano.iglesias', 'name' => 'Mariano Iglesias'),
1711
                                25 => array('user' => 'gwoo', 'name' => 'The Gwoo')
1712
                        ),
1713
                        2 => array(
1714
                                14 => array('user' => 'phpnut', 'name' => 'Larry E. Masters')
1715
                        )
1716
                );
1717
                $this->assertEquals($expected, $result);
1718

    
1719
                $result = Hash::combine($a, '{n}.User.id', '{n}.User.Data.name', '{n}.User.group_id');
1720
                $expected = array(
1721
                        1 => array(
1722
                                2 => 'Mariano Iglesias',
1723
                                25 => 'The Gwoo'
1724
                        ),
1725
                        2 => array(
1726
                                14 => 'Larry E. Masters'
1727
                        )
1728
                );
1729
                $this->assertEquals($expected, $result);
1730
        }
1731

    
1732
/**
1733
 * Test combine with formatting rules.
1734
 *
1735
 * @return void
1736
 */
1737
        public function testCombineWithFormatting() {
1738
                $a = static::userData();
1739

    
1740
                $result = Hash::combine(
1741
                        $a,
1742
                        '{n}.User.id',
1743
                        array('%1$s: %2$s', '{n}.User.Data.user', '{n}.User.Data.name'),
1744
                        '{n}.User.group_id'
1745
                );
1746
                $expected = array(
1747
                        1 => array(
1748
                                2 => 'mariano.iglesias: Mariano Iglesias',
1749
                                25 => 'gwoo: The Gwoo'
1750
                        ),
1751
                        2 => array(
1752
                                14 => 'phpnut: Larry E. Masters'
1753
                        )
1754
                );
1755
                $this->assertEquals($expected, $result);
1756

    
1757
                $result = Hash::combine(
1758
                        $a,
1759
                        array(
1760
                                '%s: %s',
1761
                                '{n}.User.Data.user',
1762
                                '{n}.User.Data.name'
1763
                        ),
1764
                        '{n}.User.id'
1765
                );
1766
                $expected = array(
1767
                        'mariano.iglesias: Mariano Iglesias' => 2,
1768
                        'phpnut: Larry E. Masters' => 14,
1769
                        'gwoo: The Gwoo' => 25
1770
                );
1771
                $this->assertEquals($expected, $result);
1772

    
1773
                $result = Hash::combine(
1774
                        $a,
1775
                        array('%1$s: %2$d', '{n}.User.Data.user', '{n}.User.id'),
1776
                        '{n}.User.Data.name'
1777
                );
1778
                $expected = array(
1779
                        'mariano.iglesias: 2' => 'Mariano Iglesias',
1780
                        'phpnut: 14' => 'Larry E. Masters',
1781
                        'gwoo: 25' => 'The Gwoo'
1782
                );
1783
                $this->assertEquals($expected, $result);
1784

    
1785
                $result = Hash::combine(
1786
                        $a,
1787
                        array('%2$d: %1$s', '{n}.User.Data.user', '{n}.User.id'),
1788
                        '{n}.User.Data.name'
1789
                );
1790
                $expected = array(
1791
                        '2: mariano.iglesias' => 'Mariano Iglesias',
1792
                        '14: phpnut' => 'Larry E. Masters',
1793
                        '25: gwoo' => 'The Gwoo'
1794
                );
1795
                $this->assertEquals($expected, $result);
1796
        }
1797

    
1798
/**
1799
 * testFormat method
1800
 *
1801
 * @return void
1802
 */
1803
        public function testFormat() {
1804
                $data = static::userData();
1805

    
1806
                $result = Hash::format(
1807
                        $data,
1808
                        array('{n}.User.Data.user', '{n}.User.id'),
1809
                        '%s, %s'
1810
                );
1811
                $expected = array(
1812
                        'mariano.iglesias, 2',
1813
                        'phpnut, 14',
1814
                        'gwoo, 25'
1815
                );
1816
                $this->assertEquals($expected, $result);
1817

    
1818
                $result = Hash::format(
1819
                        $data,
1820
                        array('{n}.User.Data.user', '{n}.User.id'),
1821
                        '%2$s, %1$s'
1822
                );
1823
                $expected = array(
1824
                        '2, mariano.iglesias',
1825
                        '14, phpnut',
1826
                        '25, gwoo'
1827
                );
1828
                $this->assertEquals($expected, $result);
1829
        }
1830

    
1831
/**
1832
 * testFormattingNullValues method
1833
 *
1834
 * @return void
1835
 */
1836
        public function testFormatNullValues() {
1837
                $data = array(
1838
                        array('Person' => array(
1839
                                'first_name' => 'Nate', 'last_name' => 'Abele', 'city' => 'Boston', 'state' => 'MA', 'something' => '42'
1840
                        )),
1841
                        array('Person' => array(
1842
                                'first_name' => 'Larry', 'last_name' => 'Masters', 'city' => 'Boondock', 'state' => 'TN', 'something' => null
1843
                        )),
1844
                        array('Person' => array(
1845
                                'first_name' => 'Garrett', 'last_name' => 'Woodworth', 'city' => 'Venice Beach', 'state' => 'CA', 'something' => null
1846
                        ))
1847
                );
1848

    
1849
                $result = Hash::format($data, array('{n}.Person.something'), '%s');
1850
                $expected = array('42', '', '');
1851
                $this->assertEquals($expected, $result);
1852

    
1853
                $result = Hash::format($data, array('{n}.Person.city', '{n}.Person.something'), '%s, %s');
1854
                $expected = array('Boston, 42', 'Boondock, ', 'Venice Beach, ');
1855
                $this->assertEquals($expected, $result);
1856
        }
1857

    
1858
/**
1859
 * Test map()
1860
 *
1861
 * @return void
1862
 */
1863
        public function testMap() {
1864
                $data = static::articleData();
1865

    
1866
                $result = Hash::map($data, '{n}.Article.id', array($this, 'mapCallback'));
1867
                $expected = array(2, 4, 6, 8, 10);
1868
                $this->assertEquals($expected, $result);
1869
        }
1870

    
1871
/**
1872
 * testApply
1873
 *
1874
 * @return void
1875
 */
1876
        public function testApply() {
1877
                $data = static::articleData();
1878

    
1879
                $result = Hash::apply($data, '{n}.Article.id', 'array_sum');
1880
                $this->assertEquals(15, $result);
1881
        }
1882

    
1883
/**
1884
 * Test reduce()
1885
 *
1886
 * @return void
1887
 */
1888
        public function testReduce() {
1889
                $data = static::articleData();
1890

    
1891
                $result = Hash::reduce($data, '{n}.Article.id', array($this, 'reduceCallback'));
1892
                $this->assertEquals(15, $result);
1893
        }
1894

    
1895
/**
1896
 * testing method for map callbacks.
1897
 *
1898
 * @param mixed $value Value
1899
 * @return mixed
1900
 */
1901
        public function mapCallback($value) {
1902
                return $value * 2;
1903
        }
1904

    
1905
/**
1906
 * testing method for reduce callbacks.
1907
 *
1908
 * @param mixed $one First param
1909
 * @param mixed $two Second param
1910
 * @return mixed
1911
 */
1912
        public function reduceCallback($one, $two) {
1913
                return $one + $two;
1914
        }
1915

    
1916
/**
1917
 * test Hash nest with a normal model result set. For kicks rely on Hash nest detecting the key names
1918
 * automatically
1919
 *
1920
 * @return void
1921
 */
1922
        public function testNestModel() {
1923
                $input = array(
1924
                        array(
1925
                                'ModelName' => array(
1926
                                        'id' => 1,
1927
                                        'parent_id' => null
1928
                                ),
1929
                        ),
1930
                        array(
1931
                                'ModelName' => array(
1932
                                        'id' => 2,
1933
                                        'parent_id' => 1
1934
                                ),
1935
                        ),
1936
                        array(
1937
                                'ModelName' => array(
1938
                                        'id' => 3,
1939
                                        'parent_id' => 1
1940
                                ),
1941
                        ),
1942
                        array(
1943
                                'ModelName' => array(
1944
                                        'id' => 4,
1945
                                        'parent_id' => 1
1946
                                ),
1947
                        ),
1948
                        array(
1949
                                'ModelName' => array(
1950
                                        'id' => 5,
1951
                                        'parent_id' => 1
1952
                                ),
1953
                        ),
1954
                        array(
1955
                                'ModelName' => array(
1956
                                        'id' => 6,
1957
                                        'parent_id' => null
1958
                                ),
1959
                        ),
1960
                        array(
1961
                                'ModelName' => array(
1962
                                        'id' => 7,
1963
                                        'parent_id' => 6
1964
                                ),
1965
                        ),
1966
                        array(
1967
                                'ModelName' => array(
1968
                                        'id' => 8,
1969
                                        'parent_id' => 6
1970
                                ),
1971
                        ),
1972
                        array(
1973
                                'ModelName' => array(
1974
                                        'id' => 9,
1975
                                        'parent_id' => 6
1976
                                ),
1977
                        ),
1978
                        array(
1979
                                'ModelName' => array(
1980
                                        'id' => 10,
1981
                                        'parent_id' => 6
1982
                                )
1983
                        )
1984
                );
1985
                $expected = array(
1986
                        array(
1987
                                'ModelName' => array(
1988
                                        'id' => 1,
1989
                                        'parent_id' => null
1990
                                ),
1991
                                'children' => array(
1992
                                        array(
1993
                                                'ModelName' => array(
1994
                                                        'id' => 2,
1995
                                                        'parent_id' => 1
1996
                                                ),
1997
                                                'children' => array()
1998
                                        ),
1999
                                        array(
2000
                                                'ModelName' => array(
2001
                                                        'id' => 3,
2002
                                                        'parent_id' => 1
2003
                                                ),
2004
                                                'children' => array()
2005
                                        ),
2006
                                        array(
2007
                                                'ModelName' => array(
2008
                                                        'id' => 4,
2009
                                                        'parent_id' => 1
2010
                                                ),
2011
                                                'children' => array()
2012
                                        ),
2013
                                        array(
2014
                                                'ModelName' => array(
2015
                                                        'id' => 5,
2016
                                                        'parent_id' => 1
2017
                                                ),
2018
                                                'children' => array()
2019
                                        ),
2020

    
2021
                                )
2022
                        ),
2023
                        array(
2024
                                'ModelName' => array(
2025
                                        'id' => 6,
2026
                                        'parent_id' => null
2027
                                ),
2028
                                'children' => array(
2029
                                        array(
2030
                                                'ModelName' => array(
2031
                                                        'id' => 7,
2032
                                                        'parent_id' => 6
2033
                                                ),
2034
                                                'children' => array()
2035
                                        ),
2036
                                        array(
2037
                                                'ModelName' => array(
2038
                                                        'id' => 8,
2039
                                                        'parent_id' => 6
2040
                                                ),
2041
                                                'children' => array()
2042
                                        ),
2043
                                        array(
2044
                                                'ModelName' => array(
2045
                                                        'id' => 9,
2046
                                                        'parent_id' => 6
2047
                                                ),
2048
                                                'children' => array()
2049
                                        ),
2050
                                        array(
2051
                                                'ModelName' => array(
2052
                                                        'id' => 10,
2053
                                                        'parent_id' => 6
2054
                                                ),
2055
                                                'children' => array()
2056
                                        )
2057
                                )
2058
                        )
2059
                );
2060
                $result = Hash::nest($input);
2061
                $this->assertEquals($expected, $result);
2062
        }
2063

    
2064
/**
2065
 * test Hash nest with a normal model result set, and a nominated root id
2066
 *
2067
 * @return void
2068
 */
2069
        public function testNestModelExplicitRoot() {
2070
                $input = array(
2071
                        array(
2072
                                'ModelName' => array(
2073
                                        'id' => 1,
2074
                                        'parent_id' => null
2075
                                ),
2076
                        ),
2077
                        array(
2078
                                'ModelName' => array(
2079
                                        'id' => 2,
2080
                                        'parent_id' => 1
2081
                                ),
2082
                        ),
2083
                        array(
2084
                                'ModelName' => array(
2085
                                        'id' => 3,
2086
                                        'parent_id' => 1
2087
                                ),
2088
                        ),
2089
                        array(
2090
                                'ModelName' => array(
2091
                                        'id' => 4,
2092
                                        'parent_id' => 1
2093
                                ),
2094
                        ),
2095
                        array(
2096
                                'ModelName' => array(
2097
                                        'id' => 5,
2098
                                        'parent_id' => 1
2099
                                ),
2100
                        ),
2101
                        array(
2102
                                'ModelName' => array(
2103
                                        'id' => 6,
2104
                                        'parent_id' => null
2105
                                ),
2106
                        ),
2107
                        array(
2108
                                'ModelName' => array(
2109
                                        'id' => 7,
2110
                                        'parent_id' => 6
2111
                                ),
2112
                        ),
2113
                        array(
2114
                                'ModelName' => array(
2115
                                        'id' => 8,
2116
                                        'parent_id' => 6
2117
                                ),
2118
                        ),
2119
                        array(
2120
                                'ModelName' => array(
2121
                                        'id' => 9,
2122
                                        'parent_id' => 6
2123
                                ),
2124
                        ),
2125
                        array(
2126
                                'ModelName' => array(
2127
                                        'id' => 10,
2128
                                        'parent_id' => 6
2129
                                )
2130
                        )
2131
                );
2132
                $expected = array(
2133
                        array(
2134
                                'ModelName' => array(
2135
                                        'id' => 6,
2136
                                        'parent_id' => null
2137
                                ),
2138
                                'children' => array(
2139
                                        array(
2140
                                                'ModelName' => array(
2141
                                                        'id' => 7,
2142
                                                        'parent_id' => 6
2143
                                                ),
2144
                                                'children' => array()
2145
                                        ),
2146
                                        array(
2147
                                                'ModelName' => array(
2148
                                                        'id' => 8,
2149
                                                        'parent_id' => 6
2150
                                                ),
2151
                                                'children' => array()
2152
                                        ),
2153
                                        array(
2154
                                                'ModelName' => array(
2155
                                                        'id' => 9,
2156
                                                        'parent_id' => 6
2157
                                                ),
2158
                                                'children' => array()
2159
                                        ),
2160
                                        array(
2161
                                                'ModelName' => array(
2162
                                                        'id' => 10,
2163
                                                        'parent_id' => 6
2164
                                                ),
2165
                                                'children' => array()
2166
                                        )
2167
                                )
2168
                        )
2169
                );
2170
                $result = Hash::nest($input, array('root' => 6));
2171
                $this->assertEquals($expected, $result);
2172
        }
2173

    
2174
/**
2175
 * test Hash nest with a 1d array - this method should be able to handle any type of array input
2176
 *
2177
 * @return void
2178
 */
2179
        public function testNest1Dimensional() {
2180
                $input = array(
2181
                        array(
2182
                                'id' => 1,
2183
                                'parent_id' => null
2184
                        ),
2185
                        array(
2186
                                'id' => 2,
2187
                                'parent_id' => 1
2188
                        ),
2189
                        array(
2190
                                'id' => 3,
2191
                                'parent_id' => 1
2192
                        ),
2193
                        array(
2194
                                'id' => 4,
2195
                                'parent_id' => 1
2196
                        ),
2197
                        array(
2198
                                'id' => 5,
2199
                                'parent_id' => 1
2200
                        ),
2201
                        array(
2202
                                'id' => 6,
2203
                                'parent_id' => null
2204
                        ),
2205
                        array(
2206
                                'id' => 7,
2207
                                'parent_id' => 6
2208
                        ),
2209
                        array(
2210
                                'id' => 8,
2211
                                'parent_id' => 6
2212
                        ),
2213
                        array(
2214
                                'id' => 9,
2215
                                'parent_id' => 6
2216
                        ),
2217
                        array(
2218
                                'id' => 10,
2219
                                'parent_id' => 6
2220
                        )
2221
                );
2222
                $expected = array(
2223
                        array(
2224
                                'id' => 1,
2225
                                'parent_id' => null,
2226
                                'children' => array(
2227
                                        array(
2228
                                                'id' => 2,
2229
                                                'parent_id' => 1,
2230
                                                'children' => array()
2231
                                        ),
2232
                                        array(
2233
                                                'id' => 3,
2234
                                                'parent_id' => 1,
2235
                                                'children' => array()
2236
                                        ),
2237
                                        array(
2238
                                                'id' => 4,
2239
                                                'parent_id' => 1,
2240
                                                'children' => array()
2241
                                        ),
2242
                                        array(
2243
                                                'id' => 5,
2244
                                                'parent_id' => 1,
2245
                                                'children' => array()
2246
                                        ),
2247

    
2248
                                )
2249
                        ),
2250
                        array(
2251
                                'id' => 6,
2252
                                'parent_id' => null,
2253
                                'children' => array(
2254
                                        array(
2255
                                                'id' => 7,
2256
                                                'parent_id' => 6,
2257
                                                'children' => array()
2258
                                        ),
2259
                                        array(
2260
                                                'id' => 8,
2261
                                                'parent_id' => 6,
2262
                                                'children' => array()
2263
                                        ),
2264
                                        array(
2265
                                                'id' => 9,
2266
                                                'parent_id' => 6,
2267
                                                'children' => array()
2268
                                        ),
2269
                                        array(
2270
                                                'id' => 10,
2271
                                                'parent_id' => 6,
2272
                                                'children' => array()
2273
                                        )
2274
                                )
2275
                        )
2276
                );
2277
                $result = Hash::nest($input, array('idPath' => '{n}.id', 'parentPath' => '{n}.parent_id'));
2278
                $this->assertEquals($expected, $result);
2279
        }
2280

    
2281
/**
2282
 * test Hash nest with no specified parent data.
2283
 *
2284
 * The result should be the same as the input.
2285
 * For an easier comparison, unset all the empty children arrays from the result
2286
 *
2287
 * @return void
2288
 */
2289
        public function testMissingParent() {
2290
                $input = array(
2291
                        array(
2292
                                'id' => 1,
2293
                        ),
2294
                        array(
2295
                                'id' => 2,
2296
                        ),
2297
                        array(
2298
                                'id' => 3,
2299
                        ),
2300
                        array(
2301
                                'id' => 4,
2302
                        ),
2303
                        array(
2304
                                'id' => 5,
2305
                        ),
2306
                        array(
2307
                                'id' => 6,
2308
                        ),
2309
                        array(
2310
                                'id' => 7,
2311
                        ),
2312
                        array(
2313
                                'id' => 8,
2314
                        ),
2315
                        array(
2316
                                'id' => 9,
2317
                        ),
2318
                        array(
2319
                                'id' => 10,
2320
                        )
2321
                );
2322

    
2323
                $result = Hash::nest($input, array('idPath' => '{n}.id', 'parentPath' => '{n}.parent_id'));
2324
                foreach ($result as &$row) {
2325
                        if (empty($row['children'])) {
2326
                                unset($row['children']);
2327
                        }
2328
                }
2329
                $this->assertEquals($input, $result);
2330
        }
2331

    
2332
/**
2333
 * Tests that nest() throws an InvalidArgumentException when providing an invalid input.
2334
 *
2335
 * @expectedException InvalidArgumentException
2336
 * @return void
2337
 */
2338
        public function testNestInvalid() {
2339
                $input = array(
2340
                        array(
2341
                                'ParentCategory' => array(
2342
                                        'id' => '1',
2343
                                        'name' => 'Lorem ipsum dolor sit amet',
2344
                                        'parent_id' => '1'
2345
                                )
2346
                        )
2347
                );
2348
                Hash::nest($input);
2349
        }
2350

    
2351
/**
2352
 * testMergeDiff method
2353
 *
2354
 * @return void
2355
 */
2356
        public function testMergeDiff() {
2357
                $first = array(
2358
                        'ModelOne' => array(
2359
                                'id' => 1001,
2360
                                'field_one' => 'a1.m1.f1',
2361
                                'field_two' => 'a1.m1.f2'
2362
                        )
2363
                );
2364
                $second = array(
2365
                        'ModelTwo' => array(
2366
                                'id' => 1002,
2367
                                'field_one' => 'a2.m2.f1',
2368
                                'field_two' => 'a2.m2.f2'
2369
                        )
2370
                );
2371
                $result = Hash::mergeDiff($first, $second);
2372
                $this->assertEquals($result, $first + $second);
2373

    
2374
                $result = Hash::mergeDiff($first, array());
2375
                $this->assertEquals($result, $first);
2376

    
2377
                $result = Hash::mergeDiff(array(), $first);
2378
                $this->assertEquals($result, $first);
2379

    
2380
                $third = array(
2381
                        'ModelOne' => array(
2382
                                'id' => 1003,
2383
                                'field_one' => 'a3.m1.f1',
2384
                                'field_two' => 'a3.m1.f2',
2385
                                'field_three' => 'a3.m1.f3'
2386
                        )
2387
                );
2388
                $result = Hash::mergeDiff($first, $third);
2389
                $expected = array(
2390
                        'ModelOne' => array(
2391
                                'id' => 1001,
2392
                                'field_one' => 'a1.m1.f1',
2393
                                'field_two' => 'a1.m1.f2',
2394
                                'field_three' => 'a3.m1.f3'
2395
                        )
2396
                );
2397
                $this->assertEquals($expected, $result);
2398

    
2399
                $first = array(
2400
                        0 => array('ModelOne' => array('id' => 1001, 'field_one' => 's1.0.m1.f1', 'field_two' => 's1.0.m1.f2')),
2401
                        1 => array('ModelTwo' => array('id' => 1002, 'field_one' => 's1.1.m2.f2', 'field_two' => 's1.1.m2.f2'))
2402
                );
2403
                $second = array(
2404
                        0 => array('ModelOne' => array('id' => 1001, 'field_one' => 's2.0.m1.f1', 'field_two' => 's2.0.m1.f2')),
2405
                        1 => array('ModelTwo' => array('id' => 1002, 'field_one' => 's2.1.m2.f2', 'field_two' => 's2.1.m2.f2'))
2406
                );
2407

    
2408
                $result = Hash::mergeDiff($first, $second);
2409
                $this->assertEquals($result, $first);
2410

    
2411
                $third = array(
2412
                        0 => array(
2413
                                'ModelThree' => array(
2414
                                        'id' => 1003,
2415
                                        'field_one' => 's3.0.m3.f1',
2416
                                        'field_two' => 's3.0.m3.f2'
2417
                                )
2418
                        )
2419
                );
2420

    
2421
                $result = Hash::mergeDiff($first, $third);
2422
                $expected = array(
2423
                        0 => array(
2424
                                'ModelOne' => array(
2425
                                        'id' => 1001,
2426
                                        'field_one' => 's1.0.m1.f1',
2427
                                        'field_two' => 's1.0.m1.f2'
2428
                                ),
2429
                                'ModelThree' => array(
2430
                                        'id' => 1003,
2431
                                        'field_one' => 's3.0.m3.f1',
2432
                                        'field_two' => 's3.0.m3.f2'
2433
                                )
2434
                        ),
2435
                        1 => array(
2436
                                'ModelTwo' => array(
2437
                                        'id' => 1002,
2438
                                        'field_one' => 's1.1.m2.f2',
2439
                                        'field_two' => 's1.1.m2.f2'
2440
                                )
2441
                        )
2442
                );
2443
                $this->assertEquals($expected, $result);
2444

    
2445
                $result = Hash::mergeDiff($first, null);
2446
                $this->assertEquals($result, $first);
2447

    
2448
                $result = Hash::mergeDiff($first, $second);
2449
                $this->assertEquals($result, $first + $second);
2450
        }
2451

    
2452
/**
2453
 * Tests Hash::expand
2454
 *
2455
 * @return void
2456
 */
2457
        public function testExpand() {
2458
                $data = array('My', 'Array', 'To', 'Flatten');
2459
                $flat = Hash::flatten($data);
2460
                $result = Hash::expand($flat);
2461
                $this->assertEquals($data, $result);
2462

    
2463
                $data = array(
2464
                        '0.Post.id' => '1', '0.Post.author_id' => '1', '0.Post.title' => 'First Post', '0.Author.id' => '1',
2465
                        '0.Author.user' => 'nate', '0.Author.password' => 'foo', '1.Post.id' => '2', '1.Post.author_id' => '3',
2466
                        '1.Post.title' => 'Second Post', '1.Post.body' => 'Second Post Body', '1.Author.id' => '3',
2467
                        '1.Author.user' => 'larry', '1.Author.password' => null
2468
                );
2469
                $result = Hash::expand($data);
2470
                $expected = array(
2471
                        array(
2472
                                'Post' => array('id' => '1', 'author_id' => '1', 'title' => 'First Post'),
2473
                                'Author' => array('id' => '1', 'user' => 'nate', 'password' => 'foo'),
2474
                        ),
2475
                        array(
2476
                                'Post' => array('id' => '2', 'author_id' => '3', 'title' => 'Second Post', 'body' => 'Second Post Body'),
2477
                                'Author' => array('id' => '3', 'user' => 'larry', 'password' => null),
2478
                        )
2479
                );
2480
                $this->assertEquals($expected, $result);
2481

    
2482
                $data = array(
2483
                        '0/Post/id' => 1,
2484
                        '0/Post/name' => 'test post'
2485
                );
2486
                $result = Hash::expand($data, '/');
2487
                $expected = array(
2488
                        array(
2489
                                'Post' => array(
2490
                                        'id' => 1,
2491
                                        'name' => 'test post'
2492
                                )
2493
                        )
2494
                );
2495
                $this->assertEquals($expected, $result);
2496

    
2497
                $data = array('a.b.100.a' => null, 'a.b.200.a' => null);
2498
                $expected = array(
2499
                        'a' => array(
2500
                                'b' => array(
2501
                                        100 => array('a' => null),
2502
                                        200 => array('a' => null)
2503
                                )
2504
                        )
2505
                );
2506
                $result = Hash::expand($data);
2507
                $this->assertEquals($expected, $result);
2508
        }
2509

    
2510
/**
2511
 * Test that flattening a large complex set doesn't loop forever.
2512
 *
2513
 * @return void
2514
 */
2515
        public function testFlattenInfiniteLoop() {
2516
                $data = array(
2517
                        'Order.ASI' => '0',
2518
                        'Order.Accounting' => '0',
2519
                        'Order.Admin' => '0',
2520
                        'Order.Art' => '0',
2521
                        'Order.ArtChecker' => '0',
2522
                        'Order.Canned' => '0',
2523
                        'Order.Customer_Tags' => '',
2524
                        'Order.Embroidery' => '0',
2525
                        'Order.Item.0.Product.style_number' => 'a11222',
2526
                        'Order.Item.0.Product.slug' => 'a11222',
2527
                        'Order.Item.0.Product._id' => '4ff8b8d3d7bbe8ad30000000',
2528
                        'Order.Item.0.Product.Color.slug' => 'kelly_green',
2529
                        'Order.Item.0.Product.ColorSizes.0.Color.color' => 'Sport Grey',
2530
                        'Order.Item.0.Product.ColorSizes.0.Color.slug' => 'sport_grey',
2531
                        'Order.Item.0.Product.ColorSizes.1.Color.color' => 'Kelly Green',
2532
                        'Order.Item.0.Product.ColorSizes.1.Color.slug' => 'kelly_green',
2533
                        'Order.Item.0.Product.ColorSizes.2.Color.color' => 'Orange',
2534
                        'Order.Item.0.Product.ColorSizes.2.Color.slug' => 'orange',
2535
                        'Order.Item.0.Product.ColorSizes.3.Color.color' => 'Yellow Haze',
2536
                        'Order.Item.0.Product.ColorSizes.3.Color.slug' => 'yellow_haze',
2537
                        'Order.Item.0.Product.brand' => 'OUTER BANKS',
2538
                        'Order.Item.0.Product.style' => 'T-shirt',
2539
                        'Order.Item.0.Product.description' => 'uhiuhuih oin ooi ioo ioio',
2540
                        'Order.Item.0.Product.sizes.0.Size.qty' => '',
2541
                        'Order.Item.0.Product.sizes.0.Size.size' => '0-3mo',
2542
                        'Order.Item.0.Product.sizes.0.Size.id' => '38',
2543
                        'Order.Item.0.Product.sizes.1.Size.qty' => '',
2544
                        'Order.Item.0.Product.sizes.1.Size.size' => '3-6mo',
2545
                        'Order.Item.0.Product.sizes.1.Size.id' => '39',
2546
                        'Order.Item.0.Product.sizes.2.Size.qty' => '78',
2547
                        'Order.Item.0.Product.sizes.2.Size.size' => '6-9mo',
2548
                        'Order.Item.0.Product.sizes.2.Size.id' => '40',
2549
                        'Order.Item.0.Product.sizes.3.Size.qty' => '',
2550
                        'Order.Item.0.Product.sizes.3.Size.size' => '6-12mo',
2551
                        'Order.Item.0.Product.sizes.3.Size.id' => '41',
2552
                        'Order.Item.0.Product.sizes.4.Size.qty' => '',
2553
                        'Order.Item.0.Product.sizes.4.Size.size' => '12-18mo',
2554
                        'Order.Item.0.Product.sizes.4.Size.id' => '42',
2555
                        'Order.Item.0.Art.imprint_locations.0.id' => 2,
2556
                        'Order.Item.0.Art.imprint_locations.0.name' => 'Left Chest',
2557
                        'Order.Item.0.Art.imprint_locations.0.imprint_type.id' => 7,
2558
                        'Order.Item.0.Art.imprint_locations.0.imprint_type.type' => 'Embroidery',
2559
                        'Order.Item.0.Art.imprint_locations.0.art' => '',
2560
                        'Order.Item.0.Art.imprint_locations.0.num_colors' => 3,
2561
                        'Order.Item.0.Art.imprint_locations.0.description' => 'Wooo! This is Embroidery!!',
2562
                        'Order.Item.0.Art.imprint_locations.0.lines.0' => 'Platen',
2563
                        'Order.Item.0.Art.imprint_locations.0.lines.1' => 'Logo',
2564
                        'Order.Item.0.Art.imprint_locations.0.height' => 4,
2565
                        'Order.Item.0.Art.imprint_locations.0.width' => 5,
2566
                        'Order.Item.0.Art.imprint_locations.0.stitch_density' => 'Light',
2567
                        'Order.Item.0.Art.imprint_locations.0.metallic_thread' => true,
2568
                        'Order.Item.0.Art.imprint_locations.1.id' => 4,
2569
                        'Order.Item.0.Art.imprint_locations.1.name' => 'Full Back',
2570
                        'Order.Item.0.Art.imprint_locations.1.imprint_type.id' => 6,
2571
                        'Order.Item.0.Art.imprint_locations.1.imprint_type.type' => 'Screenprinting',
2572
                        'Order.Item.0.Art.imprint_locations.1.art' => '',
2573
                        'Order.Item.0.Art.imprint_locations.1.num_colors' => 3,
2574
                        'Order.Item.0.Art.imprint_locations.1.description' => 'Wooo! This is Screenprinting!!',
2575
                        'Order.Item.0.Art.imprint_locations.1.lines.0' => 'Platen',
2576
                        'Order.Item.0.Art.imprint_locations.1.lines.1' => 'Logo',
2577
                        'Order.Item.0.Art.imprint_locations.2.id' => 26,
2578
                        'Order.Item.0.Art.imprint_locations.2.name' => 'HS - JSY Name Below',
2579
                        'Order.Item.0.Art.imprint_locations.2.imprint_type.id' => 9,
2580
                        'Order.Item.0.Art.imprint_locations.2.imprint_type.type' => 'Names',
2581
                        'Order.Item.0.Art.imprint_locations.2.description' => 'Wooo! This is Names!!',
2582
                        'Order.Item.0.Art.imprint_locations.2.sizes.S.0.active' => 1,
2583
                        'Order.Item.0.Art.imprint_locations.2.sizes.S.0.name' => 'Benjamin Talavera',
2584
                        'Order.Item.0.Art.imprint_locations.2.sizes.S.0.color' => 'Red',
2585
                        'Order.Item.0.Art.imprint_locations.2.sizes.S.0.height' => '3',
2586
                        'Order.Item.0.Art.imprint_locations.2.sizes.S.0.layout' => 'Arched',
2587
                        'Order.Item.0.Art.imprint_locations.2.sizes.S.0.style' => 'Classic',
2588
                        'Order.Item.0.Art.imprint_locations.2.sizes.S.1.active' => 0,
2589
                        'Order.Item.0.Art.imprint_locations.2.sizes.S.1.name' => 'Rishi Narayan',
2590
                        'Order.Item.0.Art.imprint_locations.2.sizes.S.1.color' => 'Cardinal',
2591
                        'Order.Item.0.Art.imprint_locations.2.sizes.S.1.height' => '4',
2592
                        'Order.Item.0.Art.imprint_locations.2.sizes.S.1.layout' => 'Straight',
2593
                        'Order.Item.0.Art.imprint_locations.2.sizes.S.1.style' => 'Team US',
2594
                        'Order.Item.0.Art.imprint_locations.2.sizes.M.0.active' => 1,
2595
                        'Order.Item.0.Art.imprint_locations.2.sizes.M.0.name' => 'Brandon Plasters',
2596
                        'Order.Item.0.Art.imprint_locations.2.sizes.M.0.color' => 'Red',
2597
                        'Order.Item.0.Art.imprint_locations.2.sizes.M.0.height' => '3',
2598
                        'Order.Item.0.Art.imprint_locations.2.sizes.M.0.layout' => 'Arched',
2599
                        'Order.Item.0.Art.imprint_locations.2.sizes.M.0.style' => 'Classic',
2600
                        'Order.Item.0.Art.imprint_locations.2.sizes.M.1.active' => 0,
2601
                        'Order.Item.0.Art.imprint_locations.2.sizes.M.1.name' => 'Andrew Reed',
2602
                        'Order.Item.0.Art.imprint_locations.2.sizes.M.1.color' => 'Cardinal',
2603
                        'Order.Item.0.Art.imprint_locations.2.sizes.M.1.height' => '4',
2604
                        'Order.Item.0.Art.imprint_locations.2.sizes.M.1.layout' => 'Straight',
2605
                        'Order.Item.0.Art.imprint_locations.2.sizes.M.1.style' => 'Team US',
2606
                        'Order.Job.0._id' => 'job-1',
2607
                        'Order.Job.0.type' => 'screenprinting',
2608
                        'Order.Job.0.postPress' => 'job-2',
2609
                        'Order.Job.1._id' => 'job-2',
2610
                        'Order.Job.1.type' => 'embroidery',
2611
                        'Order.Postpress' => '0',
2612
                        'Order.PriceAdjustment.0._id' => 'price-adjustment-1',
2613
                        'Order.PriceAdjustment.0.adjustment' => '-20',
2614
                        'Order.PriceAdjustment.0.adjustment_type' => 'percent',
2615
                        'Order.PriceAdjustment.0.type' => 'grand_total',
2616
                        'Order.PriceAdjustment.1.adjustment' => '20',
2617
                        'Order.PriceAdjustment.1.adjustment_type' => 'flat',
2618
                        'Order.PriceAdjustment.1.min-items' => '10',
2619
                        'Order.PriceAdjustment.1.type' => 'min-items',
2620
                        'Order.PriceAdjustment.1._id' => 'another-test-adjustment',
2621
                        'Order.Purchasing' => '0',
2622
                        'Order.QualityControl' => '0',
2623
                        'Order.Receiving' => '0',
2624
                        'Order.ScreenPrinting' => '0',
2625
                        'Order.Stage.art_approval' => 0,
2626
                        'Order.Stage.draft' => 1,
2627
                        'Order.Stage.quote' => 1,
2628
                        'Order.Stage.order' => 1,
2629
                        'Order.StoreLiason' => '0',
2630
                        'Order.Tag_UI_Email' => '',
2631
                        'Order.Tags' => '',
2632
                        'Order._id' => 'test-2',
2633
                        'Order.add_print_location' => '',
2634
                        'Order.created' => '2011-Dec-29 05:40:18',
2635
                        'Order.force_admin' => '0',
2636
                        'Order.modified' => '2012-Jul-25 01:24:49',
2637
                        'Order.name' => 'towering power',
2638
                        'Order.order_id' => '135961',
2639
                        'Order.slug' => 'test-2',
2640
                        'Order.title' => 'test job 2',
2641
                        'Order.type' => 'ttt'
2642
                );
2643
                $expanded = Hash::expand($data);
2644
                $flattened = Hash::flatten($expanded);
2645
                $this->assertEquals($data, $flattened);
2646
        }
2647

    
2648
}