Subversion Repositories SmartDukaan

Rev

Details | Last modification | View Log | RSS feed

Rev Author Line No. Line
15403 manish.sha 1
<?php
2
/**
3
 * ModelWriteTest file
4
 *
5
 * CakePHP(tm) Tests <http://book.cakephp.org/2.0/en/development/testing.html>
6
 * Copyright (c) Cake Software Foundation, Inc. (http://cakefoundation.org)
7
 *
8
 * Licensed under The MIT License
9
 * For full copyright and license information, please see the LICENSE.txt
10
 * Redistributions of files must retain the above copyright notice
11
 *
12
 * @copyright     Copyright (c) Cake Software Foundation, Inc. (http://cakefoundation.org)
13
 * @link          http://book.cakephp.org/2.0/en/development/testing.html CakePHP(tm) Tests
14
 * @package       Cake.Test.Case.Model
15
 * @since         CakePHP(tm) v 1.2.0.4206
16
 * @license       http://www.opensource.org/licenses/mit-license.php MIT License
17
 */
18
 
19
App::uses('MockTransactionDboSource', 'Model/Datasource');
20
App::uses('MockTransactionAssociatedDboSource', 'Model/Datasource');
21
App::uses('MockManyTransactionDboSource', 'Model/Datasource');
22
App::uses('MockAssociatedTransactionDboSource', 'Model/Datasource');
23
 
24
require_once dirname(__FILE__) . DS . 'ModelTestBase.php';
25
 
26
/**
27
 * Helper class for testing with mocked datasources
28
 */
29
class TestAuthor extends Author {
30
 
31
	public $hasMany = array(
32
		'Post' => array(
33
			'className' => 'TestPost'
34
		)
35
	);
36
 
37
	protected $_dataSourceObject;
38
 
39
	public $dataForAfterSave;
40
 
41
/**
42
 * Helper method to set a datasource object
43
 *
44
 * @param Object $object The datasource object
45
 * @return void
46
 */
47
	public function setDataSourceObject($object) {
48
		$this->_dataSourceObject = $object;
49
	}
50
 
51
/**
52
 * Overwritten in order to return the directly set datasource object if
53
 * available
54
 *
55
 * @return DataSource
56
 */
57
	public function getDataSource() {
58
		if ($this->_dataSourceObject !== null) {
59
			return $this->_dataSourceObject;
60
		}
61
		return parent::getDataSource();
62
	}
63
 
64
}
65
 
66
/**
67
 * Helper class for testing with mocked datasources
68
 */
69
class TestPost extends Post {
70
 
71
	public $belongsTo = array(
72
		'Author' => array(
73
			'className' => 'TestAuthor'
74
		)
75
	);
76
 
77
	protected $_dataSourceObject;
78
 
79
	public $dataForAfterSave;
80
 
81
/**
82
 * Helper method to set a datasource object
83
 *
84
 * @param Object $object The datasource object
85
 * @return void
86
 */
87
	public function setDataSourceObject($object) {
88
		$this->_dataSourceObject = $object;
89
	}
90
 
91
/**
92
 * Overwritten in order to return the directly set datasource object if
93
 * available
94
 *
95
 * @return DataSource
96
 */
97
	public function getDataSource() {
98
		if ($this->_dataSourceObject !== null) {
99
			return $this->_dataSourceObject;
100
		}
101
		return parent::getDataSource();
102
	}
103
 
104
}
105
 
106
/**
107
 * ModelWriteTest
108
 *
109
 * @package       Cake.Test.Case.Model
110
 */
111
class ModelWriteTest extends BaseModelTest {
112
 
113
/**
114
 * override locale to the default (eng).
115
 *
116
 * @return void
117
 */
118
	public function setUp() {
119
		parent::setUp();
120
		Configure::write('Config.language', 'eng');
121
	}
122
 
123
/**
124
 * Test save() failing when there is no data.
125
 *
126
 * @return void
127
 */
128
	public function testInsertNoData() {
129
		$this->loadFixtures('Bid');
130
		$Bid = ClassRegistry::init('Bid');
131
 
132
		$this->assertFalse($Bid->save());
133
 
134
		$result = $Bid->save(array('Bid' => array()));
135
		$this->assertFalse($result);
136
 
137
		$result = $Bid->save(array('Bid' => array('not in schema' => 1)));
138
		$this->assertFalse($result);
139
	}
140
 
141
/**
142
 * testInsertAnotherHabtmRecordWithSameForeignKey method
143
 *
144
 * @return void
145
 */
146
	public function testInsertAnotherHabtmRecordWithSameForeignKey() {
147
		$this->loadFixtures('JoinA', 'JoinB', 'JoinAB', 'JoinC', 'JoinAC');
148
		$TestModel = new JoinA();
149
 
150
		$result = $TestModel->JoinAsJoinB->findById(1);
151
		$expected = array(
152
			'JoinAsJoinB' => array(
153
				'id' => 1,
154
				'join_a_id' => 1,
155
				'join_b_id' => 2,
156
				'other' => 'Data for Join A 1 Join B 2',
157
				'created' => '2008-01-03 10:56:33',
158
				'updated' => '2008-01-03 10:56:33'
159
		));
160
		$this->assertEquals($expected, $result);
161
 
162
		$TestModel->JoinAsJoinB->create();
163
		$data = array(
164
			'join_a_id' => 1,
165
			'join_b_id' => 1,
166
			'other' => 'Data for Join A 1 Join B 1',
167
			'created' => '2008-01-03 10:56:44',
168
			'updated' => '2008-01-03 10:56:44'
169
		);
170
		$result = $TestModel->JoinAsJoinB->save($data);
171
		$lastInsertId = $TestModel->JoinAsJoinB->getLastInsertID();
172
		$data['id'] = $lastInsertId;
173
		$this->assertEquals(array('JoinAsJoinB' => $data), $result);
174
		$this->assertTrue($lastInsertId > 0);
175
 
176
		$result = $TestModel->JoinAsJoinB->findById(1);
177
		$expected = array(
178
			'JoinAsJoinB' => array(
179
				'id' => 1,
180
				'join_a_id' => 1,
181
				'join_b_id' => 2,
182
				'other' => 'Data for Join A 1 Join B 2',
183
				'created' => '2008-01-03 10:56:33',
184
				'updated' => '2008-01-03 10:56:33'
185
		));
186
		$this->assertEquals($expected, $result);
187
 
188
		$updatedValue = 'UPDATED Data for Join A 1 Join B 2';
189
		$TestModel->JoinAsJoinB->id = 1;
190
		$result = $TestModel->JoinAsJoinB->saveField('other', $updatedValue, false);
191
		$this->assertFalse(empty($result));
192
 
193
		$result = $TestModel->JoinAsJoinB->findById(1);
194
		$this->assertEquals($updatedValue, $result['JoinAsJoinB']['other']);
195
	}
196
 
197
/**
198
 * testSaveDateAsFirstEntry method
199
 *
200
 * @return void
201
 */
202
	public function testSaveDateAsFirstEntry() {
203
		$this->loadFixtures('Article', 'User', 'Comment', 'Attachment', 'Tag', 'ArticlesTag');
204
 
205
		$Article = new Article();
206
 
207
		$data = array(
208
			'Article' => array(
209
				'created' => array(
210
					'day' => '1',
211
					'month' => '1',
212
					'year' => '2008'
213
				),
214
				'title' => 'Test Title',
215
				'user_id' => 1
216
		));
217
		$Article->create();
218
		$result = $Article->save($data);
219
		$this->assertFalse(empty($result));
220
 
221
		$testResult = $Article->find('first', array('conditions' => array('Article.title' => 'Test Title')));
222
 
223
		$this->assertEquals($data['Article']['title'], $testResult['Article']['title']);
224
		$this->assertEquals('2008-01-01 00:00:00', $testResult['Article']['created']);
225
	}
226
 
227
/**
228
 * testUnderscoreFieldSave method
229
 *
230
 * @return void
231
 */
232
	public function testUnderscoreFieldSave() {
233
		$this->loadFixtures('UnderscoreField');
234
		$UnderscoreField = new UnderscoreField();
235
 
236
		$currentCount = $UnderscoreField->find('count');
237
		$this->assertEquals(3, $currentCount);
238
		$data = array('UnderscoreField' => array(
239
			'user_id' => '1',
240
			'my_model_has_a_field' => 'Content here',
241
			'body' => 'Body',
242
			'published' => 'Y',
243
			'another_field' => 4
244
		));
245
		$ret = $UnderscoreField->save($data);
246
		$this->assertFalse(empty($ret));
247
 
248
		$currentCount = $UnderscoreField->find('count');
249
		$this->assertEquals(4, $currentCount);
250
	}
251
 
252
/**
253
 * testAutoSaveUuid method
254
 *
255
 * @return void
256
 */
257
	public function testAutoSaveUuid() {
258
		// SQLite does not support non-integer primary keys
259
		$this->skipIf($this->db instanceof Sqlite, 'This test is not compatible with SQLite.');
260
 
261
		$this->loadFixtures('Uuid');
262
		$TestModel = new Uuid();
263
 
264
		$TestModel->save(array('title' => 'Test record'));
265
		$result = $TestModel->findByTitle('Test record');
266
		$this->assertEquals(
267
			array('id', 'title', 'count', 'created', 'updated'),
268
			array_keys($result['Uuid'])
269
		);
270
		$this->assertEquals(36, strlen($result['Uuid']['id']));
271
	}
272
 
273
/**
274
 * Ensure that if the id key is null but present the save doesn't fail (with an
275
 * x sql error: "Column id specified twice")
276
 *
277
 * @return void
278
 */
279
	public function testSaveUuidNull() {
280
		// SQLite does not support non-integer primary keys
281
		$this->skipIf($this->db instanceof Sqlite, 'This test is not compatible with SQLite.');
282
 
283
		$this->loadFixtures('Uuid');
284
		$TestModel = new Uuid();
285
 
286
		$TestModel->save(array('title' => 'Test record', 'id' => null));
287
		$result = $TestModel->findByTitle('Test record');
288
		$this->assertEquals(
289
			array('id', 'title', 'count', 'created', 'updated'),
290
			array_keys($result['Uuid'])
291
		);
292
		$this->assertEquals(36, strlen($result['Uuid']['id']));
293
	}
294
 
295
/**
296
 * testZeroDefaultFieldValue method
297
 *
298
 * @return void
299
 */
300
	public function testZeroDefaultFieldValue() {
301
		$this->skipIf($this->db instanceof Sqlite, 'SQLite uses loose typing, this operation is unsupported.');
302
 
303
		$this->loadFixtures('DataTest');
304
		$TestModel = new DataTest();
305
 
306
		$TestModel->create(array());
307
		$TestModel->save();
308
		$result = $TestModel->findById($TestModel->id);
309
		$this->assertEquals(0, $result['DataTest']['count']);
310
		$this->assertEquals(0, $result['DataTest']['float']);
311
	}
312
 
313
/**
314
 * Tests validation parameter order in custom validation methods
315
 *
316
 * @return void
317
 */
318
	public function testAllowSimulatedFields() {
319
		$TestModel = new ValidationTest1();
320
 
321
		$TestModel->create(array(
322
			'title' => 'foo',
323
			'bar' => 'baz'
324
		));
325
		$expected = array(
326
			'ValidationTest1' => array(
327
				'title' => 'foo',
328
				'bar' => 'baz'
329
		));
330
		$this->assertEquals($expected, $TestModel->data);
331
	}
332
 
333
/**
334
 * test that Caches are getting cleared on save().
335
 * ensure that both inflections of controller names are getting cleared
336
 * as URL for controller could be either overallFavorites/index or overall_favorites/index
337
 *
338
 * @return void
339
 */
340
	public function testCacheClearOnSave() {
341
		$_back = array(
342
			'check' => Configure::read('Cache.check'),
343
			'disable' => Configure::read('Cache.disable'),
344
		);
345
		Configure::write('Cache.check', true);
346
		Configure::write('Cache.disable', false);
347
 
348
		$this->loadFixtures('OverallFavorite');
349
		$OverallFavorite = new OverallFavorite();
350
 
351
		touch(CACHE . 'views' . DS . 'some_dir_overallfavorites_index.php');
352
		touch(CACHE . 'views' . DS . 'some_dir_overall_favorites_index.php');
353
 
354
		$data = array(
355
			'OverallFavorite' => array(
356
				'id' => 22,
357
				'model_type' => '8-track',
358
				'model_id' => '3',
359
				'priority' => '1'
360
			)
361
		);
362
		$OverallFavorite->create($data);
363
		$OverallFavorite->save();
364
 
365
		$this->assertFalse(file_exists(CACHE . 'views' . DS . 'some_dir_overallfavorites_index.php'));
366
		$this->assertFalse(file_exists(CACHE . 'views' . DS . 'some_dir_overall_favorites_index.php'));
367
 
368
		Configure::write('Cache.check', $_back['check']);
369
		Configure::write('Cache.disable', $_back['disable']);
370
	}
371
 
372
/**
373
 * test that save() resets whitelist on failed save
374
 *
375
 * @return void
376
 */
377
	public function testSaveFieldListResetsWhitelistOnFailedSave() {
378
		$this->loadFixtures('Bidding');
379
		$model = new Bidding();
380
		$whitelist = array('title');
381
		$model->whitelist = $whitelist;
382
		$result = $model->save(
383
			array(),
384
			array('fieldList' => array('body'))
385
		);
386
		$this->assertFalse($result);
387
		$this->assertEquals($whitelist, $model->whitelist);
388
	}
389
 
390
/**
391
 * Test save() resets the whitelist after afterSave
392
 *
393
 * @return void
394
 */
395
	public function testSaveResetWhitelistOnSuccess() {
396
		$this->loadFixtures('Post');
397
 
398
		$callback = array($this, 'callbackForWhitelistReset');
399
		$model = ClassRegistry::init('Post');
400
		$model->whitelist = array('author_id', 'title', 'body');
401
		$model->getEventManager()->attach($callback, 'Model.afterSave');
402
		$data = array(
403
			'title' => 'New post',
404
			'body' => 'Post body',
405
			'author_id' => 1
406
		);
407
		$result = $model->save($data);
408
		$this->assertNotEmpty($result);
409
	}
410
 
411
/**
412
 * Callback for testing whitelist in afterSave
413
 *
414
 * @param Model $model The model having save called.
415
 * @return void
416
 */
417
	public function callbackForWhitelistReset($event) {
418
		$expected = array('author_id', 'title', 'body', 'updated', 'created');
419
		$this->assertEquals($expected, $event->subject()->whitelist);
420
	}
421
 
422
/**
423
 * testSaveWithCounterCache method
424
 *
425
 * @return void
426
 */
427
	public function testSaveWithCounterCache() {
428
		$this->loadFixtures('Syfile', 'Item', 'Image', 'Portfolio', 'ItemsPortfolio');
429
		$TestModel = new Syfile();
430
		$TestModel2 = new Item();
431
 
432
		$result = $TestModel->findById(1);
433
		$this->assertNull($result['Syfile']['item_count']);
434
 
435
		$TestModel2->save(array(
436
			'name' => 'Item 7',
437
			'syfile_id' => 1,
438
			'published' => false
439
		));
440
 
441
		$result = $TestModel->findById(1);
442
		$this->assertEquals(2, $result['Syfile']['item_count']);
443
 
444
		$TestModel2->delete(1);
445
		$result = $TestModel->findById(1);
446
		$this->assertEquals(1, $result['Syfile']['item_count']);
447
 
448
		$TestModel2->id = 2;
449
		$TestModel2->saveField('syfile_id', 1);
450
 
451
		$result = $TestModel->findById(1);
452
		$this->assertEquals(2, $result['Syfile']['item_count']);
453
 
454
		$result = $TestModel->findById(2);
455
		$this->assertEquals(0, $result['Syfile']['item_count']);
456
	}
457
 
458
/**
459
 * Tests that counter caches are updated when records are added
460
 *
461
 * @return void
462
 */
463
	public function testCounterCacheIncrease() {
464
		$this->loadFixtures('CounterCacheUser', 'CounterCachePost');
465
		$User = new CounterCacheUser();
466
		$Post = new CounterCachePost();
467
		$data = array('Post' => array(
468
			'id' => 22,
469
			'title' => 'New Post',
470
			'user_id' => 66
471
		));
472
 
473
		$Post->save($data);
474
		$user = $User->find('first', array(
475
			'conditions' => array('id' => 66),
476
			'recursive' => -1
477
		));
478
 
479
		$result = $user[$User->alias]['post_count'];
480
		$expected = 3;
481
		$this->assertEquals($expected, $result);
482
	}
483
 
484
/**
485
 * Tests that counter caches are updated when records are deleted
486
 *
487
 * @return void
488
 */
489
	public function testCounterCacheDecrease() {
490
		$this->loadFixtures('CounterCacheUser', 'CounterCachePost');
491
		$User = new CounterCacheUser();
492
		$Post = new CounterCachePost();
493
 
494
		$Post->delete(2);
495
		$user = $User->find('first', array(
496
			'conditions' => array('id' => 66),
497
			'recursive' => -1
498
		));
499
 
500
		$result = $user[$User->alias]['post_count'];
501
		$expected = 1;
502
		$this->assertEquals($expected, $result);
503
	}
504
 
505
/**
506
 * Tests that counter caches are updated when foreign keys of counted records change
507
 *
508
 * @return void
509
 */
510
	public function testCounterCacheUpdated() {
511
		$this->loadFixtures('CounterCacheUser', 'CounterCachePost');
512
		$User = new CounterCacheUser();
513
		$Post = new CounterCachePost();
514
 
515
		$data = $Post->find('first', array(
516
			'conditions' => array('id' => 1),
517
			'recursive' => -1
518
		));
519
		$data[$Post->alias]['user_id'] = 301;
520
		$Post->save($data);
521
 
522
		$users = $User->find('all', array('order' => 'User.id'));
523
		$this->assertEquals(1, $users[0]['User']['post_count']);
524
		$this->assertEquals(2, $users[1]['User']['post_count']);
525
	}
526
 
527
/**
528
 * Test counter cache with models that use a non-standard (i.e. not using 'id')
529
 * as their primary key.
530
 *
531
 * @return void
532
 */
533
	public function testCounterCacheWithNonstandardPrimaryKey() {
534
		$this->loadFixtures(
535
			'CounterCacheUserNonstandardPrimaryKey',
536
			'CounterCachePostNonstandardPrimaryKey'
537
		);
538
 
539
		$User = new CounterCacheUserNonstandardPrimaryKey();
540
		$Post = new CounterCachePostNonstandardPrimaryKey();
541
 
542
		$data = $Post->find('first', array(
543
			'conditions' => array('pid' => 1),
544
			'recursive' => -1
545
		));
546
		$data[$Post->alias]['uid'] = 301;
547
		$Post->save($data);
548
 
549
		$users = $User->find('all', array('order' => 'User.uid'));
550
		$this->assertEquals(1, $users[0]['User']['post_count']);
551
		$this->assertEquals(2, $users[1]['User']['post_count']);
552
	}
553
 
554
/**
555
 * test Counter Cache With Self Joining table
556
 *
557
 * @return void
558
 */
559
	public function testCounterCacheWithSelfJoin() {
560
		$this->skipIf($this->db instanceof Sqlite, 'SQLite 2.x does not support ALTER TABLE ADD COLUMN');
561
 
562
		$this->loadFixtures('CategoryThread');
563
		$column = 'COLUMN ';
564
		if ($this->db instanceof Sqlserver) {
565
			$column = '';
566
		}
567
		$column .= $this->db->buildColumn(array('name' => 'child_count', 'type' => 'integer'));
568
		$this->db->query('ALTER TABLE ' . $this->db->fullTableName('category_threads') . ' ADD ' . $column);
569
		$this->db->flushMethodCache();
570
		$Category = new CategoryThread();
571
		$result = $Category->updateAll(array('CategoryThread.name' => "'updated'"), array('CategoryThread.parent_id' => 5));
572
		$this->assertFalse(empty($result));
573
 
574
		$Category = new CategoryThread();
575
		$Category->belongsTo['ParentCategory']['counterCache'] = 'child_count';
576
		$Category->updateCounterCache(array('parent_id' => 5));
577
		$result = Hash::extract($Category->find('all', array('conditions' => array('CategoryThread.id' => 5))), '{n}.CategoryThread.child_count');
578
		$expected = array(1);
579
		$this->assertEquals($expected, $result);
580
	}
581
 
582
/**
583
 * testSaveWithCounterCacheScope method
584
 *
585
 * @return void
586
 */
587
	public function testSaveWithCounterCacheScope() {
588
		$this->loadFixtures('Syfile', 'Item', 'Image', 'ItemsPortfolio', 'Portfolio');
589
		$TestModel = new Syfile();
590
		$TestModel2 = new Item();
591
		$TestModel2->belongsTo['Syfile']['counterCache'] = true;
592
		$TestModel2->belongsTo['Syfile']['counterScope'] = array('published' => true);
593
 
594
		$result = $TestModel->findById(1);
595
		$this->assertNull($result['Syfile']['item_count']);
596
 
597
		$TestModel2->save(array(
598
			'name' => 'Item 7',
599
			'syfile_id' => 1,
600
			'published' => true
601
		));
602
 
603
		$result = $TestModel->findById(1);
604
 
605
		$this->assertEquals(1, $result['Syfile']['item_count']);
606
 
607
		$TestModel2->id = 1;
608
		$TestModel2->saveField('published', true);
609
		$result = $TestModel->findById(1);
610
		$this->assertEquals(2, $result['Syfile']['item_count']);
611
 
612
		$TestModel2->save(array(
613
			'id' => 1,
614
			'syfile_id' => 1,
615
			'published' => false
616
		));
617
 
618
		$result = $TestModel->findById(1);
619
		$this->assertEquals(1, $result['Syfile']['item_count']);
620
	}
621
 
622
/**
623
 * Tests having multiple counter caches for an associated model
624
 *
625
 * @return void
626
 */
627
	public function testCounterCacheMultipleCaches() {
628
		$this->loadFixtures('CounterCacheUser', 'CounterCachePost');
629
		$User = new CounterCacheUser();
630
		$Post = new CounterCachePost();
631
		$Post->unbindModel(array('belongsTo' => array('User')), false);
632
		$Post->bindModel(array(
633
			'belongsTo' => array(
634
				'User' => array(
635
					'className' => 'CounterCacheUser',
636
					'foreignKey' => 'user_id',
637
					'counterCache' => array(
638
						true,
639
						'posts_published' => array('Post.published' => true)
640
					)
641
				)
642
			)
643
		), false);
644
 
645
		// Count Increase
646
		$data = array('Post' => array(
647
			'id' => 22,
648
			'title' => 'New Post',
649
			'user_id' => 66,
650
			'published' => true
651
		));
652
		$Post->save($data);
653
		$result = $User->find('first', array(
654
			'conditions' => array('id' => 66),
655
			'recursive' => -1
656
		));
657
		$this->assertEquals(3, $result[$User->alias]['post_count']);
658
		$this->assertEquals(2, $result[$User->alias]['posts_published']);
659
 
660
		// Count decrease
661
		$Post->delete(1);
662
		$result = $User->find('first', array(
663
			'conditions' => array('id' => 66),
664
			'recursive' => -1
665
		));
666
		$this->assertEquals(2, $result[$User->alias]['post_count']);
667
		$this->assertEquals(2, $result[$User->alias]['posts_published']);
668
 
669
		// Count update
670
		$data = $Post->find('first', array(
671
			'conditions' => array('id' => 1),
672
			'recursive' => -1
673
		));
674
		$data[$Post->alias]['user_id'] = 301;
675
		$Post->save($data);
676
		$result = $User->find('all', array('order' => 'User.id'));
677
		$this->assertEquals(2, $result[0]['User']['post_count']);
678
		$this->assertEquals(1, $result[1]['User']['posts_published']);
679
	}
680
 
681
/**
682
 * Tests that counter caches are unchanged when using 'counterCache' => false
683
 *
684
 * @return void
685
 */
686
	public function testCounterCacheSkip() {
687
		$this->loadFixtures('CounterCacheUser', 'CounterCachePost');
688
		$User = new CounterCacheUser();
689
		$Post = new CounterCachePost();
690
 
691
		$data = $Post->find('first', array(
692
			'conditions' => array('id' => 1),
693
			'recursive' => -1
694
		));
695
		$data[$Post->alias]['user_id'] = 301;
696
		$Post->save($data, array('counterCache' => false));
697
 
698
		$users = $User->find('all', array('order' => 'User.id'));
699
		$this->assertEquals(2, $users[0]['User']['post_count']);
700
		$this->assertEquals(1, $users[1]['User']['post_count']);
701
	}
702
 
703
/**
704
 * test that beforeValidate returning false can abort saves.
705
 *
706
 * @return void
707
 */
708
	public function testBeforeValidateSaveAbortion() {
709
		$this->loadFixtures('Post');
710
		$Model = new CallbackPostTestModel();
711
		$Model->beforeValidateReturn = false;
712
 
713
		$data = array(
714
			'title' => 'new article',
715
			'body' => 'this is some text.'
716
		);
717
		$Model->create();
718
		$result = $Model->save($data);
719
		$this->assertFalse($result);
720
	}
721
 
722
/**
723
 * test that beforeSave returning false can abort saves.
724
 *
725
 * @return void
726
 */
727
	public function testBeforeSaveSaveAbortion() {
728
		$this->loadFixtures('Post');
729
		$Model = new CallbackPostTestModel();
730
		$Model->beforeSaveReturn = false;
731
 
732
		$data = array(
733
			'title' => 'new article',
734
			'body' => 'this is some text.'
735
		);
736
		$Model->create();
737
		$result = $Model->save($data);
738
		$this->assertFalse($result);
739
	}
740
 
741
/**
742
 * testSaveAtomic method
743
 *
744
 * @return void
745
 */
746
	public function testSaveAtomic() {
747
		$this->loadFixtures('Article');
748
		$TestModel = new Article();
749
 
750
		// Create record with 'atomic' = false
751
 
752
		$data = array(
753
			'Article' => array(
754
				'user_id' => '1',
755
				'title' => 'Fourth Article',
756
				'body' => 'Fourth Article Body',
757
				'published' => 'Y'
758
			)
759
		);
760
		$TestModel->create();
761
		$result = $TestModel->save($data, array('atomic' => false));
762
		$this->assertTrue((bool)$result);
763
 
764
		// Check record we created
765
 
766
		$TestModel->recursive = -1;
767
		$result = $TestModel->read(array('id', 'user_id', 'title', 'body', 'published'), 4);
768
		$expected = array(
769
			'Article' => array(
770
				'id' => '4',
771
				'user_id' => '1',
772
				'title' => 'Fourth Article',
773
				'body' => 'Fourth Article Body',
774
				'published' => 'Y'
775
			)
776
		);
777
		$this->assertEquals($expected, $result);
778
 
779
		// Create record with 'atomic' = true
780
 
781
		$data = array(
782
			'Article' => array(
783
				'user_id' => '4',
784
				'title' => 'Fifth Article',
785
				'body' => 'Fifth Article Body',
786
				'published' => 'Y'
787
			)
788
		);
789
		$TestModel->create();
790
		$result = $TestModel->save($data, array('atomic' => true));
791
		$this->assertTrue((bool)$result);
792
 
793
		// Check record we created
794
 
795
		$TestModel->recursive = -1;
796
		$result = $TestModel->read(array('id', 'user_id', 'title', 'body', 'published'), 5);
797
		$expected = array(
798
			'Article' => array(
799
				'id' => '5',
800
				'user_id' => '4',
801
				'title' => 'Fifth Article',
802
				'body' => 'Fifth Article Body',
803
				'published' => 'Y'
804
			)
805
		);
806
		$this->assertEquals($expected, $result);
807
	}
808
 
809
/**
810
 * test save with transaction and ensure there is no missing rollback.
811
 *
812
 * @return void
813
 */
814
	public function testSaveTransactionNoRollback() {
815
		$this->loadFixtures('Post', 'Article');
816
 
817
		$db = $this->getMock('DboSource', array('begin', 'connect', 'rollback', 'describe'));
818
 
819
		$db->expects($this->once())
820
			->method('describe')
821
			->will($this->returnValue(array()));
822
		$db->expects($this->once())
823
			->method('begin')
824
			->will($this->returnValue(true));
825
		$db->expects($this->once())
826
			->method('rollback');
827
 
828
		$Post = new TestPost();
829
		$Post->setDataSourceObject($db);
830
 
831
		$callback = array($this, 'callbackForTestSaveTransaction');
832
		$Post->getEventManager()->attach($callback, 'Model.beforeSave');
833
 
834
		$data = array(
835
			'Post' => array(
836
				'author_id' => 1,
837
				'title' => 'New Fourth Post'
838
			)
839
		);
840
		$Post->save($data, array('atomic' => true));
841
	}
842
 
843
/**
844
 * test callback used in testSaveTransaction method
845
 *
846
 * @return bool false to stop event propagation
847
 */
848
	public function callbackForTestSaveTransaction($event) {
849
		$TestModel = new Article();
850
 
851
		// Create record. Do not use same model as in testSaveTransaction
852
		// to avoid infinite loop.
853
 
854
		$data = array(
855
			'Article' => array(
856
				'user_id' => '1',
857
				'title' => 'Fourth Article',
858
				'body' => 'Fourth Article Body',
859
				'published' => 'Y'
860
			)
861
		);
862
		$TestModel->create();
863
		$result = $TestModel->save($data);
864
		$this->assertTrue((bool)$result);
865
 
866
		// force transaction to be rolled back in Post model
867
		$event->stopPropagation();
868
		return false;
869
	}
870
 
871
/**
872
 * testSaveTransaction method
873
 *
874
 * @return void
875
 */
876
	public function testSaveTransaction() {
877
		$this->loadFixtures('Post', 'Article');
878
		$PostModel = new Post();
879
 
880
		// Check if Database supports transactions
881
 
882
		$PostModel->validate = array('title' => 'notEmpty');
883
		$data = array(
884
			array('author_id' => 1, 'title' => 'New Fourth Post'),
885
			array('author_id' => 1, 'title' => 'New Fifth Post'),
886
			array('author_id' => 1, 'title' => '')
887
		);
888
		$this->assertFalse($PostModel->saveAll($data));
889
 
890
		$result = $PostModel->find('all', array('recursive' => -1));
891
		$expectedPosts = array(
892
			array(
893
				'Post' => array(
894
					'id' => '1',
895
					'author_id' => 1,
896
					'title' => 'First Post',
897
					'body' => 'First Post Body',
898
					'published' => 'Y',
899
					'created' => '2007-03-18 10:39:23',
900
					'updated' => '2007-03-18 10:41:31'
901
				)
902
			),
903
			array(
904
				'Post' => array(
905
					'id' => '2',
906
					'author_id' => 3,
907
					'title' => 'Second Post',
908
					'body' => 'Second Post Body',
909
					'published' => 'Y',
910
					'created' => '2007-03-18 10:41:23',
911
					'updated' => '2007-03-18 10:43:31'
912
				)
913
			),
914
			array(
915
				'Post' => array(
916
					'id' => '3',
917
					'author_id' => 1,
918
					'title' => 'Third Post',
919
					'body' => 'Third Post Body',
920
					'published' => 'Y',
921
					'created' => '2007-03-18 10:43:23',
922
					'updated' => '2007-03-18 10:45:31'
923
				)
924
			)
925
		);
926
 
927
		$this->skipIf(count($result) !== 3, 'Database does not support transactions.');
928
 
929
		$this->assertEquals($expectedPosts, $result);
930
 
931
		// Database supports transactions --> continue tests
932
 
933
		$data = array(
934
			'Post' => array(
935
				'author_id' => 1,
936
				'title' => 'New Fourth Post'
937
			)
938
		);
939
 
940
		$callback = array($this, 'callbackForTestSaveTransaction');
941
		$PostModel->getEventManager()->attach($callback, 'Model.beforeSave');
942
 
943
		$PostModel->create();
944
		$result = $PostModel->save($data, array('atomic' => true));
945
		$this->assertFalse($result);
946
 
947
		$result = $PostModel->find('all', array('recursive' => -1));
948
		$this->assertEquals($expectedPosts, $result);
949
 
950
		// Check record we created in callbackForTestSaveTransaction method.
951
		// record should not exist due to rollback
952
 
953
		$ArticleModel = new Article();
954
		$result = $ArticleModel->find('all', array('recursive' => -1));
955
		$expectedArticles = array(
956
			array(
957
				'Article' => array(
958
					'user_id' => '1',
959
					'title' => 'First Article',
960
					'body' => 'First Article Body',
961
					'published' => 'Y',
962
					'created' => '2007-03-18 10:39:23',
963
					'updated' => '2007-03-18 10:41:31',
964
					'id' => '1'
965
				)
966
			),
967
			array(
968
				'Article' => array(
969
					'user_id' => '3',
970
					'title' => 'Second Article',
971
					'body' => 'Second Article Body',
972
					'published' => 'Y',
973
					'created' => '2007-03-18 10:41:23',
974
					'updated' => '2007-03-18 10:43:31',
975
					'id' => '2'
976
				)
977
			),
978
			array(
979
				'Article' => array(
980
					'user_id' => '1',
981
					'title' => 'Third Article',
982
					'body' => 'Third Article Body',
983
					'published' => 'Y',
984
					'created' => '2007-03-18 10:43:23',
985
					'updated' => '2007-03-18 10:45:31',
986
					'id' => '3'
987
				)
988
			)
989
		);
990
		$this->assertEquals($expectedArticles, $result);
991
	}
992
 
993
/**
994
 * testSaveField method
995
 *
996
 * @return void
997
 */
998
	public function testSaveField() {
999
		$this->loadFixtures('Article');
1000
		$TestModel = new Article();
1001
 
1002
		$TestModel->id = 1;
1003
		$result = $TestModel->saveField('title', 'New First Article');
1004
		$this->assertFalse(empty($result));
1005
 
1006
		$TestModel->recursive = -1;
1007
		$result = $TestModel->read(array('id', 'user_id', 'title', 'body'), 1);
1008
		$expected = array('Article' => array(
1009
			'id' => '1',
1010
			'user_id' => '1',
1011
			'title' => 'New First Article',
1012
			'body' => 'First Article Body'
1013
		));
1014
		$this->assertEquals($expected, $result);
1015
 
1016
		$TestModel->id = 1;
1017
		$result = $TestModel->saveField('title', '');
1018
		$this->assertFalse(empty($result));
1019
 
1020
		$TestModel->recursive = -1;
1021
		$result = $TestModel->read(array('id', 'user_id', 'title', 'body'), 1);
1022
		$expected = array('Article' => array(
1023
			'id' => '1',
1024
			'user_id' => '1',
1025
			'title' => '',
1026
			'body' => 'First Article Body'
1027
		));
1028
		$result['Article']['title'] = trim($result['Article']['title']);
1029
		$this->assertEquals($expected, $result);
1030
 
1031
		$TestModel->id = 1;
1032
		$TestModel->set('body', 'Messed up data');
1033
		$result = $TestModel->saveField('title', 'First Article');
1034
		$this->assertFalse(empty($result));
1035
		$result = $TestModel->read(array('id', 'user_id', 'title', 'body'), 1);
1036
		$expected = array('Article' => array(
1037
			'id' => '1',
1038
			'user_id' => '1',
1039
			'title' => 'First Article',
1040
			'body' => 'First Article Body'
1041
		));
1042
		$this->assertEquals($expected, $result);
1043
 
1044
		$TestModel->recursive = -1;
1045
		$TestModel->read(array('id', 'user_id', 'title', 'body'), 1);
1046
 
1047
		$TestModel->id = 1;
1048
		$result = $TestModel->saveField('title', '', true);
1049
		$this->assertFalse($result);
1050
 
1051
		$TestModel->recursive = -1;
1052
		$TestModel->id = 1;
1053
		$result = $TestModel->saveField('user_id', 9999);
1054
		$this->assertTrue((bool)$result);
1055
 
1056
		$result = $TestModel->read(array('id', 'user_id'), 1);
1057
		$expected = array('Article' => array(
1058
			'id' => '1',
1059
			'user_id' => '9999',
1060
		));
1061
		$this->assertEquals($expected, $result);
1062
 
1063
		$this->loadFixtures('Node', 'Dependency');
1064
		$Node = new Node();
1065
		$Node->set('id', 1);
1066
		$result = $Node->read();
1067
		$this->assertEquals(array('Second'), Hash::extract($result, 'ParentNode.{n}.name'));
1068
 
1069
		$Node->saveField('state', 10);
1070
		$result = $Node->read();
1071
		$this->assertEquals(array('Second'), Hash::extract($result, 'ParentNode.{n}.name'));
1072
	}
1073
 
1074
/**
1075
 * testSaveWithCreate method
1076
 *
1077
 * @return void
1078
 */
1079
	public function testSaveWithCreate() {
1080
		$this->loadFixtures(
1081
			'User',
1082
			'Article',
1083
			'User',
1084
			'Comment',
1085
			'Tag',
1086
			'ArticlesTag',
1087
			'Attachment'
1088
		);
1089
		$TestModel = new User();
1090
 
1091
		$data = array('User' => array(
1092
			'user' => 'user',
1093
			'password' => ''
1094
		));
1095
		$result = $TestModel->save($data);
1096
		$this->assertFalse($result);
1097
		$this->assertTrue(!empty($TestModel->validationErrors));
1098
 
1099
		$TestModel = new Article();
1100
 
1101
		$data = array('Article' => array(
1102
			'user_id' => '',
1103
			'title' => '',
1104
			'body' => ''
1105
		));
1106
		$result = $TestModel->create($data) && $TestModel->save();
1107
		$this->assertFalse($result);
1108
		$this->assertTrue(!empty($TestModel->validationErrors));
1109
 
1110
		$data = array('Article' => array(
1111
			'id' => 1,
1112
			'user_id' => '1',
1113
			'title' => 'New First Article',
1114
			'body' => ''
1115
		));
1116
		$result = $TestModel->create($data) && $TestModel->save();
1117
		$this->assertFalse($result);
1118
 
1119
		$data = array('Article' => array(
1120
			'id' => 1,
1121
			'title' => 'New First Article'
1122
		));
1123
		$result = $TestModel->create() && $TestModel->save($data, false);
1124
		$this->assertFalse(empty($result));
1125
 
1126
		$TestModel->recursive = -1;
1127
		$result = $TestModel->read(array('id', 'user_id', 'title', 'body', 'published'), 1);
1128
		$expected = array('Article' => array(
1129
			'id' => '1',
1130
			'user_id' => '1',
1131
			'title' => 'New First Article',
1132
			'body' => 'First Article Body',
1133
			'published' => 'N'
1134
		));
1135
		$this->assertEquals($expected, $result);
1136
 
1137
		$data = array('Article' => array(
1138
			'id' => 1,
1139
			'user_id' => '2',
1140
			'title' => 'First Article',
1141
			'body' => 'New First Article Body',
1142
			'published' => 'Y'
1143
		));
1144
		$result = $TestModel->create() && $TestModel->save($data, true, array('id', 'title', 'published'));
1145
		$this->assertFalse(empty($result));
1146
 
1147
		$TestModel->recursive = -1;
1148
		$result = $TestModel->read(array('id', 'user_id', 'title', 'body', 'published'), 1);
1149
		$expected = array('Article' => array(
1150
			'id' => '1',
1151
			'user_id' => '1',
1152
			'title' => 'First Article',
1153
			'body' => 'First Article Body',
1154
			'published' => 'Y'
1155
		));
1156
		$this->assertEquals($expected, $result);
1157
 
1158
		$data = array(
1159
			'Article' => array(
1160
				'user_id' => '2',
1161
				'title' => 'New Article',
1162
				'body' => 'New Article Body',
1163
				'created' => '2007-03-18 14:55:23',
1164
				'updated' => '2007-03-18 14:57:31'
1165
			),
1166
			'Tag' => array('Tag' => array(1, 3))
1167
		);
1168
		$TestModel->create();
1169
		$result = $TestModel->create() && $TestModel->save($data);
1170
		$this->assertFalse(empty($result));
1171
 
1172
		$TestModel->recursive = 2;
1173
		$result = $TestModel->read(null, 4);
1174
		$expected = array(
1175
			'Article' => array(
1176
				'id' => '4',
1177
				'user_id' => '2',
1178
				'title' => 'New Article',
1179
				'body' => 'New Article Body',
1180
				'published' => 'N',
1181
				'created' => '2007-03-18 14:55:23',
1182
				'updated' => '2007-03-18 14:57:31'
1183
			),
1184
			'User' => array(
1185
				'id' => '2',
1186
				'user' => 'nate',
1187
				'password' => '5f4dcc3b5aa765d61d8327deb882cf99',
1188
				'created' => '2007-03-17 01:18:23',
1189
				'updated' => '2007-03-17 01:20:31'
1190
			),
1191
			'Comment' => array(),
1192
			'Tag' => array(
1193
				array(
1194
					'id' => '1',
1195
					'tag' => 'tag1',
1196
					'created' => '2007-03-18 12:22:23',
1197
					'updated' => '2007-03-18 12:24:31'
1198
				),
1199
				array(
1200
					'id' => '3',
1201
					'tag' => 'tag3',
1202
					'created' => '2007-03-18 12:26:23',
1203
					'updated' => '2007-03-18 12:28:31'
1204
		)));
1205
		$this->assertEquals($expected, $result);
1206
 
1207
		$data = array('Comment' => array(
1208
			'article_id' => '4',
1209
			'user_id' => '1',
1210
			'comment' => 'Comment New Article',
1211
			'published' => 'Y',
1212
			'created' => '2007-03-18 14:57:23',
1213
			'updated' => '2007-03-18 14:59:31'
1214
		));
1215
		$result = $TestModel->Comment->create() && $TestModel->Comment->save($data);
1216
		$this->assertFalse(empty($result));
1217
 
1218
		$data = array('Attachment' => array(
1219
			'comment_id' => '7',
1220
			'attachment' => 'newattachment.zip',
1221
			'created' => '2007-03-18 15:02:23',
1222
			'updated' => '2007-03-18 15:04:31'
1223
		));
1224
		$result = $TestModel->Comment->Attachment->save($data);
1225
		$this->assertFalse(empty($result));
1226
 
1227
		$TestModel->recursive = 2;
1228
		$result = $TestModel->read(null, 4);
1229
		$expected = array(
1230
			'Article' => array(
1231
				'id' => '4',
1232
				'user_id' => '2',
1233
				'title' => 'New Article',
1234
				'body' => 'New Article Body',
1235
				'published' => 'N',
1236
				'created' => '2007-03-18 14:55:23',
1237
				'updated' => '2007-03-18 14:57:31'
1238
			),
1239
			'User' => array(
1240
				'id' => '2',
1241
				'user' => 'nate',
1242
				'password' => '5f4dcc3b5aa765d61d8327deb882cf99',
1243
				'created' => '2007-03-17 01:18:23',
1244
				'updated' => '2007-03-17 01:20:31'
1245
			),
1246
			'Comment' => array(
1247
				array(
1248
					'id' => '7',
1249
					'article_id' => '4',
1250
					'user_id' => '1',
1251
					'comment' => 'Comment New Article',
1252
					'published' => 'Y',
1253
					'created' => '2007-03-18 14:57:23',
1254
					'updated' => '2007-03-18 14:59:31',
1255
					'Article' => array(
1256
						'id' => '4',
1257
						'user_id' => '2',
1258
						'title' => 'New Article',
1259
						'body' => 'New Article Body',
1260
						'published' => 'N',
1261
						'created' => '2007-03-18 14:55:23',
1262
						'updated' => '2007-03-18 14:57:31'
1263
					),
1264
					'User' => array(
1265
						'id' => '1',
1266
						'user' => 'mariano',
1267
						'password' => '5f4dcc3b5aa765d61d8327deb882cf99',
1268
						'created' => '2007-03-17 01:16:23',
1269
						'updated' => '2007-03-17 01:18:31'
1270
					),
1271
					'Attachment' => array(
1272
						'id' => '2',
1273
						'comment_id' => '7',
1274
						'attachment' => 'newattachment.zip',
1275
						'created' => '2007-03-18 15:02:23',
1276
						'updated' => '2007-03-18 15:04:31'
1277
			))),
1278
			'Tag' => array(
1279
				array(
1280
					'id' => '1',
1281
					'tag' => 'tag1',
1282
					'created' => '2007-03-18 12:22:23',
1283
					'updated' => '2007-03-18 12:24:31'
1284
				),
1285
				array(
1286
					'id' => '3',
1287
					'tag' => 'tag3',
1288
					'created' => '2007-03-18 12:26:23',
1289
					'updated' => '2007-03-18 12:28:31'
1290
		)));
1291
 
1292
		$this->assertEquals($expected, $result);
1293
	}
1294
 
1295
/**
1296
 * test that a null Id doesn't cause errors
1297
 *
1298
 * @return void
1299
 */
1300
	public function testSaveWithNullId() {
1301
		$this->loadFixtures('User');
1302
		$User = new User();
1303
		$User->read(null, 1);
1304
		$User->data['User']['id'] = null;
1305
		$result = $User->save(array('password' => 'test'));
1306
		$this->assertFalse(empty($result));
1307
		$this->assertTrue($User->id > 0);
1308
 
1309
		$User->read(null, 2);
1310
		$User->data['User']['id'] = null;
1311
		$result = $User->save(array('password' => 'test'));
1312
		$this->assertFalse(empty($result));
1313
		$this->assertTrue($User->id > 0);
1314
 
1315
		$User->data['User'] = array('password' => 'something');
1316
		$result = $User->save();
1317
		$this->assertFalse(empty($result));
1318
		$result = $User->read();
1319
		$this->assertEquals('something', $User->data['User']['password']);
1320
	}
1321
 
1322
/**
1323
 * testSaveWithSet method
1324
 *
1325
 * @return void
1326
 */
1327
	public function testSaveWithSet() {
1328
		$this->loadFixtures('Article');
1329
		$TestModel = new Article();
1330
 
1331
		// Create record we will be updating later
1332
 
1333
		$data = array('Article' => array(
1334
			'user_id' => '1',
1335
			'title' => 'Fourth Article',
1336
			'body' => 'Fourth Article Body',
1337
			'published' => 'Y'
1338
		));
1339
		$result = $TestModel->create() && $TestModel->save($data);
1340
		$this->assertFalse(empty($result));
1341
 
1342
		// Check record we created
1343
 
1344
		$TestModel->recursive = -1;
1345
		$result = $TestModel->read(array('id', 'user_id', 'title', 'body', 'published'), 4);
1346
		$expected = array('Article' => array(
1347
			'id' => '4',
1348
			'user_id' => '1',
1349
			'title' => 'Fourth Article',
1350
			'body' => 'Fourth Article Body',
1351
			'published' => 'Y'
1352
		));
1353
		$this->assertEquals($expected, $result);
1354
 
1355
		// Create new record just to overlap Model->id on previously created record
1356
 
1357
		$data = array('Article' => array(
1358
			'user_id' => '4',
1359
			'title' => 'Fifth Article',
1360
			'body' => 'Fifth Article Body',
1361
			'published' => 'Y'
1362
		));
1363
		$result = $TestModel->create() && $TestModel->save($data);
1364
		$this->assertFalse(empty($result));
1365
 
1366
		$TestModel->recursive = -1;
1367
		$result = $TestModel->read(array('id', 'user_id', 'title', 'body', 'published'), 5);
1368
		$expected = array('Article' => array(
1369
			'id' => '5',
1370
			'user_id' => '4',
1371
			'title' => 'Fifth Article',
1372
			'body' => 'Fifth Article Body',
1373
			'published' => 'Y'
1374
		));
1375
		$this->assertEquals($expected, $result);
1376
 
1377
		// Go back and edit the first article we created, starting by checking it's still there
1378
 
1379
		$TestModel->recursive = -1;
1380
		$result = $TestModel->read(array('id', 'user_id', 'title', 'body', 'published'), 4);
1381
		$expected = array('Article' => array(
1382
			'id' => '4',
1383
			'user_id' => '1',
1384
			'title' => 'Fourth Article',
1385
			'body' => 'Fourth Article Body',
1386
			'published' => 'Y'
1387
		));
1388
		$this->assertEquals($expected, $result);
1389
 
1390
		// And now do the update with set()
1391
 
1392
		$data = array('Article' => array(
1393
			'id' => '4',
1394
			'title' => 'Fourth Article - New Title',
1395
			'published' => 'N'
1396
		));
1397
		$result = $TestModel->set($data) && $TestModel->save();
1398
		$this->assertFalse(empty($result));
1399
 
1400
		$TestModel->recursive = -1;
1401
		$result = $TestModel->read(array('id', 'user_id', 'title', 'body', 'published'), 4);
1402
		$expected = array('Article' => array(
1403
			'id' => '4',
1404
			'user_id' => '1',
1405
			'title' => 'Fourth Article - New Title',
1406
			'body' => 'Fourth Article Body',
1407
			'published' => 'N'
1408
		));
1409
		$this->assertEquals($expected, $result);
1410
 
1411
		$TestModel->recursive = -1;
1412
		$result = $TestModel->read(array('id', 'user_id', 'title', 'body', 'published'), 5);
1413
		$expected = array('Article' => array(
1414
			'id' => '5',
1415
			'user_id' => '4',
1416
			'title' => 'Fifth Article',
1417
			'body' => 'Fifth Article Body',
1418
			'published' => 'Y'
1419
		));
1420
		$this->assertEquals($expected, $result);
1421
 
1422
		$data = array('Article' => array('id' => '5', 'title' => 'Fifth Article - New Title 5'));
1423
		$result = ($TestModel->set($data) && $TestModel->save());
1424
		$this->assertFalse(empty($result));
1425
 
1426
		$TestModel->recursive = -1;
1427
		$result = $TestModel->read(array('id', 'user_id', 'title', 'body', 'published'), 5);
1428
		$expected = array('Article' => array(
1429
			'id' => '5',
1430
			'user_id' => '4',
1431
			'title' => 'Fifth Article - New Title 5',
1432
			'body' => 'Fifth Article Body',
1433
			'published' => 'Y'
1434
		));
1435
		$this->assertEquals($expected, $result);
1436
 
1437
		$TestModel->recursive = -1;
1438
		$result = $TestModel->find('all', array(
1439
			'fields' => array('id', 'title'),
1440
			'order' => array('Article.id' => 'ASC')
1441
		));
1442
		$expected = array(
1443
			array('Article' => array('id' => 1, 'title' => 'First Article')),
1444
			array('Article' => array('id' => 2, 'title' => 'Second Article')),
1445
			array('Article' => array('id' => 3, 'title' => 'Third Article')),
1446
			array('Article' => array('id' => 4, 'title' => 'Fourth Article - New Title')),
1447
			array('Article' => array('id' => 5, 'title' => 'Fifth Article - New Title 5'))
1448
		);
1449
		$this->assertEquals($expected, $result);
1450
	}
1451
 
1452
/**
1453
 * testSaveWithNonExistentFields method
1454
 *
1455
 * @return void
1456
 */
1457
	public function testSaveWithNonExistentFields() {
1458
		$this->loadFixtures('Article');
1459
		$TestModel = new Article();
1460
		$TestModel->recursive = -1;
1461
 
1462
		$data = array(
1463
			'non_existent' => 'This field does not exist',
1464
			'user_id' => '1',
1465
			'title' => 'Fourth Article - New Title',
1466
			'body' => 'Fourth Article Body',
1467
			'published' => 'N'
1468
		);
1469
		$result = $TestModel->create() && $TestModel->save($data);
1470
		$this->assertFalse(empty($result));
1471
 
1472
		$expected = array('Article' => array(
1473
			'id' => '4',
1474
			'user_id' => '1',
1475
			'title' => 'Fourth Article - New Title',
1476
			'body' => 'Fourth Article Body',
1477
			'published' => 'N'
1478
		));
1479
		$result = $TestModel->read(array('id', 'user_id', 'title', 'body', 'published'), 4);
1480
		$this->assertEquals($expected, $result);
1481
 
1482
		$data = array(
1483
			'user_id' => '1',
1484
			'non_existent' => 'This field does not exist',
1485
			'title' => 'Fifth Article - New Title',
1486
			'body' => 'Fifth Article Body',
1487
			'published' => 'N'
1488
		);
1489
		$result = $TestModel->create() && $TestModel->save($data);
1490
		$this->assertFalse(empty($result));
1491
 
1492
		$expected = array('Article' => array(
1493
			'id' => '5',
1494
			'user_id' => '1',
1495
			'title' => 'Fifth Article - New Title',
1496
			'body' => 'Fifth Article Body',
1497
			'published' => 'N'
1498
		));
1499
		$result = $TestModel->read(array('id', 'user_id', 'title', 'body', 'published'), 5);
1500
		$this->assertEquals($expected, $result);
1501
	}
1502
 
1503
/**
1504
 * testSaveFromXml method
1505
 *
1506
 * @return void
1507
 */
1508
	public function testSaveFromXml() {
1509
		$this->markTestSkipped('This feature needs to be fixed or dropped');
1510
		$this->loadFixtures('Article');
1511
		App::uses('Xml', 'Utility');
1512
 
1513
		$Article = new Article();
1514
		$result = $Article->save(Xml::build('<article title="test xml" user_id="5" />'));
1515
		$this->assertFalse(empty($result));
1516
		$results = $Article->find('first', array('conditions' => array('Article.title' => 'test xml')));
1517
		$this->assertFalse(empty($results));
1518
 
1519
		$result = $Article->save(Xml::build('<article><title>testing</title><user_id>6</user_id></article>'));
1520
		$this->assertFalse(empty($result));
1521
		$results = $Article->find('first', array('conditions' => array('Article.title' => 'testing')));
1522
		$this->assertFalse(empty($results));
1523
 
1524
		$result = $Article->save(Xml::build('<article><title>testing with DOMDocument</title><user_id>7</user_id></article>', array('return' => 'domdocument')));
1525
		$this->assertFalse(empty($result));
1526
		$results = $Article->find('first', array('conditions' => array('Article.title' => 'testing with DOMDocument')));
1527
		$this->assertFalse(empty($results));
1528
	}
1529
 
1530
/**
1531
 * testSaveHabtm method
1532
 *
1533
 * @return void
1534
 */
1535
	public function testSaveHabtm() {
1536
		$this->loadFixtures('Article', 'User', 'Comment', 'Tag', 'ArticlesTag');
1537
		$TestModel = new Article();
1538
 
1539
		$result = $TestModel->findById(2);
1540
		$expected = array(
1541
			'Article' => array(
1542
				'id' => '2',
1543
				'user_id' => '3',
1544
				'title' => 'Second Article',
1545
				'body' => 'Second Article Body',
1546
				'published' => 'Y',
1547
				'created' => '2007-03-18 10:41:23',
1548
				'updated' => '2007-03-18 10:43:31'
1549
			),
1550
			'User' => array(
1551
				'id' => '3',
1552
				'user' => 'larry',
1553
				'password' => '5f4dcc3b5aa765d61d8327deb882cf99',
1554
				'created' => '2007-03-17 01:20:23',
1555
				'updated' => '2007-03-17 01:22:31'
1556
			),
1557
			'Comment' => array(
1558
				array(
1559
					'id' => '5',
1560
					'article_id' => '2',
1561
					'user_id' => '1',
1562
					'comment' => 'First Comment for Second Article',
1563
					'published' => 'Y',
1564
					'created' => '2007-03-18 10:53:23',
1565
					'updated' => '2007-03-18 10:55:31'
1566
				),
1567
				array(
1568
					'id' => '6',
1569
					'article_id' => '2',
1570
					'user_id' => '2',
1571
					'comment' => 'Second Comment for Second Article',
1572
					'published' => 'Y',
1573
					'created' => '2007-03-18 10:55:23',
1574
					'updated' => '2007-03-18 10:57:31'
1575
			)),
1576
			'Tag' => array(
1577
				array(
1578
					'id' => '1',
1579
					'tag' => 'tag1',
1580
					'created' => '2007-03-18 12:22:23',
1581
					'updated' => '2007-03-18 12:24:31'
1582
				),
1583
				array(
1584
					'id' => '3',
1585
					'tag' => 'tag3',
1586
					'created' => '2007-03-18 12:26:23',
1587
					'updated' => '2007-03-18 12:28:31'
1588
				)
1589
			)
1590
		);
1591
		$this->assertEquals($expected, $result);
1592
 
1593
		$data = array(
1594
			'Article' => array(
1595
				'id' => '2',
1596
				'title' => 'New Second Article'
1597
			),
1598
			'Tag' => array('Tag' => array(1, 2))
1599
		);
1600
 
1601
		$result = $TestModel->set($data);
1602
		$this->assertFalse(empty($result));
1603
		$result = $TestModel->save();
1604
		$this->assertFalse(empty($result));
1605
		$this->assertEquals($data['Tag'], $result['Tag']);
1606
 
1607
		$TestModel->unbindModel(array('belongsTo' => array('User'), 'hasMany' => array('Comment')));
1608
		$result = $TestModel->find('first', array('fields' => array('id', 'user_id', 'title', 'body'), 'conditions' => array('Article.id' => 2)));
1609
		$expected = array(
1610
			'Article' => array(
1611
				'id' => '2',
1612
				'user_id' => '3',
1613
				'title' => 'New Second Article',
1614
				'body' => 'Second Article Body'
1615
			),
1616
			'Tag' => array(
1617
				array(
1618
					'id' => '1',
1619
					'tag' => 'tag1',
1620
					'created' => '2007-03-18 12:22:23',
1621
					'updated' => '2007-03-18 12:24:31'
1622
				),
1623
				array(
1624
					'id' => '2',
1625
					'tag' => 'tag2',
1626
					'created' => '2007-03-18 12:24:23',
1627
					'updated' => '2007-03-18 12:26:31'
1628
		)));
1629
		$this->assertEquals($expected, $result);
1630
 
1631
		$data = array('Article' => array('id' => '2'), 'Tag' => array('Tag' => array(2, 3)));
1632
		$result = $TestModel->set($data);
1633
		$this->assertFalse(empty($result));
1634
 
1635
		$result = $TestModel->save();
1636
		$this->assertFalse(empty($result));
1637
 
1638
		$TestModel->unbindModel(array(
1639
			'belongsTo' => array('User'),
1640
			'hasMany' => array('Comment')
1641
		));
1642
		$result = $TestModel->find('first', array('fields' => array('id', 'user_id', 'title', 'body'), 'conditions' => array('Article.id' => 2)));
1643
		$expected = array(
1644
			'Article' => array(
1645
				'id' => '2',
1646
				'user_id' => '3',
1647
				'title' => 'New Second Article',
1648
				'body' => 'Second Article Body'
1649
			),
1650
			'Tag' => array(
1651
				array(
1652
					'id' => '2',
1653
					'tag' => 'tag2',
1654
					'created' => '2007-03-18 12:24:23',
1655
					'updated' => '2007-03-18 12:26:31'
1656
				),
1657
				array(
1658
					'id' => '3',
1659
					'tag' => 'tag3',
1660
					'created' => '2007-03-18 12:26:23',
1661
					'updated' => '2007-03-18 12:28:31'
1662
		)));
1663
		$this->assertEquals($expected, $result);
1664
 
1665
		$data = array('Tag' => array('Tag' => array(1, 2, 3)));
1666
 
1667
		$result = $TestModel->set($data);
1668
		$this->assertFalse(empty($result));
1669
 
1670
		$result = $TestModel->save();
1671
		$this->assertFalse(empty($result));
1672
 
1673
		$TestModel->unbindModel(array(
1674
			'belongsTo' => array('User'),
1675
			'hasMany' => array('Comment')
1676
		));
1677
		$result = $TestModel->find('first', array('fields' => array('id', 'user_id', 'title', 'body'), 'conditions' => array('Article.id' => 2)));
1678
		$expected = array(
1679
			'Article' => array(
1680
				'id' => '2',
1681
				'user_id' => '3',
1682
				'title' => 'New Second Article',
1683
				'body' => 'Second Article Body'
1684
			),
1685
			'Tag' => array(
1686
				array(
1687
					'id' => '1',
1688
					'tag' => 'tag1',
1689
					'created' => '2007-03-18 12:22:23',
1690
					'updated' => '2007-03-18 12:24:31'
1691
				),
1692
				array(
1693
					'id' => '2',
1694
					'tag' => 'tag2',
1695
					'created' => '2007-03-18 12:24:23',
1696
					'updated' => '2007-03-18 12:26:31'
1697
				),
1698
				array(
1699
					'id' => '3',
1700
					'tag' => 'tag3',
1701
					'created' => '2007-03-18 12:26:23',
1702
					'updated' => '2007-03-18 12:28:31'
1703
		)));
1704
		$this->assertEquals($expected, $result);
1705
 
1706
		$data = array('Tag' => array('Tag' => array()));
1707
		$result = $TestModel->set($data);
1708
		$this->assertFalse(empty($result));
1709
 
1710
		$result = $TestModel->save();
1711
		$this->assertFalse(empty($result));
1712
 
1713
		$data = array('Tag' => array('Tag' => ''));
1714
		$result = $TestModel->set($data);
1715
		$this->assertFalse(empty($result));
1716
 
1717
		$result = $TestModel->save();
1718
		$this->assertFalse(empty($result));
1719
 
1720
		$TestModel->unbindModel(array(
1721
			'belongsTo' => array('User'),
1722
			'hasMany' => array('Comment')
1723
		));
1724
		$result = $TestModel->find('first', array('fields' => array('id', 'user_id', 'title', 'body'), 'conditions' => array('Article.id' => 2)));
1725
		$expected = array(
1726
			'Article' => array(
1727
				'id' => '2',
1728
				'user_id' => '3',
1729
				'title' => 'New Second Article',
1730
				'body' => 'Second Article Body'
1731
			),
1732
			'Tag' => array()
1733
		);
1734
		$this->assertEquals($expected, $result);
1735
 
1736
		$data = array('Tag' => array('Tag' => array(2, 3)));
1737
		$result = $TestModel->set($data);
1738
		$this->assertFalse(empty($result));
1739
 
1740
		$result = $TestModel->save();
1741
		$this->assertFalse(empty($result));
1742
 
1743
		$TestModel->unbindModel(array(
1744
			'belongsTo' => array('User'),
1745
			'hasMany' => array('Comment')
1746
		));
1747
		$result = $TestModel->find('first', array('fields' => array('id', 'user_id', 'title', 'body'), 'conditions' => array('Article.id' => 2)));
1748
		$expected = array(
1749
			'Article' => array(
1750
				'id' => '2',
1751
				'user_id' => '3',
1752
				'title' => 'New Second Article',
1753
				'body' => 'Second Article Body'
1754
			),
1755
			'Tag' => array(
1756
				array(
1757
					'id' => '2',
1758
					'tag' => 'tag2',
1759
					'created' => '2007-03-18 12:24:23',
1760
					'updated' => '2007-03-18 12:26:31'
1761
				),
1762
				array(
1763
					'id' => '3',
1764
					'tag' => 'tag3',
1765
					'created' => '2007-03-18 12:26:23',
1766
					'updated' => '2007-03-18 12:28:31'
1767
		)));
1768
		$this->assertEquals($expected, $result);
1769
 
1770
		$data = array(
1771
			'Tag' => array(
1772
				'Tag' => array(1, 2)
1773
			),
1774
			'Article' => array(
1775
				'id' => '2',
1776
				'title' => 'New Second Article'
1777
		));
1778
		$result = $TestModel->set($data);
1779
		$this->assertFalse(empty($result));
1780
		$result = $TestModel->save();
1781
		$this->assertFalse(empty($result));
1782
 
1783
		$TestModel->unbindModel(array(
1784
			'belongsTo' => array('User'),
1785
			'hasMany' => array('Comment')
1786
		));
1787
		$result = $TestModel->find('first', array('fields' => array('id', 'user_id', 'title', 'body'), 'conditions' => array('Article.id' => 2)));
1788
		$expected = array(
1789
			'Article' => array(
1790
				'id' => '2',
1791
				'user_id' => '3',
1792
				'title' => 'New Second Article',
1793
				'body' => 'Second Article Body'
1794
			),
1795
			'Tag' => array(
1796
				array(
1797
					'id' => '1',
1798
					'tag' => 'tag1',
1799
					'created' => '2007-03-18 12:22:23',
1800
					'updated' => '2007-03-18 12:24:31'
1801
				),
1802
				array(
1803
					'id' => '2',
1804
					'tag' => 'tag2',
1805
					'created' => '2007-03-18 12:24:23',
1806
					'updated' => '2007-03-18 12:26:31'
1807
		)));
1808
		$this->assertEquals($expected, $result);
1809
 
1810
		$data = array(
1811
			'Tag' => array(
1812
				'Tag' => array(1, 2)
1813
			),
1814
			'Article' => array(
1815
				'id' => '2',
1816
				'title' => 'New Second Article Title'
1817
		));
1818
		$result = $TestModel->set($data);
1819
		$this->assertFalse(empty($result));
1820
		$result = $TestModel->save();
1821
		$this->assertFalse(empty($result));
1822
 
1823
		$TestModel->unbindModel(array(
1824
			'belongsTo' => array('User'),
1825
			'hasMany' => array('Comment')
1826
		));
1827
		$result = $TestModel->find('first', array('fields' => array('id', 'user_id', 'title', 'body'), 'conditions' => array('Article.id' => 2)));
1828
		$expected = array(
1829
			'Article' => array(
1830
				'id' => '2',
1831
				'user_id' => '3',
1832
				'title' => 'New Second Article Title',
1833
				'body' => 'Second Article Body'
1834
			),
1835
			'Tag' => array(
1836
				array(
1837
					'id' => '1',
1838
					'tag' => 'tag1',
1839
					'created' => '2007-03-18 12:22:23',
1840
					'updated' => '2007-03-18 12:24:31'
1841
				),
1842
				array(
1843
					'id' => '2',
1844
					'tag' => 'tag2',
1845
					'created' => '2007-03-18 12:24:23',
1846
					'updated' => '2007-03-18 12:26:31'
1847
				)
1848
			)
1849
		);
1850
		$this->assertEquals($expected, $result);
1851
 
1852
		$data = array(
1853
			'Tag' => array(
1854
				'Tag' => array(2, 3)
1855
			),
1856
			'Article' => array(
1857
				'id' => '2',
1858
				'title' => 'Changed Second Article'
1859
		));
1860
		$result = $TestModel->set($data);
1861
		$this->assertFalse(empty($result));
1862
		$result = $TestModel->save();
1863
		$this->assertFalse(empty($result));
1864
 
1865
		$TestModel->unbindModel(array(
1866
			'belongsTo' => array('User'),
1867
			'hasMany' => array('Comment')
1868
		));
1869
		$result = $TestModel->find('first', array('fields' => array('id', 'user_id', 'title', 'body'), 'conditions' => array('Article.id' => 2)));
1870
		$expected = array(
1871
			'Article' => array(
1872
				'id' => '2',
1873
				'user_id' => '3',
1874
				'title' => 'Changed Second Article',
1875
				'body' => 'Second Article Body'
1876
			),
1877
			'Tag' => array(
1878
				array(
1879
					'id' => '2',
1880
					'tag' => 'tag2',
1881
					'created' => '2007-03-18 12:24:23',
1882
					'updated' => '2007-03-18 12:26:31'
1883
				),
1884
				array(
1885
					'id' => '3',
1886
					'tag' => 'tag3',
1887
					'created' => '2007-03-18 12:26:23',
1888
					'updated' => '2007-03-18 12:28:31'
1889
				)
1890
			)
1891
		);
1892
		$this->assertEquals($expected, $result);
1893
 
1894
		$data = array(
1895
			'Tag' => array(
1896
				'Tag' => array(1, 3)
1897
			),
1898
			'Article' => array('id' => '2'),
1899
		);
1900
 
1901
		$result = $TestModel->set($data);
1902
		$this->assertFalse(empty($result));
1903
 
1904
		$result = $TestModel->save();
1905
		$this->assertFalse(empty($result));
1906
 
1907
		$TestModel->unbindModel(array(
1908
			'belongsTo' => array('User'),
1909
			'hasMany' => array('Comment')
1910
		));
1911
		$result = $TestModel->find('first', array('fields' => array('id', 'user_id', 'title', 'body'), 'conditions' => array('Article.id' => 2)));
1912
		$expected = array(
1913
			'Article' => array(
1914
				'id' => '2',
1915
				'user_id' => '3',
1916
				'title' => 'Changed Second Article',
1917
				'body' => 'Second Article Body'
1918
			),
1919
			'Tag' => array(
1920
				array(
1921
					'id' => '1',
1922
					'tag' => 'tag1',
1923
					'created' => '2007-03-18 12:22:23',
1924
					'updated' => '2007-03-18 12:24:31'
1925
				),
1926
				array(
1927
					'id' => '3',
1928
					'tag' => 'tag3',
1929
					'created' => '2007-03-18 12:26:23',
1930
					'updated' => '2007-03-18 12:28:31'
1931
		)));
1932
		$this->assertEquals($expected, $result);
1933
 
1934
		$data = array(
1935
			'Article' => array(
1936
				'id' => 10,
1937
				'user_id' => '2',
1938
				'title' => 'New Article With Tags and fieldList',
1939
				'body' => 'New Article Body with Tags and fieldList',
1940
				'created' => '2007-03-18 14:55:23',
1941
				'updated' => '2007-03-18 14:57:31'
1942
			),
1943
			'Tag' => array(
1944
				'Tag' => array(1, 2, 3)
1945
			)
1946
		);
1947
		$result = $TestModel->create()
1948
				&& $TestModel->save($data, true, array('user_id', 'title', 'published'));
1949
		$this->assertFalse(empty($result));
1950
 
1951
		$TestModel->unbindModel(array(
1952
			'belongsTo' => array('User'),
1953
			'hasMany' => array('Comment')
1954
		));
1955
		$result = $TestModel->read();
1956
		$expected = array(
1957
			'Article' => array(
1958
				'id' => 4,
1959
				'user_id' => 2,
1960
				'title' => 'New Article With Tags and fieldList',
1961
				'body' => '',
1962
				'published' => 'N',
1963
				'created' => '',
1964
				'updated' => ''
1965
			),
1966
			'Tag' => array(
1967
 
1968
					'id' => 1,
1969
					'tag' => 'tag1',
1970
					'created' => '2007-03-18 12:22:23',
1971
					'updated' => '2007-03-18 12:24:31'
1972
				),
1973
				1 => array(
1974
					'id' => 2,
1975
					'tag' => 'tag2',
1976
					'created' => '2007-03-18 12:24:23',
1977
					'updated' => '2007-03-18 12:26:31'
1978
				),
1979
				2 => array(
1980
					'id' => 3,
1981
					'tag' => 'tag3',
1982
					'created' => '2007-03-18 12:26:23',
1983
					'updated' => '2007-03-18 12:28:31'
1984
		)));
1985
		$this->assertEquals($expected, $result);
1986
 
1987
		$this->loadFixtures('JoinA', 'JoinC', 'JoinAC', 'JoinB', 'JoinAB');
1988
		$TestModel = new JoinA();
1989
		$TestModel->hasBelongsToMany = array('JoinC' => array('unique' => true));
1990
		$data = array(
1991
			'JoinA' => array(
1992
				'id' => 1,
1993
				'name' => 'Join A 1',
1994
				'body' => 'Join A 1 Body',
1995
			),
1996
			'JoinC' => array(
1997
				'JoinC' => array(
1998
					array('join_c_id' => 2, 'other' => 'new record'),
1999
					array('join_c_id' => 3, 'other' => 'new record')
2000
				)
2001
			)
2002
		);
2003
		$TestModel->save($data);
2004
		$result = $TestModel->read(null, 1);
2005
		$expected = array(4, 5);
2006
		$this->assertEquals($expected, Hash::extract($result, 'JoinC.{n}.JoinAsJoinC.id'));
2007
		$expected = array('new record', 'new record');
2008
		$this->assertEquals($expected, Hash::extract($result, 'JoinC.{n}.JoinAsJoinC.other'));
2009
	}
2010
 
2011
/**
2012
 * test that saving HABTM with an empty array will clear existing HABTM if
2013
 * unique is true
2014
 *
2015
 * @return void
2016
 */
2017
	public function testSaveHabtmEmptyData() {
2018
		$this->loadFixtures('Node', 'Dependency');
2019
		$Node = new Node();
2020
 
2021
		$data = array(
2022
			'Node' => array('name' => 'New First')
2023
		);
2024
		$Node->id = 1;
2025
		$Node->save($data);
2026
 
2027
		$node = $Node->find('first', array(
2028
			'conditions' => array('Node.id' => 1),
2029
			'contain' => array('ParentNode')
2030
		));
2031
 
2032
		$result = Hash::extract($node, 'ParentNode.{n}.id');
2033
		$expected = array(2);
2034
		$this->assertEquals($expected, $result);
2035
 
2036
		$data = array(
2037
			'ParentNode' => array()
2038
		);
2039
		$Node->id = 1;
2040
		$Node->save($data);
2041
 
2042
		$node = $Node->find('first', array(
2043
			'conditions' => array('Node.id' => 1),
2044
			'contain' => array('ParentNode')
2045
		));
2046
 
2047
		$result = Hash::extract($node, 'ParentNode.{n}.id');
2048
		$expected = array();
2049
		$this->assertEquals($expected, $result);
2050
	}
2051
 
2052
/**
2053
 * testSaveHabtmNoPrimaryData method
2054
 *
2055
 * @return void
2056
 */
2057
	public function testSaveHabtmNoPrimaryData() {
2058
		$this->loadFixtures('Article', 'User', 'Comment', 'Tag', 'ArticlesTag');
2059
		$TestModel = new Article();
2060
 
2061
		$TestModel->unbindModel(array('belongsTo' => array('User'), 'hasMany' => array('Comment')), false);
2062
		$result = $TestModel->findById(2);
2063
		$expected = array(
2064
			'Article' => array(
2065
				'id' => '2',
2066
				'user_id' => '3',
2067
				'title' => 'Second Article',
2068
				'body' => 'Second Article Body',
2069
				'published' => 'Y',
2070
				'created' => '2007-03-18 10:41:23',
2071
				'updated' => '2007-03-18 10:43:31'
2072
			),
2073
			'Tag' => array(
2074
				array(
2075
					'id' => '1',
2076
					'tag' => 'tag1',
2077
					'created' => '2007-03-18 12:22:23',
2078
					'updated' => '2007-03-18 12:24:31'
2079
				),
2080
				array(
2081
					'id' => '3',
2082
					'tag' => 'tag3',
2083
					'created' => '2007-03-18 12:26:23',
2084
					'updated' => '2007-03-18 12:28:31'
2085
				)
2086
			)
2087
		);
2088
		$this->assertEquals($expected, $result);
2089
 
2090
		$TestModel->id = 2;
2091
		$data = array('Tag' => array('Tag' => array(2)));
2092
		$result = $TestModel->save($data);
2093
 
2094
		$this->assertEquals($data['Tag'], $result['Tag']);
2095
 
2096
		$result = $TestModel->findById(2);
2097
		$expected = array(
2098
			'Article' => array(
2099
				'id' => '2',
2100
				'user_id' => '3',
2101
				'title' => 'Second Article',
2102
				'body' => 'Second Article Body',
2103
				'published' => 'Y',
2104
				'created' => '2007-03-18 10:41:23',
2105
				'updated' => self::date()
2106
			),
2107
			'Tag' => array(
2108
				array(
2109
					'id' => '2',
2110
					'tag' => 'tag2',
2111
					'created' => '2007-03-18 12:24:23',
2112
					'updated' => '2007-03-18 12:26:31'
2113
				)
2114
			)
2115
		);
2116
		$this->assertEquals($expected, $result);
2117
 
2118
		$this->loadFixtures('Portfolio', 'Item', 'ItemsPortfolio');
2119
		$TestModel = new Portfolio();
2120
		$result = $TestModel->findById(2);
2121
		$expected = array(
2122
			'Portfolio' => array(
2123
				'id' => 2,
2124
				'seller_id' => 1,
2125
				'name' => 'Portfolio 2'
2126
			),
2127
			'Item' => array(
2128
				array(
2129
					'id' => 2,
2130
					'syfile_id' => 2,
2131
					'published' => '',
2132
					'name' => 'Item 2',
2133
					'ItemsPortfolio' => array(
2134
						'id' => 2,
2135
						'item_id' => 2,
2136
						'portfolio_id' => 2
2137
					)
2138
				),
2139
				array(
2140
					'id' => 6,
2141
					'syfile_id' => 6,
2142
					'published' => '',
2143
					'name' => 'Item 6',
2144
					'ItemsPortfolio' => array(
2145
						'id' => 6,
2146
						'item_id' => 6,
2147
						'portfolio_id' => 2
2148
					)
2149
				)
2150
			)
2151
		);
2152
		$this->assertEquals($expected, $result);
2153
 
2154
		$data = array('Item' => array('Item' => array(1, 2)));
2155
		$TestModel->id = 2;
2156
		$result = $TestModel->save($data);
2157
		$this->assertTrue((bool)$result);
2158
 
2159
		$result = $TestModel->findById(2);
2160
		$result['Item'] = Hash::sort($result['Item'], '{n}.id', 'asc');
2161
		$expected = array(
2162
			'Portfolio' => array(
2163
				'id' => 2,
2164
				'seller_id' => 1,
2165
				'name' => 'Portfolio 2'
2166
			),
2167
			'Item' => array(
2168
				array(
2169
					'id' => 1,
2170
					'syfile_id' => 1,
2171
					'published' => '',
2172
					'name' => 'Item 1',
2173
					'ItemsPortfolio' => array(
2174
						'id' => 7,
2175
						'item_id' => 1,
2176
						'portfolio_id' => 2
2177
					)
2178
				),
2179
				array(
2180
					'id' => 2,
2181
					'syfile_id' => 2,
2182
					'published' => '',
2183
					'name' => 'Item 2',
2184
					'ItemsPortfolio' => array(
2185
						'id' => 8,
2186
						'item_id' => 2,
2187
						'portfolio_id' => 2
2188
					)
2189
				)
2190
			)
2191
		);
2192
		$this->assertEquals($expected, $result);
2193
	}
2194
 
2195
/**
2196
 * testSaveHabtmCustomKeys method
2197
 *
2198
 * @return void
2199
 */
2200
	public function testSaveHabtmCustomKeys() {
2201
		$this->loadFixtures('Story', 'StoriesTag', 'Tag');
2202
		$Story = new Story();
2203
 
2204
		$data = array(
2205
			'Story' => array('story' => '1'),
2206
			'Tag' => array(
2207
				'Tag' => array(2, 3)
2208
		));
2209
		$result = $Story->set($data);
2210
		$this->assertFalse(empty($result));
2211
 
2212
		$result = $Story->save();
2213
		$this->assertFalse(empty($result));
2214
 
2215
		$result = $Story->find('all', array('order' => array('Story.story')));
2216
		$expected = array(
2217
			array(
2218
				'Story' => array(
2219
					'story' => 1,
2220
					'title' => 'First Story'
2221
				),
2222
				'Tag' => array(
2223
					array(
2224
						'id' => 2,
2225
						'tag' => 'tag2',
2226
						'created' => '2007-03-18 12:24:23',
2227
						'updated' => '2007-03-18 12:26:31'
2228
					),
2229
					array(
2230
						'id' => 3,
2231
						'tag' => 'tag3',
2232
						'created' => '2007-03-18 12:26:23',
2233
						'updated' => '2007-03-18 12:28:31'
2234
			))),
2235
			array(
2236
				'Story' => array(
2237
					'story' => 2,
2238
					'title' => 'Second Story'
2239
				),
2240
				'Tag' => array()
2241
		));
2242
		$this->assertEquals($expected, $result);
2243
	}
2244
 
2245
/**
2246
 * test that saving habtm records respects conditions set in the 'conditions' key
2247
 * for the association.
2248
 *
2249
 * @return void
2250
 */
2251
	public function testHabtmSaveWithConditionsInAssociation() {
2252
		$this->loadFixtures('JoinThing', 'Something', 'SomethingElse');
2253
		$Something = new Something();
2254
		$Something->unbindModel(array('hasAndBelongsToMany' => array('SomethingElse')), false);
2255
 
2256
		$Something->bindModel(array(
2257
			'hasAndBelongsToMany' => array(
2258
				'DoomedSomethingElse' => array(
2259
					'className' => 'SomethingElse',
2260
					'joinTable' => 'join_things',
2261
					'conditions' => array('JoinThing.doomed' => true),
2262
					'unique' => true
2263
				),
2264
				'NotDoomedSomethingElse' => array(
2265
					'className' => 'SomethingElse',
2266
					'joinTable' => 'join_things',
2267
					'conditions' => array('JoinThing.doomed' => 0),
2268
					'unique' => true
2269
				)
2270
			)
2271
		), false);
2272
		$result = $Something->read(null, 1);
2273
		$this->assertTrue(empty($result['NotDoomedSomethingElse']));
2274
		$this->assertEquals(1, count($result['DoomedSomethingElse']));
2275
 
2276
		$data = array(
2277
			'Something' => array('id' => 1),
2278
			'NotDoomedSomethingElse' => array(
2279
				'NotDoomedSomethingElse' => array(
2280
					array('something_else_id' => 2, 'doomed' => 0),
2281
					array('something_else_id' => 3, 'doomed' => 0)
2282
				)
2283
			)
2284
		);
2285
		$Something->create($data);
2286
		$result = $Something->save();
2287
		$this->assertFalse(empty($result));
2288
 
2289
		$result = $Something->read(null, 1);
2290
		$this->assertEquals(2, count($result['NotDoomedSomethingElse']));
2291
		$this->assertEquals(1, count($result['DoomedSomethingElse']));
2292
	}
2293
 
2294
/**
2295
 * testHabtmSaveKeyResolution method
2296
 *
2297
 * @return void
2298
 */
2299
	public function testHabtmSaveKeyResolution() {
2300
		$this->loadFixtures('Apple', 'Device', 'ThePaperMonkies');
2301
		$ThePaper = new ThePaper();
2302
 
2303
		$ThePaper->id = 1;
2304
		$ThePaper->save(array('Monkey' => array(2, 3)));
2305
 
2306
		$result = $ThePaper->findById(1);
2307
		$expected = array(
2308
			array(
2309
				'id' => '2',
2310
				'device_type_id' => '1',
2311
				'name' => 'Device 2',
2312
				'typ' => '1'
2313
			),
2314
			array(
2315
				'id' => '3',
2316
				'device_type_id' => '1',
2317
				'name' => 'Device 3',
2318
				'typ' => '2'
2319
		));
2320
		$this->assertEquals($expected, $result['Monkey']);
2321
 
2322
		$ThePaper->id = 2;
2323
		$ThePaper->save(array('Monkey' => array(1, 2, 3)));
2324
 
2325
		$result = $ThePaper->findById(2);
2326
		$expected = array(
2327
			array(
2328
				'id' => '1',
2329
				'device_type_id' => '1',
2330
				'name' => 'Device 1',
2331
				'typ' => '1'
2332
			),
2333
			array(
2334
				'id' => '2',
2335
				'device_type_id' => '1',
2336
				'name' => 'Device 2',
2337
				'typ' => '1'
2338
			),
2339
			array(
2340
				'id' => '3',
2341
				'device_type_id' => '1',
2342
				'name' => 'Device 3',
2343
				'typ' => '2'
2344
		));
2345
		$this->assertEquals($expected, $result['Monkey']);
2346
 
2347
		$ThePaper->id = 2;
2348
		$ThePaper->save(array('Monkey' => array(1, 3)));
2349
 
2350
		$result = $ThePaper->findById(2);
2351
		$expected = array(
2352
			array(
2353
				'id' => '1',
2354
				'device_type_id' => '1',
2355
				'name' => 'Device 1',
2356
				'typ' => '1'
2357
			),
2358
			array(
2359
				'id' => '3',
2360
				'device_type_id' => '1',
2361
				'name' => 'Device 3',
2362
				'typ' => '2'
2363
			));
2364
		$this->assertEquals($expected, $result['Monkey']);
2365
 
2366
		$result = $ThePaper->findById(1);
2367
		$expected = array(
2368
			array(
2369
				'id' => '2',
2370
				'device_type_id' => '1',
2371
				'name' => 'Device 2',
2372
				'typ' => '1'
2373
			),
2374
			array(
2375
				'id' => '3',
2376
				'device_type_id' => '1',
2377
				'name' => 'Device 3',
2378
				'typ' => '2'
2379
		));
2380
		$this->assertEquals($expected, $result['Monkey']);
2381
	}
2382
 
2383
/**
2384
 * testCreationOfEmptyRecord method
2385
 *
2386
 * @return void
2387
 */
2388
	public function testCreationOfEmptyRecord() {
2389
		$this->loadFixtures('Author');
2390
		$TestModel = new Author();
2391
		$this->assertEquals(4, $TestModel->find('count'));
2392
 
2393
		$TestModel->deleteAll(true, false, false);
2394
		$this->assertEquals(0, $TestModel->find('count'));
2395
 
2396
		$result = $TestModel->save();
2397
		$this->assertTrue(isset($result['Author']['created']));
2398
		$this->assertTrue(isset($result['Author']['updated']));
2399
		$this->assertEquals(1, $TestModel->find('count'));
2400
	}
2401
 
2402
/**
2403
 * testCreateWithPKFiltering method
2404
 *
2405
 * @return void
2406
 */
2407
	public function testCreateWithPKFiltering() {
2408
		$TestModel = new Article();
2409
		$data = array(
2410
			'id' => 5,
2411
			'user_id' => 2,
2412
			'title' => 'My article',
2413
			'body' => 'Some text'
2414
		);
2415
 
2416
		$result = $TestModel->create($data);
2417
		$expected = array(
2418
			'Article' => array(
2419
				'published' => 'N',
2420
				'id' => 5,
2421
				'user_id' => 2,
2422
				'title' => 'My article',
2423
				'body' => 'Some text'
2424
		));
2425
 
2426
		$this->assertEquals($expected, $result);
2427
		$this->assertEquals(5, $TestModel->id);
2428
 
2429
		$result = $TestModel->create($data, true);
2430
		$expected = array(
2431
			'Article' => array(
2432
				'published' => 'N',
2433
				'id' => false,
2434
				'user_id' => 2,
2435
				'title' => 'My article',
2436
				'body' => 'Some text'
2437
		));
2438
 
2439
		$this->assertEquals($expected, $result);
2440
		$this->assertFalse($TestModel->id);
2441
 
2442
		$result = $TestModel->create(array('Article' => $data), true);
2443
		$expected = array(
2444
			'Article' => array(
2445
				'published' => 'N',
2446
				'id' => false,
2447
				'user_id' => 2,
2448
				'title' => 'My article',
2449
				'body' => 'Some text'
2450
		));
2451
 
2452
		$this->assertEquals($expected, $result);
2453
		$this->assertFalse($TestModel->id);
2454
 
2455
		$data = array(
2456
			'id' => 6,
2457
			'user_id' => 2,
2458
			'title' => 'My article',
2459
			'body' => 'Some text',
2460
			'created' => '1970-01-01 00:00:00',
2461
			'updated' => '1970-01-01 12:00:00',
2462
			'modified' => '1970-01-01 12:00:00'
2463
		);
2464
 
2465
		$result = $TestModel->create($data);
2466
		$expected = array(
2467
			'Article' => array(
2468
				'published' => 'N',
2469
				'id' => 6,
2470
				'user_id' => 2,
2471
				'title' => 'My article',
2472
				'body' => 'Some text',
2473
				'created' => '1970-01-01 00:00:00',
2474
				'updated' => '1970-01-01 12:00:00',
2475
				'modified' => '1970-01-01 12:00:00'
2476
		));
2477
		$this->assertEquals($expected, $result);
2478
		$this->assertEquals(6, $TestModel->id);
2479
 
2480
		$result = $TestModel->create(array(
2481
			'Article' => array_diff_key($data, array(
2482
				'created' => true,
2483
				'updated' => true,
2484
				'modified' => true
2485
		))), true);
2486
		$expected = array(
2487
			'Article' => array(
2488
				'published' => 'N',
2489
				'id' => false,
2490
				'user_id' => 2,
2491
				'title' => 'My article',
2492
				'body' => 'Some text'
2493
		));
2494
		$this->assertEquals($expected, $result);
2495
		$this->assertFalse($TestModel->id);
2496
	}
2497
 
2498
/**
2499
 * testCreationWithMultipleData method
2500
 *
2501
 * @return void
2502
 */
2503
	public function testCreationWithMultipleData() {
2504
		$this->loadFixtures('Article', 'Comment');
2505
		$Article = new Article();
2506
		$Comment = new Comment();
2507
 
2508
		$articles = $Article->find('all', array(
2509
			'fields' => array('id', 'title'),
2510
			'recursive' => -1,
2511
			'order' => array('Article.id' => 'ASC')
2512
		));
2513
		$expected = array(
2514
			array('Article' => array(
2515
				'id' => 1,
2516
				'title' => 'First Article'
2517
			)),
2518
			array('Article' => array(
2519
				'id' => 2,
2520
				'title' => 'Second Article'
2521
			)),
2522
			array('Article' => array(
2523
				'id' => 3,
2524
				'title' => 'Third Article'
2525
		)));
2526
		$this->assertEquals($expected, $articles);
2527
 
2528
		$comments = $Comment->find('all', array(
2529
			'fields' => array('id', 'article_id', 'user_id', 'comment', 'published'),
2530
			'recursive' => -1,
2531
			'order' => array('Comment.id' => 'ASC')
2532
		));
2533
		$expected = array(
2534
			array('Comment' => array(
2535
				'id' => 1,
2536
				'article_id' => 1,
2537
				'user_id' => 2,
2538
				'comment' => 'First Comment for First Article',
2539
				'published' => 'Y'
2540
			)),
2541
			array('Comment' => array(
2542
				'id' => 2,
2543
				'article_id' => 1,
2544
				'user_id' => 4,
2545
				'comment' => 'Second Comment for First Article',
2546
				'published' => 'Y'
2547
			)),
2548
			array('Comment' => array(
2549
				'id' => 3,
2550
				'article_id' => 1,
2551
				'user_id' => 1,
2552
				'comment' => 'Third Comment for First Article',
2553
				'published' => 'Y'
2554
			)),
2555
			array('Comment' => array(
2556
				'id' => 4,
2557
				'article_id' => 1,
2558
				'user_id' => 1,
2559
				'comment' => 'Fourth Comment for First Article',
2560
				'published' => 'N'
2561
			)),
2562
			array('Comment' => array(
2563
				'id' => 5,
2564
				'article_id' => 2,
2565
				'user_id' => 1,
2566
				'comment' => 'First Comment for Second Article',
2567
				'published' => 'Y'
2568
			)),
2569
			array('Comment' => array(
2570
				'id' => 6,
2571
				'article_id' => 2,
2572
				'user_id' => 2,
2573
				'comment' => 'Second Comment for Second Article',
2574
				'published' => 'Y'
2575
		)));
2576
		$this->assertEquals($expected, $comments);
2577
 
2578
		$data = array(
2579
			'Comment' => array(
2580
				'article_id' => 2,
2581
				'user_id' => 4,
2582
				'comment' => 'Brand New Comment',
2583
				'published' => 'N'
2584
			),
2585
			'Article' => array(
2586
				'id' => 2,
2587
				'title' => 'Second Article Modified'
2588
		));
2589
		$result = $Comment->create($data);
2590
		$this->assertFalse(empty($result));
2591
 
2592
		$result = $Comment->save();
2593
		$this->assertFalse(empty($result));
2594
 
2595
		$articles = $Article->find('all', array(
2596
			'fields' => array('id', 'title'),
2597
			'recursive' => -1,
2598
			'order' => array('Article.id' => 'ASC')
2599
		));
2600
		$expected = array(
2601
			array('Article' => array(
2602
				'id' => 1,
2603
				'title' => 'First Article'
2604
			)),
2605
			array('Article' => array(
2606
				'id' => 2,
2607
				'title' => 'Second Article'
2608
			)),
2609
			array('Article' => array(
2610
				'id' => 3,
2611
				'title' => 'Third Article'
2612
		)));
2613
		$this->assertEquals($expected, $articles);
2614
 
2615
		$comments = $Comment->find('all', array(
2616
			'fields' => array('id', 'article_id', 'user_id', 'comment', 'published'),
2617
			'recursive' => -1,
2618
			'order' => array('Comment.id' => 'ASC')
2619
		));
2620
		$expected = array(
2621
			array('Comment' => array(
2622
				'id' => 1,
2623
				'article_id' => 1,
2624
				'user_id' => 2,
2625
				'comment' => 'First Comment for First Article',
2626
				'published' => 'Y'
2627
			)),
2628
			array('Comment' => array(
2629
				'id' => 2,
2630
				'article_id' => 1,
2631
				'user_id' => 4,
2632
				'comment' => 'Second Comment for First Article',
2633
				'published' => 'Y'
2634
			)),
2635
			array('Comment' => array(
2636
				'id' => 3,
2637
				'article_id' => 1,
2638
				'user_id' => 1,
2639
				'comment' => 'Third Comment for First Article',
2640
				'published' => 'Y'
2641
			)),
2642
			array('Comment' => array(
2643
				'id' => 4,
2644
				'article_id' => 1,
2645
				'user_id' => 1,
2646
				'comment' => 'Fourth Comment for First Article',
2647
				'published' => 'N'
2648
			)),
2649
			array('Comment' => array(
2650
				'id' => 5,
2651
				'article_id' => 2,
2652
				'user_id' => 1,
2653
				'comment' => 'First Comment for Second Article',
2654
				'published' => 'Y'
2655
			)),
2656
			array('Comment' => array(
2657
				'id' => 6,
2658
				'article_id' => 2,
2659
				'user_id' => 2, 'comment' =>
2660
				'Second Comment for Second Article',
2661
				'published' => 'Y'
2662
			)),
2663
			array('Comment' => array(
2664
				'id' => 7,
2665
				'article_id' => 2,
2666
				'user_id' => 4,
2667
				'comment' => 'Brand New Comment',
2668
				'published' => 'N'
2669
		)));
2670
		$this->assertEquals($expected, $comments);
2671
	}
2672
 
2673
/**
2674
 * testCreationWithMultipleDataSameModel method
2675
 *
2676
 * @return void
2677
 */
2678
	public function testCreationWithMultipleDataSameModel() {
2679
		$this->loadFixtures('Article');
2680
		$Article = new Article();
2681
 
2682
		$result = $Article->field('title', array('id' => 1));
2683
		$this->assertEquals('First Article', $result);
2684
 
2685
		$data = array(
2686
			'Article' => array(
2687
				'user_id' => 2,
2688
				'title' => 'Brand New Article',
2689
				'body' => 'Brand New Article Body',
2690
				'published' => 'Y'
2691
			),
2692
			'SecondaryArticle' => array(
2693
				'id' => 1
2694
		));
2695
 
2696
		$Article->create();
2697
		$result = $Article->save($data);
2698
		$this->assertFalse(empty($result));
2699
 
2700
		$result = $Article->getInsertID();
2701
		$this->assertTrue(!empty($result));
2702
 
2703
		$result = $Article->field('title', array('id' => 1));
2704
		$this->assertEquals('First Article', $result);
2705
 
2706
		$articles = $Article->find('all', array(
2707
			'fields' => array('id', 'title'),
2708
			'recursive' => -1,
2709
			'order' => array('Article.id' => 'ASC')
2710
		));
2711
		$expected = array(
2712
			array('Article' => array(
2713
				'id' => 1,
2714
				'title' => 'First Article'
2715
			)),
2716
			array('Article' => array(
2717
				'id' => 2,
2718
				'title' => 'Second Article'
2719
			)),
2720
			array('Article' => array(
2721
				'id' => 3,
2722
				'title' => 'Third Article'
2723
			)),
2724
			array('Article' => array(
2725
				'id' => 4,
2726
				'title' => 'Brand New Article'
2727
		)));
2728
 
2729
		$this->assertEquals($expected, $articles);
2730
	}
2731
 
2732
/**
2733
 * testCreationWithMultipleDataSameModelManualInstances method
2734
 *
2735
 * @return void
2736
 */
2737
	public function testCreationWithMultipleDataSameModelManualInstances() {
2738
		$this->loadFixtures('PrimaryModel');
2739
		$Primary = new PrimaryModel();
2740
 
2741
		$result = $Primary->field('primary_name', array('id' => 1));
2742
		$this->assertEquals('Primary Name Existing', $result);
2743
 
2744
		$data = array(
2745
			'PrimaryModel' => array(
2746
				'primary_name' => 'Primary Name New'
2747
			),
2748
			'SecondaryModel' => array(
2749
				'id' => array(1)
2750
		));
2751
 
2752
		$Primary->create();
2753
		$result = $Primary->save($data);
2754
		$this->assertFalse(empty($result));
2755
 
2756
		$result = $Primary->field('primary_name', array('id' => 1));
2757
		$this->assertEquals('Primary Name Existing', $result);
2758
 
2759
		$result = $Primary->getInsertID();
2760
		$this->assertTrue(!empty($result));
2761
 
2762
		$result = $Primary->field('primary_name', array('id' => $result));
2763
		$this->assertEquals('Primary Name New', $result);
2764
 
2765
		$result = $Primary->find('count');
2766
		$this->assertEquals(2, $result);
2767
	}
2768
 
2769
/**
2770
 * testRecordExists method
2771
 *
2772
 * @return void
2773
 */
2774
	public function testRecordExists() {
2775
		$this->loadFixtures('User');
2776
		$TestModel = new User();
2777
 
2778
		$this->assertFalse($TestModel->exists());
2779
		$TestModel->read(null, 1);
2780
		$this->assertTrue($TestModel->exists());
2781
		$TestModel->create();
2782
		$this->assertFalse($TestModel->exists());
2783
		$TestModel->id = 4;
2784
		$this->assertTrue($TestModel->exists());
2785
 
2786
		$TestModel = new TheVoid();
2787
		$this->assertFalse($TestModel->exists());
2788
	}
2789
 
2790
/**
2791
 * testRecordExistsMissingTable method
2792
 *
2793
 * @expectedException PDOException
2794
 * @return void
2795
 */
2796
	public function testRecordExistsMissingTable() {
2797
		$TestModel = new TheVoid();
2798
		$TestModel->id = 5;
2799
		$TestModel->exists();
2800
	}
2801
 
2802
/**
2803
 * testUpdateExisting method
2804
 *
2805
 * @return void
2806
 */
2807
	public function testUpdateExisting() {
2808
		$this->loadFixtures('User', 'Article', 'Comment');
2809
		$TestModel = new User();
2810
		$TestModel->create();
2811
 
2812
		$TestModel->save(array(
2813
			'User' => array(
2814
				'user' => 'some user',
2815
				'password' => 'some password'
2816
		)));
2817
		$this->assertTrue(is_int($TestModel->id) || ((int)$TestModel->id === 5));
2818
		$id = $TestModel->id;
2819
 
2820
		$TestModel->save(array(
2821
			'User' => array(
2822
				'user' => 'updated user'
2823
		)));
2824
		$this->assertEquals($id, $TestModel->id);
2825
 
2826
		$result = $TestModel->findById($id);
2827
		$this->assertEquals('updated user', $result['User']['user']);
2828
		$this->assertEquals('some password', $result['User']['password']);
2829
 
2830
		$Article = new Article();
2831
		$Comment = new Comment();
2832
		$data = array(
2833
			'Comment' => array(
2834
				'id' => 1,
2835
				'comment' => 'First Comment for First Article'
2836
			),
2837
			'Article' => array(
2838
				'id' => 2,
2839
				'title' => 'Second Article'
2840
		));
2841
 
2842
		$result = $Article->save($data);
2843
		$this->assertFalse(empty($result));
2844
 
2845
		$result = $Comment->save($data);
2846
		$this->assertFalse(empty($result));
2847
	}
2848
 
2849
/**
2850
 * test updating records and saving blank values.
2851
 *
2852
 * @return void
2853
 */
2854
	public function testUpdateSavingBlankValues() {
2855
		$this->loadFixtures('Article');
2856
		$Article = new Article();
2857
		$Article->validate = array();
2858
		$Article->create();
2859
		$result = $Article->save(array(
2860
			'id' => 1,
2861
			'title' => '',
2862
			'body' => ''
2863
		));
2864
		$this->assertTrue((bool)$result);
2865
		$result = $Article->find('first', array('conditions' => array('Article.id' => 1)));
2866
		$this->assertEquals('', $result['Article']['title'], 'Title is not blank');
2867
		$this->assertEquals('', $result['Article']['body'], 'Body is not blank');
2868
	}
2869
 
2870
/**
2871
 * testUpdateMultiple method
2872
 *
2873
 * @return void
2874
 */
2875
	public function testUpdateMultiple() {
2876
		$this->loadFixtures('Comment', 'Article', 'User', 'CategoryThread');
2877
		$TestModel = new Comment();
2878
		$result = Hash::extract($TestModel->find('all'), '{n}.Comment.user_id');
2879
		$expected = array('2', '4', '1', '1', '1', '2');
2880
		$this->assertEquals($expected, $result);
2881
 
2882
		$TestModel->updateAll(array('Comment.user_id' => 5), array('Comment.user_id' => 2));
2883
		$result = Hash::combine($TestModel->find('all'), '{n}.Comment.id', '{n}.Comment.user_id');
2884
		$expected = array(1 => 5, 2 => 4, 3 => 1, 4 => 1, 5 => 1, 6 => 5);
2885
		$this->assertEquals($expected, $result);
2886
 
2887
		$result = $TestModel->updateAll(
2888
			array('Comment.comment' => "'Updated today'"),
2889
			array('Comment.user_id' => 5)
2890
		);
2891
		$this->assertFalse(empty($result));
2892
		$result = Hash::extract(
2893
			$TestModel->find('all', array(
2894
				'conditions' => array(
2895
					'Comment.user_id' => 5
2896
			))),
2897
			'{n}.Comment.comment'
2898
		);
2899
		$expected = array_fill(0, 2, 'Updated today');
2900
		$this->assertEquals($expected, $result);
2901
	}
2902
 
2903
/**
2904
 * testHabtmUuidWithUuidId method
2905
 *
2906
 * @return void
2907
 */
2908
	public function testHabtmUuidWithUuidId() {
2909
		$this->loadFixtures('Uuidportfolio', 'Uuiditem', 'UuiditemsUuidportfolio', 'UuiditemsUuidportfolioNumericid');
2910
		$TestModel = new Uuidportfolio();
2911
 
2912
		$data = array('Uuidportfolio' => array('name' => 'Portfolio 3'));
2913
		$data['Uuiditem']['Uuiditem'] = array('483798c8-c7cc-430e-8cf9-4fcc40cf8569');
2914
		$TestModel->create($data);
2915
		$TestModel->save();
2916
		$id = $TestModel->id;
2917
		$result = $TestModel->read(null, $id);
2918
		$this->assertEquals(1, count($result['Uuiditem']));
2919
		$this->assertEquals(36, strlen($result['Uuiditem'][0]['UuiditemsUuidportfolio']['id']));
2920
	}
2921
 
2922
/**
2923
 * test HABTM saving when join table has no primary key and only 2 columns.
2924
 *
2925
 * @return void
2926
 */
2927
	public function testHabtmSavingWithNoPrimaryKeyUuidJoinTable() {
2928
		$this->loadFixtures('UuidTag', 'Fruit', 'FruitsUuidTag');
2929
		$Fruit = new Fruit();
2930
		$Fruit->FruitsUuidTag->order = null;
2931
		$data = array(
2932
			'Fruit' => array(
2933
				'color' => 'Red',
2934
				'shape' => 'Heart-shaped',
2935
				'taste' => 'sweet',
2936
				'name' => 'Strawberry',
2937
			),
2938
			'UuidTag' => array(
2939
				'UuidTag' => array(
2940
					'481fc6d0-b920-43e0-e50f-6d1740cf8569'
2941
				)
2942
			)
2943
		);
2944
		$result = $Fruit->save($data);
2945
		$this->assertFalse(empty($result));
2946
	}
2947
 
2948
/**
2949
 * test HABTM saving when join table has no primary key and only 2 columns, no with model is used.
2950
 *
2951
 * @return void
2952
 */
2953
	public function testHabtmSavingWithNoPrimaryKeyUuidJoinTableNoWith() {
2954
		$this->loadFixtures('UuidTag', 'Fruit', 'FruitsUuidTag');
2955
		$Fruit = new FruitNoWith();
2956
		$data = array(
2957
			'Fruit' => array(
2958
				'color' => 'Red',
2959
				'shape' => 'Heart-shaped',
2960
				'taste' => 'sweet',
2961
				'name' => 'Strawberry',
2962
			),
2963
			'UuidTag' => array(
2964
				'UuidTag' => array(
2965
					'481fc6d0-b920-43e0-e50f-6d1740cf8569'
2966
				)
2967
			)
2968
		);
2969
		$result = $Fruit->save($data);
2970
		$this->assertFalse(empty($result));
2971
	}
2972
 
2973
/**
2974
 * testHabtmUuidWithNumericId method
2975
 *
2976
 * @return void
2977
 */
2978
	public function testHabtmUuidWithNumericId() {
2979
		$this->loadFixtures('Uuidportfolio', 'Uuiditem', 'UuiditemsUuidportfolioNumericid');
2980
		$TestModel = new Uuiditem();
2981
 
2982
		$data = array('Uuiditem' => array('name' => 'Item 7', 'published' => 0));
2983
		$data['Uuidportfolio']['Uuidportfolio'] = array('480af662-eb8c-47d3-886b-230540cf8569');
2984
		$TestModel->create($data);
2985
		$TestModel->save();
2986
		$id = $TestModel->id;
2987
		$result = $TestModel->read(null, $id);
2988
		$this->assertEquals(1, count($result['Uuidportfolio']));
2989
	}
2990
 
2991
/**
2992
 * testSaveMultipleHabtm method
2993
 *
2994
 * @return void
2995
 */
2996
	public function testSaveMultipleHabtm() {
2997
		$this->loadFixtures('JoinA', 'JoinB', 'JoinC', 'JoinAB', 'JoinAC');
2998
		$TestModel = new JoinA();
2999
		$result = $TestModel->findById(1);
3000
 
3001
		$expected = array(
3002
			'JoinA' => array(
3003
				'id' => 1,
3004
				'name' => 'Join A 1',
3005
				'body' => 'Join A 1 Body',
3006
				'created' => '2008-01-03 10:54:23',
3007
				'updated' => '2008-01-03 10:54:23'
3008
			),
3009
			'JoinB' => array(
3010
 
3011
					'id' => 2,
3012
					'name' => 'Join B 2',
3013
					'created' => '2008-01-03 10:55:02',
3014
					'updated' => '2008-01-03 10:55:02',
3015
					'JoinAsJoinB' => array(
3016
						'id' => 1,
3017
						'join_a_id' => 1,
3018
						'join_b_id' => 2,
3019
						'other' => 'Data for Join A 1 Join B 2',
3020
						'created' => '2008-01-03 10:56:33',
3021
						'updated' => '2008-01-03 10:56:33'
3022
			))),
3023
			'JoinC' => array(
3024
 
3025
					'id' => 2,
3026
					'name' => 'Join C 2',
3027
					'created' => '2008-01-03 10:56:12',
3028
					'updated' => '2008-01-03 10:56:12',
3029
					'JoinAsJoinC' => array(
3030
						'id' => 1,
3031
						'join_a_id' => 1,
3032
						'join_c_id' => 2,
3033
						'other' => 'Data for Join A 1 Join C 2',
3034
						'created' => '2008-01-03 10:57:22',
3035
						'updated' => '2008-01-03 10:57:22'
3036
		))));
3037
 
3038
		$this->assertEquals($expected, $result);
3039
 
3040
		$TestModel->id = 1;
3041
		$data = array(
3042
			'JoinA' => array(
3043
				'id' => '1',
3044
				'name' => 'New name for Join A 1',
3045
				'updated' => self::date()
3046
			),
3047
			'JoinB' => array(
3048
				array(
3049
					'id' => 1,
3050
					'join_b_id' => 2,
3051
					'other' => 'New data for Join A 1 Join B 2',
3052
					'created' => self::date(),
3053
					'updated' => self::date()
3054
			)),
3055
			'JoinC' => array(
3056
				array(
3057
					'id' => 1,
3058
					'join_c_id' => 2,
3059
					'other' => 'New data for Join A 1 Join C 2',
3060
					'created' => self::date(),
3061
					'updated' => self::date()
3062
		)));
3063
 
3064
		$TestModel->set($data);
3065
		$TestModel->save();
3066
 
3067
		$result = $TestModel->findById(1);
3068
		$expected = array(
3069
			'JoinA' => array(
3070
				'id' => 1,
3071
				'name' => 'New name for Join A 1',
3072
				'body' => 'Join A 1 Body',
3073
				'created' => '2008-01-03 10:54:23',
3074
				'updated' => self::date()
3075
			),
3076
			'JoinB' => array(
3077
 
3078
					'id' => 2,
3079
					'name' => 'Join B 2',
3080
					'created' => '2008-01-03 10:55:02',
3081
					'updated' => '2008-01-03 10:55:02',
3082
					'JoinAsJoinB' => array(
3083
						'id' => 1,
3084
						'join_a_id' => 1,
3085
						'join_b_id' => 2,
3086
						'other' => 'New data for Join A 1 Join B 2',
3087
						'created' => self::date(),
3088
						'updated' => self::date()
3089
			))),
3090
			'JoinC' => array(
3091
 
3092
					'id' => 2,
3093
					'name' => 'Join C 2',
3094
					'created' => '2008-01-03 10:56:12',
3095
					'updated' => '2008-01-03 10:56:12',
3096
					'JoinAsJoinC' => array(
3097
						'id' => 1,
3098
						'join_a_id' => 1,
3099
						'join_c_id' => 2,
3100
						'other' => 'New data for Join A 1 Join C 2',
3101
						'created' => self::date(),
3102
						'updated' => self::date()
3103
		))));
3104
 
3105
		$this->assertEquals($expected, $result);
3106
	}
3107
 
3108
/**
3109
 * testSaveAll method
3110
 *
3111
 * @return void
3112
 */
3113
	public function testSaveAll() {
3114
		$this->loadFixtures('Post', 'Author', 'Comment', 'Attachment', 'Article', 'User');
3115
		$TestModel = new Post();
3116
 
3117
		$result = $TestModel->find('all');
3118
		$this->assertEquals(3, count($result));
3119
		$this->assertFalse(isset($result[3]));
3120
 
3121
		$TestModel->saveAll(array(
3122
			'Post' => array(
3123
				'title' => 'Post with Author',
3124
				'body' => 'This post will be saved with an author'
3125
			),
3126
			'Author' => array(
3127
				'user' => 'bob',
3128
				'password' => '5f4dcc3b5aa765d61d8327deb882cf90'
3129
		)));
3130
 
3131
		$result = $TestModel->find('all');
3132
		$expected = array(
3133
			'Post' => array(
3134
				'id' => '4',
3135
				'author_id' => '5',
3136
				'title' => 'Post with Author',
3137
				'body' => 'This post will be saved with an author',
3138
				'published' => 'N'
3139
			),
3140
			'Author' => array(
3141
				'id' => '5',
3142
				'user' => 'bob',
3143
				'password' => '5f4dcc3b5aa765d61d8327deb882cf90',
3144
				'test' => 'working'
3145
		));
3146
		$this->assertEquals(self::date(), $result[3]['Post']['created']);
3147
		$this->assertEquals(self::date(), $result[3]['Post']['updated']);
3148
		$this->assertEquals(self::date(), $result[3]['Author']['created']);
3149
		$this->assertEquals(self::date(), $result[3]['Author']['updated']);
3150
		unset($result[3]['Post']['created'], $result[3]['Post']['updated']);
3151
		unset($result[3]['Author']['created'], $result[3]['Author']['updated']);
3152
		$this->assertEquals($expected, $result[3]);
3153
		$this->assertEquals(4, count($result));
3154
 
3155
		$TestModel->deleteAll(true);
3156
		$this->assertEquals(array(), $TestModel->find('all'));
3157
 
3158
		// SQLite seems to reset the PK counter when that happens, so we need this to make the tests pass
3159
		$this->db->truncate($TestModel);
3160
 
3161
		$TestModel->saveAll(array(
3162
			array(
3163
				'title' => 'Multi-record post 1',
3164
				'body' => 'First multi-record post',
3165
				'author_id' => 2
3166
			),
3167
			array(
3168
				'title' => 'Multi-record post 2',
3169
				'body' => 'Second multi-record post',
3170
				'author_id' => 2
3171
		)));
3172
 
3173
		$result = $TestModel->find('all', array(
3174
			'recursive' => -1,
3175
			'order' => 'Post.id ASC'
3176
		));
3177
		$expected = array(
3178
			array(
3179
				'Post' => array(
3180
					'id' => '1',
3181
					'author_id' => '2',
3182
					'title' => 'Multi-record post 1',
3183
					'body' => 'First multi-record post',
3184
					'published' => 'N'
3185
			)),
3186
			array(
3187
				'Post' => array(
3188
					'id' => '2',
3189
					'author_id' => '2',
3190
					'title' => 'Multi-record post 2',
3191
					'body' => 'Second multi-record post',
3192
					'published' => 'N'
3193
		)));
3194
		$this->assertEquals(self::date(), $result[0]['Post']['created']);
3195
		$this->assertEquals(self::date(), $result[0]['Post']['updated']);
3196
		$this->assertEquals(self::date(), $result[1]['Post']['created']);
3197
		$this->assertEquals(self::date(), $result[1]['Post']['updated']);
3198
		unset($result[0]['Post']['created'], $result[0]['Post']['updated']);
3199
		unset($result[1]['Post']['created'], $result[1]['Post']['updated']);
3200
		$this->assertEquals($expected, $result);
3201
 
3202
		$TestModel = new Comment();
3203
		$result = $TestModel->saveAll(array(
3204
			'Comment' => array(
3205
				'article_id' => 2,
3206
				'user_id' => 2,
3207
				'comment' => 'New comment with attachment',
3208
				'published' => 'Y'
3209
			),
3210
			'Attachment' => array(
3211
				'attachment' => 'some_file.tgz'
3212
			)));
3213
		$this->assertFalse(empty($result));
3214
 
3215
		$result = $TestModel->find('all');
3216
		$expected = array(
3217
			'id' => '7',
3218
			'article_id' => '2',
3219
			'user_id' => '2',
3220
			'comment' => 'New comment with attachment',
3221
			'published' => 'Y'
3222
		);
3223
		$this->assertEquals(self::date(), $result[6]['Comment']['created']);
3224
		$this->assertEquals(self::date(), $result[6]['Comment']['updated']);
3225
		unset($result[6]['Comment']['created'], $result[6]['Comment']['updated']);
3226
		$this->assertEquals($expected, $result[6]['Comment']);
3227
 
3228
		$expected = array(
3229
			'id' => '2',
3230
			'comment_id' => '7',
3231
			'attachment' => 'some_file.tgz'
3232
		);
3233
		$this->assertEquals(self::date(), $result[6]['Attachment']['created']);
3234
		$this->assertEquals(self::date(), $result[6]['Attachment']['updated']);
3235
		unset($result[6]['Attachment']['created'], $result[6]['Attachment']['updated']);
3236
		$this->assertEquals($expected, $result[6]['Attachment']);
3237
	}
3238
 
3239
/**
3240
 * Test SaveAll with Habtm relations
3241
 *
3242
 * @return void
3243
 */
3244
	public function testSaveAllHabtm() {
3245
		$this->loadFixtures('Article', 'Tag', 'Comment', 'User', 'ArticlesTag');
3246
		$data = array(
3247
			'Article' => array(
3248
				'user_id' => 1,
3249
				'title' => 'Article Has and belongs to Many Tags'
3250
			),
3251
			'Tag' => array(
3252
				'Tag' => array(1, 2)
3253
			),
3254
			'Comment' => array(
3255
				array(
3256
					'comment' => 'Article comment',
3257
					'user_id' => 1
3258
		)));
3259
		$Article = new Article();
3260
		$result = $Article->saveAll($data);
3261
		$this->assertFalse(empty($result));
3262
 
3263
		$result = $Article->read();
3264
		$this->assertEquals(2, count($result['Tag']));
3265
		$this->assertEquals('tag1', $result['Tag'][0]['tag']);
3266
		$this->assertEquals(1, count($result['Comment']));
3267
		$this->assertEquals(1, count($result['Comment'][0]['comment']));
3268
	}
3269
 
3270
/**
3271
 * Test SaveAll with Habtm relations and extra join table fields
3272
 *
3273
 * @return void
3274
 */
3275
	public function testSaveAllHabtmWithExtraJoinTableFields() {
3276
		$this->loadFixtures('Something', 'SomethingElse', 'JoinThing');
3277
 
3278
		$data = array(
3279
			'Something' => array(
3280
				'id' => 4,
3281
				'title' => 'Extra Fields',
3282
				'body' => 'Extra Fields Body',
3283
				'published' => '1'
3284
			),
3285
			'SomethingElse' => array(
3286
				array('something_else_id' => 1, 'doomed' => '1'),
3287
				array('something_else_id' => 2, 'doomed' => '0'),
3288
				array('something_else_id' => 3, 'doomed' => '1')
3289
			)
3290
		);
3291
 
3292
		$Something = new Something();
3293
		$result = $Something->saveAll($data);
3294
		$this->assertFalse(empty($result));
3295
		$result = $Something->read();
3296
 
3297
		$this->assertEquals(3, count($result['SomethingElse']));
3298
		$this->assertTrue(Set::matches('/Something[id=4]', $result));
3299
 
3300
		$this->assertTrue(Set::matches('/SomethingElse[id=1]', $result));
3301
		$this->assertTrue(Set::matches('/SomethingElse[id=1]/JoinThing[something_else_id=1]', $result));
3302
		$this->assertTrue(Set::matches('/SomethingElse[id=1]/JoinThing[doomed=1]', $result));
3303
 
3304
		$this->assertTrue(Set::matches('/SomethingElse[id=2]', $result));
3305
		$this->assertTrue(Set::matches('/SomethingElse[id=2]/JoinThing[something_else_id=2]', $result));
3306
		$this->assertTrue(Set::matches('/SomethingElse[id=2]/JoinThing[doomed=0]', $result));
3307
 
3308
		$this->assertTrue(Set::matches('/SomethingElse[id=3]', $result));
3309
		$this->assertTrue(Set::matches('/SomethingElse[id=3]/JoinThing[something_else_id=3]', $result));
3310
		$this->assertTrue(Set::matches('/SomethingElse[id=3]/JoinThing[doomed=1]', $result));
3311
	}
3312
 
3313
/**
3314
 * testSaveAllHasOne method
3315
 *
3316
 * @return void
3317
 */
3318
	public function testSaveAllHasOne() {
3319
		$model = new Comment();
3320
		$model->deleteAll(true);
3321
		$this->assertEquals(array(), $model->find('all'));
3322
 
3323
		$model->Attachment->deleteAll(true);
3324
		$this->assertEquals(array(), $model->Attachment->find('all'));
3325
 
3326
		$this->assertTrue($model->saveAll(array(
3327
			'Comment' => array(
3328
				'comment' => 'Comment with attachment',
3329
				'article_id' => 1,
3330
				'user_id' => 1
3331
			),
3332
			'Attachment' => array(
3333
				'attachment' => 'some_file.zip'
3334
		))));
3335
		$result = $model->find('all', array('fields' => array(
3336
			'Comment.id', 'Comment.comment', 'Attachment.id',
3337
			'Attachment.comment_id', 'Attachment.attachment'
3338
		)));
3339
		$expected = array(array(
3340
			'Comment' => array(
3341
				'id' => '1',
3342
				'comment' => 'Comment with attachment'
3343
			),
3344
			'Attachment' => array(
3345
				'id' => '1',
3346
				'comment_id' => '1',
3347
				'attachment' => 'some_file.zip'
3348
		)));
3349
		$this->assertEquals($expected, $result);
3350
 
3351
		$model->Attachment->bindModel(array('belongsTo' => array('Comment')), false);
3352
		$data = array(
3353
			'Comment' => array(
3354
				'comment' => 'Comment with attachment',
3355
				'article_id' => 1,
3356
				'user_id' => 1
3357
			),
3358
			'Attachment' => array(
3359
				'attachment' => 'some_file.zip'
3360
		));
3361
		$this->assertTrue($model->saveAll($data, array('validate' => 'first')));
3362
	}
3363
 
3364
/**
3365
 * testSaveAllBelongsTo method
3366
 *
3367
 * @return void
3368
 */
3369
	public function testSaveAllBelongsTo() {
3370
		$model = new Comment();
3371
		$model->deleteAll(true);
3372
		$this->assertEquals(array(), $model->find('all'));
3373
 
3374
		$model->Article->deleteAll(true);
3375
		$this->assertEquals(array(), $model->Article->find('all'));
3376
 
3377
		$this->assertTrue($model->saveAll(array(
3378
			'Comment' => array(
3379
				'comment' => 'Article comment',
3380
				'article_id' => 1,
3381
				'user_id' => 1
3382
			),
3383
			'Article' => array(
3384
				'title' => 'Model Associations 101',
3385
				'user_id' => 1
3386
		))));
3387
		$result = $model->find('all', array('fields' => array(
3388
			'Comment.id', 'Comment.comment', 'Comment.article_id', 'Article.id', 'Article.title'
3389
		)));
3390
		$expected = array(array(
3391
			'Comment' => array(
3392
				'id' => '1',
3393
				'article_id' => '1',
3394
				'comment' => 'Article comment'
3395
			),
3396
			'Article' => array(
3397
				'id' => '1',
3398
				'title' => 'Model Associations 101'
3399
		)));
3400
		$this->assertEquals($expected, $result);
3401
	}
3402
 
3403
/**
3404
 * testSaveAllHasOneValidation method
3405
 *
3406
 * @return void
3407
 */
3408
	public function testSaveAllHasOneValidation() {
3409
		$model = new Comment();
3410
		$model->deleteAll(true);
3411
		$this->assertEquals(array(), $model->find('all'));
3412
 
3413
		$model->Attachment->deleteAll(true);
3414
		$this->assertEquals(array(), $model->Attachment->find('all'));
3415
 
3416
		$model->validate = array('comment' => 'notEmpty');
3417
		$model->Attachment->validate = array('attachment' => 'notEmpty');
3418
		$model->Attachment->bindModel(array('belongsTo' => array('Comment')));
3419
 
3420
		$result = $model->saveAll(
3421
			array(
3422
				'Comment' => array(
3423
					'comment' => '',
3424
					'article_id' => 1,
3425
					'user_id' => 1
3426
				),
3427
				'Attachment' => array('attachment' => '')
3428
			),
3429
			array('validate' => 'first')
3430
		);
3431
		$this->assertEquals(false, $result);
3432
		$expected = array(
3433
			'comment' => array('This field cannot be left blank'),
3434
			'Attachment' => array(
3435
				'attachment' => array('This field cannot be left blank')
3436
			)
3437
		);
3438
		$this->assertEquals($expected, $model->validationErrors);
3439
		$this->assertEquals($expected['Attachment'], $model->Attachment->validationErrors);
3440
	}
3441
 
3442
/**
3443
 * testSaveAllAtomic method
3444
 *
3445
 * @return void
3446
 */
3447
	public function testSaveAllAtomic() {
3448
		$this->loadFixtures('Article', 'User', 'Comment');
3449
		$TestModel = new Article();
3450
 
3451
		$result = $TestModel->saveAll(array(
3452
			'Article' => array(
3453
				'title' => 'Post with Author',
3454
				'body' => 'This post will be saved with an author',
3455
				'user_id' => 2
3456
			),
3457
			'Comment' => array(
3458
				array('comment' => 'First new comment', 'user_id' => 2))
3459
		), array('atomic' => false));
3460
 
3461
		$this->assertSame($result, array('Article' => true, 'Comment' => array(true)));
3462
 
3463
		$result = $TestModel->saveAll(array(
3464
			array(
3465
				'id' => '1',
3466
				'title' => 'Baleeted First Post',
3467
				'body' => 'Baleeted!',
3468
				'published' => 'N'
3469
			),
3470
			array(
3471
				'id' => '2',
3472
				'title' => 'Just update the title'
3473
			),
3474
			array(
3475
				'title' => 'Creating a fourth post',
3476
				'body' => 'Fourth post body',
3477
				'user_id' => 2
3478
			)
3479
		), array('atomic' => false));
3480
		$this->assertSame($result, array(true, true, true));
3481
 
3482
		$result = $TestModel->saveAll(array(
3483
			'Article' => array('id' => 2),
3484
			'Comment' => array(
3485
				array(
3486
					'comment' => 'First new comment',
3487
					'published' => 'Y',
3488
					'user_id' => 1
3489
				),
3490
				array(
3491
					'comment' => 'Second new comment',
3492
					'published' => 'Y',
3493
					'user_id' => 2
3494
			))
3495
		), array('validate' => true, 'atomic' => false));
3496
		$this->assertSame($result, array('Article' => true, 'Comment' => array(true, true)));
3497
 
3498
		$TestModel->validate = array(
3499
			'title' => 'notEmpty',
3500
			'author_id' => 'numeric'
3501
		);
3502
		$result = $TestModel->saveAll(array(
3503
			array(
3504
				'id' => '1',
3505
				'title' => 'Un-Baleeted First Post',
3506
				'body' => 'Not Baleeted!',
3507
				'published' => 'Y'
3508
			),
3509
			array(
3510
				'id' => '2',
3511
				'title' => '',
3512
				'body' => 'Trying to get away with an empty title'
3513
			)
3514
		), array('validate' => true, 'atomic' => false));
3515
		$this->assertSame(array(true, false), $result);
3516
	}
3517
 
3518
/**
3519
 * testSaveAllDeepAssociated method
3520
 *
3521
 * @return void
3522
 */
3523
	public function testSaveAllDeepAssociated() {
3524
		$this->loadFixtures('Article', 'Comment', 'User', 'Attachment');
3525
		$TestModel = new Article();
3526
		$TestModel->hasMany['Comment']['order'] = array('Comment.created' => 'ASC');
3527
		$TestModel->hasAndBelongsToMany = array();
3528
 
3529
		$result = $TestModel->saveAll(array(
3530
			'Article' => array('id' => 2),
3531
			'Comment' => array(
3532
				array('comment' => 'First new comment', 'published' => 'Y', 'User' => array('user' => 'newuser', 'password' => 'newuserpass')),
3533
				array('comment' => 'Second new comment', 'published' => 'Y', 'user_id' => 2)
3534
			)
3535
		), array('deep' => true));
3536
		$this->assertTrue($result);
3537
 
3538
		$result = $TestModel->findById(2);
3539
		$expected = array(
3540
			'First Comment for Second Article',
3541
			'Second Comment for Second Article',
3542
			'First new comment',
3543
			'Second new comment'
3544
		);
3545
		$result = Hash::extract(Hash::sort($result['Comment'], '{n}.id', 'ASC'), '{n}.comment');
3546
		$this->assertEquals($expected, $result);
3547
 
3548
		$result = $TestModel->Comment->User->field('id', array('user' => 'newuser', 'password' => 'newuserpass'));
3549
		$this->assertEquals(5, $result);
3550
		$result = $TestModel->saveAll(array(
3551
			'Article' => array('id' => 2),
3552
			'Comment' => array(
3553
				array('comment' => 'Third new comment', 'published' => 'Y', 'user_id' => 5),
3554
				array('comment' => 'Fourth new comment', 'published' => 'Y', 'user_id' => 2, 'Attachment' => array('attachment' => 'deepsaved'))
3555
			)
3556
		), array('deep' => true));
3557
		$this->assertTrue($result);
3558
 
3559
		$result = $TestModel->findById(2);
3560
		$expected = array(
3561
			'First Comment for Second Article',
3562
			'Second Comment for Second Article',
3563
			'First new comment',
3564
			'Second new comment',
3565
			'Third new comment',
3566
			'Fourth new comment'
3567
		);
3568
		$result = Hash::extract(Hash::sort($result['Comment'], '{n}.id', 'ASC'), '{n}.comment');
3569
		$this->assertEquals($expected, $result);
3570
 
3571
		$result = $TestModel->Comment->Attachment->field('id', array('attachment' => 'deepsaved'));
3572
		$this->assertEquals(2, $result);
3573
		$data = array(
3574
			'Attachment' => array(
3575
				'attachment' => 'deepsave insert',
3576
			),
3577
			'Comment' => array(
3578
				'comment' => 'First comment deepsave insert',
3579
				'published' => 'Y',
3580
				'user_id' => 5,
3581
				'Article' => array(
3582
					'title' => 'First Article deepsave insert',
3583
					'body' => 'First Article Body deepsave insert',
3584
					'User' => array(
3585
						'user' => '',
3586
						'password' => 'magic'
3587
					),
3588
				),
3589
			)
3590
		);
3591
 
3592
		$TestModel->Comment->Attachment->create();
3593
		$result = $TestModel->Comment->Attachment->saveAll($data, array('deep' => true));
3594
		$this->assertFalse($result);
3595
 
3596
		$expected = array('User' => array('user' => array('This field cannot be left blank')));
3597
		$this->assertEquals($expected, $TestModel->validationErrors);
3598
 
3599
		$data['Comment']['Article']['User']['user'] = 'deepsave';
3600
		$TestModel->Comment->Attachment->create();
3601
		$result = $TestModel->Comment->Attachment->saveAll($data, array('deep' => true));
3602
		$this->assertTrue($result);
3603
 
3604
		$result = $TestModel->Comment->Attachment->findById($TestModel->Comment->Attachment->id);
3605
		$expected = array(
3606
			'Attachment' => array(
3607
				'id' => '3',
3608
				'comment_id' => '11',
3609
				'attachment' => 'deepsave insert',
3610
			),
3611
			'Comment' => array(
3612
				'id' => '11',
3613
				'article_id' => '4',
3614
				'user_id' => '5',
3615
				'comment' => 'First comment deepsave insert',
3616
				'published' => 'Y',
3617
			)
3618
		);
3619
		unset($result['Attachment']['created'], $result['Attachment']['updated']);
3620
		$this->assertEquals($expected['Attachment'], $result['Attachment']);
3621
 
3622
		unset($result['Comment']['created'], $result['Comment']['updated']);
3623
		$this->assertEquals($expected['Comment'], $result['Comment']);
3624
 
3625
		$result = $TestModel->findById($result['Comment']['article_id']);
3626
		$expected = array(
3627
			'Article' => array(
3628
				'id' => '4',
3629
				'user_id' => '6',
3630
				'title' => 'First Article deepsave insert',
3631
				'body' => 'First Article Body deepsave insert',
3632
				'published' => 'N',
3633
			),
3634
			'User' => array(
3635
				'id' => '6',
3636
				'user' => 'deepsave',
3637
				'password' => 'magic',
3638
			),
3639
			'Comment' => array(
3640
				array(
3641
					'id' => '11',
3642
					'article_id' => '4',
3643
					'user_id' => '5',
3644
					'comment' => 'First comment deepsave insert',
3645
					'published' => 'Y',
3646
				)
3647
			)
3648
		);
3649
		unset(
3650
			$result['Article']['created'], $result['Article']['updated'],
3651
			$result['User']['created'], $result['User']['updated'],
3652
			$result['Comment'][0]['created'], $result['Comment'][0]['updated']
3653
		);
3654
		$this->assertEquals($expected, $result);
3655
	}
3656
 
3657
/**
3658
 * testSaveAllDeepMany
3659
 * tests the validate methods with deeper recursive data
3660
 *
3661
 * @return void
3662
 */
3663
	public function testSaveAllDeepMany() {
3664
		$this->loadFixtures('Article', 'Comment', 'User', 'Attachment');
3665
		$TestModel = new Article();
3666
		$TestModel->hasMany['Comment']['order'] = array('Comment.created' => 'ASC');
3667
		$TestModel->hasAndBelongsToMany = array();
3668
 
3669
		$data = array(
3670
			array(
3671
				'Article' => array('id' => 1),
3672
				'Comment' => array(
3673
					array('comment' => 'First comment deepsaved article 1', 'published' => 'Y', 'User' => array('user' => 'savemany', 'password' => 'manysaved')),
3674
					array('comment' => 'Second comment deepsaved article 1', 'published' => 'Y', 'user_id' => 2)
3675
				)
3676
			),
3677
			array(
3678
				'Article' => array('id' => 2),
3679
				'Comment' => array(
3680
					array('comment' => 'First comment deepsaved article 2', 'published' => 'Y', 'User' => array('user' => 'savemore', 'password' => 'moresaved')),
3681
					array('comment' => 'Second comment deepsaved article 2', 'published' => 'Y', 'user_id' => 2)
3682
				)
3683
			)
3684
		);
3685
		$result = $TestModel->saveAll($data, array('deep' => true));
3686
		$this->assertTrue($result);
3687
 
3688
		$data = array(
3689
			array(
3690
				'id' => 1, 'body' => '',
3691
				'Comment' => array(
3692
					array('comment' => '', 'published' => 'Y', 'User' => array('user' => '', 'password' => 'manysaved')),
3693
					array('comment' => 'Second comment deepsaved article 1', 'published' => 'Y', 'user_id' => 2)
3694
				)
3695
			),
3696
			array(
3697
				'Article' => array('id' => 2),
3698
				'Comment' => array(
3699
					array('comment' => 'First comment deepsaved article 2', 'published' => 'Y', 'User' => array('user' => 'savemore', 'password' => '')),
3700
					array('comment' => '', 'published' => 'Y', 'user_id' => 2)
3701
				)
3702
			)
3703
		);
3704
		$TestModel->Comment->validate['comment'] = 'notEmpty';
3705
		$result = $TestModel->saveAll($data, array('deep' => true));
3706
		$this->assertFalse($result);
3707
 
3708
		$expected = array(
3709
 
3710
				'body' => array('This field cannot be left blank'),
3711
				'Comment' => array(
3712
 
3713
						'comment' => array('This field cannot be left blank'),
3714
						'User' => array(
3715
							'user' => array('This field cannot be left blank')
3716
						)
3717
					)
3718
				)
3719
			),
3720
			1 => array(
3721
				'Comment' => array(
3722
 
3723
						'User' => array(
3724
							'password' => array('This field cannot be left blank')
3725
						)
3726
					),
3727
					1 => array(
3728
						'comment' => array('This field cannot be left blank')
3729
					)
3730
				)
3731
			)
3732
		);
3733
		$result = $TestModel->validationErrors;
3734
		$this->assertSame($expected, $result);
3735
	}
3736
/**
3737
 * testSaveAllDeepValidateOnly
3738
 * tests the validate methods with deeper recursive data
3739
 *
3740
 * @return void
3741
 */
3742
	public function testSaveAllDeepValidateOnly() {
3743
		$this->loadFixtures('Article', 'Comment', 'User', 'Attachment');
3744
		$TestModel = new Article();
3745
		$TestModel->hasMany['Comment']['order'] = array('Comment.created' => 'ASC');
3746
		$TestModel->hasAndBelongsToMany = array();
3747
		$TestModel->Comment->Attachment->validate['attachment'] = 'notEmpty';
3748
		$TestModel->Comment->validate['comment'] = 'notEmpty';
3749
 
3750
		$result = $TestModel->saveAll(
3751
			array(
3752
				'Article' => array('id' => 2),
3753
				'Comment' => array(
3754
					array('comment' => 'First new comment', 'published' => 'Y', 'User' => array('user' => 'newuser', 'password' => 'newuserpass')),
3755
					array('comment' => 'Second new comment', 'published' => 'Y', 'user_id' => 2)
3756
				)
3757
			),
3758
			array('validate' => 'only', 'deep' => true)
3759
		);
3760
		$this->assertTrue($result);
3761
 
3762
		$result = $TestModel->saveAll(
3763
			array(
3764
				'Article' => array('id' => 2),
3765
				'Comment' => array(
3766
					array('comment' => 'First new comment', 'published' => 'Y', 'User' => array('user' => '', 'password' => 'newuserpass')),
3767
					array('comment' => 'Second new comment', 'published' => 'Y', 'user_id' => 2)
3768
				)
3769
			),
3770
			array('validate' => 'only', 'deep' => true)
3771
		);
3772
		$this->assertFalse($result);
3773
 
3774
		$result = $TestModel->saveAll(
3775
			array(
3776
				'Article' => array('id' => 2),
3777
				'Comment' => array(
3778
					array('comment' => 'First new comment', 'published' => 'Y', 'User' => array('user' => 'newuser', 'password' => 'newuserpass')),
3779
					array('comment' => 'Second new comment', 'published' => 'Y', 'user_id' => 2)
3780
				)
3781
			),
3782
			array('validate' => 'only', 'atomic' => false, 'deep' => true)
3783
		);
3784
		$expected = array(
3785
			'Article' => true,
3786
			'Comment' => array(
3787
				true,
3788
				true
3789
			)
3790
		);
3791
		$this->assertSame($expected, $result);
3792
 
3793
		$result = $TestModel->saveAll(
3794
			array(
3795
				'Article' => array('id' => 2),
3796
				'Comment' => array(
3797
					array('comment' => 'First new comment', 'published' => 'Y', 'User' => array('user' => '', 'password' => 'newuserpass')),
3798
					array('comment' => 'Second new comment', 'published' => 'Y', 'user_id' => 2)
3799
				)
3800
			),
3801
			array('validate' => 'only', 'atomic' => false, 'deep' => true)
3802
		);
3803
		$expected = array(
3804
			'Article' => true,
3805
			'Comment' => array(
3806
				false,
3807
				true
3808
			)
3809
		);
3810
		$this->assertSame($expected, $result);
3811
 
3812
		$result = $TestModel->saveAll(array(
3813
			'Article' => array('id' => 2),
3814
			'Comment' => array(
3815
				array('comment' => 'Third new comment', 'published' => 'Y', 'user_id' => 5),
3816
				array('comment' => 'Fourth new comment', 'published' => 'Y', 'user_id' => 2, 'Attachment' => array('attachment' => 'deepsaved'))
3817
			)
3818
		),
3819
		array('validate' => 'only', 'deep' => true)
3820
		);
3821
		$this->assertTrue($result);
3822
 
3823
		$result = $TestModel->saveAll(array(
3824
			'Article' => array('id' => 2),
3825
			'Comment' => array(
3826
				array('comment' => 'Third new comment', 'published' => 'Y', 'user_id' => 5),
3827
				array('comment' => 'Fourth new comment', 'published' => 'Y', 'user_id' => 2, 'Attachment' => array('attachment' => ''))
3828
			)
3829
		),
3830
		array('validate' => 'only', 'deep' => true)
3831
		);
3832
		$this->assertFalse($result);
3833
 
3834
		$result = $TestModel->saveAll(array(
3835
			'Article' => array('id' => 2),
3836
			'Comment' => array(
3837
				array('comment' => 'Third new comment', 'published' => 'Y', 'user_id' => 5),
3838
				array('comment' => 'Fourth new comment', 'published' => 'Y', 'user_id' => 2, 'Attachment' => array('attachment' => 'deepsave'))
3839
			)
3840
		),
3841
		array('validate' => 'only', 'atomic' => false, 'deep' => true)
3842
		);
3843
		$expected = array(
3844
			'Article' => true,
3845
			'Comment' => array(
3846
				true,
3847
				true
3848
			)
3849
		);
3850
		$this->assertSame($expected, $result);
3851
 
3852
		$result = $TestModel->saveAll(array(
3853
			'Article' => array('id' => 2),
3854
			'Comment' => array(
3855
				array('comment' => 'Third new comment', 'published' => 'Y', 'user_id' => 5),
3856
				array('comment' => 'Fourth new comment', 'published' => 'Y', 'user_id' => 2, 'Attachment' => array('attachment' => ''))
3857
			)
3858
		),
3859
		array('validate' => 'only', 'atomic' => false, 'deep' => true)
3860
		);
3861
		$expected = array(
3862
			'Article' => true,
3863
			'Comment' => array(
3864
				true,
3865
				false
3866
			)
3867
		);
3868
		$this->assertSame($expected, $result);
3869
 
3870
		$expected = array(
3871
			'Comment' => array(
3872
				1 => array(
3873
					'Attachment' => array(
3874
						'attachment' => array('This field cannot be left blank')
3875
					)
3876
				)
3877
			)
3878
		);
3879
		$result = $TestModel->validationErrors;
3880
		$this->assertSame($expected, $result);
3881
 
3882
		$data = array(
3883
			'Attachment' => array(
3884
				'attachment' => 'deepsave insert',
3885
			),
3886
			'Comment' => array(
3887
				'comment' => 'First comment deepsave insert',
3888
				'published' => 'Y',
3889
				'user_id' => 5,
3890
				'Article' => array(
3891
					'title' => 'First Article deepsave insert',
3892
					'body' => 'First Article Body deepsave insert',
3893
					'User' => array(
3894
						'user' => 'deepsave',
3895
						'password' => 'magic'
3896
					),
3897
				),
3898
			)
3899
		);
3900
 
3901
		$result = $TestModel->Comment->Attachment->saveAll($data, array('validate' => 'only', 'deep' => true));
3902
		$this->assertTrue($result);
3903
 
3904
		$result = $TestModel->Comment->Attachment->saveAll($data, array('validate' => 'only', 'atomic' => false, 'deep' => true));
3905
		$expected = array(
3906
			'Attachment' => true,
3907
			'Comment' => true
3908
		);
3909
		$this->assertSame($expected, $result);
3910
 
3911
		$data = array(
3912
			'Attachment' => array(
3913
				'attachment' => 'deepsave insert',
3914
			),
3915
			'Comment' => array(
3916
				'comment' => 'First comment deepsave insert',
3917
				'published' => 'Y',
3918
				'user_id' => 5,
3919
				'Article' => array(
3920
					'title' => 'First Article deepsave insert',
3921
					'body' => 'First Article Body deepsave insert',
3922
					'User' => array(
3923
						'user' => '',
3924
						'password' => 'magic'
3925
					),
3926
				),
3927
			)
3928
		);
3929
 
3930
		$result = $TestModel->Comment->Attachment->saveAll($data, array('validate' => 'only', 'deep' => true));
3931
		$this->assertFalse($result);
3932
 
3933
		$result = $TestModel->Comment->Attachment->validationErrors;
3934
		$expected = array(
3935
			'Comment' => array(
3936
				'Article' => array(
3937
					'User' => array(
3938
						'user' => array('This field cannot be left blank')
3939
					)
3940
				)
3941
			)
3942
		);
3943
		$this->assertSame($expected, $result);
3944
 
3945
		$result = $TestModel->Comment->Attachment->saveAll($data, array('validate' => 'only', 'atomic' => false, 'deep' => true));
3946
		$expected = array(
3947
			'Attachment' => true,
3948
			'Comment' => false
3949
		);
3950
		$this->assertEquals($expected, $result);
3951
 
3952
		$data['Comment']['Article']['body'] = '';
3953
		$result = $TestModel->Comment->Attachment->saveAll($data, array('validate' => 'only', 'deep' => true));
3954
		$this->assertFalse($result);
3955
 
3956
		$result = $TestModel->Comment->Attachment->validationErrors;
3957
		$expected = array(
3958
			'Comment' => array(
3959
				'Article' => array(
3960
					'body' => array('This field cannot be left blank'),
3961
					'User' => array(
3962
						'user' => array('This field cannot be left blank')
3963
					)
3964
				)
3965
			)
3966
		);
3967
		$this->assertSame($expected, $result);
3968
 
3969
		$result = $TestModel->Comment->Attachment->saveAll($data, array('validate' => 'only', 'atomic' => false, 'deep' => true));
3970
		$expected = array(
3971
			'Attachment' => true,
3972
			'Comment' => false
3973
		);
3974
		$this->assertEquals($expected, $result);
3975
 
3976
		$data['Comment']['comment'] = '';
3977
		$result = $TestModel->Comment->Attachment->saveAll($data, array('validate' => 'only', 'deep' => true));
3978
		$this->assertFalse($result);
3979
 
3980
		$result = $TestModel->Comment->Attachment->validationErrors;
3981
		$expected = array(
3982
			'Comment' => array(
3983
				'comment' => array('This field cannot be left blank'),
3984
				'Article' => array(
3985
					'body' => array('This field cannot be left blank'),
3986
					'User' => array(
3987
						'user' => array('This field cannot be left blank')
3988
					)
3989
				)
3990
			)
3991
		);
3992
		$this->assertSame($expected, $result);
3993
 
3994
		$result = $TestModel->Comment->Attachment->saveAll($data, array('validate' => 'only', 'atomic' => false, 'deep' => true));
3995
		$expected = array(
3996
			'Attachment' => true,
3997
			'Comment' => false
3998
		);
3999
		$this->assertEquals($expected, $result);
4000
 
4001
		$data['Attachment']['attachment'] = '';
4002
		$result = $TestModel->Comment->Attachment->saveAll($data, array('validate' => 'only', 'deep' => true));
4003
		$this->assertFalse($result);
4004
 
4005
		$result = $TestModel->Comment->Attachment->validationErrors;
4006
		$expected = array(
4007
			'attachment' => array('This field cannot be left blank'),
4008
			'Comment' => array(
4009
				'comment' => array('This field cannot be left blank'),
4010
				'Article' => array(
4011
					'body' => array('This field cannot be left blank'),
4012
					'User' => array(
4013
						'user' => array('This field cannot be left blank')
4014
					)
4015
				)
4016
			)
4017
		);
4018
		$this->assertSame($expected, $result);
4019
 
4020
		$result = $TestModel->Comment->validationErrors;
4021
		$expected = array(
4022
			'comment' => array('This field cannot be left blank'),
4023
			'Article' => array(
4024
				'body' => array('This field cannot be left blank'),
4025
				'User' => array(
4026
					'user' => array('This field cannot be left blank')
4027
				)
4028
			)
4029
		);
4030
		$this->assertSame($expected, $result);
4031
 
4032
		$result = $TestModel->Comment->Attachment->saveAll($data, array('validate' => 'only', 'atomic' => false, 'deep' => true));
4033
		$expected = array(
4034
			'Attachment' => false,
4035
			'Comment' => false
4036
		);
4037
		$this->assertEquals($expected, $result);
4038
	}
4039
 
4040
/**
4041
 * testSaveAllNotDeepAssociated method
4042
 * test that only directly associated data gets saved
4043
 *
4044
 * @return void
4045
 */
4046
	public function testSaveAllNotDeepAssociated() {
4047
		$this->loadFixtures('Article', 'Comment', 'User', 'Attachment');
4048
		$TestModel = new Article();
4049
		$TestModel->hasMany['Comment']['order'] = array('Comment.created' => 'ASC');
4050
		$TestModel->hasAndBelongsToMany = array();
4051
 
4052
		$result = $TestModel->saveAll(array(
4053
			'Article' => array('id' => 2),
4054
			'Comment' => array(
4055
				array(
4056
					'comment' => 'First new comment', 'published' => 'Y', 'user_id' => 2,
4057
					'User' => array('user' => 'newuser', 'password' => 'newuserpass')
4058
				),
4059
				array('comment' => 'Second new comment', 'published' => 'Y', 'user_id' => 2)
4060
			)
4061
		), array('deep' => false));
4062
		$this->assertTrue($result);
4063
 
4064
		$result = $TestModel->Comment->User->field('id', array('user' => 'newuser', 'password' => 'newuserpass'));
4065
		$this->assertFalse($result);
4066
 
4067
		$result = $TestModel->saveAll(array(
4068
			'Article' => array('id' => 2),
4069
			'Comment' => array(
4070
				array('comment' => 'Third new comment', 'published' => 'Y', 'user_id' => 4),
4071
				array('comment' => 'Fourth new comment', 'published' => 'Y', 'user_id' => 2, 'Attachment' => array('attachment' => 'deepsaved'))
4072
			)
4073
		), array('deep' => false));
4074
		$this->assertTrue($result);
4075
 
4076
		$result = $TestModel->Comment->Attachment->field('id', array('attachment' => 'deepsaved'));
4077
		$this->assertFalse($result);
4078
 
4079
		$data = array(
4080
			'Attachment' => array(
4081
				'attachment' => 'deepsave insert',
4082
			),
4083
			'Comment' => array(
4084
				'comment' => 'First comment deepsave insert',
4085
				'published' => 'Y',
4086
				'user_id' => 4,
4087
				'article_id' => 1,
4088
				'Article' => array(
4089
					'title' => 'First Article deepsave insert',
4090
					'body' => 'First Article Body deepsave insert',
4091
					'User' => array(
4092
						'user' => 'deepsave',
4093
						'password' => 'magic'
4094
					),
4095
				),
4096
			)
4097
		);
4098
		$expected = $TestModel->User->find('count');
4099
 
4100
		$TestModel->Comment->Attachment->create();
4101
		$result = $TestModel->Comment->Attachment->saveAll($data, array('deep' => false));
4102
		$this->assertTrue($result);
4103
 
4104
		$result = $TestModel->User->find('count');
4105
		$this->assertEquals($expected, $result);
4106
 
4107
		$result = $TestModel->Comment->Attachment->findById($TestModel->Comment->Attachment->id);
4108
		$expected = array(
4109
			'Attachment' => array(
4110
				'id' => '2',
4111
				'comment_id' => '11',
4112
				'attachment' => 'deepsave insert',
4113
			),
4114
			'Comment' => array(
4115
				'id' => '11',
4116
				'article_id' => 1,
4117
				'user_id' => '4',
4118
				'comment' => 'First comment deepsave insert',
4119
				'published' => 'Y',
4120
			)
4121
		);
4122
		unset($result['Attachment']['created'], $result['Attachment']['updated']);
4123
		$this->assertEquals($expected['Attachment'], $result['Attachment']);
4124
 
4125
		unset($result['Comment']['created'], $result['Comment']['updated']);
4126
		$this->assertEquals($expected['Comment'], $result['Comment']);
4127
	}
4128
 
4129
/**
4130
 * testSaveAllNotDeepMany
4131
 * tests the save methods to not save deeper recursive data
4132
 *
4133
 * @return void
4134
 */
4135
	public function testSaveAllNotDeepMany() {
4136
		$this->loadFixtures('Article', 'Comment', 'User', 'Attachment');
4137
		$TestModel = new Article();
4138
		$TestModel->hasMany['Comment']['order'] = array('Comment.created' => 'ASC');
4139
		$TestModel->hasAndBelongsToMany = array();
4140
 
4141
		$data = array(
4142
			array(
4143
				'id' => 1,
4144
				'body' => '',
4145
				'Comment' => array(
4146
					array('comment' => '', 'published' => 'Y', 'User' => array('user' => '', 'password' => 'manysaved')),
4147
					array('comment' => 'Second comment deepsaved article 1', 'published' => 'Y', 'user_id' => 2)
4148
				)
4149
			),
4150
			array(
4151
				'Article' => array('id' => 2),
4152
				'Comment' => array(
4153
					array('comment' => 'First comment deepsaved article 2', 'published' => 'Y', 'User' => array('user' => 'savemore', 'password' => '')),
4154
					array('comment' => '', 'published' => 'Y', 'user_id' => 2)
4155
				)
4156
			)
4157
		);
4158
		$TestModel->Comment->validate['comment'] = 'notEmpty';
4159
		$result = $TestModel->saveAll($data, array('deep' => false));
4160
		$this->assertFalse($result);
4161
 
4162
		$expected = array(
4163
 
4164
				'body' => array('This field cannot be left blank')
4165
			)
4166
		);
4167
		$result = $TestModel->validationErrors;
4168
		$this->assertSame($expected, $result);
4169
 
4170
		$data = array(
4171
			array(
4172
				'Article' => array('id' => 1, 'body' => 'Ignore invalid comment'),
4173
				'Comment' => array(
4174
					array('comment' => '', 'published' => 'Y', 'user_id' => 2)
4175
				)
4176
			),
4177
			array(
4178
				'Article' => array('id' => 2),
4179
				'Comment' => array(
4180
					array('comment' => '', 'published' => 'Y', 'user_id' => 2)
4181
				)
4182
			)
4183
		);
4184
		$result = $TestModel->saveAll($data, array('deep' => false));
4185
		$this->assertTrue($result);
4186
	}
4187
/**
4188
 * testSaveAllNotDeepValidateOnly
4189
 * tests the validate methods to not validate deeper recursive data
4190
 *
4191
 * @return void
4192
 */
4193
	public function testSaveAllNotDeepValidateOnly() {
4194
		$this->loadFixtures('Article', 'Comment', 'User', 'Attachment');
4195
		$TestModel = new Article();
4196
		$TestModel->hasMany['Comment']['order'] = array('Comment.created' => 'ASC');
4197
		$TestModel->hasAndBelongsToMany = array();
4198
		$TestModel->Comment->Attachment->validate['attachment'] = 'notEmpty';
4199
		$TestModel->Comment->validate['comment'] = 'notEmpty';
4200
 
4201
		$result = $TestModel->saveAll(
4202
			array(
4203
				'Article' => array('id' => 2, 'body' => ''),
4204
				'Comment' => array(
4205
					array('comment' => 'First new comment', 'published' => 'Y', 'User' => array('user' => '', 'password' => 'newuserpass')),
4206
					array('comment' => 'Second new comment', 'published' => 'Y', 'user_id' => 2)
4207
				)
4208
			),
4209
			array('validate' => 'only', 'deep' => false)
4210
		);
4211
		$this->assertFalse($result);
4212
 
4213
		$expected = array('body' => array('This field cannot be left blank'));
4214
		$result = $TestModel->validationErrors;
4215
		$this->assertSame($expected, $result);
4216
 
4217
		$result = $TestModel->saveAll(
4218
			array(
4219
				'Article' => array('id' => 2, 'body' => 'Ignore invalid user data'),
4220
				'Comment' => array(
4221
					array('comment' => 'First new comment', 'published' => 'Y', 'User' => array('user' => '', 'password' => 'newuserpass')),
4222
					array('comment' => 'Second new comment', 'published' => 'Y', 'user_id' => 2)
4223
				)
4224
			),
4225
			array('validate' => 'only', 'deep' => false)
4226
		);
4227
		$this->assertTrue($result);
4228
 
4229
		$result = $TestModel->saveAll(
4230
			array(
4231
				'Article' => array('id' => 2, 'body' => 'Ignore invalid user data'),
4232
				'Comment' => array(
4233
					array('comment' => 'First new comment', 'published' => 'Y', 'User' => array('user' => '', 'password' => 'newuserpass')),
4234
					array('comment' => 'Second new comment', 'published' => 'Y', 'user_id' => 2)
4235
				)
4236
			),
4237
			array('validate' => 'only', 'atomic' => false, 'deep' => false)
4238
		);
4239
		$expected = array(
4240
			'Article' => true,
4241
			'Comment' => array(
4242
				true,
4243
				true
4244
			)
4245
		);
4246
		$this->assertSame($expected, $result);
4247
 
4248
		$result = $TestModel->saveAll(array(
4249
			'Article' => array('id' => 2, 'body' => 'Ignore invalid attachment data'),
4250
			'Comment' => array(
4251
				array('comment' => 'Third new comment', 'published' => 'Y', 'user_id' => 5),
4252
				array('comment' => 'Fourth new comment', 'published' => 'Y', 'user_id' => 2, 'Attachment' => array('attachment' => ''))
4253
			)
4254
		),
4255
		array('validate' => 'only', 'deep' => false)
4256
		);
4257
		$this->assertTrue($result);
4258
 
4259
		$result = $TestModel->saveAll(array(
4260
			'Article' => array('id' => 2, 'body' => 'Ignore invalid attachment data'),
4261
			'Comment' => array(
4262
				array('comment' => 'Third new comment', 'published' => 'Y', 'user_id' => 5),
4263
				array('comment' => 'Fourth new comment', 'published' => 'Y', 'user_id' => 2, 'Attachment' => array('attachment' => ''))
4264
			)
4265
		),
4266
		array('validate' => 'only', 'atomic' => false, 'deep' => false)
4267
		);
4268
		$expected = array(
4269
			'Article' => true,
4270
			'Comment' => array(
4271
				true,
4272
				true
4273
			)
4274
		);
4275
		$this->assertSame($expected, $result);
4276
 
4277
		$expected = array();
4278
		$result = $TestModel->validationErrors;
4279
		$this->assertSame($expected, $result);
4280
 
4281
		$data = array(
4282
			'Attachment' => array(
4283
				'attachment' => 'deepsave insert',
4284
			),
4285
			'Comment' => array(
4286
				'comment' => 'First comment deepsave insert',
4287
				'published' => 'Y',
4288
				'user_id' => 5,
4289
				'Article' => array(
4290
					'title' => 'First Article deepsave insert ignored',
4291
					'body' => 'First Article Body deepsave insert',
4292
					'User' => array(
4293
						'user' => '',
4294
						'password' => 'magic'
4295
					),
4296
				),
4297
			)
4298
		);
4299
 
4300
		$result = $TestModel->Comment->Attachment->saveAll($data, array('validate' => 'only', 'deep' => false));
4301
		$this->assertTrue($result);
4302
 
4303
		$result = $TestModel->Comment->Attachment->validationErrors;
4304
		$expected = array();
4305
		$this->assertSame($expected, $result);
4306
 
4307
		$result = $TestModel->Comment->Attachment->saveAll($data, array('validate' => 'only', 'atomic' => false, 'deep' => false));
4308
		$expected = array(
4309
			'Attachment' => true,
4310
			'Comment' => true
4311
		);
4312
		$this->assertEquals($expected, $result);
4313
 
4314
		$data['Comment']['Article']['body'] = '';
4315
		$result = $TestModel->Comment->Attachment->saveAll($data, array('validate' => 'only', 'deep' => false));
4316
		$this->assertTrue($result);
4317
 
4318
		$result = $TestModel->Comment->Attachment->validationErrors;
4319
		$expected = array();
4320
		$this->assertSame($expected, $result);
4321
 
4322
		$result = $TestModel->Comment->Attachment->saveAll($data, array('validate' => 'only', 'atomic' => false, 'deep' => false));
4323
		$expected = array(
4324
			'Attachment' => true,
4325
			'Comment' => true
4326
		);
4327
		$this->assertEquals($expected, $result);
4328
	}
4329
 
4330
/**
4331
 * testSaveAllHasMany method
4332
 *
4333
 * @return void
4334
 */
4335
	public function testSaveAllHasMany() {
4336
		$this->loadFixtures('Article', 'Comment');
4337
		$TestModel = new Article();
4338
		$TestModel->hasMany['Comment']['order'] = array('Comment.created' => 'ASC');
4339
		$TestModel->belongsTo = $TestModel->hasAndBelongsToMany = array();
4340
 
4341
		$result = $TestModel->saveAll(array(
4342
			'Article' => array('id' => 2),
4343
			'Comment' => array(
4344
				array('comment' => 'First new comment', 'published' => 'Y', 'user_id' => 1),
4345
				array('comment' => 'Second new comment', 'published' => 'Y', 'user_id' => 2)
4346
			)
4347
		));
4348
		$this->assertFalse(empty($result));
4349
 
4350
		$result = $TestModel->findById(2);
4351
		$expected = array(
4352
			'First Comment for Second Article',
4353
			'Second Comment for Second Article',
4354
			'First new comment',
4355
			'Second new comment'
4356
		);
4357
		$result = Hash::extract(Hash::sort($result['Comment'], '{n}.id', 'ASC'), '{n}.comment');
4358
		$this->assertEquals($expected, $result);
4359
 
4360
		$result = $TestModel->saveAll(
4361
			array(
4362
				'Article' => array('id' => 2),
4363
				'Comment' => array(
4364
					array(
4365
						'comment' => 'Third new comment',
4366
						'published' => 'Y',
4367
						'user_id' => 1
4368
			))),
4369
			array('atomic' => false)
4370
		);
4371
		$this->assertFalse(empty($result));
4372
 
4373
		$result = $TestModel->findById(2);
4374
		$expected = array(
4375
			'First Comment for Second Article',
4376
			'Second Comment for Second Article',
4377
			'First new comment',
4378
			'Second new comment',
4379
			'Third new comment'
4380
		);
4381
		$result = Hash::extract(Hash::sort($result['Comment'], '{n}.id', 'ASC'), '{n}.comment');
4382
		$this->assertEquals($expected, $result);
4383
 
4384
		$TestModel->beforeSaveReturn = false;
4385
		$result = $TestModel->saveAll(
4386
			array(
4387
				'Article' => array('id' => 2),
4388
				'Comment' => array(
4389
					array(
4390
						'comment' => 'Fourth new comment',
4391
						'published' => 'Y',
4392
						'user_id' => 1
4393
			))),
4394
			array('atomic' => false)
4395
		);
4396
		$this->assertEquals(array('Article' => false), $result);
4397
 
4398
		$result = $TestModel->findById(2);
4399
		$expected = array(
4400
			'First Comment for Second Article',
4401
			'Second Comment for Second Article',
4402
			'First new comment',
4403
			'Second new comment',
4404
			'Third new comment'
4405
		);
4406
		$result = Hash::extract(Hash::sort($result['Comment'], '{n}.id', 'ASC'), '{n}.comment');
4407
		$this->assertEquals($expected, $result);
4408
	}
4409
 
4410
/**
4411
 * testSaveAllHasManyValidation method
4412
 *
4413
 * @return void
4414
 */
4415
	public function testSaveAllHasManyValidation() {
4416
		$this->loadFixtures('Article', 'Comment');
4417
		$TestModel = new Article();
4418
		$TestModel->belongsTo = $TestModel->hasAndBelongsToMany = array();
4419
		$TestModel->Comment->validate = array('comment' => 'notEmpty');
4420
 
4421
		$result = $TestModel->saveAll(array(
4422
			'Article' => array('id' => 2),
4423
			'Comment' => array(
4424
				array('comment' => '', 'published' => 'Y', 'user_id' => 1),
4425
			)
4426
		), array('validate' => true));
4427
		$this->assertFalse($result);
4428
 
4429
		$expected = array('Comment' => array(
4430
			array('comment' => array('This field cannot be left blank'))
4431
		));
4432
		$this->assertEquals($expected, $TestModel->validationErrors);
4433
		$expected = array(
4434
			array('comment' => array('This field cannot be left blank'))
4435
		);
4436
		$this->assertEquals($expected, $TestModel->Comment->validationErrors);
4437
 
4438
		$result = $TestModel->saveAll(array(
4439
			'Article' => array('id' => 2),
4440
			'Comment' => array(
4441
				array(
4442
					'comment' => '',
4443
					'published' => 'Y',
4444
					'user_id' => 1
4445
			))
4446
		), array('validate' => 'first'));
4447
		$this->assertFalse($result);
4448
	}
4449
 
4450
/**
4451
 * test saveAll with transactions and ensure there is no missing rollback.
4452
 *
4453
 * @return void
4454
 */
4455
	public function testSaveAllManyRowsTransactionNoRollback() {
4456
		$this->loadFixtures('Post');
4457
 
4458
		$Post = new TestPost();
4459
		$Post->validate = array(
4460
			'title' => array('rule' => array('notEmpty'))
4461
		);
4462
 
4463
		// If validation error occurs, rollback() should be called.
4464
		$db = $this->_getMockDboSource(array('begin', 'commit', 'rollback'));
4465
		$db->expects($this->once())->method('begin')->will($this->returnValue(true));
4466
		$db->expects($this->never())->method('commit');
4467
		$db->expects($this->once())->method('rollback');
4468
 
4469
		$Post->setDataSourceObject($db);
4470
 
4471
		$data = array(
4472
			array('author_id' => 1, 'title' => 'New Fourth Post'),
4473
			array('author_id' => 1, 'title' => '')
4474
		);
4475
		$Post->saveAll($data, array('atomic' => true, 'validate' => true));
4476
 
4477
		// If exception thrown, rollback() should be called too.
4478
		$db = $this->_getMockDboSource(array('begin', 'commit', 'rollback'));
4479
		$db->expects($this->once())->method('begin')->will($this->returnValue(true));
4480
		$db->expects($this->never())->method('commit');
4481
		$db->expects($this->once())->method('rollback');
4482
 
4483
		$Post->setDataSourceObject($db);
4484
 
4485
		$data = array(
4486
			array('author_id' => 1, 'title' => 'New Fourth Post'),
4487
			array('author_id' => 1, 'title' => 'New Fifth Post', 'body' => $db->expression('PDO_EXCEPTION()'))
4488
		);
4489
 
4490
		try {
4491
			$Post->saveAll($data, array('atomic' => true, 'validate' => true));
4492
			$this->fail('No exception thrown');
4493
		} catch (PDOException $e) {
4494
		}
4495
 
4496
		// Otherwise, commit() should be called.
4497
		$db = $this->_getMockDboSource(array('begin', 'commit', 'rollback'));
4498
		$db->expects($this->once())->method('begin')->will($this->returnValue(true));
4499
		$db->expects($this->once())->method('commit');
4500
		$db->expects($this->never())->method('rollback');
4501
 
4502
		$Post->setDataSourceObject($db);
4503
 
4504
		$data = array(
4505
			array('author_id' => 1, 'title' => 'New Fourth Post'),
4506
			array('author_id' => 1, 'title' => 'New Fifth Post')
4507
		);
4508
		$Post->saveAll($data, array('atomic' => true, 'validate' => true));
4509
	}
4510
 
4511
/**
4512
 * test saveAll with transactions and ensure there is no missing rollback.
4513
 *
4514
 * @return void
4515
 */
4516
	public function testSaveAllAssociatedTransactionNoRollback() {
4517
		$this->loadFixtures('Post', 'Author');
4518
 
4519
		$Post = new TestPost();
4520
		$Post->Author->validate = array(
4521
			'user' => array('rule' => array('notEmpty'))
4522
		);
4523
 
4524
		// If validation error occurs, rollback() should be called.
4525
		$db = $this->_getMockDboSource(array('begin', 'commit', 'rollback'));
4526
		$db->expects($this->once())->method('begin')->will($this->returnValue(true));
4527
		$db->expects($this->never())->method('commit');
4528
		$db->expects($this->once())->method('rollback');
4529
 
4530
		$Post->setDataSourceObject($db);
4531
		$Post->Author->setDataSourceObject($db);
4532
 
4533
		$data = array(
4534
			'Post' => array(
4535
				'title' => 'New post',
4536
				'body' => 'Content',
4537
				'published' => 'Y'
4538
			),
4539
			'Author' => array(
4540
				'user' => '',
4541
				'password' => "sekret"
4542
			)
4543
		);
4544
		$Post->saveAll($data, array('validate' => true));
4545
 
4546
		// If exception thrown, rollback() should be called too.
4547
		$db = $this->_getMockDboSource(array('begin', 'commit', 'rollback'));
4548
		$db->expects($this->once())->method('begin')->will($this->returnValue(true));
4549
		$db->expects($this->never())->method('commit');
4550
		$db->expects($this->once())->method('rollback');
4551
 
4552
		$Post->setDataSourceObject($db);
4553
		$Post->Author->setDataSourceObject($db);
4554
 
4555
		$data = array(
4556
			'Post' => array(
4557
				'title' => 'New post',
4558
				'body' => $db->expression('PDO_EXCEPTION()'),
4559
				'published' => 'Y'
4560
			),
4561
			'Author' => array(
4562
				'user' => 'New user',
4563
				'password' => "sekret"
4564
			)
4565
		);
4566
 
4567
		try {
4568
			$Post->saveAll($data, array('validate' => true));
4569
			$this->fail('No exception thrown');
4570
		} catch (PDOException $e) {
4571
		}
4572
 
4573
		// Otherwise, commit() should be called.
4574
		$db = $this->_getMockDboSource(array('begin', 'commit', 'rollback'));
4575
		$db->expects($this->once())->method('begin')->will($this->returnValue(true));
4576
		$db->expects($this->once())->method('commit');
4577
		$db->expects($this->never())->method('rollback');
4578
 
4579
		$Post->setDataSourceObject($db);
4580
		$Post->Author->setDataSourceObject($db);
4581
 
4582
		$data = array(
4583
			'Post' => array(
4584
				'title' => 'New post',
4585
				'body' => 'Content',
4586
				'published' => 'Y'
4587
			),
4588
			'Author' => array(
4589
				'user' => 'New user',
4590
				'password' => "sekret"
4591
			)
4592
		);
4593
		$Post->saveAll($data, array('validate' => true));
4594
	}
4595
 
4596
/**
4597
 * test saveAll with nested saveAll call.
4598
 *
4599
 * @return void
4600
 */
4601
	public function testSaveAllNestedSaveAll() {
4602
		$this->loadFixtures('Sample');
4603
		$TransactionTestModel = new TransactionTestModel();
4604
 
4605
		$data = array(
4606
			array('apple_id' => 1, 'name' => 'sample5'),
4607
		);
4608
 
4609
		$this->assertTrue($TransactionTestModel->saveAll($data, array('atomic' => true)));
4610
	}
4611
 
4612
/**
4613
 * testSaveAllTransaction method
4614
 *
4615
 * @return void
4616
 */
4617
	public function testSaveAllTransaction() {
4618
		$this->loadFixtures('Post', 'Author', 'Comment', 'Attachment');
4619
		$TestModel = new Post();
4620
 
4621
		$TestModel->validate = array('title' => 'notEmpty');
4622
		$data = array(
4623
			array('author_id' => 1, 'title' => 'New Fourth Post'),
4624
			array('author_id' => 1, 'title' => 'New Fifth Post'),
4625
			array('author_id' => 1, 'title' => '')
4626
		);
4627
		$this->assertFalse($TestModel->saveAll($data));
4628
 
4629
		$result = $TestModel->find('all', array('recursive' => -1));
4630
		$expected = array(
4631
			array('Post' => array(
4632
				'id' => '1',
4633
				'author_id' => 1,
4634
				'title' => 'First Post',
4635
				'body' => 'First Post Body',
4636
				'published' => 'Y',
4637
				'created' => '2007-03-18 10:39:23',
4638
				'updated' => '2007-03-18 10:41:31'
4639
			)),
4640
			array('Post' => array(
4641
				'id' => '2',
4642
				'author_id' => 3,
4643
				'title' => 'Second Post',
4644
				'body' => 'Second Post Body',
4645
				'published' => 'Y',
4646
				'created' => '2007-03-18 10:41:23',
4647
				'updated' => '2007-03-18 10:43:31'
4648
			)),
4649
			array('Post' => array(
4650
				'id' => '3',
4651
				'author_id' => 1,
4652
				'title' => 'Third Post',
4653
				'body' => 'Third Post Body',
4654
				'published' => 'Y',
4655
				'created' => '2007-03-18 10:43:23',
4656
				'updated' => '2007-03-18 10:45:31'
4657
		)));
4658
 
4659
		if (count($result) != 3) {
4660
			// Database doesn't support transactions
4661
			$expected[] = array(
4662
				'Post' => array(
4663
					'id' => '4',
4664
					'author_id' => 1,
4665
					'title' => 'New Fourth Post',
4666
					'body' => null,
4667
					'published' => 'N',
4668
					'created' => self::date(),
4669
					'updated' => self::date()
4670
			));
4671
 
4672
			$expected[] = array(
4673
				'Post' => array(
4674
					'id' => '5',
4675
					'author_id' => 1,
4676
					'title' => 'New Fifth Post',
4677
					'body' => null,
4678
					'published' => 'N',
4679
					'created' => self::date(),
4680
					'updated' => self::date()
4681
			));
4682
 
4683
			$this->assertEquals($expected, $result);
4684
			// Skip the rest of the transactional tests
4685
			return;
4686
		}
4687
 
4688
		$this->assertEquals($expected, $result);
4689
 
4690
		$data = array(
4691
			array('author_id' => 1, 'title' => 'New Fourth Post'),
4692
			array('author_id' => 1, 'title' => ''),
4693
			array('author_id' => 1, 'title' => 'New Sixth Post')
4694
		);
4695
		$this->assertFalse($TestModel->saveAll($data));
4696
 
4697
		$result = $TestModel->find('all', array('recursive' => -1));
4698
		$expected = array(
4699
			array('Post' => array(
4700
				'id' => '1',
4701
				'author_id' => 1,
4702
				'title' => 'First Post',
4703
				'body' => 'First Post Body',
4704
				'published' => 'Y',
4705
				'created' => '2007-03-18 10:39:23',
4706
				'updated' => '2007-03-18 10:41:31'
4707
			)),
4708
			array('Post' => array(
4709
				'id' => '2',
4710
				'author_id' => 3,
4711
				'title' => 'Second Post',
4712
				'body' => 'Second Post Body',
4713
				'published' => 'Y',
4714
				'created' => '2007-03-18 10:41:23',
4715
				'updated' => '2007-03-18 10:43:31'
4716
			)),
4717
			array('Post' => array(
4718
				'id' => '3',
4719
				'author_id' => 1,
4720
				'title' => 'Third Post',
4721
				'body' => 'Third Post Body',
4722
				'published' => 'Y',
4723
				'created' => '2007-03-18 10:43:23',
4724
				'updated' => '2007-03-18 10:45:31'
4725
		)));
4726
 
4727
		if (count($result) != 3) {
4728
			// Database doesn't support transactions
4729
			$expected[] = array(
4730
				'Post' => array(
4731
					'id' => '4',
4732
					'author_id' => 1,
4733
					'title' => 'New Fourth Post',
4734
					'body' => 'Third Post Body',
4735
					'published' => 'N',
4736
					'created' => self::date(),
4737
					'updated' => self::date()
4738
			));
4739
 
4740
			$expected[] = array(
4741
				'Post' => array(
4742
					'id' => '5',
4743
					'author_id' => 1,
4744
					'title' => 'Third Post',
4745
					'body' => 'Third Post Body',
4746
					'published' => 'N',
4747
					'created' => self::date(),
4748
					'updated' => self::date()
4749
			));
4750
		}
4751
		$this->assertEquals($expected, $result);
4752
 
4753
		$TestModel->validate = array('title' => 'notEmpty');
4754
		$data = array(
4755
			array('author_id' => 1, 'title' => 'New Fourth Post'),
4756
			array('author_id' => 1, 'title' => 'New Fifth Post'),
4757
			array('author_id' => 1, 'title' => 'New Sixth Post')
4758
		);
4759
		$this->assertTrue($TestModel->saveAll($data));
4760
 
4761
		$result = $TestModel->find('all', array(
4762
			'recursive' => -1,
4763
			'fields' => array('author_id', 'title', 'body', 'published'),
4764
			'order' => array('Post.created' => 'ASC')
4765
		));
4766
 
4767
		$expected = array(
4768
			array('Post' => array(
4769
				'author_id' => 1,
4770
				'title' => 'First Post',
4771
				'body' => 'First Post Body',
4772
				'published' => 'Y'
4773
			)),
4774
			array('Post' => array(
4775
				'author_id' => 3,
4776
				'title' => 'Second Post',
4777
				'body' => 'Second Post Body',
4778
				'published' => 'Y'
4779
			)),
4780
			array('Post' => array(
4781
				'author_id' => 1,
4782
				'title' => 'Third Post',
4783
				'body' => 'Third Post Body',
4784
				'published' => 'Y'
4785
			)),
4786
			array('Post' => array(
4787
				'author_id' => 1,
4788
				'title' => 'New Fourth Post',
4789
				'body' => '',
4790
				'published' => 'N'
4791
			)),
4792
			array('Post' => array(
4793
				'author_id' => 1,
4794
				'title' => 'New Fifth Post',
4795
				'body' => '',
4796
				'published' => 'N'
4797
			)),
4798
			array('Post' => array(
4799
				'author_id' => 1,
4800
				'title' => 'New Sixth Post',
4801
				'body' => '',
4802
				'published' => 'N'
4803
		)));
4804
		$this->assertEquals($expected, $result);
4805
	}
4806
 
4807
/**
4808
 * testSaveAllValidation method
4809
 *
4810
 * @return void
4811
 */
4812
	public function testSaveAllValidation() {
4813
		$this->loadFixtures('Post', 'Author', 'Comment', 'Attachment');
4814
		$TestModel = new Post();
4815
 
4816
		$data = array(
4817
			array(
4818
				'id' => '1',
4819
				'title' => 'Baleeted First Post',
4820
				'body' => 'Baleeted!',
4821
				'published' => 'N'
4822
			),
4823
			array(
4824
				'id' => '2',
4825
				'title' => 'Just update the title'
4826
			),
4827
			array(
4828
				'title' => 'Creating a fourth post',
4829
				'body' => 'Fourth post body',
4830
				'author_id' => 2
4831
		));
4832
 
4833
		$this->assertTrue($TestModel->saveAll($data));
4834
 
4835
		$result = $TestModel->find('all', array('recursive' => -1, 'order' => 'Post.id ASC'));
4836
		$expected = array(
4837
			array(
4838
				'Post' => array(
4839
					'id' => '1',
4840
					'author_id' => '1',
4841
					'title' => 'Baleeted First Post',
4842
					'body' => 'Baleeted!',
4843
					'published' => 'N',
4844
					'created' => '2007-03-18 10:39:23'
4845
			)),
4846
			array(
4847
				'Post' => array(
4848
					'id' => '2',
4849
					'author_id' => '3',
4850
					'title' => 'Just update the title',
4851
					'body' => 'Second Post Body',
4852
					'published' => 'Y',
4853
					'created' => '2007-03-18 10:41:23'
4854
			)),
4855
			array(
4856
				'Post' => array(
4857
					'id' => '3',
4858
					'author_id' => '1',
4859
					'title' => 'Third Post',
4860
					'body' => 'Third Post Body',
4861
					'published' => 'Y',
4862
					'created' => '2007-03-18 10:43:23',
4863
					'updated' => '2007-03-18 10:45:31'
4864
			)),
4865
			array(
4866
				'Post' => array(
4867
					'id' => '4',
4868
					'author_id' => '2',
4869
					'title' => 'Creating a fourth post',
4870
					'body' => 'Fourth post body',
4871
					'published' => 'N'
4872
		)));
4873
		$this->assertEquals(self::date(), $result[0]['Post']['updated']);
4874
		$this->assertEquals(self::date(), $result[1]['Post']['updated']);
4875
		$this->assertEquals(self::date(), $result[3]['Post']['created']);
4876
		$this->assertEquals(self::date(), $result[3]['Post']['updated']);
4877
		unset($result[0]['Post']['updated'], $result[1]['Post']['updated']);
4878
		unset($result[3]['Post']['created'], $result[3]['Post']['updated']);
4879
		$this->assertEquals($expected, $result);
4880
 
4881
		$TestModel->validate = array('title' => 'notEmpty', 'author_id' => 'numeric');
4882
		$data = array(
4883
			array(
4884
				'id' => '1',
4885
				'title' => 'Un-Baleeted First Post',
4886
				'body' => 'Not Baleeted!',
4887
				'published' => 'Y'
4888
			),
4889
			array(
4890
				'id' => '2',
4891
				'title' => '',
4892
				'body' => 'Trying to get away with an empty title'
4893
		));
4894
		$result = $TestModel->saveAll($data);
4895
		$this->assertFalse($result);
4896
 
4897
		$result = $TestModel->find('all', array('recursive' => -1, 'order' => 'Post.id ASC'));
4898
		$errors = array(1 => array('title' => array('This field cannot be left blank')));
4899
		$transactionWorked = Set::matches('/Post[1][title=Baleeted First Post]', $result);
4900
		if (!$transactionWorked) {
4901
			$this->assertTrue(Set::matches('/Post[1][title=Un-Baleeted First Post]', $result));
4902
			$this->assertTrue(Set::matches('/Post[2][title=Just update the title]', $result));
4903
		}
4904
 
4905
		$this->assertEquals($errors, $TestModel->validationErrors);
4906
 
4907
		$TestModel->validate = array('title' => 'notEmpty', 'author_id' => 'numeric');
4908
		$data = array(
4909
			array(
4910
				'id' => '1',
4911
				'title' => 'Un-Baleeted First Post',
4912
				'body' => 'Not Baleeted!',
4913
				'published' => 'Y'
4914
			),
4915
			array(
4916
				'id' => '2',
4917
				'title' => '',
4918
				'body' => 'Trying to get away with an empty title'
4919
		));
4920
		$result = $TestModel->saveAll($data, array('validate' => true, 'atomic' => false));
4921
		$this->assertEquals(array(true, false), $result);
4922
		$result = $TestModel->find('all', array('recursive' => -1, 'order' => 'Post.id ASC'));
4923
		$errors = array(1 => array('title' => array('This field cannot be left blank')));
4924
		$expected = array(
4925
			array(
4926
				'Post' => array(
4927
					'id' => '1',
4928
					'author_id' => '1',
4929
					'title' => 'Un-Baleeted First Post',
4930
					'body' => 'Not Baleeted!',
4931
					'published' => 'Y',
4932
					'created' => '2007-03-18 10:39:23'
4933
				)
4934
			),
4935
			array(
4936
				'Post' => array(
4937
					'id' => '2',
4938
					'author_id' => '3',
4939
					'title' => 'Just update the title',
4940
					'body' => 'Second Post Body',
4941
					'published' => 'Y',
4942
					'created' => '2007-03-18 10:41:23'
4943
				)
4944
			),
4945
			array(
4946
				'Post' => array(
4947
					'id' => '3',
4948
					'author_id' => '1',
4949
					'title' => 'Third Post',
4950
					'body' => 'Third Post Body',
4951
					'published' => 'Y',
4952
					'created' => '2007-03-18 10:43:23',
4953
					'updated' => '2007-03-18 10:45:31'
4954
				)
4955
			),
4956
			array(
4957
				'Post' => array(
4958
					'id' => '4',
4959
					'author_id' => '2',
4960
					'title' => 'Creating a fourth post',
4961
					'body' => 'Fourth post body',
4962
					'published' => 'N'
4963
				)
4964
			)
4965
		);
4966
 
4967
		$this->assertEquals(self::date(), $result[0]['Post']['updated']);
4968
		$this->assertEquals(self::date(), $result[1]['Post']['updated']);
4969
		$this->assertEquals(self::date(), $result[3]['Post']['updated']);
4970
		$this->assertEquals(self::date(), $result[3]['Post']['created']);
4971
		unset(
4972
			$result[0]['Post']['updated'], $result[1]['Post']['updated'],
4973
			$result[3]['Post']['updated'], $result[3]['Post']['created']
4974
		);
4975
		$this->assertEquals($expected, $result);
4976
		$this->assertEquals($errors, $TestModel->validationErrors);
4977
 
4978
		$data = array(
4979
			array(
4980
				'id' => '1',
4981
				'title' => 'Re-Baleeted First Post',
4982
				'body' => 'Baleeted!',
4983
				'published' => 'N'
4984
			),
4985
			array(
4986
				'id' => '2',
4987
				'title' => '',
4988
				'body' => 'Trying to get away with an empty title'
4989
		));
4990
		$this->assertFalse($TestModel->saveAll($data, array('validate' => 'first')));
4991
 
4992
		$result = $TestModel->find('all', array('recursive' => -1, 'order' => 'Post.id ASC'));
4993
		unset(
4994
			$result[0]['Post']['updated'], $result[1]['Post']['updated'],
4995
			$result[3]['Post']['updated'], $result[3]['Post']['created']
4996
		);
4997
		$this->assertEquals($expected, $result);
4998
		$this->assertEquals($errors, $TestModel->validationErrors);
4999
	}
5000
 
5001
/**
5002
 * testSaveAllValidationOnly method
5003
 *
5004
 * @return void
5005
 */
5006
	public function testSaveAllValidationOnly() {
5007
		$this->loadFixtures('Comment', 'Attachment');
5008
		$TestModel = new Comment();
5009
		$TestModel->Attachment->validate = array('attachment' => 'notEmpty');
5010
 
5011
		$data = array(
5012
			'Comment' => array(
5013
				'comment' => 'This is the comment'
5014
			),
5015
			'Attachment' => array(
5016
				'attachment' => ''
5017
			)
5018
		);
5019
 
5020
		$result = $TestModel->saveAll($data, array('validate' => 'only'));
5021
		$this->assertFalse($result);
5022
 
5023
		$TestModel = new Article();
5024
		$TestModel->validate = array('title' => 'notEmpty');
5025
		$result = $TestModel->saveAll(
5026
			array(
5027
 
5028
				1 => array('title' => 'title 1'),
5029
				2 => array('title' => 'title 2'),
5030
			),
5031
			array('validate' => 'only')
5032
		);
5033
		$this->assertFalse($result);
5034
		$expected = array(
5035
 
5036
		);
5037
		$this->assertEquals($expected, $TestModel->validationErrors);
5038
 
5039
		$result = $TestModel->saveAll(
5040
			array(
5041
 
5042
				1 => array('title' => ''),
5043
				2 => array('title' => 'title 2'),
5044
			),
5045
			array('validate' => 'only')
5046
		);
5047
		$this->assertFalse($result);
5048
		$expected = array(
5049
			1 => array('title' => array('This field cannot be left blank')),
5050
		);
5051
		$this->assertEquals($expected, $TestModel->validationErrors);
5052
	}
5053
 
5054
/**
5055
 * testSaveAllValidateFirst method
5056
 *
5057
 * @return void
5058
 */
5059
	public function testSaveAllValidateFirst() {
5060
		$this->loadFixtures('Article', 'Comment', 'Attachment', 'User', 'ArticlesTag', 'Tag');
5061
		$model = new Article();
5062
		$model->deleteAll(true);
5063
 
5064
		$model->Comment->validate = array('comment' => 'notEmpty');
5065
		$result = $model->saveAll(array(
5066
			'Article' => array(
5067
				'title' => 'Post with Author',
5068
				'body' => 'This post will be saved author'
5069
			),
5070
			'Comment' => array(
5071
				array('comment' => 'First new comment'),
5072
				array('comment' => '')
5073
			)
5074
		), array('validate' => 'first'));
5075
 
5076
		$this->assertFalse($result);
5077
 
5078
		$result = $model->find('all');
5079
		$this->assertSame(array(), $result);
5080
		$expected = array('Comment' => array(
5081
			1 => array('comment' => array('This field cannot be left blank'))
5082
		));
5083
 
5084
		$this->assertEquals($expected['Comment'], $model->Comment->validationErrors);
5085
 
5086
		$this->assertSame($model->Comment->find('count'), 0);
5087
 
5088
		$result = $model->saveAll(
5089
			array(
5090
				'Article' => array(
5091
					'title' => 'Post with Author',
5092
					'body' => 'This post will be saved with an author',
5093
					'user_id' => 2
5094
				),
5095
				'Comment' => array(
5096
					array(
5097
						'comment' => 'Only new comment',
5098
						'user_id' => 2
5099
			))),
5100
			array('validate' => 'first')
5101
		);
5102
 
5103
		$this->assertTrue($result);
5104
 
5105
		$result = $model->Comment->find('all');
5106
		$this->assertSame(count($result), 1);
5107
		$result = Hash::extract($result, '{n}.Comment.article_id');
5108
		$this->assertEquals(4, $result[0]);
5109
 
5110
		$model->deleteAll(true);
5111
		$data = array(
5112
			'Article' => array(
5113
				'title' => 'Post with Author saveAlled from comment',
5114
				'body' => 'This post will be saved with an author',
5115
				'user_id' => 2
5116
			),
5117
			'Comment' => array(
5118
				'comment' => 'Only new comment', 'user_id' => 2
5119
		));
5120
 
5121
		$result = $model->Comment->saveAll($data, array('validate' => 'first'));
5122
		$this->assertFalse(empty($result));
5123
 
5124
		$result = $model->find('all');
5125
		$this->assertEquals(
5126
			$result[0]['Article']['title'],
5127
			'Post with Author saveAlled from comment'
5128
		);
5129
		$this->assertEquals('Only new comment', $result[0]['Comment'][0]['comment']);
5130
	}
5131
 
5132
/**
5133
 * test saveAll()'s return is correct when using atomic = false and validate = first.
5134
 *
5135
 * @return void
5136
 */
5137
	public function testSaveAllValidateFirstAtomicFalse() {
5138
		$this->loadFixtures('Something');
5139
		$Something = new Something();
5140
		$invalidData = array(
5141
			array(
5142
				'title' => 'foo',
5143
				'body' => 'bar',
5144
				'published' => 'baz',
5145
			),
5146
			array(
5147
				'body' => 3,
5148
				'published' => 'sd',
5149
			),
5150
		);
5151
		$Something->create();
5152
		$Something->validate = array(
5153
			'title' => array(
5154
				'rule' => 'alphaNumeric',
5155
				'required' => true,
5156
			),
5157
			'body' => array(
5158
				'rule' => 'alphaNumeric',
5159
				'required' => true,
5160
				'allowEmpty' => true,
5161
			),
5162
		);
5163
		$result = $Something->saveAll($invalidData, array(
5164
			'atomic' => false,
5165
			'validate' => 'first',
5166
		));
5167
		$expected = array(true, false);
5168
		$this->assertEquals($expected, $result);
5169
 
5170
		$Something = new Something();
5171
		$validData = array(
5172
			array(
5173
				'title' => 'title value',
5174
				'body' => 'body value',
5175
				'published' => 'baz',
5176
			),
5177
			array(
5178
				'title' => 'valid',
5179
				'body' => 'this body',
5180
				'published' => 'sd',
5181
			),
5182
		);
5183
		$Something->create();
5184
		$result = $Something->saveAll($validData, array(
5185
			'atomic' => false,
5186
			'validate' => 'first',
5187
		));
5188
		$expected = array(true, true);
5189
		$this->assertEquals($expected, $result);
5190
	}
5191
 
5192
/**
5193
 * testSaveAllHasManyValidationOnly method
5194
 *
5195
 * @return void
5196
 */
5197
	public function testSaveAllHasManyValidationOnly() {
5198
		$this->loadFixtures('Article', 'Comment', 'Attachment');
5199
		$TestModel = new Article();
5200
		$TestModel->belongsTo = $TestModel->hasAndBelongsToMany = array();
5201
		$TestModel->Comment->validate = array('comment' => 'notEmpty');
5202
 
5203
		$result = $TestModel->saveAll(
5204
			array(
5205
				'Article' => array('id' => 2),
5206
				'Comment' => array(
5207
					array(
5208
						'id' => 1,
5209
						'comment' => '',
5210
						'published' => 'Y',
5211
						'user_id' => 1),
5212
					array(
5213
						'id' => 2,
5214
						'comment' =>
5215
						'comment',
5216
						'published' => 'Y',
5217
						'user_id' => 1
5218
			))),
5219
			array('validate' => 'only')
5220
		);
5221
		$this->assertFalse($result);
5222
 
5223
		$result = $TestModel->saveAll(
5224
			array(
5225
				'Article' => array('id' => 2),
5226
				'Comment' => array(
5227
					array(
5228
						'id' => 1,
5229
						'comment' => '',
5230
						'published' => 'Y',
5231
						'user_id' => 1
5232
					),
5233
					array(
5234
						'id' => 2,
5235
						'comment' => 'comment',
5236
						'published' => 'Y',
5237
						'user_id' => 1
5238
					),
5239
					array(
5240
						'id' => 3,
5241
						'comment' => '',
5242
						'published' => 'Y',
5243
						'user_id' => 1
5244
			))),
5245
			array(
5246
				'validate' => 'only',
5247
				'atomic' => false
5248
		));
5249
		$expected = array(
5250
			'Article' => true,
5251
			'Comment' => array(false, true, false)
5252
		);
5253
		$this->assertSame($expected, $result);
5254
 
5255
		$expected = array('Comment' => array(
5256
 
5257
			2 => array('comment' => array('This field cannot be left blank'))
5258
		));
5259
		$this->assertEquals($expected, $TestModel->validationErrors);
5260
 
5261
		$expected = array(
5262
 
5263
			2 => array('comment' => array('This field cannot be left blank'))
5264
		);
5265
		$this->assertEquals($expected, $TestModel->Comment->validationErrors);
5266
	}
5267
 
5268
/**
5269
 * test that saveAll still behaves like previous versions (does not necessarily need a first argument)
5270
 *
5271
 * @return void
5272
 */
5273
	public function testSaveAllWithSet() {
5274
		$this->loadFixtures('Article', 'Tag', 'Comment', 'User', 'ArticlesTag');
5275
		$data = array(
5276
			'Article' => array(
5277
				'user_id' => 1,
5278
				'title' => 'Article Has and belongs to Many Tags'
5279
			),
5280
			'Tag' => array(
5281
				'Tag' => array(1, 2)
5282
			),
5283
			'Comment' => array(
5284
				array(
5285
					'comment' => 'Article comment',
5286
					'user_id' => 1
5287
		)));
5288
		$Article = new Article();
5289
		$Article->set($data);
5290
		$result = $Article->saveAll();
5291
		$this->assertFalse(empty($result));
5292
	}
5293
 
5294
/**
5295
 * test that saveAll behaves like plain save() when supplied empty data
5296
 *
5297
 * @link https://cakephp.lighthouseapp.com/projects/42648/tickets/277-test-saveall-with-validation-returns-incorrect-boolean-when-saving-empty-data
5298
 * @return void
5299
 */
5300
	public function testSaveAllEmptyData() {
5301
		$this->skipIf($this->db instanceof Sqlserver, 'This test is not compatible with SQL Server.');
5302
 
5303
		$this->loadFixtures('Article', 'ProductUpdateAll', 'Comment', 'Attachment');
5304
		$model = new Article();
5305
		$result = $model->saveAll(array(), array('validate' => 'first'));
5306
		$this->assertFalse(empty($result));
5307
 
5308
		$model = new ProductUpdateAll();
5309
		$result = $model->saveAll();
5310
		$this->assertFalse($result);
5311
	}
5312
 
5313
/**
5314
 * testSaveAssociated method
5315
 *
5316
 * @return void
5317
 */
5318
	public function testSaveAssociated() {
5319
		$this->loadFixtures('Post', 'Author', 'Comment', 'Attachment', 'Article', 'User');
5320
		$TestModel = new Post();
5321
 
5322
		$result = $TestModel->find('all');
5323
		$this->assertEquals(3, count($result));
5324
		$this->assertFalse(isset($result[3]));
5325
 
5326
		$TestModel->saveAssociated(array(
5327
			'Post' => array(
5328
				'title' => 'Post with Author',
5329
				'body' => 'This post will be saved with an author'
5330
			),
5331
			'Author' => array(
5332
				'user' => 'bob',
5333
				'password' => '5f4dcc3b5aa765d61d8327deb882cf90'
5334
		)));
5335
 
5336
		$result = $TestModel->find('all', array('order' => array('Post.id ' => 'ASC')));
5337
		$expected = array(
5338
			'Post' => array(
5339
				'id' => '4',
5340
				'author_id' => '5',
5341
				'title' => 'Post with Author',
5342
				'body' => 'This post will be saved with an author',
5343
				'published' => 'N'
5344
			),
5345
			'Author' => array(
5346
				'id' => '5',
5347
				'user' => 'bob',
5348
				'password' => '5f4dcc3b5aa765d61d8327deb882cf90',
5349
				'test' => 'working'
5350
		));
5351
		$this->assertEquals(self::date(), $result[3]['Post']['updated']);
5352
		$this->assertEquals(self::date(), $result[3]['Post']['created']);
5353
		$this->assertEquals(self::date(), $result[3]['Author']['created']);
5354
		$this->assertEquals(self::date(), $result[3]['Author']['updated']);
5355
		unset(
5356
			$result[3]['Post']['updated'], $result[3]['Post']['created'],
5357
			$result[3]['Author']['updated'], $result[3]['Author']['created']
5358
		);
5359
		$this->assertEquals($expected, $result[3]);
5360
		$this->assertEquals(4, count($result));
5361
 
5362
		$TestModel = new Comment();
5363
		$result = $TestModel->saveAssociated(array(
5364
			'Comment' => array(
5365
				'article_id' => 2,
5366
				'user_id' => 2,
5367
				'comment' => 'New comment with attachment',
5368
				'published' => 'Y'
5369
			),
5370
			'Attachment' => array(
5371
				'attachment' => 'some_file.tgz'
5372
			)));
5373
		$this->assertFalse(empty($result));
5374
 
5375
		$result = $TestModel->find('all');
5376
		$expected = array(
5377
			'id' => '7',
5378
			'article_id' => '2',
5379
			'user_id' => '2',
5380
			'comment' => 'New comment with attachment',
5381
			'published' => 'Y'
5382
		);
5383
		$this->assertEquals(self::date(), $result[6]['Comment']['updated']);
5384
		$this->assertEquals(self::date(), $result[6]['Comment']['created']);
5385
		unset($result[6]['Comment']['updated'], $result[6]['Comment']['created']);
5386
		$this->assertEquals($expected, $result[6]['Comment']);
5387
 
5388
		$expected = array(
5389
			'id' => '2',
5390
			'comment_id' => '7',
5391
			'attachment' => 'some_file.tgz'
5392
		);
5393
		$this->assertEquals(self::date(), $result[6]['Attachment']['updated']);
5394
		$this->assertEquals(self::date(), $result[6]['Attachment']['created']);
5395
		unset($result[6]['Attachment']['updated'], $result[6]['Attachment']['created']);
5396
		$this->assertEquals($expected, $result[6]['Attachment']);
5397
	}
5398
 
5399
/**
5400
 * Test that validate = first, atomic = false works when associated records
5401
 * fail validation.
5402
 *
5403
 * @return void
5404
 */
5405
	public function testSaveAssociatedAtomicFalseValidateFirstWithErrors() {
5406
		$this->loadFixtures('Comment', 'Article', 'User');
5407
		$Article = ClassRegistry::init('Article');
5408
		$Article->Comment->validator()->add('comment', array(
5409
			array('rule' => 'notEmpty')
5410
		));
5411
 
5412
		$data = array(
5413
			'Article' => array(
5414
				'user_id' => 1,
5415
				'title' => 'Foo',
5416
				'body' => 'text',
5417
				'published' => 'N'
5418
			),
5419
			'Comment' => array(
5420
				array(
5421
					'user_id' => 1,
5422
					'comment' => '',
5423
					'published' => 'N',
5424
				)
5425
			),
5426
		);
5427
 
5428
		$Article->saveAssociated(
5429
			$data,
5430
			array('validate' => 'first', 'atomic' => false)
5431
		);
5432
 
5433
		$result = $Article->validationErrors;
5434
		$expected = array(
5435
			'Comment' => array(
5436
				array(
5437
					'comment' => array('This field cannot be left blank')
5438
				)
5439
			)
5440
		);
5441
		$this->assertEquals($expected, $result);
5442
	}
5443
 
5444
/**
5445
 * testSaveMany method
5446
 *
5447
 * @return void
5448
 */
5449
	public function testSaveMany() {
5450
		$this->loadFixtures('Post');
5451
		$TestModel = new Post();
5452
		$TestModel->deleteAll(true);
5453
		$this->assertEquals(array(), $TestModel->find('all'));
5454
 
5455
		// SQLite seems to reset the PK counter when that happens, so we need this to make the tests pass
5456
		$this->db->truncate($TestModel);
5457
 
5458
		$TestModel->saveMany(array(
5459
			array(
5460
				'title' => 'Multi-record post 1',
5461
				'body' => 'First multi-record post',
5462
				'author_id' => 2
5463
			),
5464
			array(
5465
				'title' => 'Multi-record post 2',
5466
				'body' => 'Second multi-record post',
5467
				'author_id' => 2
5468
		)));
5469
 
5470
		$result = $TestModel->find('all', array(
5471
			'recursive' => -1,
5472
			'order' => 'Post.id ASC'
5473
		));
5474
		$expected = array(
5475
			array(
5476
				'Post' => array(
5477
					'id' => '1',
5478
					'author_id' => '2',
5479
					'title' => 'Multi-record post 1',
5480
					'body' => 'First multi-record post',
5481
					'published' => 'N'
5482
				)
5483
			),
5484
			array(
5485
				'Post' => array(
5486
					'id' => '2',
5487
					'author_id' => '2',
5488
					'title' => 'Multi-record post 2',
5489
					'body' => 'Second multi-record post',
5490
					'published' => 'N'
5491
				)
5492
			)
5493
		);
5494
		$this->assertEquals(self::date(), $result[0]['Post']['updated']);
5495
		$this->assertEquals(self::date(), $result[0]['Post']['created']);
5496
		$this->assertEquals(self::date(), $result[1]['Post']['updated']);
5497
		$this->assertEquals(self::date(), $result[1]['Post']['created']);
5498
		unset($result[0]['Post']['updated'], $result[0]['Post']['created']);
5499
		unset($result[1]['Post']['updated'], $result[1]['Post']['created']);
5500
		$this->assertEquals($expected, $result);
5501
	}
5502
 
5503
/**
5504
 * Test SaveMany with validate=false.
5505
 *
5506
 * @return void
5507
 */
5508
	public function testSaveManyValidateFalse() {
5509
		$this->loadFixtures('Post');
5510
		$TestModel = new Post();
5511
		$TestModel->deleteAll(true);
5512
		$data = array(
5513
			array('id' => 1, 'author_id' => 1, 'title' => 'hi'),
5514
			array('id' => 2, 'author_id' => 1, 'title' => 'bye')
5515
		);
5516
		$result = $TestModel->saveAll($data, array('validate' => false));
5517
		$this->assertTrue($result);
5518
	}
5519
 
5520
/**
5521
 * Test SaveAssociated with Habtm relations
5522
 *
5523
 * @return void
5524
 */
5525
	public function testSaveAssociatedHabtm() {
5526
		$this->loadFixtures('Article', 'Tag', 'Comment', 'User', 'ArticlesTag');
5527
		$data = array(
5528
			'Article' => array(
5529
				'user_id' => 1,
5530
				'title' => 'Article Has and belongs to Many Tags'
5531
			),
5532
			'Tag' => array(
5533
				'Tag' => array(1, 2)
5534
			),
5535
			'Comment' => array(
5536
				array(
5537
					'comment' => 'Article comment',
5538
					'user_id' => 1
5539
		)));
5540
		$Article = new Article();
5541
		$result = $Article->saveAssociated($data);
5542
		$this->assertFalse(empty($result));
5543
 
5544
		$result = $Article->read();
5545
		$this->assertEquals(2, count($result['Tag']));
5546
		$this->assertEquals('tag1', $result['Tag'][0]['tag']);
5547
		$this->assertEquals(1, count($result['Comment']));
5548
		$this->assertEquals(1, count($result['Comment'][0]['comment']));
5549
	}
5550
 
5551
/**
5552
 * Test SaveAssociated with Habtm relations and extra join table fields
5553
 *
5554
 * @return void
5555
 */
5556
	public function testSaveAssociatedHabtmWithExtraJoinTableFields() {
5557
		$this->loadFixtures('Something', 'SomethingElse', 'JoinThing');
5558
 
5559
		$data = array(
5560
			'Something' => array(
5561
				'id' => 4,
5562
				'title' => 'Extra Fields',
5563
				'body' => 'Extra Fields Body',
5564
				'published' => '1'
5565
			),
5566
			'SomethingElse' => array(
5567
				array('something_else_id' => 1, 'doomed' => '1'),
5568
				array('something_else_id' => 2, 'doomed' => '0'),
5569
				array('something_else_id' => 3, 'doomed' => '1')
5570
			)
5571
		);
5572
 
5573
		$Something = new Something();
5574
		$result = $Something->saveAssociated($data);
5575
		$this->assertFalse(empty($result));
5576
		$result = $Something->read();
5577
 
5578
		$this->assertEquals(3, count($result['SomethingElse']));
5579
		$this->assertTrue(Set::matches('/Something[id=4]', $result));
5580
 
5581
		$this->assertTrue(Set::matches('/SomethingElse[id=1]', $result));
5582
		$this->assertTrue(Set::matches('/SomethingElse[id=1]/JoinThing[something_else_id=1]', $result));
5583
		$this->assertTrue(Set::matches('/SomethingElse[id=1]/JoinThing[doomed=1]', $result));
5584
 
5585
		$this->assertTrue(Set::matches('/SomethingElse[id=2]', $result));
5586
		$this->assertTrue(Set::matches('/SomethingElse[id=2]/JoinThing[something_else_id=2]', $result));
5587
		$this->assertTrue(Set::matches('/SomethingElse[id=2]/JoinThing[doomed=0]', $result));
5588
 
5589
		$this->assertTrue(Set::matches('/SomethingElse[id=3]', $result));
5590
		$this->assertTrue(Set::matches('/SomethingElse[id=3]/JoinThing[something_else_id=3]', $result));
5591
		$this->assertTrue(Set::matches('/SomethingElse[id=3]/JoinThing[doomed=1]', $result));
5592
	}
5593
 
5594
/**
5595
 * testSaveAssociatedHasOne method
5596
 *
5597
 * @return void
5598
 */
5599
	public function testSaveAssociatedHasOne() {
5600
		$model = new Comment();
5601
		$model->deleteAll(true);
5602
		$this->assertEquals(array(), $model->find('all'));
5603
 
5604
		$model->Attachment->deleteAll(true);
5605
		$this->assertEquals(array(), $model->Attachment->find('all'));
5606
 
5607
		$this->assertTrue($model->saveAssociated(array(
5608
			'Comment' => array(
5609
				'comment' => 'Comment with attachment',
5610
				'article_id' => 1,
5611
				'user_id' => 1
5612
			),
5613
			'Attachment' => array(
5614
				'attachment' => 'some_file.zip'
5615
		))));
5616
		$result = $model->find('all', array('fields' => array(
5617
			'Comment.id', 'Comment.comment', 'Attachment.id',
5618
			'Attachment.comment_id', 'Attachment.attachment'
5619
		)));
5620
		$expected = array(array(
5621
			'Comment' => array(
5622
				'id' => '1',
5623
				'comment' => 'Comment with attachment'
5624
			),
5625
			'Attachment' => array(
5626
				'id' => '1',
5627
				'comment_id' => '1',
5628
				'attachment' => 'some_file.zip'
5629
		)));
5630
		$this->assertEquals($expected, $result);
5631
 
5632
		$model->Attachment->bindModel(array('belongsTo' => array('Comment')), false);
5633
		$data = array(
5634
			'Comment' => array(
5635
				'comment' => 'Comment with attachment',
5636
				'article_id' => 1,
5637
				'user_id' => 1
5638
			),
5639
			'Attachment' => array(
5640
				'attachment' => 'some_file.zip'
5641
		));
5642
		$this->assertTrue($model->saveAssociated($data, array('validate' => 'first')));
5643
	}
5644
 
5645
/**
5646
 * testSaveAssociatedBelongsTo method
5647
 *
5648
 * @return void
5649
 */
5650
	public function testSaveAssociatedBelongsTo() {
5651
		$model = new Comment();
5652
		$model->deleteAll(true);
5653
		$this->assertEquals(array(), $model->find('all'));
5654
 
5655
		$model->Article->deleteAll(true);
5656
		$this->assertEquals(array(), $model->Article->find('all'));
5657
 
5658
		$this->assertTrue($model->saveAssociated(array(
5659
			'Comment' => array(
5660
				'comment' => 'Article comment',
5661
				'article_id' => 1,
5662
				'user_id' => 1
5663
			),
5664
			'Article' => array(
5665
				'title' => 'Model Associations 101',
5666
				'user_id' => 1
5667
		))));
5668
		$result = $model->find('all', array('fields' => array(
5669
			'Comment.id', 'Comment.comment', 'Comment.article_id', 'Article.id', 'Article.title'
5670
		)));
5671
		$expected = array(array(
5672
			'Comment' => array(
5673
				'id' => '1',
5674
				'article_id' => '1',
5675
				'comment' => 'Article comment'
5676
			),
5677
			'Article' => array(
5678
				'id' => '1',
5679
				'title' => 'Model Associations 101'
5680
		)));
5681
		$this->assertEquals($expected, $result);
5682
	}
5683
 
5684
/**
5685
 * testSaveAssociatedHasOneValidation method
5686
 *
5687
 * @return void
5688
 */
5689
	public function testSaveAssociatedHasOneValidation() {
5690
		$model = new Comment();
5691
		$model->deleteAll(true);
5692
		$this->assertEquals(array(), $model->find('all'));
5693
 
5694
		$model->Attachment->deleteAll(true);
5695
		$this->assertEquals(array(), $model->Attachment->find('all'));
5696
 
5697
		$model->validate = array('comment' => 'notEmpty');
5698
		$model->Attachment->validate = array('attachment' => 'notEmpty');
5699
		$model->Attachment->bindModel(array('belongsTo' => array('Comment')));
5700
 
5701
		$result = $model->saveAssociated(
5702
			array(
5703
				'Comment' => array(
5704
					'comment' => '',
5705
					'article_id' => 1,
5706
					'user_id' => 1
5707
				),
5708
				'Attachment' => array('attachment' => '')
5709
			)
5710
		);
5711
		$this->assertFalse($result);
5712
		$expected = array(
5713
			'comment' => array(
5714
				'This field cannot be left blank'
5715
			),
5716
			'Attachment' => array(
5717
				'attachment' => array(
5718
					'This field cannot be left blank'
5719
				)
5720
			)
5721
		);
5722
		$this->assertEquals($expected, $model->validationErrors);
5723
		$this->assertEquals($expected['Attachment'], $model->Attachment->validationErrors);
5724
	}
5725
 
5726
/**
5727
 * testSaveAssociatedAtomic method
5728
 *
5729
 * @return void
5730
 */
5731
	public function testSaveAssociatedAtomic() {
5732
		$this->loadFixtures('Article', 'User');
5733
		$TestModel = new Article();
5734
 
5735
		$result = $TestModel->saveAssociated(array(
5736
			'Article' => array(
5737
				'title' => 'Post with Author',
5738
				'body' => 'This post will be saved with an author',
5739
				'user_id' => 2
5740
			),
5741
			'Comment' => array(
5742
				array('comment' => 'First new comment', 'user_id' => 2))
5743
		), array('atomic' => false));
5744
 
5745
		$this->assertSame($result, array('Article' => true, 'Comment' => array(true)));
5746
 
5747
		$result = $TestModel->saveAssociated(array(
5748
			'Article' => array('id' => 2),
5749
			'Comment' => array(
5750
				array(
5751
					'comment' => 'First new comment',
5752
					'published' => 'Y',
5753
					'user_id' => 1
5754
				),
5755
				array(
5756
					'comment' => 'Second new comment',
5757
					'published' => 'Y',
5758
					'user_id' => 2
5759
			))
5760
		), array('validate' => true, 'atomic' => false));
5761
		$this->assertSame($result, array('Article' => true, 'Comment' => array(true, true)));
5762
	}
5763
 
5764
/**
5765
 * testSaveManyAtomic method
5766
 *
5767
 * @return void
5768
 */
5769
	public function testSaveManyAtomic() {
5770
		$this->loadFixtures('Article', 'User');
5771
		$TestModel = new Article();
5772
 
5773
		$result = $TestModel->saveMany(array(
5774
			array(
5775
				'id' => '1',
5776
				'title' => 'Baleeted First Post',
5777
				'body' => 'Baleeted!',
5778
				'published' => 'N'
5779
			),
5780
			array(
5781
				'id' => '2',
5782
				'title' => 'Just update the title'
5783
			),
5784
			array(
5785
				'title' => 'Creating a fourth post',
5786
				'body' => 'Fourth post body',
5787
				'user_id' => 2
5788
			)
5789
		), array('atomic' => false));
5790
		$this->assertSame($result, array(true, true, true));
5791
 
5792
		$TestModel->validate = array('title' => 'notEmpty', 'author_id' => 'numeric');
5793
		$result = $TestModel->saveMany(array(
5794
			array(
5795
				'id' => '1',
5796
				'title' => 'Un-Baleeted First Post',
5797
				'body' => 'Not Baleeted!',
5798
				'published' => 'Y'
5799
			),
5800
			array(
5801
				'id' => '2',
5802
				'title' => '',
5803
				'body' => 'Trying to get away with an empty title'
5804
			)
5805
		), array('validate' => true, 'atomic' => false));
5806
 
5807
		$this->assertSame(array(true, false), $result);
5808
	}
5809
 
5810
/**
5811
 * testSaveAssociatedHasMany method
5812
 *
5813
 * @return void
5814
 */
5815
	public function testSaveAssociatedHasMany() {
5816
		$this->loadFixtures('Article', 'Comment');
5817
		$TestModel = new Article();
5818
		$TestModel->belongsTo = $TestModel->hasAndBelongsToMany = array();
5819
 
5820
		$result = $TestModel->saveAssociated(array(
5821
			'Article' => array('id' => 2),
5822
			'Comment' => array(
5823
				array('comment' => 'First new comment', 'published' => 'Y', 'user_id' => 1),
5824
				array('comment' => 'Second new comment', 'published' => 'Y', 'user_id' => 2)
5825
			)
5826
		));
5827
		$this->assertFalse(empty($result));
5828
 
5829
		$result = $TestModel->findById(2);
5830
		$expected = array(
5831
			'First Comment for Second Article',
5832
			'Second Comment for Second Article',
5833
			'First new comment',
5834
			'Second new comment'
5835
		);
5836
		$this->assertEquals($expected, Hash::extract($result['Comment'], '{n}.comment'));
5837
 
5838
		$result = $TestModel->saveAssociated(
5839
			array(
5840
				'Article' => array('id' => 2),
5841
				'Comment' => array(
5842
					array(
5843
						'comment' => 'Third new comment',
5844
						'published' => 'Y',
5845
						'user_id' => 1
5846
			))),
5847
			array('atomic' => false)
5848
		);
5849
		$this->assertFalse(empty($result));
5850
 
5851
		$result = $TestModel->findById(2);
5852
		$expected = array(
5853
			'First Comment for Second Article',
5854
			'Second Comment for Second Article',
5855
			'First new comment',
5856
			'Second new comment',
5857
			'Third new comment'
5858
		);
5859
		$this->assertEquals($expected, Hash::extract($result['Comment'], '{n}.comment'));
5860
 
5861
		$TestModel->beforeSaveReturn = false;
5862
		$result = $TestModel->saveAssociated(
5863
			array(
5864
				'Article' => array('id' => 2),
5865
				'Comment' => array(
5866
					array(
5867
						'comment' => 'Fourth new comment',
5868
						'published' => 'Y',
5869
						'user_id' => 1
5870
			))),
5871
			array('atomic' => false)
5872
		);
5873
		$this->assertEquals(array('Article' => false), $result);
5874
 
5875
		$result = $TestModel->findById(2);
5876
		$expected = array(
5877
			'First Comment for Second Article',
5878
			'Second Comment for Second Article',
5879
			'First new comment',
5880
			'Second new comment',
5881
			'Third new comment'
5882
		);
5883
		$this->assertEquals($expected, Hash::extract($result['Comment'], '{n}.comment'));
5884
	}
5885
 
5886
/**
5887
 * testSaveAssociatedHasManyEmpty method
5888
 *
5889
 * @return void
5890
 */
5891
	public function testSaveAssociatedHasManyEmpty() {
5892
		$this->loadFixtures('Article', 'Comment');
5893
		$TestModel = new Article();
5894
		$TestModel->belongsTo = $TestModel->hasAndBelongsToMany = array();
5895
		$TestModel->validate = $TestModel->Comment->validate = array('user_id' => array('notEmpty' => array('rule' => 'notEmpty', 'required' => true)));
5896
 
5897
		//empty hasMany data is ignored in save
5898
		$result = $TestModel->saveAssociated(array(
5899
			'Article' => array('title' => 'title', 'user_id' => 1),
5900
			'Comment' => array()
5901
		), array('validate' => true));
5902
		$this->assertTrue($result);
5903
 
5904
		$result = $TestModel->saveAssociated(array(
5905
			'Article' => array('title' => 'title', 'user_id' => 1),
5906
			'Comment' => array()
5907
		), array('validate' => true, 'atomic' => false));
5908
		$this->assertEquals(array('Article' => true), $result);
5909
 
5910
		//empty primary data is not ignored
5911
		$result = $TestModel->saveAssociated(array('Article' => array()), array('validate' => true));
5912
		$this->assertFalse($result);
5913
 
5914
		$result = $TestModel->saveAssociated(array('Article' => array()), array('validate' => true, 'atomic' => false));
5915
		$this->assertEquals(array('Article' => false), $result);
5916
	}
5917
 
5918
/**
5919
 * testSaveAssociatedHasManyValidation method
5920
 *
5921
 * @return void
5922
 */
5923
	public function testSaveAssociatedHasManyValidation() {
5924
		$this->loadFixtures('Article', 'Comment');
5925
		$TestModel = new Article();
5926
		$TestModel->belongsTo = $TestModel->hasAndBelongsToMany = array();
5927
		$TestModel->Comment->validate = array('comment' => 'notEmpty');
5928
 
5929
		$result = $TestModel->saveAssociated(array(
5930
			'Article' => array('id' => 2),
5931
			'Comment' => array(
5932
				array('comment' => '', 'published' => 'Y', 'user_id' => 1),
5933
			)
5934
		), array('validate' => true));
5935
		$this->assertFalse($result);
5936
 
5937
		$expected = array('Comment' => array(
5938
			array('comment' => array('This field cannot be left blank'))
5939
		));
5940
		$this->assertEquals($expected, $TestModel->validationErrors);
5941
		$expected = array(
5942
			array('comment' => array('This field cannot be left blank'))
5943
		);
5944
		$this->assertEquals($expected, $TestModel->Comment->validationErrors);
5945
 
5946
		$result = $TestModel->saveAssociated(array(
5947
			'Article' => array('id' => 2),
5948
			'Comment' => array(
5949
				array(
5950
					'comment' => '',
5951
					'published' => 'Y',
5952
					'user_id' => 1
5953
			))
5954
		), array('validate' => 'first'));
5955
		$this->assertFalse($result);
5956
	}
5957
 
5958
/**
5959
 * test saveMany with transactions and ensure there is no missing rollback.
5960
 *
5961
 * @return void
5962
 */
5963
	public function testSaveManyTransactionNoRollback() {
5964
		$this->loadFixtures('Post');
5965
 
5966
		$Post = new TestPost();
5967
		$Post->validate = array(
5968
			'title' => array('rule' => array('notEmpty'))
5969
		);
5970
 
5971
		// If validation error occurs, rollback() should be called.
5972
		$db = $this->_getMockDboSource(array('begin', 'commit', 'rollback'));
5973
		$db->expects($this->once())->method('begin')->will($this->returnValue(true));
5974
		$db->expects($this->never())->method('commit');
5975
		$db->expects($this->once())->method('rollback');
5976
 
5977
		$Post->setDataSourceObject($db);
5978
 
5979
		$data = array(
5980
			array('author_id' => 1, 'title' => 'New Fourth Post'),
5981
			array('author_id' => 1, 'title' => '')
5982
		);
5983
		$Post->saveMany($data, array('validate' => true));
5984
 
5985
		// If exception thrown, rollback() should be called too.
5986
		$db = $this->_getMockDboSource(array('begin', 'commit', 'rollback'));
5987
		$db->expects($this->once())->method('begin')->will($this->returnValue(true));
5988
		$db->expects($this->never())->method('commit');
5989
		$db->expects($this->once())->method('rollback');
5990
 
5991
		$Post->setDataSourceObject($db);
5992
 
5993
		$data = array(
5994
			array('author_id' => 1, 'title' => 'New Fourth Post'),
5995
			array('author_id' => 1, 'title' => 'New Fifth Post', 'body' => $db->expression('PDO_EXCEPTION()'))
5996
		);
5997
 
5998
		try {
5999
			$Post->saveMany($data, array('validate' => true));
6000
			$this->fail('No exception thrown');
6001
		} catch (PDOException $e) {
6002
		}
6003
 
6004
		// Otherwise, commit() should be called.
6005
		$db = $this->_getMockDboSource(array('begin', 'commit', 'rollback'));
6006
		$db->expects($this->once())->method('begin')->will($this->returnValue(true));
6007
		$db->expects($this->once())->method('commit');
6008
		$db->expects($this->never())->method('rollback');
6009
 
6010
		$Post->setDataSourceObject($db);
6011
 
6012
		$data = array(
6013
			array('author_id' => 1, 'title' => 'New Fourth Post'),
6014
			array('author_id' => 1, 'title' => 'New Fifth Post')
6015
		);
6016
		$Post->saveMany($data, array('validate' => true));
6017
	}
6018
 
6019
/**
6020
 * test saveAssociated with transactions and ensure there is no missing rollback.
6021
 *
6022
 * @return void
6023
 */
6024
	public function testSaveAssociatedTransactionNoRollback() {
6025
		$this->loadFixtures('Post', 'Author');
6026
 
6027
		$Post = new TestPost();
6028
		$Post->Author->validate = array(
6029
			'user' => array('rule' => array('notEmpty'))
6030
		);
6031
 
6032
		// If validation error occurs, rollback() should be called.
6033
		$db = $this->_getMockDboSource(array('begin', 'commit', 'rollback'));
6034
		$db->expects($this->once())->method('begin')->will($this->returnValue(true));
6035
		$db->expects($this->never())->method('commit');
6036
		$db->expects($this->once())->method('rollback');
6037
 
6038
		$Post->setDataSourceObject($db);
6039
		$Post->Author->setDataSourceObject($db);
6040
 
6041
		$data = array(
6042
			'Post' => array(
6043
				'title' => 'New post',
6044
				'body' => 'Content',
6045
				'published' => 'Y'
6046
			),
6047
			'Author' => array(
6048
				'user' => '',
6049
				'password' => "sekret"
6050
			)
6051
		);
6052
		$Post->saveAssociated($data, array('validate' => true, 'atomic' => true));
6053
 
6054
		// If exception thrown, commit() should be called.
6055
		$db = $this->_getMockDboSource(array('begin', 'commit', 'rollback'));
6056
		$db->expects($this->once())->method('begin')->will($this->returnValue(true));
6057
		$db->expects($this->never())->method('commit');
6058
		$db->expects($this->once())->method('rollback');
6059
 
6060
		$Post->setDataSourceObject($db);
6061
		$Post->Author->setDataSourceObject($db);
6062
 
6063
		$data = array(
6064
			'Post' => array(
6065
				'title' => 'New post',
6066
				'body' => $db->expression('PDO_EXCEPTION()'),
6067
				'published' => 'Y'
6068
			),
6069
			'Author' => array(
6070
				'user' => 'New user',
6071
				'password' => "sekret"
6072
			)
6073
		);
6074
 
6075
		try {
6076
			$Post->saveAssociated($data, array('validate' => true, 'atomic' => true));
6077
			$this->fail('No exception thrown');
6078
		} catch (PDOException $e) {
6079
		}
6080
 
6081
		// Otherwise, commit() should be called.
6082
		$db = $this->_getMockDboSource(array('begin', 'commit', 'rollback'));
6083
		$db->expects($this->once())->method('begin')->will($this->returnValue(true));
6084
		$db->expects($this->once())->method('commit');
6085
		$db->expects($this->never())->method('rollback');
6086
 
6087
		$Post->setDataSourceObject($db);
6088
		$Post->Author->setDataSourceObject($db);
6089
 
6090
		$data = array(
6091
			'Post' => array(
6092
				'title' => 'New post',
6093
				'body' => 'Content',
6094
				'published' => 'Y'
6095
			),
6096
			'Author' => array(
6097
				'user' => 'New user',
6098
				'password' => "sekret"
6099
			)
6100
		);
6101
		$Post->saveAssociated($data, array('validate' => true, 'atomic' => true));
6102
	}
6103
 
6104
/**
6105
 * test saveMany with nested saveMany call.
6106
 *
6107
 * @return void
6108
 */
6109
	public function testSaveManyNestedSaveMany() {
6110
		$this->loadFixtures('Sample');
6111
		$TransactionManyTestModel = new TransactionManyTestModel();
6112
 
6113
		$data = array(
6114
			array('apple_id' => 1, 'name' => 'sample5'),
6115
		);
6116
 
6117
		$this->assertTrue($TransactionManyTestModel->saveMany($data, array('atomic' => true)));
6118
	}
6119
 
6120
/**
6121
 * testSaveManyTransaction method
6122
 *
6123
 * @return void
6124
 */
6125
	public function testSaveManyTransaction() {
6126
		$this->loadFixtures('Post', 'Author', 'Comment', 'Attachment');
6127
		$TestModel = new Post();
6128
 
6129
		$TestModel->validate = array('title' => 'notEmpty');
6130
		$data = array(
6131
			array('author_id' => 1, 'title' => 'New Fourth Post'),
6132
			array('author_id' => 1, 'title' => 'New Fifth Post'),
6133
			array('author_id' => 1, 'title' => '')
6134
		);
6135
		$this->assertFalse($TestModel->saveMany($data));
6136
 
6137
		$result = $TestModel->find('all', array('recursive' => -1));
6138
		$expected = array(
6139
			array('Post' => array(
6140
				'id' => '1',
6141
				'author_id' => 1,
6142
				'title' => 'First Post',
6143
				'body' => 'First Post Body',
6144
				'published' => 'Y',
6145
				'created' => '2007-03-18 10:39:23',
6146
				'updated' => '2007-03-18 10:41:31'
6147
			)),
6148
			array('Post' => array(
6149
				'id' => '2',
6150
				'author_id' => 3,
6151
				'title' => 'Second Post',
6152
				'body' => 'Second Post Body',
6153
				'published' => 'Y',
6154
				'created' => '2007-03-18 10:41:23',
6155
				'updated' => '2007-03-18 10:43:31'
6156
			)),
6157
			array('Post' => array(
6158
				'id' => '3',
6159
				'author_id' => 1,
6160
				'title' => 'Third Post',
6161
				'body' => 'Third Post Body',
6162
				'published' => 'Y',
6163
				'created' => '2007-03-18 10:43:23',
6164
				'updated' => '2007-03-18 10:45:31'
6165
		)));
6166
 
6167
		if (count($result) != 3) {
6168
			// Database doesn't support transactions
6169
			$expected[] = array(
6170
				'Post' => array(
6171
					'id' => '4',
6172
					'author_id' => 1,
6173
					'title' => 'New Fourth Post',
6174
					'body' => null,
6175
					'published' => 'N'
6176
			));
6177
 
6178
			$expected[] = array(
6179
				'Post' => array(
6180
					'id' => '5',
6181
					'author_id' => 1,
6182
					'title' => 'New Fifth Post',
6183
					'body' => null,
6184
					'published' => 'N',
6185
			));
6186
 
6187
			$this->assertEquals(self::date(), $result[3]['Post']['created']);
6188
			$this->assertEquals(self::date(), $result[3]['Post']['updated']);
6189
			$this->assertEquals(self::date(), $result[4]['Post']['created']);
6190
			$this->assertEquals(self::date(), $result[4]['Post']['updated']);
6191
			unset($result[3]['Post']['created'], $result[3]['Post']['updated']);
6192
			unset($result[4]['Post']['created'], $result[4]['Post']['updated']);
6193
			$this->assertEquals($expected, $result);
6194
			// Skip the rest of the transactional tests
6195
			return;
6196
		}
6197
 
6198
		$this->assertEquals($expected, $result);
6199
 
6200
		$data = array(
6201
			array('author_id' => 1, 'title' => 'New Fourth Post'),
6202
			array('author_id' => 1, 'title' => ''),
6203
			array('author_id' => 1, 'title' => 'New Sixth Post')
6204
		);
6205
		$this->assertFalse($TestModel->saveMany($data));
6206
 
6207
		$result = $TestModel->find('all', array('recursive' => -1));
6208
		$expected = array(
6209
			array('Post' => array(
6210
				'id' => '1',
6211
				'author_id' => 1,
6212
				'title' => 'First Post',
6213
				'body' => 'First Post Body',
6214
				'published' => 'Y',
6215
				'created' => '2007-03-18 10:39:23',
6216
				'updated' => '2007-03-18 10:41:31'
6217
			)),
6218
			array('Post' => array(
6219
				'id' => '2',
6220
				'author_id' => 3,
6221
				'title' => 'Second Post',
6222
				'body' => 'Second Post Body',
6223
				'published' => 'Y',
6224
				'created' => '2007-03-18 10:41:23',
6225
				'updated' => '2007-03-18 10:43:31'
6226
			)),
6227
			array('Post' => array(
6228
				'id' => '3',
6229
				'author_id' => 1,
6230
				'title' => 'Third Post',
6231
				'body' => 'Third Post Body',
6232
				'published' => 'Y',
6233
				'created' => '2007-03-18 10:43:23',
6234
				'updated' => '2007-03-18 10:45:31'
6235
		)));
6236
 
6237
		if (count($result) != 3) {
6238
			// Database doesn't support transactions
6239
			$expected[] = array(
6240
				'Post' => array(
6241
					'id' => '4',
6242
					'author_id' => 1,
6243
					'title' => 'New Fourth Post',
6244
					'body' => 'Third Post Body',
6245
					'published' => 'N'
6246
			));
6247
 
6248
			$expected[] = array(
6249
				'Post' => array(
6250
					'id' => '5',
6251
					'author_id' => 1,
6252
					'title' => 'Third Post',
6253
					'body' => 'Third Post Body',
6254
					'published' => 'N'
6255
			));
6256
			$this->assertEquals(self::date(), $result[3]['Post']['created']);
6257
			$this->assertEquals(self::date(), $result[3]['Post']['updated']);
6258
			$this->assertEquals(self::date(), $result[4]['Post']['created']);
6259
			$this->assertEquals(self::date(), $result[4]['Post']['updated']);
6260
			unset($result[3]['Post']['created'], $result[3]['Post']['updated']);
6261
			unset($result[4]['Post']['created'], $result[4]['Post']['updated']);
6262
		}
6263
		$this->assertEquals($expected, $result);
6264
 
6265
		$TestModel->validate = array('title' => 'notEmpty');
6266
		$data = array(
6267
			array('author_id' => 1, 'title' => 'New Fourth Post'),
6268
			array('author_id' => 1, 'title' => 'New Fifth Post'),
6269
			array('author_id' => 1, 'title' => 'New Sixth Post')
6270
		);
6271
		$this->assertTrue($TestModel->saveMany($data));
6272
 
6273
		$result = $TestModel->find('all', array(
6274
			'recursive' => -1,
6275
			'fields' => array('author_id', 'title', 'body', 'published'),
6276
			'order' => array('Post.created' => 'ASC')
6277
		));
6278
 
6279
		$expected = array(
6280
			array('Post' => array(
6281
				'author_id' => 1,
6282
				'title' => 'First Post',
6283
				'body' => 'First Post Body',
6284
				'published' => 'Y'
6285
			)),
6286
			array('Post' => array(
6287
				'author_id' => 3,
6288
				'title' => 'Second Post',
6289
				'body' => 'Second Post Body',
6290
				'published' => 'Y'
6291
			)),
6292
			array('Post' => array(
6293
				'author_id' => 1,
6294
				'title' => 'Third Post',
6295
				'body' => 'Third Post Body',
6296
				'published' => 'Y'
6297
			)),
6298
			array('Post' => array(
6299
				'author_id' => 1,
6300
				'title' => 'New Fourth Post',
6301
				'body' => '',
6302
				'published' => 'N'
6303
			)),
6304
			array('Post' => array(
6305
				'author_id' => 1,
6306
				'title' => 'New Fifth Post',
6307
				'body' => '',
6308
				'published' => 'N'
6309
			)),
6310
			array('Post' => array(
6311
				'author_id' => 1,
6312
				'title' => 'New Sixth Post',
6313
				'body' => '',
6314
				'published' => 'N'
6315
		)));
6316
		$this->assertEquals($expected, $result);
6317
	}
6318
 
6319
/**
6320
 * testSaveManyValidation method
6321
 *
6322
 * @return void
6323
 */
6324
	public function testSaveManyValidation() {
6325
		$this->loadFixtures('Post', 'Author', 'Comment', 'Attachment');
6326
		$TestModel = new Post();
6327
 
6328
		$data = array(
6329
			array(
6330
				'id' => '1',
6331
				'title' => 'Baleeted First Post',
6332
				'body' => 'Baleeted!',
6333
				'published' => 'N'
6334
			),
6335
			array(
6336
				'id' => '2',
6337
				'title' => 'Just update the title'
6338
			),
6339
			array(
6340
				'title' => 'Creating a fourth post',
6341
				'body' => 'Fourth post body',
6342
				'author_id' => 2
6343
		));
6344
 
6345
		$this->assertTrue($TestModel->saveMany($data));
6346
 
6347
		$result = $TestModel->find('all', array('recursive' => -1, 'order' => 'Post.id ASC'));
6348
		$expected = array(
6349
			array(
6350
				'Post' => array(
6351
					'id' => '1',
6352
					'author_id' => '1',
6353
					'title' => 'Baleeted First Post',
6354
					'body' => 'Baleeted!',
6355
					'published' => 'N',
6356
					'created' => '2007-03-18 10:39:23'
6357
				)
6358
			),
6359
			array(
6360
				'Post' => array(
6361
					'id' => '2',
6362
					'author_id' => '3',
6363
					'title' => 'Just update the title',
6364
					'body' => 'Second Post Body',
6365
					'published' => 'Y',
6366
					'created' => '2007-03-18 10:41:23'
6367
				)
6368
			),
6369
			array(
6370
				'Post' => array(
6371
					'id' => '3',
6372
					'author_id' => '1',
6373
					'title' => 'Third Post',
6374
					'body' => 'Third Post Body',
6375
					'published' => 'Y',
6376
					'created' => '2007-03-18 10:43:23',
6377
					'updated' => '2007-03-18 10:45:31'
6378
			)),
6379
			array(
6380
				'Post' => array(
6381
					'id' => '4',
6382
					'author_id' => '2',
6383
					'title' => 'Creating a fourth post',
6384
					'body' => 'Fourth post body',
6385
					'published' => 'N'
6386
				)
6387
			)
6388
		);
6389
 
6390
		$this->assertEquals(self::date(), $result[0]['Post']['updated']);
6391
		$this->assertEquals(self::date(), $result[1]['Post']['updated']);
6392
		$this->assertEquals(self::date(), $result[3]['Post']['created']);
6393
		$this->assertEquals(self::date(), $result[3]['Post']['updated']);
6394
		unset($result[0]['Post']['updated'], $result[1]['Post']['updated']);
6395
		unset($result[3]['Post']['created'], $result[3]['Post']['updated']);
6396
		$this->assertEquals($expected, $result);
6397
 
6398
		$TestModel->validate = array('title' => 'notEmpty', 'author_id' => 'numeric');
6399
		$data = array(
6400
			array(
6401
				'id' => '1',
6402
				'title' => 'Un-Baleeted First Post',
6403
				'body' => 'Not Baleeted!',
6404
				'published' => 'Y'
6405
			),
6406
			array(
6407
				'id' => '2',
6408
				'title' => '',
6409
				'body' => 'Trying to get away with an empty title'
6410
		));
6411
		$result = $TestModel->saveMany($data);
6412
		$this->assertFalse($result);
6413
 
6414
		$result = $TestModel->find('all', array('recursive' => -1, 'order' => 'Post.id ASC'));
6415
		$errors = array(1 => array('title' => array('This field cannot be left blank')));
6416
		$transactionWorked = Set::matches('/Post[1][title=Baleeted First Post]', $result);
6417
		if (!$transactionWorked) {
6418
			$this->assertTrue(Set::matches('/Post[1][title=Un-Baleeted First Post]', $result));
6419
			$this->assertTrue(Set::matches('/Post[2][title=Just update the title]', $result));
6420
		}
6421
 
6422
		$this->assertEquals($errors, $TestModel->validationErrors);
6423
 
6424
		$TestModel->validate = array('title' => 'notEmpty', 'author_id' => 'numeric');
6425
		$data = array(
6426
			array(
6427
				'id' => '1',
6428
				'title' => 'Un-Baleeted First Post',
6429
				'body' => 'Not Baleeted!',
6430
				'published' => 'Y'
6431
			),
6432
			array(
6433
				'id' => '2',
6434
				'title' => '',
6435
				'body' => 'Trying to get away with an empty title'
6436
		));
6437
		$result = $TestModel->saveMany($data, array('validate' => true, 'atomic' => false));
6438
		$this->assertEquals(array(true, false), $result);
6439
 
6440
		$result = $TestModel->find('all', array(
6441
			'fields' => array('id', 'author_id', 'title', 'body', 'published'),
6442
			'recursive' => -1,
6443
			'order' => 'Post.id ASC'
6444
		));
6445
		$errors = array(1 => array('title' => array('This field cannot be left blank')));
6446
		$expected = array(
6447
			array(
6448
				'Post' => array(
6449
					'id' => '1',
6450
					'author_id' => '1',
6451
					'title' => 'Un-Baleeted First Post',
6452
					'body' => 'Not Baleeted!',
6453
					'published' => 'Y',
6454
			)),
6455
			array(
6456
				'Post' => array(
6457
					'id' => '2',
6458
					'author_id' => '3',
6459
					'title' => 'Just update the title',
6460
					'body' => 'Second Post Body',
6461
					'published' => 'Y',
6462
			)),
6463
			array(
6464
				'Post' => array(
6465
					'id' => '3',
6466
					'author_id' => '1',
6467
					'title' => 'Third Post',
6468
					'body' => 'Third Post Body',
6469
					'published' => 'Y',
6470
			)),
6471
			array(
6472
				'Post' => array(
6473
					'id' => '4',
6474
					'author_id' => '2',
6475
					'title' => 'Creating a fourth post',
6476
					'body' => 'Fourth post body',
6477
					'published' => 'N',
6478
		)));
6479
		$this->assertEquals($expected, $result);
6480
		$this->assertEquals($errors, $TestModel->validationErrors);
6481
 
6482
		$data = array(
6483
			array(
6484
				'id' => '1',
6485
				'title' => 'Re-Baleeted First Post',
6486
				'body' => 'Baleeted!',
6487
				'published' => 'N'
6488
			),
6489
			array(
6490
				'id' => '2',
6491
				'title' => '',
6492
				'body' => 'Trying to get away with an empty title'
6493
		));
6494
		$this->assertFalse($TestModel->saveMany($data, array('validate' => 'first')));
6495
 
6496
		$result = $TestModel->find('all', array(
6497
			'fields' => array('id', 'author_id', 'title', 'body', 'published'),
6498
			'recursive' => -1,
6499
			'order' => 'Post.id ASC'
6500
		));
6501
		$this->assertEquals($expected, $result);
6502
		$this->assertEquals($errors, $TestModel->validationErrors);
6503
	}
6504
 
6505
/**
6506
 * testValidateMany method
6507
 *
6508
 * @return void
6509
 */
6510
	public function testValidateMany() {
6511
		$TestModel = new Article();
6512
		$TestModel->validate = array('title' => 'notEmpty');
6513
		$data = array(
6514
 
6515
				1 => array('title' => 'title 1'),
6516
				2 => array('title' => 'title 2'),
6517
		);
6518
		$result = $TestModel->validateMany($data);
6519
		$this->assertFalse($result);
6520
		$expected = array(
6521
 
6522
		);
6523
		$this->assertEquals($expected, $TestModel->validationErrors);
6524
 
6525
		$data = array(
6526
 
6527
				1 => array('title' => ''),
6528
				2 => array('title' => 'title 2'),
6529
		);
6530
		$result = $TestModel->validateMany($data);
6531
		$this->assertFalse($result);
6532
		$expected = array(
6533
			1 => array('title' => array('This field cannot be left blank')),
6534
		);
6535
		$this->assertEquals($expected, $TestModel->validationErrors);
6536
	}
6537
 
6538
/**
6539
 * testSaveAssociatedValidateFirst method
6540
 *
6541
 * @return void
6542
 */
6543
	public function testSaveAssociatedValidateFirst() {
6544
		$this->loadFixtures('Article', 'Comment', 'Attachment');
6545
		$model = new Article();
6546
		$model->deleteAll(true);
6547
 
6548
		$model->Comment->validate = array('comment' => 'notEmpty');
6549
		$result = $model->saveAssociated(array(
6550
			'Article' => array(
6551
				'title' => 'Post with Author',
6552
				'body' => 'This post will be saved author'
6553
			),
6554
			'Comment' => array(
6555
				array('comment' => 'First new comment'),
6556
				array('comment' => '')
6557
			)
6558
		), array('validate' => 'first'));
6559
 
6560
		$this->assertFalse($result);
6561
 
6562
		$result = $model->find('all');
6563
		$this->assertSame(array(), $result);
6564
		$expected = array('Comment' => array(
6565
			1 => array('comment' => array('This field cannot be left blank'))
6566
		));
6567
 
6568
		$this->assertEquals($expected['Comment'], $model->Comment->validationErrors);
6569
 
6570
		$this->assertSame($model->Comment->find('count'), 0);
6571
 
6572
		$result = $model->saveAssociated(
6573
			array(
6574
				'Article' => array(
6575
					'title' => 'Post with Author',
6576
					'body' => 'This post will be saved with an author',
6577
					'user_id' => 2
6578
				),
6579
				'Comment' => array(
6580
					array(
6581
						'comment' => 'Only new comment',
6582
						'user_id' => 2
6583
			))),
6584
			array('validate' => 'first')
6585
		);
6586
 
6587
		$this->assertTrue($result);
6588
 
6589
		$result = $model->Comment->find('all');
6590
		$this->assertSame(count($result), 1);
6591
		$result = Hash::extract($result, '{n}.Comment.article_id');
6592
		$this->assertEquals(4, $result[0]);
6593
 
6594
		$model->deleteAll(true);
6595
		$data = array(
6596
			'Article' => array(
6597
				'title' => 'Post with Author saveAlled from comment',
6598
				'body' => 'This post will be saved with an author',
6599
				'user_id' => 2
6600
			),
6601
			'Comment' => array(
6602
				'comment' => 'Only new comment', 'user_id' => 2
6603
		));
6604
 
6605
		$result = $model->Comment->saveAssociated($data, array('validate' => 'first'));
6606
		$this->assertFalse(empty($result));
6607
 
6608
		$result = $model->find('all');
6609
		$this->assertEquals(
6610
			'Post with Author saveAlled from comment',
6611
			$result[0]['Article']['title']
6612
		);
6613
		$this->assertEquals('Only new comment', $result[0]['Comment'][0]['comment']);
6614
	}
6615
 
6616
/**
6617
 * test saveMany()'s return is correct when using atomic = false and validate = first.
6618
 *
6619
 * @return void
6620
 */
6621
	public function testSaveManyValidateFirstAtomicFalse() {
6622
		$Something = new Something();
6623
		$invalidData = array(
6624
			array(
6625
				'title' => 'foo',
6626
				'body' => 'bar',
6627
				'published' => 'baz',
6628
			),
6629
			array(
6630
				'body' => 3,
6631
				'published' => 'sd',
6632
			),
6633
		);
6634
		$Something->create();
6635
		$Something->validate = array(
6636
			'title' => array(
6637
				'rule' => 'alphaNumeric',
6638
				'required' => true,
6639
			),
6640
			'body' => array(
6641
				'rule' => 'alphaNumeric',
6642
				'required' => true,
6643
				'allowEmpty' => true,
6644
			),
6645
		);
6646
		$result = $Something->saveMany($invalidData, array(
6647
			'atomic' => false,
6648
			'validate' => 'first',
6649
		));
6650
		$expected = array(true, false);
6651
		$this->assertEquals($expected, $result);
6652
 
6653
		$Something = new Something();
6654
		$validData = array(
6655
			array(
6656
				'title' => 'title value',
6657
				'body' => 'body value',
6658
				'published' => 'baz',
6659
			),
6660
			array(
6661
				'title' => 'valid',
6662
				'body' => 'this body',
6663
				'published' => 'sd',
6664
			),
6665
		);
6666
		$Something->create();
6667
		$result = $Something->saveMany($validData, array(
6668
			'atomic' => false,
6669
			'validate' => 'first',
6670
		));
6671
		$expected = array(true, true);
6672
		$this->assertEquals($expected, $result);
6673
	}
6674
 
6675
/**
6676
 * testValidateAssociated method
6677
 *
6678
 * @return void
6679
 */
6680
	public function testValidateAssociated() {
6681
		$this->loadFixtures('Attachment', 'Article', 'Comment');
6682
		$TestModel = new Comment();
6683
		$TestModel->Attachment->validate = array('attachment' => 'notEmpty');
6684
 
6685
		$data = array(
6686
			'Comment' => array(
6687
				'comment' => 'This is the comment'
6688
			),
6689
			'Attachment' => array(
6690
				'attachment' => ''
6691
			)
6692
		);
6693
 
6694
		$result = $TestModel->validateAssociated($data);
6695
		$this->assertFalse($result);
6696
 
6697
		$TestModel = new Article();
6698
		$TestModel->belongsTo = $TestModel->hasAndBelongsToMany = array();
6699
		$TestModel->Comment->validate = array('comment' => 'notEmpty');
6700
 
6701
		$data = array(
6702
			'Article' => array('id' => 2),
6703
			'Comment' => array(
6704
				array(
6705
					'id' => 1,
6706
					'comment' => '',
6707
					'published' => 'Y',
6708
					'user_id' => 1),
6709
				array(
6710
					'id' => 2,
6711
					'comment' =>
6712
					'comment',
6713
					'published' => 'Y',
6714
					'user_id' => 1
6715
		)));
6716
		$result = $TestModel->validateAssociated($data);
6717
		$this->assertFalse($result);
6718
 
6719
		$data = array(
6720
			'Article' => array('id' => 2),
6721
			'Comment' => array(
6722
				array(
6723
					'id' => 1,
6724
					'comment' => '',
6725
					'published' => 'Y',
6726
					'user_id' => 1
6727
				),
6728
				array(
6729
					'id' => 2,
6730
					'comment' => 'comment',
6731
					'published' => 'Y',
6732
					'user_id' => 1
6733
				),
6734
				array(
6735
					'id' => 3,
6736
					'comment' => '',
6737
					'published' => 'Y',
6738
					'user_id' => 1
6739
		)));
6740
		$result = $TestModel->validateAssociated($data, array(
6741
				'atomic' => false
6742
		));
6743
		$expected = array(
6744
			'Article' => true,
6745
			'Comment' => array(false, true, false)
6746
		);
6747
		$this->assertSame($expected, $result);
6748
 
6749
		$expected = array('Comment' => array(
6750
 
6751
			2 => array('comment' => array('This field cannot be left blank'))
6752
		));
6753
		$this->assertEquals($expected, $TestModel->validationErrors);
6754
 
6755
		$expected = array(
6756
 
6757
			2 => array('comment' => array('This field cannot be left blank'))
6758
		);
6759
		$this->assertEquals($expected, $TestModel->Comment->validationErrors);
6760
	}
6761
 
6762
/**
6763
 * test that saveMany behaves like plain save() when suplied empty data
6764
 *
6765
 * @link https://cakephp.lighthouseapp.com/projects/42648/tickets/277-test-saveall-with-validation-returns-incorrect-boolean-when-saving-empty-data
6766
 * @return void
6767
 */
6768
	public function testSaveManyEmptyData() {
6769
		$this->skipIf($this->db instanceof Sqlserver, 'This test is not compatible with SQL Server.');
6770
 
6771
		$this->loadFixtures('Article', 'ProductUpdateAll', 'Comment', 'Attachment');
6772
		$model = new Article();
6773
		$result = $model->saveMany(array(), array('validate' => true));
6774
		$this->assertFalse(empty($result));
6775
 
6776
		$model = new ProductUpdateAll();
6777
		$result = $model->saveMany(array());
6778
		$this->assertFalse($result);
6779
	}
6780
 
6781
/**
6782
 * test that saveAssociated behaves like plain save() when supplied empty data
6783
 *
6784
 * @link https://cakephp.lighthouseapp.com/projects/42648/tickets/277-test-saveall-with-validation-returns-incorrect-boolean-when-saving-empty-data
6785
 * @return void
6786
 */
6787
	public function testSaveAssociatedEmptyData() {
6788
		$this->skipIf($this->db instanceof Sqlserver, 'This test is not compatible with SQL Server.');
6789
 
6790
		$this->loadFixtures('Article', 'ProductUpdateAll', 'Comment', 'Attachment');
6791
		$model = new Article();
6792
		$result = $model->saveAssociated(array(), array('validate' => true));
6793
		$this->assertFalse(empty($result));
6794
 
6795
		$model = new ProductUpdateAll();
6796
		$result = $model->saveAssociated(array());
6797
		$this->assertFalse($result);
6798
	}
6799
 
6800
/**
6801
 * Test that saveAssociated will accept expression object values when saving.
6802
 *
6803
 * @return void
6804
 */
6805
	public function testSaveAssociatedExpressionObjects() {
6806
		$this->loadFixtures('Post', 'Author', 'Comment', 'Attachment', 'Article', 'User');
6807
		$TestModel = new Post();
6808
		$db = $TestModel->getDataSource();
6809
 
6810
		$TestModel->saveAssociated(array(
6811
			'Post' => array(
6812
				'title' => $db->expression("(SELECT 'Post with Author')"),
6813
				'body' => 'This post will be saved with an author'
6814
			),
6815
			'Author' => array(
6816
				'user' => 'bob',
6817
				'password' => '5f4dcc3b5aa765d61d8327deb882cf90'
6818
		)), array('atomic' => false));
6819
 
6820
		$result = $TestModel->find('first', array(
6821
			'order' => array('Post.id ' => 'DESC')
6822
		));
6823
		$this->assertEquals('Post with Author', $result['Post']['title']);
6824
	}
6825
 
6826
/**
6827
 * testUpdateWithCalculation method
6828
 *
6829
 * @return void
6830
 */
6831
	public function testUpdateWithCalculation() {
6832
		$this->loadFixtures('DataTest');
6833
		$model = new DataTest();
6834
		$model->deleteAll(true);
6835
		$result = $model->saveMany(array(
6836
			array('count' => 5, 'float' => 1.1),
6837
			array('count' => 3, 'float' => 1.2),
6838
			array('count' => 4, 'float' => 1.3),
6839
			array('count' => 1, 'float' => 2.0),
6840
		));
6841
		$this->assertFalse(empty($result));
6842
 
6843
		$result = Hash::extract($model->find('all', array('fields' => 'count')), '{n}.DataTest.count');
6844
		$this->assertEquals(array(5, 3, 4, 1), $result);
6845
 
6846
		$this->assertTrue($model->updateAll(array('count' => 'count + 2')));
6847
		$result = Hash::extract($model->find('all', array('fields' => 'count')), '{n}.DataTest.count');
6848
		$this->assertEquals(array(7, 5, 6, 3), $result);
6849
 
6850
		$this->assertTrue($model->updateAll(array('DataTest.count' => 'DataTest.count - 1')));
6851
		$result = Hash::extract($model->find('all', array('fields' => 'count')), '{n}.DataTest.count');
6852
		$this->assertEquals(array(6, 4, 5, 2), $result);
6853
	}
6854
 
6855
/**
6856
 * testToggleBoolFields method
6857
 *
6858
 * @return void
6859
 */
6860
	public function testToggleBoolFields() {
6861
		$this->loadFixtures('CounterCacheUser', 'CounterCachePost');
6862
		$Post = new CounterCachePost();
6863
		$Post->unbindModel(array('belongsTo' => array('User')), true);
6864
 
6865
		$true = array('Post' => array('published' => true, 'id' => 2));
6866
		$false = array('Post' => array('published' => false, 'id' => 2));
6867
		$fields = array('Post.published', 'Post.id');
6868
		$updateConditions = array('Post.id' => 2);
6869
 
6870
		// check its true
6871
		$result = $Post->find('first', array('conditions' => $updateConditions, 'fields' => $fields));
6872
		$this->assertEquals($true, $result);
6873
 
6874
		// Testing without the alias
6875
		$this->assertTrue($Post->updateAll(array('published' => 'NOT published'), $updateConditions));
6876
		$result = $Post->find('first', array('conditions' => $updateConditions, 'fields' => $fields));
6877
		$this->assertEquals($false, $result);
6878
 
6879
		$this->assertTrue($Post->updateAll(array('published' => 'NOT published'), $updateConditions));
6880
		$result = $Post->find('first', array('conditions' => $updateConditions, 'fields' => $fields));
6881
		$this->assertEquals($true, $result);
6882
 
6883
		$db = ConnectionManager::getDataSource('test');
6884
		$alias = $db->name('Post.published');
6885
 
6886
		// Testing with the alias
6887
		$this->assertTrue($Post->updateAll(array('Post.published' => "NOT $alias"), $updateConditions));
6888
		$result = $Post->find('first', array('conditions' => $updateConditions, 'fields' => $fields));
6889
		$this->assertEquals($false, $result);
6890
 
6891
		$this->assertTrue($Post->updateAll(array('Post.published' => "NOT $alias"), $updateConditions));
6892
		$result = $Post->find('first', array('conditions' => $updateConditions, 'fields' => $fields));
6893
		$this->assertEquals($true, $result);
6894
	}
6895
 
6896
/**
6897
 * TestFindAllWithoutForeignKey
6898
 *
6899
 * @return void
6900
 */
6901
	public function testFindAllForeignKey() {
6902
		$this->loadFixtures('ProductUpdateAll', 'GroupUpdateAll');
6903
		$ProductUpdateAll = new ProductUpdateAll();
6904
 
6905
		$conditions = array('Group.name' => 'group one');
6906
 
6907
		$ProductUpdateAll->bindModel(array(
6908
			'belongsTo' => array(
6909
				'Group' => array('className' => 'GroupUpdateAll')
6910
			)
6911
		));
6912
 
6913
		$ProductUpdateAll->belongsTo = array(
6914
			'Group' => array('className' => 'GroupUpdateAll', 'foreignKey' => 'group_id')
6915
		);
6916
 
6917
		$results = $ProductUpdateAll->find('all', compact('conditions'));
6918
		$this->assertTrue(!empty($results));
6919
 
6920
		$ProductUpdateAll->bindModel(array('belongsTo' => array('Group')));
6921
		$ProductUpdateAll->belongsTo = array(
6922
			'Group' => array(
6923
				'className' => 'GroupUpdateAll',
6924
				'foreignKey' => false,
6925
				'conditions' => 'ProductUpdateAll.groupcode = Group.code'
6926
			));
6927
 
6928
		$resultsFkFalse = $ProductUpdateAll->find('all', compact('conditions'));
6929
		$this->assertTrue(!empty($resultsFkFalse));
6930
		$expected = array(
6931
			'0' => array(
6932
				'ProductUpdateAll' => array(
6933
					'id' => 1,
6934
					'name'	=> 'product one',
6935
					'groupcode' => 120,
6936
					'group_id' => 1),
6937
				'Group' => array(
6938
					'id' => 1,
6939
					'name' => 'group one',
6940
					'code' => 120)
6941
				),
6942
			'1' => array(
6943
				'ProductUpdateAll' => array(
6944
					'id' => 2,
6945
					'name'	=> 'product two',
6946
					'groupcode'	=> 120,
6947
					'group_id'	=> 1),
6948
				'Group' => array(
6949
					'id' => 1,
6950
					'name' => 'group one',
6951
					'code' => 120)
6952
				)
6953
 
6954
			);
6955
		$this->assertEquals($expected, $results);
6956
		$this->assertEquals($expected, $resultsFkFalse);
6957
	}
6958
 
6959
/**
6960
 * test updateAll with empty values.
6961
 *
6962
 * @return void
6963
 */
6964
	public function testUpdateAllEmptyValues() {
6965
		$this->skipIf($this->db instanceof Sqlserver || $this->db instanceof Postgres, 'This test is not compatible with Postgres or SQL Server.');
6966
 
6967
		$this->loadFixtures('Author', 'Post');
6968
		$model = new Author();
6969
		$result = $model->updateAll(array('user' => '""'));
6970
		$this->assertTrue($result);
6971
	}
6972
 
6973
/**
6974
 * testUpdateAllWithJoins
6975
 *
6976
 * @return void
6977
 */
6978
	public function testUpdateAllWithJoins() {
6979
		$this->skipIf(!$this->db instanceof Mysql, 'Currently, there is no way of doing joins in an update statement in postgresql or sqlite');
6980
 
6981
		$this->loadFixtures('ProductUpdateAll', 'GroupUpdateAll');
6982
		$ProductUpdateAll = new ProductUpdateAll();
6983
 
6984
		$conditions = array('Group.name' => 'group one');
6985
 
6986
		$ProductUpdateAll->bindModel(array('belongsTo' => array(
6987
			'Group' => array('className' => 'GroupUpdateAll')))
6988
		);
6989
 
6990
		$ProductUpdateAll->updateAll(array('name' => "'new product'"), $conditions);
6991
		$results = $ProductUpdateAll->find('all', array(
6992
			'conditions' => array('ProductUpdateAll.name' => 'new product')
6993
		));
6994
		$expected = array(
6995
			'0' => array(
6996
				'ProductUpdateAll' => array(
6997
					'id' => 1,
6998
					'name' => 'new product',
6999
					'groupcode'	=> 120,
7000
					'group_id' => 1),
7001
				'Group' => array(
7002
					'id' => 1,
7003
					'name' => 'group one',
7004
					'code' => 120)
7005
				),
7006
			'1' => array(
7007
				'ProductUpdateAll' => array(
7008
					'id' => 2,
7009
					'name' => 'new product',
7010
					'groupcode' => 120,
7011
					'group_id' => 1),
7012
				'Group' => array(
7013
					'id' => 1,
7014
					'name' => 'group one',
7015
					'code' => 120)));
7016
 
7017
		$this->assertEquals($expected, $results);
7018
	}
7019
 
7020
/**
7021
 * testUpdateAllWithoutForeignKey
7022
 *
7023
 * @return void
7024
 */
7025
	public function testUpdateAllWithoutForeignKey() {
7026
		$this->skipIf(!$this->db instanceof Mysql, 'Currently, there is no way of doing joins in an update statement in postgresql');
7027
 
7028
		$this->loadFixtures('ProductUpdateAll', 'GroupUpdateAll');
7029
		$ProductUpdateAll = new ProductUpdateAll();
7030
 
7031
		$conditions = array('Group.name' => 'group one');
7032
 
7033
		$ProductUpdateAll->bindModel(array('belongsTo' => array(
7034
			'Group' => array('className' => 'GroupUpdateAll')
7035
		)));
7036
 
7037
		$ProductUpdateAll->belongsTo = array(
7038
			'Group' => array(
7039
				'className' => 'GroupUpdateAll',
7040
				'foreignKey' => false,
7041
				'conditions' => 'ProductUpdateAll.groupcode = Group.code'
7042
			)
7043
		);
7044
 
7045
		$ProductUpdateAll->updateAll(array('name' => "'new product'"), $conditions);
7046
		$resultsFkFalse = $ProductUpdateAll->find('all', array('conditions' => array('ProductUpdateAll.name' => 'new product')));
7047
		$expected = array(
7048
			'0' => array(
7049
				'ProductUpdateAll' => array(
7050
					'id' => 1,
7051
					'name' => 'new product',
7052
					'groupcode'	=> 120,
7053
					'group_id' => 1),
7054
				'Group' => array(
7055
					'id' => 1,
7056
					'name' => 'group one',
7057
					'code' => 120)
7058
				),
7059
			'1' => array(
7060
				'ProductUpdateAll' => array(
7061
					'id' => 2,
7062
					'name' => 'new product',
7063
					'groupcode' => 120,
7064
					'group_id' => 1),
7065
				'Group' => array(
7066
					'id' => 1,
7067
					'name' => 'group one',
7068
					'code' => 120)));
7069
		$this->assertEquals($expected, $resultsFkFalse);
7070
	}
7071
 
7072
/**
7073
 * test writing floats in german locale.
7074
 *
7075
 * @return void
7076
 */
7077
	public function testWriteFloatAsGerman() {
7078
		$restore = setlocale(LC_NUMERIC, 0);
7079
 
7080
		$this->skipIf(setlocale(LC_NUMERIC, 'de_DE') === false, "The German locale isn't available.");
7081
 
7082
		$model = new DataTest();
7083
		$result = $model->save(array(
7084
			'count' => 1,
7085
			'float' => 3.14593
7086
		));
7087
		$this->assertTrue((bool)$result);
7088
		setlocale(LC_NUMERIC, $restore);
7089
	}
7090
 
7091
/**
7092
 * Test returned array contains primary key when save creates a new record
7093
 *
7094
 * @return void
7095
 */
7096
	public function testPkInReturnArrayForCreate() {
7097
		$this->loadFixtures('Article');
7098
		$TestModel = new Article();
7099
 
7100
		$data = array('Article' => array(
7101
			'user_id' => '1',
7102
			'title' => 'Fourth Article',
7103
			'body' => 'Fourth Article Body',
7104
			'published' => 'Y'
7105
		));
7106
		$result = $TestModel->save($data);
7107
		$this->assertSame($result['Article']['id'], $TestModel->id);
7108
	}
7109
 
7110
/**
7111
 * testSaveAllFieldListValidateBelongsTo
7112
 *
7113
 * @return void
7114
 */
7115
	public function testSaveAllFieldListValidateBelongsTo() {
7116
		$this->loadFixtures('Post', 'Author', 'Comment', 'Attachment');
7117
		$TestModel = new Post();
7118
 
7119
		$result = $TestModel->find('all');
7120
		$this->assertEquals(3, count($result));
7121
		$this->assertFalse(isset($result[3]));
7122
 
7123
		// test belongsTo
7124
		$fieldList = array(
7125
			'Post' => array('title'),
7126
			'Author' => array('user')
7127
		);
7128
		$data = array(
7129
			'Post' => array(
7130
				'title' => 'Post without body',
7131
				'body' => 'This will not be saved',
7132
			),
7133
			'Author' => array(
7134
				'user' => 'bob',
7135
				'test' => 'This will not be saved',
7136
 
7137
		));
7138
		$TestModel->saveAll($data, array('fieldList' => $fieldList));
7139
 
7140
		$result = $TestModel->find('all', array(
7141
			'order' => 'Post.id ASC',
7142
		));
7143
		$expected = array(
7144
			'Post' => array(
7145
				'id' => '4',
7146
				'author_id' => '5',
7147
				'title' => 'Post without body',
7148
				'body' => null,
7149
				'published' => 'N',
7150
				'created' => self::date(),
7151
				'updated' => self::date(),
7152
			),
7153
			'Author' => array(
7154
				'id' => '5',
7155
				'user' => 'bob',
7156
				'password' => null,
7157
				'created' => self::date(),
7158
				'updated' => self::date(),
7159
				'test' => 'working',
7160
			),
7161
		);
7162
		$this->assertEquals($expected, $result[3]);
7163
		$this->assertEquals(4, count($result));
7164
		$this->assertEquals('', $result[3]['Post']['body']);
7165
		$this->assertEquals('working', $result[3]['Author']['test']);
7166
 
7167
		$fieldList = array(
7168
			'Post' => array('title')
7169
		);
7170
		$data = array(
7171
			'Post' => array(
7172
				'title' => 'Post without body 2',
7173
				'body' => 'This will not be saved'
7174
			),
7175
			'Author' => array(
7176
				'user' => 'jack'
7177
			)
7178
		);
7179
		$TestModel->saveAll($data, array('fieldList' => $fieldList));
7180
		$result = $TestModel->find('all', array(
7181
			'order' => 'Post.id ASC',
7182
		));
7183
		$this->assertNull($result[4]['Post']['body']);
7184
 
7185
		$fieldList = array(
7186
			'Author' => array('password')
7187
		);
7188
		$data = array(
7189
			'Post' => array(
7190
				'id' => '5',
7191
				'title' => 'Post title',
7192
				'body' => 'Post body'
7193
			),
7194
			'Author' => array(
7195
				'id' => '6',
7196
				'user' => 'will not change',
7197
				'password' => 'foobar'
7198
			)
7199
		);
7200
		$result = $TestModel->saveAll($data, array('fieldList' => $fieldList));
7201
		$this->assertTrue($result);
7202
 
7203
		$result = $TestModel->find('all', array(
7204
			'order' => 'Post.id ASC',
7205
		));
7206
		$expected = array(
7207
			'Post' => array(
7208
				'id' => '5',
7209
				'author_id' => '6',
7210
				'title' => 'Post title',
7211
				'body' => 'Post body',
7212
				'published' => 'N',
7213
				'created' => self::date(),
7214
				'updated' => self::date()
7215
			),
7216
			'Author' => array(
7217
				'id' => '6',
7218
				'user' => 'jack',
7219
				'password' => 'foobar',
7220
				'created' => self::date(),
7221
				'updated' => self::date(),
7222
				'test' => 'working'
7223
			),
7224
		);
7225
		$this->assertEquals($expected, $result[4]);
7226
 
7227
		// test multirecord
7228
		$this->db->truncate($TestModel);
7229
 
7230
		$fieldList = array('title', 'author_id');
7231
		$TestModel->saveAll(array(
7232
			array(
7233
				'title' => 'Multi-record post 1',
7234
				'body' => 'First multi-record post',
7235
				'author_id' => 2
7236
			),
7237
			array(
7238
				'title' => 'Multi-record post 2',
7239
				'body' => 'Second multi-record post',
7240
				'author_id' => 2
7241
		)), array('fieldList' => $fieldList));
7242
 
7243
		$result = $TestModel->find('all', array(
7244
			'recursive' => -1,
7245
			'order' => 'Post.id ASC'
7246
		));
7247
		$expected = array(
7248
			array(
7249
				'Post' => array(
7250
					'id' => '1',
7251
					'author_id' => '2',
7252
					'title' => 'Multi-record post 1',
7253
					'body' => '',
7254
					'published' => 'N',
7255
					'created' => self::date(),
7256
					'updated' => self::date()
7257
				)
7258
			),
7259
			array(
7260
				'Post' => array(
7261
					'id' => '2',
7262
					'author_id' => '2',
7263
					'title' => 'Multi-record post 2',
7264
					'body' => '',
7265
					'published' => 'N',
7266
					'created' => self::date(),
7267
					'updated' => self::date()
7268
				)
7269
			)
7270
		);
7271
		$this->assertEquals($expected, $result);
7272
	}
7273
 
7274
/**
7275
 * testSaveAllFieldListHasMany method
7276
 *
7277
 * @return void
7278
 */
7279
	public function testSaveAllFieldListHasMany() {
7280
		$this->loadFixtures('Article', 'Comment');
7281
		$TestModel = new Article();
7282
		$TestModel->belongsTo = $TestModel->hasAndBelongsToMany = array();
7283
 
7284
		$this->db->truncate($TestModel);
7285
		$this->db->truncate(new Comment());
7286
 
7287
		$data = array(
7288
			'Article' => array('title' => 'I will not save'),
7289
			'Comment' => array(
7290
				array('comment' => 'First new comment', 'published' => 'Y', 'user_id' => 1),
7291
				array('comment' => 'Second new comment', 'published' => 'Y', 'user_id' => 2)
7292
			)
7293
		);
7294
 
7295
		$fieldList = array(
7296
			'Article' => array('id'),
7297
			'Comment' => array('article_id', 'user_id')
7298
		);
7299
		$TestModel->saveAll($data, array('fieldList' => $fieldList));
7300
 
7301
		$result = $TestModel->find('all');
7302
		$this->assertEquals('', $result[0]['Article']['title']);
7303
		$this->assertEquals('', $result[0]['Comment'][0]['comment']);
7304
		$this->assertEquals('', $result[0]['Comment'][1]['comment']);
7305
 
7306
		$fieldList = array(
7307
			'Article' => array('id'),
7308
			'Comment' => array('user_id')
7309
		);
7310
		$TestModel->saveAll($data, array('fieldList' => $fieldList));
7311
		$result = $TestModel->find('all');
7312
 
7313
		$this->assertEquals('', $result[1]['Article']['title']);
7314
		$this->assertEquals(2, count($result[1]['Comment']));
7315
 
7316
		$TestModel->whitelist = array('id');
7317
		$TestModel->Comment->whitelist = array('user_id');
7318
		$TestModel->saveAll($data);
7319
		$result = $TestModel->find('all');
7320
 
7321
		$this->assertEquals('', $result[2]['Article']['title']);
7322
		$this->assertEquals(2, count($result[2]['Comment']));
7323
	}
7324
 
7325
/**
7326
 * testSaveAllFieldListHasOne method
7327
 *
7328
 * @return void
7329
 */
7330
	public function testSaveAllFieldListHasOne() {
7331
		$this->loadFixtures('Attachment', 'Comment', 'Article', 'User');
7332
		$TestModel = new Comment();
7333
 
7334
		$TestModel->validate = array('comment' => 'notEmpty');
7335
		$TestModel->Attachment->validate = array('attachment' => 'notEmpty');
7336
 
7337
		$record = array(
7338
			'Comment' => array(
7339
				'user_id' => 1,
7340
				'article_id' => 1,
7341
				'comment' => '',
7342
			),
7343
			'Attachment' => array(
7344
				'attachment' => ''
7345
			)
7346
		);
7347
		$result = $TestModel->saveAll($record, array('validate' => 'only'));
7348
		$this->assertFalse($result);
7349
 
7350
		$fieldList = array(
7351
			'Comment' => array('id', 'article_id', 'user_id'),
7352
			'Attachment' => array('comment_id')
7353
		);
7354
		$result = $TestModel->saveAll($record, array(
7355
			'fieldList' => $fieldList, 'validate' => 'only'
7356
		));
7357
		$this->assertTrue($result);
7358
		$this->assertEmpty($TestModel->validationErrors);
7359
	}
7360
 
7361
/**
7362
 * testSaveAllFieldListHasOneAddFkToWhitelist method
7363
 *
7364
 * @return void
7365
 */
7366
	public function testSaveAllFieldListHasOneAddFkToWhitelist() {
7367
		$this->loadFixtures('ArticleFeatured', 'Featured');
7368
		$Article = new ArticleFeatured();
7369
		$Article->belongsTo = $Article->hasMany = array();
7370
		$Article->Featured->validate = array('end_date' => 'notEmpty');
7371
 
7372
		$record = array(
7373
			'ArticleFeatured' => array(
7374
				'user_id' => 1,
7375
				'title' => 'First Article',
7376
				'body' => '',
7377
				'published' => 'Y'
7378
			),
7379
			'Featured' => array(
7380
				'category_id' => 1,
7381
				'end_date' => ''
7382
			)
7383
		);
7384
		$result = $Article->saveAll($record, array('validate' => 'only'));
7385
		$this->assertFalse($result);
7386
		$expected = array(
7387
			'body' => array(
7388
				'This field cannot be left blank'
7389
			),
7390
			'Featured' => array(
7391
				'end_date' => array(
7392
					'This field cannot be left blank'
7393
				)
7394
			)
7395
		);
7396
		$this->assertEquals($expected, $Article->validationErrors);
7397
 
7398
		$fieldList = array(
7399
			'ArticleFeatured' => array('user_id', 'title'),
7400
			'Featured' => array('category_id')
7401
		);
7402
 
7403
		$result = $Article->saveAll($record, array(
7404
			'fieldList' => $fieldList, 'validate' => 'first'
7405
		));
7406
		$this->assertTrue($result);
7407
		$this->assertEmpty($Article->validationErrors);
7408
 
7409
		$Article->recursive = 0;
7410
		$result = $Article->find('first', array('order' => array('ArticleFeatured.created' => 'DESC')));
7411
		$this->assertSame($result['ArticleFeatured']['id'], $result['Featured']['article_featured_id']);
7412
	}
7413
 
7414
/**
7415
 * testSaveAllDeepFieldListValidateBelongsTo
7416
 *
7417
 * @return void
7418
 */
7419
	public function testSaveAllDeepFieldListValidateBelongsTo() {
7420
		$this->loadFixtures('Post', 'Author', 'Comment', 'Attachment', 'Article', 'User');
7421
		$TestModel = new Post();
7422
		$TestModel->Author->bindModel(array('hasMany' => array('Comment' => array('foreignKey' => 'user_id'))), false);
7423
		$TestModel->recursive = 2;
7424
 
7425
		$result = $TestModel->find('all');
7426
		$this->assertEquals(3, count($result));
7427
		$this->assertFalse(isset($result[3]));
7428
 
7429
		// test belongsTo
7430
		$fieldList = array(
7431
			'Post' => array('title', 'author_id'),
7432
			'Author' => array('user'),
7433
			'Comment' => array('comment')
7434
		);
7435
		$TestModel->saveAll(array(
7436
			'Post' => array(
7437
				'title' => 'Post without body',
7438
				'body' => 'This will not be saved',
7439
			),
7440
			'Author' => array(
7441
				'user' => 'bob',
7442
				'test' => 'This will not be saved',
7443
				'Comment' => array(
7444
					array('id' => 5, 'comment' => 'I am still published', 'published' => 'N'))
7445
 
7446
		)), array('fieldList' => $fieldList, 'deep' => true));
7447
 
7448
		$result = $TestModel->Author->Comment->find('first', array(
7449
			'conditions' => array('Comment.id' => 5),
7450
			'fields' => array('comment', 'published')
7451
		));
7452
		$expected = array(
7453
			'Comment' => array(
7454
				'comment' => 'I am still published',
7455
				'published' => 'Y'
7456
			)
7457
		);
7458
		$this->assertEquals($expected, $result);
7459
	}
7460
 
7461
/**
7462
 * testSaveAllDeepFieldListHasMany method
7463
 *
7464
 * @return void
7465
 */
7466
	public function testSaveAllDeepFieldListHasMany() {
7467
		$this->loadFixtures('Article', 'Comment', 'User');
7468
		$TestModel = new Article();
7469
		$TestModel->belongsTo = $TestModel->hasAndBelongsToMany = array();
7470
 
7471
		$this->db->truncate($TestModel);
7472
		$this->db->truncate(new Comment());
7473
 
7474
		$fieldList = array(
7475
			'Article' => array('id'),
7476
			'Comment' => array('article_id', 'user_id'),
7477
			'User' => array('user')
7478
		);
7479
 
7480
		$result = $TestModel->saveAll(array(
7481
			'Article' => array('id' => 2, 'title' => 'I will not save'),
7482
			'Comment' => array(
7483
				array('comment' => 'First new comment', 'published' => 'Y', 'user_id' => 1),
7484
				array(
7485
					'comment' => 'Second new comment', 'published' => 'Y', 'user_id' => 2,
7486
					'User' => array('user' => 'nopassword', 'password' => 'not saved')
7487
				)
7488
			)
7489
		), array('fieldList' => $fieldList, 'deep' => true));
7490
 
7491
		$result = $TestModel->Comment->User->find('first', array(
7492
			'conditions' => array('User.user' => 'nopassword'),
7493
			'fields' => array('user', 'password')
7494
		));
7495
		$expected = array(
7496
			'User' => array(
7497
				'user' => 'nopassword',
7498
				'password' => ''
7499
			)
7500
		);
7501
		$this->assertEquals($expected, $result);
7502
	}
7503
 
7504
/**
7505
 * testSaveAllDeepHasManyBelongsTo method
7506
 *
7507
 * @return void
7508
 */
7509
	public function testSaveAllDeepHasManyBelongsTo() {
7510
		$this->loadFixtures('Article', 'Comment', 'User');
7511
		$TestModel = new Article();
7512
		$TestModel->belongsTo = $TestModel->hasAndBelongsToMany = array();
7513
 
7514
		$this->db->truncate($TestModel);
7515
		$this->db->truncate(new Comment());
7516
 
7517
		$result = $TestModel->saveAll(array(
7518
			'Article' => array('id' => 2, 'title' => 'The title'),
7519
			'Comment' => array(
7520
				array('comment' => 'First new comment', 'published' => 'Y', 'user_id' => 1),
7521
				array(
7522
					'comment' => 'belongsto', 'published' => 'Y',
7523
					'User' => array('user' => 'findme', 'password' => 'somepass')
7524
				)
7525
			)
7526
		), array('deep' => true));
7527
 
7528
		$result = $TestModel->Comment->User->find('first', array(
7529
			'conditions' => array('User.user' => 'findme'),
7530
			'fields' => array('id', 'user', 'password')
7531
		));
7532
		$expected = array(
7533
			'User' => array(
7534
				'id' => 5,
7535
				'user' => 'findme',
7536
				'password' => 'somepass',
7537
			)
7538
		);
7539
		$this->assertEquals($expected, $result);
7540
 
7541
		$result = $TestModel->Comment->find('first', array(
7542
			'conditions' => array('Comment.user_id' => 5),
7543
			'fields' => array('id', 'comment', 'published', 'user_id')
7544
		));
7545
		$expected = array(
7546
			'Comment' => array(
7547
				'id' => 2,
7548
				'comment' => 'belongsto',
7549
				'published' => 'Y',
7550
				'user_id' => 5
7551
			)
7552
		);
7553
		$this->assertEquals($expected, $result);
7554
	}
7555
 
7556
/**
7557
 * testSaveAllDeepHasManyhasMany method
7558
 *
7559
 * @return void
7560
 */
7561
	public function testSaveAllDeepHasManyHasMany() {
7562
		$this->loadFixtures('Article', 'Comment', 'User', 'Attachment');
7563
		$TestModel = new Article();
7564
		$TestModel->belongsTo = $TestModel->hasAndBelongsToMany = $TestModel->Comment->belongsTo = array();
7565
		$TestModel->Comment->unbindModel(array('hasOne' => array('Attachment')), false);
7566
		$TestModel->Comment->bindModel(array('hasMany' => array('Attachment')), false);
7567
 
7568
		$this->db->truncate($TestModel);
7569
		$this->db->truncate(new Comment());
7570
		$this->db->truncate(new Attachment());
7571
 
7572
		$result = $TestModel->saveAll(array(
7573
			'Article' => array('id' => 2, 'title' => 'The title'),
7574
			'Comment' => array(
7575
				array('comment' => 'First new comment', 'published' => 'Y', 'user_id' => 1),
7576
				array(
7577
					'comment' => 'hasmany', 'published' => 'Y', 'user_id' => 5,
7578
					'Attachment' => array(
7579
						array('attachment' => 'first deep attachment'),
7580
						array('attachment' => 'second deep attachment'),
7581
					)
7582
				)
7583
			)
7584
		), array('deep' => true));
7585
 
7586
		$result = $TestModel->Comment->find('first', array(
7587
			'conditions' => array('Comment.comment' => 'hasmany'),
7588
			'fields' => array('id', 'comment', 'published', 'user_id'),
7589
			'recursive' => -1
7590
		));
7591
		$expected = array(
7592
			'Comment' => array(
7593
				'id' => 2,
7594
				'comment' => 'hasmany',
7595
				'published' => 'Y',
7596
				'user_id' => 5
7597
			)
7598
		);
7599
		$this->assertEquals($expected, $result);
7600
 
7601
		$result = $TestModel->Comment->Attachment->find('all', array(
7602
			'fields' => array('attachment', 'comment_id'),
7603
			'order' => array('Attachment.id' => 'ASC')
7604
		));
7605
		$expected = array(
7606
			array('Attachment' => array('attachment' => 'first deep attachment', 'comment_id' => 2)),
7607
			array('Attachment' => array('attachment' => 'second deep attachment', 'comment_id' => 2)),
7608
		);
7609
		$this->assertEquals($expected, $result);
7610
	}
7611
 
7612
/**
7613
 * testSaveAllDeepOrderHasManyHasMany method
7614
 *
7615
 * @return void
7616
 */
7617
	public function testSaveAllDeepOrderHasManyHasMany() {
7618
		$this->loadFixtures('Article', 'Comment', 'User', 'Attachment');
7619
		$TestModel = new Article();
7620
		$TestModel->belongsTo = $TestModel->hasAndBelongsToMany = $TestModel->Comment->belongsTo = array();
7621
		$TestModel->Comment->unbindModel(array('hasOne' => array('Attachment')), false);
7622
		$TestModel->Comment->bindModel(array('hasMany' => array('Attachment')), false);
7623
 
7624
		$this->db->truncate($TestModel);
7625
		$this->db->truncate(new Comment());
7626
		$this->db->truncate(new Attachment());
7627
 
7628
		$result = $TestModel->saveAll(array(
7629
			'Article' => array('id' => 2, 'title' => 'Comment has its data after Attachment'),
7630
			'Comment' => array(
7631
				array(
7632
					'Attachment' => array(
7633
						array('attachment' => 'attachment should be created with comment_id'),
7634
						array('attachment' => 'comment should be created with article_id'),
7635
					),
7636
					'comment' => 'after associated data',
7637
					'user_id' => 1
7638
				)
7639
			)
7640
		), array('deep' => true));
7641
		$result = $TestModel->Comment->find('first', array(
7642
			'conditions' => array('Comment.article_id' => 2),
7643
		));
7644
 
7645
		$this->assertEquals(2, $result['Comment']['article_id']);
7646
		$this->assertEquals(2, count($result['Attachment']));
7647
	}
7648
 
7649
/**
7650
 * testSaveAllDeepEmptyHasManyHasMany method
7651
 *
7652
 * @return void
7653
 */
7654
	public function testSaveAllDeepEmptyHasManyHasMany() {
7655
		$this->skipIf(!$this->db instanceof Mysql, 'This test is only compatible with Mysql.');
7656
 
7657
		$this->loadFixtures('Article', 'Comment', 'User', 'Attachment');
7658
		$TestModel = new Article();
7659
		$TestModel->belongsTo = $TestModel->hasAndBelongsToMany = $TestModel->Comment->belongsTo = array();
7660
		$TestModel->Comment->unbindModel(array('hasOne' => array('Attachment')), false);
7661
		$TestModel->Comment->bindModel(array('hasMany' => array('Attachment')), false);
7662
 
7663
		$this->db->truncate($TestModel);
7664
		$this->db->truncate(new Comment());
7665
		$this->db->truncate(new Attachment());
7666
 
7667
		$result = $TestModel->saveAll(array(
7668
			'Article' => array('id' => 3, 'user_id' => 1, 'title' => 'Comment has no data'),
7669
			'Comment' => array(
7670
				array(
7671
					'user_id' => 1,
7672
					'Attachment' => array(
7673
						array('attachment' => 'attachment should be created with comment_id'),
7674
						array('attachment' => 'comment should be created with article_id'),
7675
					),
7676
				)
7677
			)
7678
		), array('deep' => true));
7679
		$result = $TestModel->Comment->find('first', array(
7680
			'conditions' => array('Comment.article_id' => 3),
7681
		));
7682
 
7683
		$this->assertEquals(3, $result['Comment']['article_id']);
7684
		$this->assertEquals(2, count($result['Attachment']));
7685
	}
7686
 
7687
/**
7688
 * testUpdateAllBoolean
7689
 *
7690
 * @return void
7691
 */
7692
	public function testUpdateAllBoolean() {
7693
		$this->loadFixtures('Item', 'Syfile', 'Portfolio', 'Image', 'ItemsPortfolio');
7694
		$TestModel = new Item();
7695
		$result = $TestModel->updateAll(array('published' => true));
7696
		$this->assertTrue($result);
7697
 
7698
		$result = $TestModel->find('first', array('fields' => array('id', 'published')));
7699
		$this->assertEquals(true, $result['Item']['published']);
7700
	}
7701
 
7702
/**
7703
 * testUpdateAllBooleanConditions
7704
 *
7705
 * @return void
7706
 */
7707
	public function testUpdateAllBooleanConditions() {
7708
		$this->loadFixtures('Item', 'Syfile', 'Portfolio', 'Image', 'ItemsPortfolio');
7709
		$TestModel = new Item();
7710
 
7711
		$result = $TestModel->updateAll(array('published' => true), array('Item.id' => 1));
7712
		$this->assertTrue($result);
7713
		$result = $TestModel->find('first', array(
7714
			'fields' => array('id', 'published'),
7715
			'conditions' => array('Item.id' => 1)));
7716
		$this->assertEquals(true, $result['Item']['published']);
7717
	}
7718
 
7719
/**
7720
 * testUpdateBoolean
7721
 *
7722
 * @return void
7723
 */
7724
	public function testUpdateBoolean() {
7725
		$this->loadFixtures('Item', 'Syfile', 'Portfolio', 'Image', 'ItemsPortfolio');
7726
		$TestModel = new Item();
7727
 
7728
		$result = $TestModel->save(array('published' => true, 'id' => 1));
7729
		$this->assertTrue((bool)$result);
7730
		$result = $TestModel->find('first', array(
7731
			'fields' => array('id', 'published'),
7732
			'conditions' => array('Item.id' => 1)));
7733
		$this->assertEquals(true, $result['Item']['published']);
7734
	}
7735
 
7736
/**
7737
 * Test the clear() method.
7738
 *
7739
 * @return void
7740
 */
7741
	public function testClear() {
7742
		$this->loadFixtures('Bid');
7743
		$model = ClassRegistry::init('Bid');
7744
		$model->set(array('name' => 'Testing', 'message_id' => 3));
7745
		$this->assertTrue(isset($model->data['Bid']['name']));
7746
		$this->assertTrue($model->clear());
7747
		$this->assertFalse(isset($model->data['Bid']['name']));
7748
		$this->assertFalse(isset($model->data['Bid']['message_id']));
7749
	}
7750
 
7751
/**
7752
 * Test that Model::save() doesn't generate a query with WHERE 1 = 1 on race condition.
7753
 *
7754
 * @link https://github.com/cakephp/cakephp/issues/3857
7755
 * @return void
7756
 */
7757
	public function testSafeUpdateMode() {
7758
		$this->loadFixtures('User');
7759
 
7760
		$User = ClassRegistry::init('User');
7761
		$this->assertFalse($User->__safeUpdateMode);
7762
 
7763
		$User->getEventManager()->attach(array($this, 'deleteMe'), 'Model.beforeSave');
7764
 
7765
		$User->id = 1;
7766
		$User->set(array('user' => 'nobody'));
7767
		$User->save();
7768
 
7769
		$users = $User->find('list', array('fields' => 'User.user'));
7770
 
7771
		$expected = array(
7772
			2 => 'nate',
7773
			3 => 'larry',
7774
			4 => 'garrett',
7775
		);
7776
		$this->assertEquals($expected, $users);
7777
		$this->assertFalse($User->__safeUpdateMode);
7778
 
7779
		$User->id = 2;
7780
		$User->set(array('user' => $User->getDataSource()->expression('PDO_EXCEPTION()')));
7781
		try {
7782
			$User->save(null, false);
7783
			$this->fail('No exception thrown');
7784
		} catch (PDOException $e) {
7785
			$this->assertFalse($User->__safeUpdateMode);
7786
		}
7787
	}
7788
 
7789
/**
7790
 * Emulates race condition
7791
 *
7792
 * @param CakeEvent $event containing the Model
7793
 * @return void
7794
 */
7795
	public function deleteMe($event) {
7796
		$Model = $event->subject;
7797
		$Model->getDataSource()->delete($Model, array($Model->alias . '.' . $Model->primaryKey => $Model->id));
7798
	}
7799
 
7800
/**
7801
 * Creates a convenient mock DboSource
7802
 *
7803
 * We cannot call several methods via mock DboSource, such as DboSource::value()
7804
 * because mock DboSource has no $_connection.
7805
 * This method helps us to avoid this problem.
7806
 *
7807
 * @param array $methods Configurable method names.
7808
 * @return DboSource
7809
 */
7810
	protected function _getMockDboSource($methods = array()) {
7811
		$testDb = ConnectionManager::getDataSource('test');
7812
 
7813
		$passthrough = array_diff(array('value', 'begin', 'rollback', 'commit', 'describe', 'lastInsertId', 'execute'), $methods);
7814
 
7815
		$methods = array_merge($methods, $passthrough);
7816
		if (!in_array('connect', $methods)) {
7817
			$methods[] = 'connect'; // This will be called by DboSource::__construct().
7818
		}
7819
 
7820
		$db = $this->getMock('DboSource', $methods);
7821
		$db->columns = $testDb->columns;
7822
		$db->startQuote = $testDb->startQuote;
7823
		$db->endQuote = $testDb->endQuote;
7824
 
7825
		foreach ($passthrough as $method) {
7826
			$db->expects($this->any())
7827
				->method($method)
7828
				->will($this->returnCallback(array($testDb, $method)));
7829
		}
7830
 
7831
		return $db;
7832
	}
7833
 
7834
/**
7835
 * Test that transactions behave correctly on nested saveMany calls.
7836
 *
7837
 * @return void
7838
 */
7839
	public function testTransactionOnNestedSaveMany() {
7840
		$this->loadFixtures('Post');
7841
		$Post = new TestPost();
7842
		$Post->getEventManager()->attach(array($this, 'nestedSaveMany'), 'Model.afterSave');
7843
 
7844
		// begin -> [ begin -> commit ] -> commit
7845
		$db = $this->_getMockDboSource(array('begin', 'commit', 'rollback'));
7846
		$db->expects($this->exactly(2))->method('begin')->will($this->returnValue(true));
7847
		$db->expects($this->exactly(2))->method('commit');
7848
		$db->expects($this->never())->method('rollback');
7849
		$Post->setDataSourceObject($db);
7850
 
7851
		$data = array(
7852
			array('author_id' => 1, 'title' => 'Outer Post'),
7853
		);
7854
		$Post->dataForAfterSave = array(
7855
			array('author_id' => 1, 'title' => 'Inner Post'),
7856
		);
7857
		$this->assertTrue($Post->saveMany($data));
7858
 
7859
		// begin -> [  begin(false) ] -> commit
7860
		$db = $this->_getMockDboSource(array('begin', 'commit', 'rollback'));
7861
		$db->expects($this->at(0))->method('begin')->will($this->returnValue(true));
7862
		$db->expects($this->at(1))->method('begin')->will($this->returnValue(false));
7863
		$db->expects($this->once())->method('commit');
7864
		$db->expects($this->never())->method('rollback');
7865
		$Post->setDataSourceObject($db);
7866
 
7867
		$data = array(
7868
			array('author_id' => 1, 'title' => 'Outer Post'),
7869
		);
7870
		$Post->dataForAfterSave = array(
7871
			array('author_id' => 1, 'title' => 'Inner Post'),
7872
		);
7873
		$this->assertTrue($Post->saveMany($data));
7874
 
7875
		// begin -> [ begin -> rollback ] -> rollback
7876
		$db = $this->_getMockDboSource(array('begin', 'commit', 'rollback'));
7877
		$db->expects($this->exactly(2))->method('begin')->will($this->returnValue(true));
7878
		$db->expects($this->never())->method('commit');
7879
		$db->expects($this->exactly(2))->method('rollback');
7880
		$Post->setDataSourceObject($db);
7881
		$data = array(
7882
			array('author_id' => 1, 'title' => 'Outer Post'),
7883
		);
7884
		$Post->dataForAfterSave = array(
7885
			array('author_id' => 1, 'title' => 'Inner Post', 'body' => $db->expression('PDO_EXCEPTION()')),
7886
		);
7887
 
7888
		try {
7889
			$Post->saveMany($data);
7890
			$this->fail('No exception thrown');
7891
		} catch(Exception $e) {
7892
		}
7893
	}
7894
 
7895
/**
7896
 * Test that transaction behaves correctly on nested saveAssociated calls.
7897
 *
7898
 * @return void
7899
 */
7900
	public function testTransactionOnNestedSaveAssociated() {
7901
		$this->loadFixtures('Author', 'Post');
7902
 
7903
		$Author = new TestAuthor();
7904
		$Author->getEventManager()->attach(array($this, 'nestedSaveAssociated'), 'Model.afterSave');
7905
 
7906
		// begin -> [ begin -> commit ] -> commit
7907
		$db = $this->_getMockDboSource(array('begin', 'commit', 'rollback'));
7908
		$db->expects($this->exactly(2))->method('begin')->will($this->returnValue(true));
7909
		$db->expects($this->exactly(2))->method('commit');
7910
		$db->expects($this->never())->method('rollback');
7911
		$Author->setDataSourceObject($db);
7912
		$Author->Post->setDataSourceObject($db);
7913
 
7914
		$data = array(
7915
			'Author' => array('user' => 'outer'),
7916
			'Post' => array(
7917
				array('title' => 'Outer Post'),
7918
			)
7919
		);
7920
		$Author->dataForAfterSave = array(
7921
			'Author' => array('user' => 'inner'),
7922
			'Post' => array(
7923
				array('title' => 'Inner Post'),
7924
			)
7925
		);
7926
		$this->assertTrue($Author->saveAssociated($data));
7927
 
7928
		// begin -> [  begin(false) ] -> commit
7929
		$db = $this->_getMockDboSource(array('begin', 'commit', 'rollback'));
7930
		$db->expects($this->at(0))->method('begin')->will($this->returnValue(true));
7931
		$db->expects($this->at(1))->method('begin')->will($this->returnValue(false));
7932
		$db->expects($this->once())->method('commit');
7933
		$db->expects($this->never())->method('rollback');
7934
		$Author->setDataSourceObject($db);
7935
		$Author->Post->setDataSourceObject($db);
7936
		$data = array(
7937
			'Author' => array('user' => 'outer'),
7938
			'Post' => array(
7939
				array('title' => 'Outer Post'),
7940
			)
7941
		);
7942
		$Author->dataForAfterSave = array(
7943
			'Author' => array('user' => 'inner'),
7944
			'Post' => array(
7945
				array('title' => 'Inner Post'),
7946
			)
7947
		);
7948
		$this->assertTrue($Author->saveAssociated($data));
7949
 
7950
		// begin -> [ begin -> rollback ] -> rollback
7951
		$db = $this->_getMockDboSource(array('begin', 'commit', 'rollback'));
7952
		$db->expects($this->exactly(2))->method('begin')->will($this->returnValue(true));
7953
		$db->expects($this->never())->method('commit');
7954
		$db->expects($this->exactly(2))->method('rollback');
7955
		$Author->setDataSourceObject($db);
7956
		$Author->Post->setDataSourceObject($db);
7957
		$data = array(
7958
			'Author' => array('user' => 'outer'),
7959
			'Post' => array(
7960
				array('title' => 'Outer Post'),
7961
			)
7962
		);
7963
		$Author->dataForAfterSave = array(
7964
			'Author' => array('user' => 'inner', 'password' => $db->expression('PDO_EXCEPTION()')),
7965
			'Post' => array(
7966
				array('title' => 'Inner Post'),
7967
			)
7968
		);
7969
 
7970
		try {
7971
			$Author->saveAssociated($data);
7972
			$this->fail('No exception thrown');
7973
		} catch(Exception $e) {
7974
		}
7975
	}
7976
 
7977
/**
7978
 * A callback for testing nested saveMany.
7979
 *
7980
 * @param CakeEvent $event containing the Model
7981
 * @return void
7982
 */
7983
	public function nestedSaveMany($event) {
7984
		$Model = $event->subject;
7985
		$Model->saveMany($Model->dataForAfterSave, array('callbacks' => false));
7986
	}
7987
 
7988
/**
7989
 * A callback for testing nested saveAssociated.
7990
 *
7991
 * @param CakeEvent $event containing the Model
7992
 * @return void
7993
 */
7994
	public function nestedSaveAssociated($event) {
7995
		$Model = $event->subject;
7996
		$Model->saveAssociated($Model->dataForAfterSave, array('callbacks' => false));
7997
	}
7998
}