Subversion Repositories SmartDukaan

Rev

Details | Last modification | View Log | RSS feed

Rev Author Line No. Line
16591 anikendra 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' => 'notBlank');
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' => static::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
		$TestModel->id = 5;
2790
		$this->assertFalse($TestModel->exists());
2791
	}
2792
 
2793
/**
2794
 * testUpdateExisting method
2795
 *
2796
 * @return void
2797
 */
2798
	public function testUpdateExisting() {
2799
		$this->loadFixtures('User', 'Article', 'Comment');
2800
		$TestModel = new User();
2801
		$TestModel->create();
2802
 
2803
		$TestModel->save(array(
2804
			'User' => array(
2805
				'user' => 'some user',
2806
				'password' => 'some password'
2807
		)));
2808
		$this->assertTrue(is_int($TestModel->id) || ((int)$TestModel->id === 5));
2809
		$id = $TestModel->id;
2810
 
2811
		$TestModel->save(array(
2812
			'User' => array(
2813
				'user' => 'updated user'
2814
		)));
2815
		$this->assertEquals($id, $TestModel->id);
2816
 
2817
		$result = $TestModel->findById($id);
2818
		$this->assertEquals('updated user', $result['User']['user']);
2819
		$this->assertEquals('some password', $result['User']['password']);
2820
 
2821
		$Article = new Article();
2822
		$Comment = new Comment();
2823
		$data = array(
2824
			'Comment' => array(
2825
				'id' => 1,
2826
				'comment' => 'First Comment for First Article'
2827
			),
2828
			'Article' => array(
2829
				'id' => 2,
2830
				'title' => 'Second Article'
2831
		));
2832
 
2833
		$result = $Article->save($data);
2834
		$this->assertFalse(empty($result));
2835
 
2836
		$result = $Comment->save($data);
2837
		$this->assertFalse(empty($result));
2838
	}
2839
 
2840
/**
2841
 * test updating records and saving blank values.
2842
 *
2843
 * @return void
2844
 */
2845
	public function testUpdateSavingBlankValues() {
2846
		$this->loadFixtures('Article');
2847
		$Article = new Article();
2848
		$Article->validate = array();
2849
		$Article->create();
2850
		$result = $Article->save(array(
2851
			'id' => 1,
2852
			'title' => '',
2853
			'body' => ''
2854
		));
2855
		$this->assertTrue((bool)$result);
2856
		$result = $Article->find('first', array('conditions' => array('Article.id' => 1)));
2857
		$this->assertEquals('', $result['Article']['title'], 'Title is not blank');
2858
		$this->assertEquals('', $result['Article']['body'], 'Body is not blank');
2859
	}
2860
 
2861
/**
2862
 * testUpdateMultiple method
2863
 *
2864
 * @return void
2865
 */
2866
	public function testUpdateMultiple() {
2867
		$this->loadFixtures('Comment', 'Article', 'User', 'CategoryThread');
2868
		$TestModel = new Comment();
2869
		$result = Hash::extract($TestModel->find('all'), '{n}.Comment.user_id');
2870
		$expected = array('2', '4', '1', '1', '1', '2');
2871
		$this->assertEquals($expected, $result);
2872
 
2873
		$TestModel->updateAll(array('Comment.user_id' => 5), array('Comment.user_id' => 2));
2874
		$result = Hash::combine($TestModel->find('all'), '{n}.Comment.id', '{n}.Comment.user_id');
2875
		$expected = array(1 => 5, 2 => 4, 3 => 1, 4 => 1, 5 => 1, 6 => 5);
2876
		$this->assertEquals($expected, $result);
2877
 
2878
		$result = $TestModel->updateAll(
2879
			array('Comment.comment' => "'Updated today'"),
2880
			array('Comment.user_id' => 5)
2881
		);
2882
		$this->assertFalse(empty($result));
2883
		$result = Hash::extract(
2884
			$TestModel->find('all', array(
2885
				'conditions' => array(
2886
					'Comment.user_id' => 5
2887
			))),
2888
			'{n}.Comment.comment'
2889
		);
2890
		$expected = array_fill(0, 2, 'Updated today');
2891
		$this->assertEquals($expected, $result);
2892
	}
2893
 
2894
/**
2895
 * testHabtmUuidWithUuidId method
2896
 *
2897
 * @return void
2898
 */
2899
	public function testHabtmUuidWithUuidId() {
2900
		$this->loadFixtures('Uuidportfolio', 'Uuiditem', 'UuiditemsUuidportfolio', 'UuiditemsUuidportfolioNumericid');
2901
		$TestModel = new Uuidportfolio();
2902
 
2903
		$data = array('Uuidportfolio' => array('name' => 'Portfolio 3'));
2904
		$data['Uuiditem']['Uuiditem'] = array('483798c8-c7cc-430e-8cf9-4fcc40cf8569');
2905
		$TestModel->create($data);
2906
		$TestModel->save();
2907
		$id = $TestModel->id;
2908
		$result = $TestModel->read(null, $id);
2909
		$this->assertEquals(1, count($result['Uuiditem']));
2910
		$this->assertEquals(36, strlen($result['Uuiditem'][0]['UuiditemsUuidportfolio']['id']));
2911
	}
2912
 
2913
/**
2914
 * test HABTM saving when join table has no primary key and only 2 columns.
2915
 *
2916
 * @return void
2917
 */
2918
	public function testHabtmSavingWithNoPrimaryKeyUuidJoinTable() {
2919
		$this->loadFixtures('UuidTag', 'Fruit', 'FruitsUuidTag');
2920
		$Fruit = new Fruit();
2921
		$Fruit->FruitsUuidTag->order = null;
2922
		$data = array(
2923
			'Fruit' => array(
2924
				'color' => 'Red',
2925
				'shape' => 'Heart-shaped',
2926
				'taste' => 'sweet',
2927
				'name' => 'Strawberry',
2928
			),
2929
			'UuidTag' => array(
2930
				'UuidTag' => array(
2931
					'481fc6d0-b920-43e0-e50f-6d1740cf8569'
2932
				)
2933
			)
2934
		);
2935
		$result = $Fruit->save($data);
2936
		$this->assertFalse(empty($result));
2937
	}
2938
 
2939
/**
2940
 * test HABTM saving when join table has no primary key and only 2 columns, no with model is used.
2941
 *
2942
 * @return void
2943
 */
2944
	public function testHabtmSavingWithNoPrimaryKeyUuidJoinTableNoWith() {
2945
		$this->loadFixtures('UuidTag', 'Fruit', 'FruitsUuidTag');
2946
		$Fruit = new FruitNoWith();
2947
		$data = array(
2948
			'Fruit' => array(
2949
				'color' => 'Red',
2950
				'shape' => 'Heart-shaped',
2951
				'taste' => 'sweet',
2952
				'name' => 'Strawberry',
2953
			),
2954
			'UuidTag' => array(
2955
				'UuidTag' => array(
2956
					'481fc6d0-b920-43e0-e50f-6d1740cf8569'
2957
				)
2958
			)
2959
		);
2960
		$result = $Fruit->save($data);
2961
		$this->assertFalse(empty($result));
2962
	}
2963
 
2964
/**
2965
 * testHabtmUuidWithNumericId method
2966
 *
2967
 * @return void
2968
 */
2969
	public function testHabtmUuidWithNumericId() {
2970
		$this->loadFixtures('Uuidportfolio', 'Uuiditem', 'UuiditemsUuidportfolioNumericid');
2971
		$TestModel = new Uuiditem();
2972
 
2973
		$data = array('Uuiditem' => array('name' => 'Item 7', 'published' => 0));
2974
		$data['Uuidportfolio']['Uuidportfolio'] = array('480af662-eb8c-47d3-886b-230540cf8569');
2975
		$TestModel->create($data);
2976
		$TestModel->save();
2977
		$id = $TestModel->id;
2978
		$result = $TestModel->read(null, $id);
2979
		$this->assertEquals(1, count($result['Uuidportfolio']));
2980
	}
2981
 
2982
/**
2983
 * testSaveMultipleHabtm method
2984
 *
2985
 * @return void
2986
 */
2987
	public function testSaveMultipleHabtm() {
2988
		$this->loadFixtures('JoinA', 'JoinB', 'JoinC', 'JoinAB', 'JoinAC');
2989
		$TestModel = new JoinA();
2990
		$result = $TestModel->findById(1);
2991
 
2992
		$expected = array(
2993
			'JoinA' => array(
2994
				'id' => 1,
2995
				'name' => 'Join A 1',
2996
				'body' => 'Join A 1 Body',
2997
				'created' => '2008-01-03 10:54:23',
2998
				'updated' => '2008-01-03 10:54:23'
2999
			),
3000
			'JoinB' => array(
3001
 
3002
					'id' => 2,
3003
					'name' => 'Join B 2',
3004
					'created' => '2008-01-03 10:55:02',
3005
					'updated' => '2008-01-03 10:55:02',
3006
					'JoinAsJoinB' => array(
3007
						'id' => 1,
3008
						'join_a_id' => 1,
3009
						'join_b_id' => 2,
3010
						'other' => 'Data for Join A 1 Join B 2',
3011
						'created' => '2008-01-03 10:56:33',
3012
						'updated' => '2008-01-03 10:56:33'
3013
			))),
3014
			'JoinC' => array(
3015
 
3016
					'id' => 2,
3017
					'name' => 'Join C 2',
3018
					'created' => '2008-01-03 10:56:12',
3019
					'updated' => '2008-01-03 10:56:12',
3020
					'JoinAsJoinC' => array(
3021
						'id' => 1,
3022
						'join_a_id' => 1,
3023
						'join_c_id' => 2,
3024
						'other' => 'Data for Join A 1 Join C 2',
3025
						'created' => '2008-01-03 10:57:22',
3026
						'updated' => '2008-01-03 10:57:22'
3027
		))));
3028
 
3029
		$this->assertEquals($expected, $result);
3030
 
3031
		$TestModel->id = 1;
3032
		$data = array(
3033
			'JoinA' => array(
3034
				'id' => '1',
3035
				'name' => 'New name for Join A 1',
3036
				'updated' => static::date()
3037
			),
3038
			'JoinB' => array(
3039
				array(
3040
					'id' => 1,
3041
					'join_b_id' => 2,
3042
					'other' => 'New data for Join A 1 Join B 2',
3043
					'created' => static::date(),
3044
					'updated' => static::date()
3045
			)),
3046
			'JoinC' => array(
3047
				array(
3048
					'id' => 1,
3049
					'join_c_id' => 2,
3050
					'other' => 'New data for Join A 1 Join C 2',
3051
					'created' => static::date(),
3052
					'updated' => static::date()
3053
		)));
3054
 
3055
		$TestModel->set($data);
3056
		$TestModel->save();
3057
 
3058
		$result = $TestModel->findById(1);
3059
		$expected = array(
3060
			'JoinA' => array(
3061
				'id' => 1,
3062
				'name' => 'New name for Join A 1',
3063
				'body' => 'Join A 1 Body',
3064
				'created' => '2008-01-03 10:54:23',
3065
				'updated' => static::date()
3066
			),
3067
			'JoinB' => array(
3068
 
3069
					'id' => 2,
3070
					'name' => 'Join B 2',
3071
					'created' => '2008-01-03 10:55:02',
3072
					'updated' => '2008-01-03 10:55:02',
3073
					'JoinAsJoinB' => array(
3074
						'id' => 1,
3075
						'join_a_id' => 1,
3076
						'join_b_id' => 2,
3077
						'other' => 'New data for Join A 1 Join B 2',
3078
						'created' => static::date(),
3079
						'updated' => static::date()
3080
			))),
3081
			'JoinC' => array(
3082
 
3083
					'id' => 2,
3084
					'name' => 'Join C 2',
3085
					'created' => '2008-01-03 10:56:12',
3086
					'updated' => '2008-01-03 10:56:12',
3087
					'JoinAsJoinC' => array(
3088
						'id' => 1,
3089
						'join_a_id' => 1,
3090
						'join_c_id' => 2,
3091
						'other' => 'New data for Join A 1 Join C 2',
3092
						'created' => static::date(),
3093
						'updated' => static::date()
3094
		))));
3095
 
3096
		$this->assertEquals($expected, $result);
3097
	}
3098
 
3099
/**
3100
 * testSaveAll method
3101
 *
3102
 * @return void
3103
 */
3104
	public function testSaveAll() {
3105
		$this->loadFixtures('Post', 'Author', 'Comment', 'Attachment', 'Article', 'User');
3106
		$TestModel = new Post();
3107
 
3108
		$result = $TestModel->find('all');
3109
		$this->assertEquals(3, count($result));
3110
		$this->assertFalse(isset($result[3]));
3111
 
3112
		$TestModel->saveAll(array(
3113
			'Post' => array(
3114
				'title' => 'Post with Author',
3115
				'body' => 'This post will be saved with an author'
3116
			),
3117
			'Author' => array(
3118
				'user' => 'bob',
3119
				'password' => '5f4dcc3b5aa765d61d8327deb882cf90'
3120
		)));
3121
 
3122
		$result = $TestModel->find('all');
3123
		$expected = array(
3124
			'Post' => array(
3125
				'id' => '4',
3126
				'author_id' => '5',
3127
				'title' => 'Post with Author',
3128
				'body' => 'This post will be saved with an author',
3129
				'published' => 'N'
3130
			),
3131
			'Author' => array(
3132
				'id' => '5',
3133
				'user' => 'bob',
3134
				'password' => '5f4dcc3b5aa765d61d8327deb882cf90',
3135
				'test' => 'working'
3136
		));
3137
		$this->assertEquals(static::date(), $result[3]['Post']['created']);
3138
		$this->assertEquals(static::date(), $result[3]['Post']['updated']);
3139
		$this->assertEquals(static::date(), $result[3]['Author']['created']);
3140
		$this->assertEquals(static::date(), $result[3]['Author']['updated']);
3141
		unset($result[3]['Post']['created'], $result[3]['Post']['updated']);
3142
		unset($result[3]['Author']['created'], $result[3]['Author']['updated']);
3143
		$this->assertEquals($expected, $result[3]);
3144
		$this->assertEquals(4, count($result));
3145
 
3146
		$TestModel->deleteAll(true);
3147
		$this->assertEquals(array(), $TestModel->find('all'));
3148
 
3149
		// SQLite seems to reset the PK counter when that happens, so we need this to make the tests pass
3150
		$this->db->truncate($TestModel);
3151
 
3152
		$TestModel->saveAll(array(
3153
			array(
3154
				'title' => 'Multi-record post 1',
3155
				'body' => 'First multi-record post',
3156
				'author_id' => 2
3157
			),
3158
			array(
3159
				'title' => 'Multi-record post 2',
3160
				'body' => 'Second multi-record post',
3161
				'author_id' => 2
3162
		)));
3163
 
3164
		$result = $TestModel->find('all', array(
3165
			'recursive' => -1,
3166
			'order' => 'Post.id ASC'
3167
		));
3168
		$expected = array(
3169
			array(
3170
				'Post' => array(
3171
					'id' => '1',
3172
					'author_id' => '2',
3173
					'title' => 'Multi-record post 1',
3174
					'body' => 'First multi-record post',
3175
					'published' => 'N'
3176
			)),
3177
			array(
3178
				'Post' => array(
3179
					'id' => '2',
3180
					'author_id' => '2',
3181
					'title' => 'Multi-record post 2',
3182
					'body' => 'Second multi-record post',
3183
					'published' => 'N'
3184
		)));
3185
		$this->assertEquals(static::date(), $result[0]['Post']['created']);
3186
		$this->assertEquals(static::date(), $result[0]['Post']['updated']);
3187
		$this->assertEquals(static::date(), $result[1]['Post']['created']);
3188
		$this->assertEquals(static::date(), $result[1]['Post']['updated']);
3189
		unset($result[0]['Post']['created'], $result[0]['Post']['updated']);
3190
		unset($result[1]['Post']['created'], $result[1]['Post']['updated']);
3191
		$this->assertEquals($expected, $result);
3192
 
3193
		$TestModel = new Comment();
3194
		$result = $TestModel->saveAll(array(
3195
			'Comment' => array(
3196
				'article_id' => 2,
3197
				'user_id' => 2,
3198
				'comment' => 'New comment with attachment',
3199
				'published' => 'Y'
3200
			),
3201
			'Attachment' => array(
3202
				'attachment' => 'some_file.tgz'
3203
			)));
3204
		$this->assertFalse(empty($result));
3205
 
3206
		$result = $TestModel->find('all');
3207
		$expected = array(
3208
			'id' => '7',
3209
			'article_id' => '2',
3210
			'user_id' => '2',
3211
			'comment' => 'New comment with attachment',
3212
			'published' => 'Y'
3213
		);
3214
		$this->assertEquals(static::date(), $result[6]['Comment']['created']);
3215
		$this->assertEquals(static::date(), $result[6]['Comment']['updated']);
3216
		unset($result[6]['Comment']['created'], $result[6]['Comment']['updated']);
3217
		$this->assertEquals($expected, $result[6]['Comment']);
3218
 
3219
		$expected = array(
3220
			'id' => '2',
3221
			'comment_id' => '7',
3222
			'attachment' => 'some_file.tgz'
3223
		);
3224
		$this->assertEquals(static::date(), $result[6]['Attachment']['created']);
3225
		$this->assertEquals(static::date(), $result[6]['Attachment']['updated']);
3226
		unset($result[6]['Attachment']['created'], $result[6]['Attachment']['updated']);
3227
		$this->assertEquals($expected, $result[6]['Attachment']);
3228
	}
3229
 
3230
/**
3231
 * Test SaveAll with Habtm relations
3232
 *
3233
 * @return void
3234
 */
3235
	public function testSaveAllHabtm() {
3236
		$this->loadFixtures('Article', 'Tag', 'Comment', 'User', 'ArticlesTag');
3237
		$data = array(
3238
			'Article' => array(
3239
				'user_id' => 1,
3240
				'title' => 'Article Has and belongs to Many Tags'
3241
			),
3242
			'Tag' => array(
3243
				'Tag' => array(1, 2)
3244
			),
3245
			'Comment' => array(
3246
				array(
3247
					'comment' => 'Article comment',
3248
					'user_id' => 1
3249
		)));
3250
		$Article = new Article();
3251
		$result = $Article->saveAll($data);
3252
		$this->assertFalse(empty($result));
3253
 
3254
		$result = $Article->read();
3255
		$this->assertEquals(2, count($result['Tag']));
3256
		$this->assertEquals('tag1', $result['Tag'][0]['tag']);
3257
		$this->assertEquals(1, count($result['Comment']));
3258
		$this->assertEquals(1, count($result['Comment'][0]['comment']));
3259
	}
3260
 
3261
/**
3262
 * Test SaveAll with Habtm relations and extra join table fields
3263
 *
3264
 * @return void
3265
 */
3266
	public function testSaveAllHabtmWithExtraJoinTableFields() {
3267
		$this->loadFixtures('Something', 'SomethingElse', 'JoinThing');
3268
 
3269
		$data = array(
3270
			'Something' => array(
3271
				'id' => 4,
3272
				'title' => 'Extra Fields',
3273
				'body' => 'Extra Fields Body',
3274
				'published' => '1'
3275
			),
3276
			'SomethingElse' => array(
3277
				array('something_else_id' => 1, 'doomed' => '1'),
3278
				array('something_else_id' => 2, 'doomed' => '0'),
3279
				array('something_else_id' => 3, 'doomed' => '1')
3280
			)
3281
		);
3282
 
3283
		$Something = new Something();
3284
		$result = $Something->saveAll($data);
3285
		$this->assertFalse(empty($result));
3286
		$result = $Something->read();
3287
 
3288
		$this->assertEquals(3, count($result['SomethingElse']));
3289
		$this->assertTrue(Set::matches('/Something[id=4]', $result));
3290
 
3291
		$this->assertTrue(Set::matches('/SomethingElse[id=1]', $result));
3292
		$this->assertTrue(Set::matches('/SomethingElse[id=1]/JoinThing[something_else_id=1]', $result));
3293
		$this->assertTrue(Set::matches('/SomethingElse[id=1]/JoinThing[doomed=1]', $result));
3294
 
3295
		$this->assertTrue(Set::matches('/SomethingElse[id=2]', $result));
3296
		$this->assertTrue(Set::matches('/SomethingElse[id=2]/JoinThing[something_else_id=2]', $result));
3297
		$this->assertTrue(Set::matches('/SomethingElse[id=2]/JoinThing[doomed=0]', $result));
3298
 
3299
		$this->assertTrue(Set::matches('/SomethingElse[id=3]', $result));
3300
		$this->assertTrue(Set::matches('/SomethingElse[id=3]/JoinThing[something_else_id=3]', $result));
3301
		$this->assertTrue(Set::matches('/SomethingElse[id=3]/JoinThing[doomed=1]', $result));
3302
	}
3303
 
3304
/**
3305
 * testSaveAllHasOne method
3306
 *
3307
 * @return void
3308
 */
3309
	public function testSaveAllHasOne() {
3310
		$model = new Comment();
3311
		$model->deleteAll(true);
3312
		$this->assertEquals(array(), $model->find('all'));
3313
 
3314
		$model->Attachment->deleteAll(true);
3315
		$this->assertEquals(array(), $model->Attachment->find('all'));
3316
 
3317
		$this->assertTrue($model->saveAll(array(
3318
			'Comment' => array(
3319
				'comment' => 'Comment with attachment',
3320
				'article_id' => 1,
3321
				'user_id' => 1
3322
			),
3323
			'Attachment' => array(
3324
				'attachment' => 'some_file.zip'
3325
		))));
3326
		$result = $model->find('all', array('fields' => array(
3327
			'Comment.id', 'Comment.comment', 'Attachment.id',
3328
			'Attachment.comment_id', 'Attachment.attachment'
3329
		)));
3330
		$expected = array(array(
3331
			'Comment' => array(
3332
				'id' => '1',
3333
				'comment' => 'Comment with attachment'
3334
			),
3335
			'Attachment' => array(
3336
				'id' => '1',
3337
				'comment_id' => '1',
3338
				'attachment' => 'some_file.zip'
3339
		)));
3340
		$this->assertEquals($expected, $result);
3341
 
3342
		$model->Attachment->bindModel(array('belongsTo' => array('Comment')), false);
3343
		$data = array(
3344
			'Comment' => array(
3345
				'comment' => 'Comment with attachment',
3346
				'article_id' => 1,
3347
				'user_id' => 1
3348
			),
3349
			'Attachment' => array(
3350
				'attachment' => 'some_file.zip'
3351
		));
3352
		$this->assertTrue($model->saveAll($data, array('validate' => 'first')));
3353
	}
3354
 
3355
/**
3356
 * testSaveAllBelongsTo method
3357
 *
3358
 * @return void
3359
 */
3360
	public function testSaveAllBelongsTo() {
3361
		$model = new Comment();
3362
		$model->deleteAll(true);
3363
		$this->assertEquals(array(), $model->find('all'));
3364
 
3365
		$model->Article->deleteAll(true);
3366
		$this->assertEquals(array(), $model->Article->find('all'));
3367
 
3368
		$this->assertTrue($model->saveAll(array(
3369
			'Comment' => array(
3370
				'comment' => 'Article comment',
3371
				'article_id' => 1,
3372
				'user_id' => 1
3373
			),
3374
			'Article' => array(
3375
				'title' => 'Model Associations 101',
3376
				'user_id' => 1
3377
		))));
3378
		$result = $model->find('all', array('fields' => array(
3379
			'Comment.id', 'Comment.comment', 'Comment.article_id', 'Article.id', 'Article.title'
3380
		)));
3381
		$expected = array(array(
3382
			'Comment' => array(
3383
				'id' => '1',
3384
				'article_id' => '1',
3385
				'comment' => 'Article comment'
3386
			),
3387
			'Article' => array(
3388
				'id' => '1',
3389
				'title' => 'Model Associations 101'
3390
		)));
3391
		$this->assertEquals($expected, $result);
3392
	}
3393
 
3394
/**
3395
 * testSaveAllHasOneValidation method
3396
 *
3397
 * @return void
3398
 */
3399
	public function testSaveAllHasOneValidation() {
3400
		$model = new Comment();
3401
		$model->deleteAll(true);
3402
		$this->assertEquals(array(), $model->find('all'));
3403
 
3404
		$model->Attachment->deleteAll(true);
3405
		$this->assertEquals(array(), $model->Attachment->find('all'));
3406
 
3407
		$model->validate = array('comment' => 'notBlank');
3408
		$model->Attachment->validate = array('attachment' => 'notBlank');
3409
		$model->Attachment->bindModel(array('belongsTo' => array('Comment')));
3410
 
3411
		$result = $model->saveAll(
3412
			array(
3413
				'Comment' => array(
3414
					'comment' => '',
3415
					'article_id' => 1,
3416
					'user_id' => 1
3417
				),
3418
				'Attachment' => array('attachment' => '')
3419
			),
3420
			array('validate' => 'first')
3421
		);
3422
		$this->assertEquals(false, $result);
3423
		$expected = array(
3424
			'comment' => array('This field cannot be left blank'),
3425
			'Attachment' => array(
3426
				'attachment' => array('This field cannot be left blank')
3427
			)
3428
		);
3429
		$this->assertEquals($expected, $model->validationErrors);
3430
		$this->assertEquals($expected['Attachment'], $model->Attachment->validationErrors);
3431
	}
3432
 
3433
/**
3434
 * testSaveAllAtomic method
3435
 *
3436
 * @return void
3437
 */
3438
	public function testSaveAllAtomic() {
3439
		$this->loadFixtures('Article', 'User', 'Comment');
3440
		$TestModel = new Article();
3441
 
3442
		$result = $TestModel->saveAll(array(
3443
			'Article' => array(
3444
				'title' => 'Post with Author',
3445
				'body' => 'This post will be saved with an author',
3446
				'user_id' => 2
3447
			),
3448
			'Comment' => array(
3449
				array('comment' => 'First new comment', 'user_id' => 2))
3450
		), array('atomic' => false));
3451
 
3452
		$this->assertSame($result, array('Article' => true, 'Comment' => array(true)));
3453
 
3454
		$result = $TestModel->saveAll(array(
3455
			array(
3456
				'id' => '1',
3457
				'title' => 'Baleeted First Post',
3458
				'body' => 'Baleeted!',
3459
				'published' => 'N'
3460
			),
3461
			array(
3462
				'id' => '2',
3463
				'title' => 'Just update the title'
3464
			),
3465
			array(
3466
				'title' => 'Creating a fourth post',
3467
				'body' => 'Fourth post body',
3468
				'user_id' => 2
3469
			)
3470
		), array('atomic' => false));
3471
		$this->assertSame($result, array(true, true, true));
3472
 
3473
		$result = $TestModel->saveAll(array(
3474
			'Article' => array('id' => 2),
3475
			'Comment' => array(
3476
				array(
3477
					'comment' => 'First new comment',
3478
					'published' => 'Y',
3479
					'user_id' => 1
3480
				),
3481
				array(
3482
					'comment' => 'Second new comment',
3483
					'published' => 'Y',
3484
					'user_id' => 2
3485
			))
3486
		), array('validate' => true, 'atomic' => false));
3487
		$this->assertSame($result, array('Article' => true, 'Comment' => array(true, true)));
3488
 
3489
		$TestModel->validate = array(
3490
			'title' => 'notBlank',
3491
			'author_id' => 'numeric'
3492
		);
3493
		$result = $TestModel->saveAll(array(
3494
			array(
3495
				'id' => '1',
3496
				'title' => 'Un-Baleeted First Post',
3497
				'body' => 'Not Baleeted!',
3498
				'published' => 'Y'
3499
			),
3500
			array(
3501
				'id' => '2',
3502
				'title' => '',
3503
				'body' => 'Trying to get away with an empty title'
3504
			)
3505
		), array('validate' => true, 'atomic' => false));
3506
		$this->assertSame(array(true, false), $result);
3507
	}
3508
 
3509
/**
3510
 * testSaveAllDeepAssociated method
3511
 *
3512
 * @return void
3513
 */
3514
	public function testSaveAllDeepAssociated() {
3515
		$this->loadFixtures('Article', 'Comment', 'User', 'Attachment');
3516
		$TestModel = new Article();
3517
		$TestModel->hasMany['Comment']['order'] = array('Comment.created' => 'ASC');
3518
		$TestModel->hasAndBelongsToMany = array();
3519
 
3520
		$result = $TestModel->saveAll(array(
3521
			'Article' => array('id' => 2),
3522
			'Comment' => array(
3523
				array('comment' => 'First new comment', 'published' => 'Y', 'User' => array('user' => 'newuser', 'password' => 'newuserpass')),
3524
				array('comment' => 'Second new comment', 'published' => 'Y', 'user_id' => 2)
3525
			)
3526
		), array('deep' => true));
3527
		$this->assertTrue($result);
3528
 
3529
		$result = $TestModel->findById(2);
3530
		$expected = array(
3531
			'First Comment for Second Article',
3532
			'Second Comment for Second Article',
3533
			'First new comment',
3534
			'Second new comment'
3535
		);
3536
		$result = Hash::extract(Hash::sort($result['Comment'], '{n}.id', 'ASC'), '{n}.comment');
3537
		$this->assertEquals($expected, $result);
3538
 
3539
		$result = $TestModel->Comment->User->field('id', array('user' => 'newuser', 'password' => 'newuserpass'));
3540
		$this->assertEquals(5, $result);
3541
		$result = $TestModel->saveAll(array(
3542
			'Article' => array('id' => 2),
3543
			'Comment' => array(
3544
				array('comment' => 'Third new comment', 'published' => 'Y', 'user_id' => 5),
3545
				array('comment' => 'Fourth new comment', 'published' => 'Y', 'user_id' => 2, 'Attachment' => array('attachment' => 'deepsaved'))
3546
			)
3547
		), array('deep' => true));
3548
		$this->assertTrue($result);
3549
 
3550
		$result = $TestModel->findById(2);
3551
		$expected = array(
3552
			'First Comment for Second Article',
3553
			'Second Comment for Second Article',
3554
			'First new comment',
3555
			'Second new comment',
3556
			'Third new comment',
3557
			'Fourth new comment'
3558
		);
3559
		$result = Hash::extract(Hash::sort($result['Comment'], '{n}.id', 'ASC'), '{n}.comment');
3560
		$this->assertEquals($expected, $result);
3561
 
3562
		$result = $TestModel->Comment->Attachment->field('id', array('attachment' => 'deepsaved'));
3563
		$this->assertEquals(2, $result);
3564
		$data = array(
3565
			'Attachment' => array(
3566
				'attachment' => 'deepsave insert',
3567
			),
3568
			'Comment' => array(
3569
				'comment' => 'First comment deepsave insert',
3570
				'published' => 'Y',
3571
				'user_id' => 5,
3572
				'Article' => array(
3573
					'title' => 'First Article deepsave insert',
3574
					'body' => 'First Article Body deepsave insert',
3575
					'User' => array(
3576
						'user' => '',
3577
						'password' => 'magic'
3578
					),
3579
				),
3580
			)
3581
		);
3582
 
3583
		$TestModel->Comment->Attachment->create();
3584
		$result = $TestModel->Comment->Attachment->saveAll($data, array('deep' => true));
3585
		$this->assertFalse($result);
3586
 
3587
		$expected = array('User' => array('user' => array('This field cannot be left blank')));
3588
		$this->assertEquals($expected, $TestModel->validationErrors);
3589
 
3590
		$data['Comment']['Article']['User']['user'] = 'deepsave';
3591
		$TestModel->Comment->Attachment->create();
3592
		$result = $TestModel->Comment->Attachment->saveAll($data, array('deep' => true));
3593
		$this->assertTrue($result);
3594
 
3595
		$result = $TestModel->Comment->Attachment->findById($TestModel->Comment->Attachment->id);
3596
		$expected = array(
3597
			'Attachment' => array(
3598
				'id' => '3',
3599
				'comment_id' => '11',
3600
				'attachment' => 'deepsave insert',
3601
			),
3602
			'Comment' => array(
3603
				'id' => '11',
3604
				'article_id' => '4',
3605
				'user_id' => '5',
3606
				'comment' => 'First comment deepsave insert',
3607
				'published' => 'Y',
3608
			)
3609
		);
3610
		unset($result['Attachment']['created'], $result['Attachment']['updated']);
3611
		$this->assertEquals($expected['Attachment'], $result['Attachment']);
3612
 
3613
		unset($result['Comment']['created'], $result['Comment']['updated']);
3614
		$this->assertEquals($expected['Comment'], $result['Comment']);
3615
 
3616
		$result = $TestModel->findById($result['Comment']['article_id']);
3617
		$expected = array(
3618
			'Article' => array(
3619
				'id' => '4',
3620
				'user_id' => '6',
3621
				'title' => 'First Article deepsave insert',
3622
				'body' => 'First Article Body deepsave insert',
3623
				'published' => 'N',
3624
			),
3625
			'User' => array(
3626
				'id' => '6',
3627
				'user' => 'deepsave',
3628
				'password' => 'magic',
3629
			),
3630
			'Comment' => array(
3631
				array(
3632
					'id' => '11',
3633
					'article_id' => '4',
3634
					'user_id' => '5',
3635
					'comment' => 'First comment deepsave insert',
3636
					'published' => 'Y',
3637
				)
3638
			)
3639
		);
3640
		unset(
3641
			$result['Article']['created'], $result['Article']['updated'],
3642
			$result['User']['created'], $result['User']['updated'],
3643
			$result['Comment'][0]['created'], $result['Comment'][0]['updated']
3644
		);
3645
		$this->assertEquals($expected, $result);
3646
	}
3647
 
3648
/**
3649
 * testSaveAllDeepMany
3650
 * tests the validate methods with deeper recursive data
3651
 *
3652
 * @return void
3653
 */
3654
	public function testSaveAllDeepMany() {
3655
		$this->loadFixtures('Article', 'Comment', 'User', 'Attachment');
3656
		$TestModel = new Article();
3657
		$TestModel->hasMany['Comment']['order'] = array('Comment.created' => 'ASC');
3658
		$TestModel->hasAndBelongsToMany = array();
3659
 
3660
		$data = array(
3661
			array(
3662
				'Article' => array('id' => 1),
3663
				'Comment' => array(
3664
					array('comment' => 'First comment deepsaved article 1', 'published' => 'Y', 'User' => array('user' => 'savemany', 'password' => 'manysaved')),
3665
					array('comment' => 'Second comment deepsaved article 1', 'published' => 'Y', 'user_id' => 2)
3666
				)
3667
			),
3668
			array(
3669
				'Article' => array('id' => 2),
3670
				'Comment' => array(
3671
					array('comment' => 'First comment deepsaved article 2', 'published' => 'Y', 'User' => array('user' => 'savemore', 'password' => 'moresaved')),
3672
					array('comment' => 'Second comment deepsaved article 2', 'published' => 'Y', 'user_id' => 2)
3673
				)
3674
			)
3675
		);
3676
		$result = $TestModel->saveAll($data, array('deep' => true));
3677
		$this->assertTrue($result);
3678
 
3679
		$data = array(
3680
			array(
3681
				'id' => 1, 'body' => '',
3682
				'Comment' => array(
3683
					array('comment' => '', 'published' => 'Y', 'User' => array('user' => '', 'password' => 'manysaved')),
3684
					array('comment' => 'Second comment deepsaved article 1', 'published' => 'Y', 'user_id' => 2)
3685
				)
3686
			),
3687
			array(
3688
				'Article' => array('id' => 2),
3689
				'Comment' => array(
3690
					array('comment' => 'First comment deepsaved article 2', 'published' => 'Y', 'User' => array('user' => 'savemore', 'password' => '')),
3691
					array('comment' => '', 'published' => 'Y', 'user_id' => 2)
3692
				)
3693
			)
3694
		);
3695
		$TestModel->Comment->validate['comment'] = 'notBlank';
3696
		$result = $TestModel->saveAll($data, array('deep' => true));
3697
		$this->assertFalse($result);
3698
 
3699
		$expected = array(
3700
 
3701
				'body' => array('This field cannot be left blank'),
3702
				'Comment' => array(
3703
 
3704
						'comment' => array('This field cannot be left blank'),
3705
						'User' => array(
3706
							'user' => array('This field cannot be left blank')
3707
						)
3708
					)
3709
				)
3710
			),
3711
			1 => array(
3712
				'Comment' => array(
3713
 
3714
						'User' => array(
3715
							'password' => array('This field cannot be left blank')
3716
						)
3717
					),
3718
					1 => array(
3719
						'comment' => array('This field cannot be left blank')
3720
					)
3721
				)
3722
			)
3723
		);
3724
		$result = $TestModel->validationErrors;
3725
		$this->assertSame($expected, $result);
3726
	}
3727
/**
3728
 * testSaveAllDeepValidateOnly
3729
 * tests the validate methods with deeper recursive data
3730
 *
3731
 * @return void
3732
 */
3733
	public function testSaveAllDeepValidateOnly() {
3734
		$this->loadFixtures('Article', 'Comment', 'User', 'Attachment');
3735
		$TestModel = new Article();
3736
		$TestModel->hasMany['Comment']['order'] = array('Comment.created' => 'ASC');
3737
		$TestModel->hasAndBelongsToMany = array();
3738
		$TestModel->Comment->Attachment->validate['attachment'] = 'notBlank';
3739
		$TestModel->Comment->validate['comment'] = 'notBlank';
3740
 
3741
		$result = $TestModel->saveAll(
3742
			array(
3743
				'Article' => array('id' => 2),
3744
				'Comment' => array(
3745
					array('comment' => 'First new comment', 'published' => 'Y', 'User' => array('user' => 'newuser', 'password' => 'newuserpass')),
3746
					array('comment' => 'Second new comment', 'published' => 'Y', 'user_id' => 2)
3747
				)
3748
			),
3749
			array('validate' => 'only', 'deep' => true)
3750
		);
3751
		$this->assertTrue($result);
3752
 
3753
		$result = $TestModel->saveAll(
3754
			array(
3755
				'Article' => array('id' => 2),
3756
				'Comment' => array(
3757
					array('comment' => 'First new comment', 'published' => 'Y', 'User' => array('user' => '', 'password' => 'newuserpass')),
3758
					array('comment' => 'Second new comment', 'published' => 'Y', 'user_id' => 2)
3759
				)
3760
			),
3761
			array('validate' => 'only', 'deep' => true)
3762
		);
3763
		$this->assertFalse($result);
3764
 
3765
		$result = $TestModel->saveAll(
3766
			array(
3767
				'Article' => array('id' => 2),
3768
				'Comment' => array(
3769
					array('comment' => 'First new comment', 'published' => 'Y', 'User' => array('user' => 'newuser', 'password' => 'newuserpass')),
3770
					array('comment' => 'Second new comment', 'published' => 'Y', 'user_id' => 2)
3771
				)
3772
			),
3773
			array('validate' => 'only', 'atomic' => false, 'deep' => true)
3774
		);
3775
		$expected = array(
3776
			'Article' => true,
3777
			'Comment' => array(
3778
				true,
3779
				true
3780
			)
3781
		);
3782
		$this->assertSame($expected, $result);
3783
 
3784
		$result = $TestModel->saveAll(
3785
			array(
3786
				'Article' => array('id' => 2),
3787
				'Comment' => array(
3788
					array('comment' => 'First new comment', 'published' => 'Y', 'User' => array('user' => '', 'password' => 'newuserpass')),
3789
					array('comment' => 'Second new comment', 'published' => 'Y', 'user_id' => 2)
3790
				)
3791
			),
3792
			array('validate' => 'only', 'atomic' => false, 'deep' => true)
3793
		);
3794
		$expected = array(
3795
			'Article' => true,
3796
			'Comment' => array(
3797
				false,
3798
				true
3799
			)
3800
		);
3801
		$this->assertSame($expected, $result);
3802
 
3803
		$result = $TestModel->saveAll(array(
3804
			'Article' => array('id' => 2),
3805
			'Comment' => array(
3806
				array('comment' => 'Third new comment', 'published' => 'Y', 'user_id' => 5),
3807
				array('comment' => 'Fourth new comment', 'published' => 'Y', 'user_id' => 2, 'Attachment' => array('attachment' => 'deepsaved'))
3808
			)
3809
		),
3810
		array('validate' => 'only', 'deep' => true)
3811
		);
3812
		$this->assertTrue($result);
3813
 
3814
		$result = $TestModel->saveAll(array(
3815
			'Article' => array('id' => 2),
3816
			'Comment' => array(
3817
				array('comment' => 'Third new comment', 'published' => 'Y', 'user_id' => 5),
3818
				array('comment' => 'Fourth new comment', 'published' => 'Y', 'user_id' => 2, 'Attachment' => array('attachment' => ''))
3819
			)
3820
		),
3821
		array('validate' => 'only', 'deep' => true)
3822
		);
3823
		$this->assertFalse($result);
3824
 
3825
		$result = $TestModel->saveAll(array(
3826
			'Article' => array('id' => 2),
3827
			'Comment' => array(
3828
				array('comment' => 'Third new comment', 'published' => 'Y', 'user_id' => 5),
3829
				array('comment' => 'Fourth new comment', 'published' => 'Y', 'user_id' => 2, 'Attachment' => array('attachment' => 'deepsave'))
3830
			)
3831
		),
3832
		array('validate' => 'only', 'atomic' => false, 'deep' => true)
3833
		);
3834
		$expected = array(
3835
			'Article' => true,
3836
			'Comment' => array(
3837
				true,
3838
				true
3839
			)
3840
		);
3841
		$this->assertSame($expected, $result);
3842
 
3843
		$result = $TestModel->saveAll(array(
3844
			'Article' => array('id' => 2),
3845
			'Comment' => array(
3846
				array('comment' => 'Third new comment', 'published' => 'Y', 'user_id' => 5),
3847
				array('comment' => 'Fourth new comment', 'published' => 'Y', 'user_id' => 2, 'Attachment' => array('attachment' => ''))
3848
			)
3849
		),
3850
		array('validate' => 'only', 'atomic' => false, 'deep' => true)
3851
		);
3852
		$expected = array(
3853
			'Article' => true,
3854
			'Comment' => array(
3855
				true,
3856
				false
3857
			)
3858
		);
3859
		$this->assertSame($expected, $result);
3860
 
3861
		$expected = array(
3862
			'Comment' => array(
3863
				1 => array(
3864
					'Attachment' => array(
3865
						'attachment' => array('This field cannot be left blank')
3866
					)
3867
				)
3868
			)
3869
		);
3870
		$result = $TestModel->validationErrors;
3871
		$this->assertSame($expected, $result);
3872
 
3873
		$data = array(
3874
			'Attachment' => array(
3875
				'attachment' => 'deepsave insert',
3876
			),
3877
			'Comment' => array(
3878
				'comment' => 'First comment deepsave insert',
3879
				'published' => 'Y',
3880
				'user_id' => 5,
3881
				'Article' => array(
3882
					'title' => 'First Article deepsave insert',
3883
					'body' => 'First Article Body deepsave insert',
3884
					'User' => array(
3885
						'user' => 'deepsave',
3886
						'password' => 'magic'
3887
					),
3888
				),
3889
			)
3890
		);
3891
 
3892
		$result = $TestModel->Comment->Attachment->saveAll($data, array('validate' => 'only', 'deep' => true));
3893
		$this->assertTrue($result);
3894
 
3895
		$result = $TestModel->Comment->Attachment->saveAll($data, array('validate' => 'only', 'atomic' => false, 'deep' => true));
3896
		$expected = array(
3897
			'Attachment' => true,
3898
			'Comment' => true
3899
		);
3900
		$this->assertSame($expected, $result);
3901
 
3902
		$data = array(
3903
			'Attachment' => array(
3904
				'attachment' => 'deepsave insert',
3905
			),
3906
			'Comment' => array(
3907
				'comment' => 'First comment deepsave insert',
3908
				'published' => 'Y',
3909
				'user_id' => 5,
3910
				'Article' => array(
3911
					'title' => 'First Article deepsave insert',
3912
					'body' => 'First Article Body deepsave insert',
3913
					'User' => array(
3914
						'user' => '',
3915
						'password' => 'magic'
3916
					),
3917
				),
3918
			)
3919
		);
3920
 
3921
		$result = $TestModel->Comment->Attachment->saveAll($data, array('validate' => 'only', 'deep' => true));
3922
		$this->assertFalse($result);
3923
 
3924
		$result = $TestModel->Comment->Attachment->validationErrors;
3925
		$expected = array(
3926
			'Comment' => array(
3927
				'Article' => array(
3928
					'User' => array(
3929
						'user' => array('This field cannot be left blank')
3930
					)
3931
				)
3932
			)
3933
		);
3934
		$this->assertSame($expected, $result);
3935
 
3936
		$result = $TestModel->Comment->Attachment->saveAll($data, array('validate' => 'only', 'atomic' => false, 'deep' => true));
3937
		$expected = array(
3938
			'Attachment' => true,
3939
			'Comment' => false
3940
		);
3941
		$this->assertEquals($expected, $result);
3942
 
3943
		$data['Comment']['Article']['body'] = '';
3944
		$result = $TestModel->Comment->Attachment->saveAll($data, array('validate' => 'only', 'deep' => true));
3945
		$this->assertFalse($result);
3946
 
3947
		$result = $TestModel->Comment->Attachment->validationErrors;
3948
		$expected = array(
3949
			'Comment' => array(
3950
				'Article' => array(
3951
					'body' => array('This field cannot be left blank'),
3952
					'User' => array(
3953
						'user' => array('This field cannot be left blank')
3954
					)
3955
				)
3956
			)
3957
		);
3958
		$this->assertSame($expected, $result);
3959
 
3960
		$result = $TestModel->Comment->Attachment->saveAll($data, array('validate' => 'only', 'atomic' => false, 'deep' => true));
3961
		$expected = array(
3962
			'Attachment' => true,
3963
			'Comment' => false
3964
		);
3965
		$this->assertEquals($expected, $result);
3966
 
3967
		$data['Comment']['comment'] = '';
3968
		$result = $TestModel->Comment->Attachment->saveAll($data, array('validate' => 'only', 'deep' => true));
3969
		$this->assertFalse($result);
3970
 
3971
		$result = $TestModel->Comment->Attachment->validationErrors;
3972
		$expected = array(
3973
			'Comment' => array(
3974
				'comment' => array('This field cannot be left blank'),
3975
				'Article' => array(
3976
					'body' => array('This field cannot be left blank'),
3977
					'User' => array(
3978
						'user' => array('This field cannot be left blank')
3979
					)
3980
				)
3981
			)
3982
		);
3983
		$this->assertSame($expected, $result);
3984
 
3985
		$result = $TestModel->Comment->Attachment->saveAll($data, array('validate' => 'only', 'atomic' => false, 'deep' => true));
3986
		$expected = array(
3987
			'Attachment' => true,
3988
			'Comment' => false
3989
		);
3990
		$this->assertEquals($expected, $result);
3991
 
3992
		$data['Attachment']['attachment'] = '';
3993
		$result = $TestModel->Comment->Attachment->saveAll($data, array('validate' => 'only', 'deep' => true));
3994
		$this->assertFalse($result);
3995
 
3996
		$result = $TestModel->Comment->Attachment->validationErrors;
3997
		$expected = array(
3998
			'attachment' => array('This field cannot be left blank'),
3999
			'Comment' => array(
4000
				'comment' => array('This field cannot be left blank'),
4001
				'Article' => array(
4002
					'body' => array('This field cannot be left blank'),
4003
					'User' => array(
4004
						'user' => array('This field cannot be left blank')
4005
					)
4006
				)
4007
			)
4008
		);
4009
		$this->assertSame($expected, $result);
4010
 
4011
		$result = $TestModel->Comment->validationErrors;
4012
		$expected = array(
4013
			'comment' => array('This field cannot be left blank'),
4014
			'Article' => array(
4015
				'body' => array('This field cannot be left blank'),
4016
				'User' => array(
4017
					'user' => array('This field cannot be left blank')
4018
				)
4019
			)
4020
		);
4021
		$this->assertSame($expected, $result);
4022
 
4023
		$result = $TestModel->Comment->Attachment->saveAll($data, array('validate' => 'only', 'atomic' => false, 'deep' => true));
4024
		$expected = array(
4025
			'Attachment' => false,
4026
			'Comment' => false
4027
		);
4028
		$this->assertEquals($expected, $result);
4029
	}
4030
 
4031
/**
4032
 * testSaveAllNotDeepAssociated method
4033
 * test that only directly associated data gets saved
4034
 *
4035
 * @return void
4036
 */
4037
	public function testSaveAllNotDeepAssociated() {
4038
		$this->loadFixtures('Article', 'Comment', 'User', 'Attachment');
4039
		$TestModel = new Article();
4040
		$TestModel->hasMany['Comment']['order'] = array('Comment.created' => 'ASC');
4041
		$TestModel->hasAndBelongsToMany = array();
4042
 
4043
		$result = $TestModel->saveAll(array(
4044
			'Article' => array('id' => 2),
4045
			'Comment' => array(
4046
				array(
4047
					'comment' => 'First new comment', 'published' => 'Y', 'user_id' => 2,
4048
					'User' => array('user' => 'newuser', 'password' => 'newuserpass')
4049
				),
4050
				array('comment' => 'Second new comment', 'published' => 'Y', 'user_id' => 2)
4051
			)
4052
		), array('deep' => false));
4053
		$this->assertTrue($result);
4054
 
4055
		$result = $TestModel->Comment->User->field('id', array('user' => 'newuser', 'password' => 'newuserpass'));
4056
		$this->assertFalse($result);
4057
 
4058
		$result = $TestModel->saveAll(array(
4059
			'Article' => array('id' => 2),
4060
			'Comment' => array(
4061
				array('comment' => 'Third new comment', 'published' => 'Y', 'user_id' => 4),
4062
				array('comment' => 'Fourth new comment', 'published' => 'Y', 'user_id' => 2, 'Attachment' => array('attachment' => 'deepsaved'))
4063
			)
4064
		), array('deep' => false));
4065
		$this->assertTrue($result);
4066
 
4067
		$result = $TestModel->Comment->Attachment->field('id', array('attachment' => 'deepsaved'));
4068
		$this->assertFalse($result);
4069
 
4070
		$data = array(
4071
			'Attachment' => array(
4072
				'attachment' => 'deepsave insert',
4073
			),
4074
			'Comment' => array(
4075
				'comment' => 'First comment deepsave insert',
4076
				'published' => 'Y',
4077
				'user_id' => 4,
4078
				'article_id' => 1,
4079
				'Article' => array(
4080
					'title' => 'First Article deepsave insert',
4081
					'body' => 'First Article Body deepsave insert',
4082
					'User' => array(
4083
						'user' => 'deepsave',
4084
						'password' => 'magic'
4085
					),
4086
				),
4087
			)
4088
		);
4089
		$expected = $TestModel->User->find('count');
4090
 
4091
		$TestModel->Comment->Attachment->create();
4092
		$result = $TestModel->Comment->Attachment->saveAll($data, array('deep' => false));
4093
		$this->assertTrue($result);
4094
 
4095
		$result = $TestModel->User->find('count');
4096
		$this->assertEquals($expected, $result);
4097
 
4098
		$result = $TestModel->Comment->Attachment->findById($TestModel->Comment->Attachment->id);
4099
		$expected = array(
4100
			'Attachment' => array(
4101
				'id' => '2',
4102
				'comment_id' => '11',
4103
				'attachment' => 'deepsave insert',
4104
			),
4105
			'Comment' => array(
4106
				'id' => '11',
4107
				'article_id' => 1,
4108
				'user_id' => '4',
4109
				'comment' => 'First comment deepsave insert',
4110
				'published' => 'Y',
4111
			)
4112
		);
4113
		unset($result['Attachment']['created'], $result['Attachment']['updated']);
4114
		$this->assertEquals($expected['Attachment'], $result['Attachment']);
4115
 
4116
		unset($result['Comment']['created'], $result['Comment']['updated']);
4117
		$this->assertEquals($expected['Comment'], $result['Comment']);
4118
	}
4119
 
4120
/**
4121
 * testSaveAllNotDeepMany
4122
 * tests the save methods to not save deeper recursive data
4123
 *
4124
 * @return void
4125
 */
4126
	public function testSaveAllNotDeepMany() {
4127
		$this->loadFixtures('Article', 'Comment', 'User', 'Attachment');
4128
		$TestModel = new Article();
4129
		$TestModel->hasMany['Comment']['order'] = array('Comment.created' => 'ASC');
4130
		$TestModel->hasAndBelongsToMany = array();
4131
 
4132
		$data = array(
4133
			array(
4134
				'id' => 1,
4135
				'body' => '',
4136
				'Comment' => array(
4137
					array('comment' => '', 'published' => 'Y', 'User' => array('user' => '', 'password' => 'manysaved')),
4138
					array('comment' => 'Second comment deepsaved article 1', 'published' => 'Y', 'user_id' => 2)
4139
				)
4140
			),
4141
			array(
4142
				'Article' => array('id' => 2),
4143
				'Comment' => array(
4144
					array('comment' => 'First comment deepsaved article 2', 'published' => 'Y', 'User' => array('user' => 'savemore', 'password' => '')),
4145
					array('comment' => '', 'published' => 'Y', 'user_id' => 2)
4146
				)
4147
			)
4148
		);
4149
		$TestModel->Comment->validate['comment'] = 'notBlank';
4150
		$result = $TestModel->saveAll($data, array('deep' => false));
4151
		$this->assertFalse($result);
4152
 
4153
		$expected = array(
4154
 
4155
				'body' => array('This field cannot be left blank')
4156
			)
4157
		);
4158
		$result = $TestModel->validationErrors;
4159
		$this->assertSame($expected, $result);
4160
 
4161
		$data = array(
4162
			array(
4163
				'Article' => array('id' => 1, 'body' => 'Ignore invalid comment'),
4164
				'Comment' => array(
4165
					array('comment' => '', 'published' => 'Y', 'user_id' => 2)
4166
				)
4167
			),
4168
			array(
4169
				'Article' => array('id' => 2),
4170
				'Comment' => array(
4171
					array('comment' => '', 'published' => 'Y', 'user_id' => 2)
4172
				)
4173
			)
4174
		);
4175
		$result = $TestModel->saveAll($data, array('deep' => false));
4176
		$this->assertTrue($result);
4177
	}
4178
/**
4179
 * testSaveAllNotDeepValidateOnly
4180
 * tests the validate methods to not validate deeper recursive data
4181
 *
4182
 * @return void
4183
 */
4184
	public function testSaveAllNotDeepValidateOnly() {
4185
		$this->loadFixtures('Article', 'Comment', 'User', 'Attachment');
4186
		$TestModel = new Article();
4187
		$TestModel->hasMany['Comment']['order'] = array('Comment.created' => 'ASC');
4188
		$TestModel->hasAndBelongsToMany = array();
4189
		$TestModel->Comment->Attachment->validate['attachment'] = 'notBlank';
4190
		$TestModel->Comment->validate['comment'] = 'notBlank';
4191
 
4192
		$result = $TestModel->saveAll(
4193
			array(
4194
				'Article' => array('id' => 2, 'body' => ''),
4195
				'Comment' => array(
4196
					array('comment' => 'First new comment', 'published' => 'Y', 'User' => array('user' => '', 'password' => 'newuserpass')),
4197
					array('comment' => 'Second new comment', 'published' => 'Y', 'user_id' => 2)
4198
				)
4199
			),
4200
			array('validate' => 'only', 'deep' => false)
4201
		);
4202
		$this->assertFalse($result);
4203
 
4204
		$expected = array('body' => array('This field cannot be left blank'));
4205
		$result = $TestModel->validationErrors;
4206
		$this->assertSame($expected, $result);
4207
 
4208
		$result = $TestModel->saveAll(
4209
			array(
4210
				'Article' => array('id' => 2, 'body' => 'Ignore invalid user data'),
4211
				'Comment' => array(
4212
					array('comment' => 'First new comment', 'published' => 'Y', 'User' => array('user' => '', 'password' => 'newuserpass')),
4213
					array('comment' => 'Second new comment', 'published' => 'Y', 'user_id' => 2)
4214
				)
4215
			),
4216
			array('validate' => 'only', 'deep' => false)
4217
		);
4218
		$this->assertTrue($result);
4219
 
4220
		$result = $TestModel->saveAll(
4221
			array(
4222
				'Article' => array('id' => 2, 'body' => 'Ignore invalid user data'),
4223
				'Comment' => array(
4224
					array('comment' => 'First new comment', 'published' => 'Y', 'User' => array('user' => '', 'password' => 'newuserpass')),
4225
					array('comment' => 'Second new comment', 'published' => 'Y', 'user_id' => 2)
4226
				)
4227
			),
4228
			array('validate' => 'only', 'atomic' => false, 'deep' => false)
4229
		);
4230
		$expected = array(
4231
			'Article' => true,
4232
			'Comment' => array(
4233
				true,
4234
				true
4235
			)
4236
		);
4237
		$this->assertSame($expected, $result);
4238
 
4239
		$result = $TestModel->saveAll(array(
4240
			'Article' => array('id' => 2, 'body' => 'Ignore invalid attachment data'),
4241
			'Comment' => array(
4242
				array('comment' => 'Third new comment', 'published' => 'Y', 'user_id' => 5),
4243
				array('comment' => 'Fourth new comment', 'published' => 'Y', 'user_id' => 2, 'Attachment' => array('attachment' => ''))
4244
			)
4245
		),
4246
		array('validate' => 'only', 'deep' => false)
4247
		);
4248
		$this->assertTrue($result);
4249
 
4250
		$result = $TestModel->saveAll(array(
4251
			'Article' => array('id' => 2, 'body' => 'Ignore invalid attachment data'),
4252
			'Comment' => array(
4253
				array('comment' => 'Third new comment', 'published' => 'Y', 'user_id' => 5),
4254
				array('comment' => 'Fourth new comment', 'published' => 'Y', 'user_id' => 2, 'Attachment' => array('attachment' => ''))
4255
			)
4256
		),
4257
		array('validate' => 'only', 'atomic' => false, 'deep' => false)
4258
		);
4259
		$expected = array(
4260
			'Article' => true,
4261
			'Comment' => array(
4262
				true,
4263
				true
4264
			)
4265
		);
4266
		$this->assertSame($expected, $result);
4267
 
4268
		$expected = array();
4269
		$result = $TestModel->validationErrors;
4270
		$this->assertSame($expected, $result);
4271
 
4272
		$data = array(
4273
			'Attachment' => array(
4274
				'attachment' => 'deepsave insert',
4275
			),
4276
			'Comment' => array(
4277
				'comment' => 'First comment deepsave insert',
4278
				'published' => 'Y',
4279
				'user_id' => 5,
4280
				'Article' => array(
4281
					'title' => 'First Article deepsave insert ignored',
4282
					'body' => 'First Article Body deepsave insert',
4283
					'User' => array(
4284
						'user' => '',
4285
						'password' => 'magic'
4286
					),
4287
				),
4288
			)
4289
		);
4290
 
4291
		$result = $TestModel->Comment->Attachment->saveAll($data, array('validate' => 'only', 'deep' => false));
4292
		$this->assertTrue($result);
4293
 
4294
		$result = $TestModel->Comment->Attachment->validationErrors;
4295
		$expected = array();
4296
		$this->assertSame($expected, $result);
4297
 
4298
		$result = $TestModel->Comment->Attachment->saveAll($data, array('validate' => 'only', 'atomic' => false, 'deep' => false));
4299
		$expected = array(
4300
			'Attachment' => true,
4301
			'Comment' => true
4302
		);
4303
		$this->assertEquals($expected, $result);
4304
 
4305
		$data['Comment']['Article']['body'] = '';
4306
		$result = $TestModel->Comment->Attachment->saveAll($data, array('validate' => 'only', 'deep' => false));
4307
		$this->assertTrue($result);
4308
 
4309
		$result = $TestModel->Comment->Attachment->validationErrors;
4310
		$expected = array();
4311
		$this->assertSame($expected, $result);
4312
 
4313
		$result = $TestModel->Comment->Attachment->saveAll($data, array('validate' => 'only', 'atomic' => false, 'deep' => false));
4314
		$expected = array(
4315
			'Attachment' => true,
4316
			'Comment' => true
4317
		);
4318
		$this->assertEquals($expected, $result);
4319
	}
4320
 
4321
/**
4322
 * testSaveAllHasMany method
4323
 *
4324
 * @return void
4325
 */
4326
	public function testSaveAllHasMany() {
4327
		$this->loadFixtures('Article', 'Comment');
4328
		$TestModel = new Article();
4329
		$TestModel->hasMany['Comment']['order'] = array('Comment.created' => 'ASC');
4330
		$TestModel->belongsTo = $TestModel->hasAndBelongsToMany = array();
4331
 
4332
		$result = $TestModel->saveAll(array(
4333
			'Article' => array('id' => 2),
4334
			'Comment' => array(
4335
				array('comment' => 'First new comment', 'published' => 'Y', 'user_id' => 1),
4336
				array('comment' => 'Second new comment', 'published' => 'Y', 'user_id' => 2)
4337
			)
4338
		));
4339
		$this->assertFalse(empty($result));
4340
 
4341
		$result = $TestModel->findById(2);
4342
		$expected = array(
4343
			'First Comment for Second Article',
4344
			'Second Comment for Second Article',
4345
			'First new comment',
4346
			'Second new comment'
4347
		);
4348
		$result = Hash::extract(Hash::sort($result['Comment'], '{n}.id', 'ASC'), '{n}.comment');
4349
		$this->assertEquals($expected, $result);
4350
 
4351
		$result = $TestModel->saveAll(
4352
			array(
4353
				'Article' => array('id' => 2),
4354
				'Comment' => array(
4355
					array(
4356
						'comment' => 'Third new comment',
4357
						'published' => 'Y',
4358
						'user_id' => 1
4359
			))),
4360
			array('atomic' => false)
4361
		);
4362
		$this->assertFalse(empty($result));
4363
 
4364
		$result = $TestModel->findById(2);
4365
		$expected = array(
4366
			'First Comment for Second Article',
4367
			'Second Comment for Second Article',
4368
			'First new comment',
4369
			'Second new comment',
4370
			'Third new comment'
4371
		);
4372
		$result = Hash::extract(Hash::sort($result['Comment'], '{n}.id', 'ASC'), '{n}.comment');
4373
		$this->assertEquals($expected, $result);
4374
 
4375
		$TestModel->beforeSaveReturn = false;
4376
		$result = $TestModel->saveAll(
4377
			array(
4378
				'Article' => array('id' => 2),
4379
				'Comment' => array(
4380
					array(
4381
						'comment' => 'Fourth new comment',
4382
						'published' => 'Y',
4383
						'user_id' => 1
4384
			))),
4385
			array('atomic' => false)
4386
		);
4387
		$this->assertEquals(array('Article' => false), $result);
4388
 
4389
		$result = $TestModel->findById(2);
4390
		$expected = array(
4391
			'First Comment for Second Article',
4392
			'Second Comment for Second Article',
4393
			'First new comment',
4394
			'Second new comment',
4395
			'Third new comment'
4396
		);
4397
		$result = Hash::extract(Hash::sort($result['Comment'], '{n}.id', 'ASC'), '{n}.comment');
4398
		$this->assertEquals($expected, $result);
4399
	}
4400
 
4401
/**
4402
 * testSaveAllHasManyValidation method
4403
 *
4404
 * @return void
4405
 */
4406
	public function testSaveAllHasManyValidation() {
4407
		$this->loadFixtures('Article', 'Comment');
4408
		$TestModel = new Article();
4409
		$TestModel->belongsTo = $TestModel->hasAndBelongsToMany = array();
4410
		$TestModel->Comment->validate = array('comment' => 'notBlank');
4411
 
4412
		$result = $TestModel->saveAll(array(
4413
			'Article' => array('id' => 2),
4414
			'Comment' => array(
4415
				array('comment' => '', 'published' => 'Y', 'user_id' => 1),
4416
			)
4417
		), array('validate' => true));
4418
		$this->assertFalse($result);
4419
 
4420
		$expected = array('Comment' => array(
4421
			array('comment' => array('This field cannot be left blank'))
4422
		));
4423
		$this->assertEquals($expected, $TestModel->validationErrors);
4424
		$expected = array(
4425
			array('comment' => array('This field cannot be left blank'))
4426
		);
4427
		$this->assertEquals($expected, $TestModel->Comment->validationErrors);
4428
 
4429
		$result = $TestModel->saveAll(array(
4430
			'Article' => array('id' => 2),
4431
			'Comment' => array(
4432
				array(
4433
					'comment' => '',
4434
					'published' => 'Y',
4435
					'user_id' => 1
4436
			))
4437
		), array('validate' => 'first'));
4438
		$this->assertFalse($result);
4439
	}
4440
 
4441
/**
4442
 * test saveAll with transactions and ensure there is no missing rollback.
4443
 *
4444
 * @return void
4445
 */
4446
	public function testSaveAllManyRowsTransactionNoRollback() {
4447
		$this->loadFixtures('Post');
4448
 
4449
		$Post = new TestPost();
4450
		$Post->validate = array(
4451
			'title' => array('rule' => array('notBlank'))
4452
		);
4453
 
4454
		// If validation error occurs, rollback() should be called.
4455
		$db = $this->_getMockDboSource(array('begin', 'commit', 'rollback'));
4456
		$db->expects($this->once())->method('begin')->will($this->returnValue(true));
4457
		$db->expects($this->never())->method('commit');
4458
		$db->expects($this->once())->method('rollback');
4459
 
4460
		$Post->setDataSourceObject($db);
4461
 
4462
		$data = array(
4463
			array('author_id' => 1, 'title' => 'New Fourth Post'),
4464
			array('author_id' => 1, 'title' => '')
4465
		);
4466
		$Post->saveAll($data, array('atomic' => true, 'validate' => true));
4467
 
4468
		// If exception thrown, rollback() should be called too.
4469
		$db = $this->_getMockDboSource(array('begin', 'commit', 'rollback'));
4470
		$db->expects($this->once())->method('begin')->will($this->returnValue(true));
4471
		$db->expects($this->never())->method('commit');
4472
		$db->expects($this->once())->method('rollback');
4473
 
4474
		$Post->setDataSourceObject($db);
4475
 
4476
		$data = array(
4477
			array('author_id' => 1, 'title' => 'New Fourth Post'),
4478
			array('author_id' => 1, 'title' => 'New Fifth Post', 'body' => $db->expression('PDO_EXCEPTION()'))
4479
		);
4480
 
4481
		try {
4482
			$Post->saveAll($data, array('atomic' => true, 'validate' => true));
4483
			$this->fail('No exception thrown');
4484
		} catch (PDOException $e) {
4485
		}
4486
 
4487
		// Otherwise, commit() should be called.
4488
		$db = $this->_getMockDboSource(array('begin', 'commit', 'rollback'));
4489
		$db->expects($this->once())->method('begin')->will($this->returnValue(true));
4490
		$db->expects($this->once())->method('commit');
4491
		$db->expects($this->never())->method('rollback');
4492
 
4493
		$Post->setDataSourceObject($db);
4494
 
4495
		$data = array(
4496
			array('author_id' => 1, 'title' => 'New Fourth Post'),
4497
			array('author_id' => 1, 'title' => 'New Fifth Post')
4498
		);
4499
		$Post->saveAll($data, array('atomic' => true, 'validate' => true));
4500
	}
4501
 
4502
/**
4503
 * test saveAll with transactions and ensure there is no missing rollback.
4504
 *
4505
 * @return void
4506
 */
4507
	public function testSaveAllAssociatedTransactionNoRollback() {
4508
		$this->loadFixtures('Post', 'Author');
4509
 
4510
		$Post = new TestPost();
4511
		$Post->Author->validate = array(
4512
			'user' => array('rule' => array('notBlank'))
4513
		);
4514
 
4515
		// If validation error occurs, rollback() should be called.
4516
		$db = $this->_getMockDboSource(array('begin', 'commit', 'rollback'));
4517
		$db->expects($this->once())->method('begin')->will($this->returnValue(true));
4518
		$db->expects($this->never())->method('commit');
4519
		$db->expects($this->once())->method('rollback');
4520
 
4521
		$Post->setDataSourceObject($db);
4522
		$Post->Author->setDataSourceObject($db);
4523
 
4524
		$data = array(
4525
			'Post' => array(
4526
				'title' => 'New post',
4527
				'body' => 'Content',
4528
				'published' => 'Y'
4529
			),
4530
			'Author' => array(
4531
				'user' => '',
4532
				'password' => "sekret"
4533
			)
4534
		);
4535
		$Post->saveAll($data, array('validate' => true));
4536
 
4537
		// If exception thrown, rollback() should be called too.
4538
		$db = $this->_getMockDboSource(array('begin', 'commit', 'rollback'));
4539
		$db->expects($this->once())->method('begin')->will($this->returnValue(true));
4540
		$db->expects($this->never())->method('commit');
4541
		$db->expects($this->once())->method('rollback');
4542
 
4543
		$Post->setDataSourceObject($db);
4544
		$Post->Author->setDataSourceObject($db);
4545
 
4546
		$data = array(
4547
			'Post' => array(
4548
				'title' => 'New post',
4549
				'body' => $db->expression('PDO_EXCEPTION()'),
4550
				'published' => 'Y'
4551
			),
4552
			'Author' => array(
4553
				'user' => 'New user',
4554
				'password' => "sekret"
4555
			)
4556
		);
4557
 
4558
		try {
4559
			$Post->saveAll($data, array('validate' => true));
4560
			$this->fail('No exception thrown');
4561
		} catch (PDOException $e) {
4562
		}
4563
 
4564
		// Otherwise, commit() should be called.
4565
		$db = $this->_getMockDboSource(array('begin', 'commit', 'rollback'));
4566
		$db->expects($this->once())->method('begin')->will($this->returnValue(true));
4567
		$db->expects($this->once())->method('commit');
4568
		$db->expects($this->never())->method('rollback');
4569
 
4570
		$Post->setDataSourceObject($db);
4571
		$Post->Author->setDataSourceObject($db);
4572
 
4573
		$data = array(
4574
			'Post' => array(
4575
				'title' => 'New post',
4576
				'body' => 'Content',
4577
				'published' => 'Y'
4578
			),
4579
			'Author' => array(
4580
				'user' => 'New user',
4581
				'password' => "sekret"
4582
			)
4583
		);
4584
		$Post->saveAll($data, array('validate' => true));
4585
	}
4586
 
4587
/**
4588
 * test saveAll with nested saveAll call.
4589
 *
4590
 * @return void
4591
 */
4592
	public function testSaveAllNestedSaveAll() {
4593
		$this->loadFixtures('Sample');
4594
		$TransactionTestModel = new TransactionTestModel();
4595
 
4596
		$data = array(
4597
			array('apple_id' => 1, 'name' => 'sample5'),
4598
		);
4599
 
4600
		$this->assertTrue($TransactionTestModel->saveAll($data, array('atomic' => true)));
4601
	}
4602
 
4603
/**
4604
 * testSaveAllTransaction method
4605
 *
4606
 * @return void
4607
 */
4608
	public function testSaveAllTransaction() {
4609
		$this->loadFixtures('Post', 'Author', 'Comment', 'Attachment');
4610
		$TestModel = new Post();
4611
 
4612
		$TestModel->validate = array('title' => 'notBlank');
4613
		$data = array(
4614
			array('author_id' => 1, 'title' => 'New Fourth Post'),
4615
			array('author_id' => 1, 'title' => 'New Fifth Post'),
4616
			array('author_id' => 1, 'title' => '')
4617
		);
4618
		$this->assertFalse($TestModel->saveAll($data));
4619
 
4620
		$result = $TestModel->find('all', array('recursive' => -1));
4621
		$expected = array(
4622
			array('Post' => array(
4623
				'id' => '1',
4624
				'author_id' => 1,
4625
				'title' => 'First Post',
4626
				'body' => 'First Post Body',
4627
				'published' => 'Y',
4628
				'created' => '2007-03-18 10:39:23',
4629
				'updated' => '2007-03-18 10:41:31'
4630
			)),
4631
			array('Post' => array(
4632
				'id' => '2',
4633
				'author_id' => 3,
4634
				'title' => 'Second Post',
4635
				'body' => 'Second Post Body',
4636
				'published' => 'Y',
4637
				'created' => '2007-03-18 10:41:23',
4638
				'updated' => '2007-03-18 10:43:31'
4639
			)),
4640
			array('Post' => array(
4641
				'id' => '3',
4642
				'author_id' => 1,
4643
				'title' => 'Third Post',
4644
				'body' => 'Third Post Body',
4645
				'published' => 'Y',
4646
				'created' => '2007-03-18 10:43:23',
4647
				'updated' => '2007-03-18 10:45:31'
4648
		)));
4649
 
4650
		if (count($result) != 3) {
4651
			// Database doesn't support transactions
4652
			$expected[] = array(
4653
				'Post' => array(
4654
					'id' => '4',
4655
					'author_id' => 1,
4656
					'title' => 'New Fourth Post',
4657
					'body' => null,
4658
					'published' => 'N',
4659
					'created' => static::date(),
4660
					'updated' => static::date()
4661
			));
4662
 
4663
			$expected[] = array(
4664
				'Post' => array(
4665
					'id' => '5',
4666
					'author_id' => 1,
4667
					'title' => 'New Fifth Post',
4668
					'body' => null,
4669
					'published' => 'N',
4670
					'created' => static::date(),
4671
					'updated' => static::date()
4672
			));
4673
 
4674
			$this->assertEquals($expected, $result);
4675
			// Skip the rest of the transactional tests
4676
			return;
4677
		}
4678
 
4679
		$this->assertEquals($expected, $result);
4680
 
4681
		$data = array(
4682
			array('author_id' => 1, 'title' => 'New Fourth Post'),
4683
			array('author_id' => 1, 'title' => ''),
4684
			array('author_id' => 1, 'title' => 'New Sixth Post')
4685
		);
4686
		$this->assertFalse($TestModel->saveAll($data));
4687
 
4688
		$result = $TestModel->find('all', array('recursive' => -1));
4689
		$expected = array(
4690
			array('Post' => array(
4691
				'id' => '1',
4692
				'author_id' => 1,
4693
				'title' => 'First Post',
4694
				'body' => 'First Post Body',
4695
				'published' => 'Y',
4696
				'created' => '2007-03-18 10:39:23',
4697
				'updated' => '2007-03-18 10:41:31'
4698
			)),
4699
			array('Post' => array(
4700
				'id' => '2',
4701
				'author_id' => 3,
4702
				'title' => 'Second Post',
4703
				'body' => 'Second Post Body',
4704
				'published' => 'Y',
4705
				'created' => '2007-03-18 10:41:23',
4706
				'updated' => '2007-03-18 10:43:31'
4707
			)),
4708
			array('Post' => array(
4709
				'id' => '3',
4710
				'author_id' => 1,
4711
				'title' => 'Third Post',
4712
				'body' => 'Third Post Body',
4713
				'published' => 'Y',
4714
				'created' => '2007-03-18 10:43:23',
4715
				'updated' => '2007-03-18 10:45:31'
4716
		)));
4717
 
4718
		if (count($result) != 3) {
4719
			// Database doesn't support transactions
4720
			$expected[] = array(
4721
				'Post' => array(
4722
					'id' => '4',
4723
					'author_id' => 1,
4724
					'title' => 'New Fourth Post',
4725
					'body' => 'Third Post Body',
4726
					'published' => 'N',
4727
					'created' => static::date(),
4728
					'updated' => static::date()
4729
			));
4730
 
4731
			$expected[] = array(
4732
				'Post' => array(
4733
					'id' => '5',
4734
					'author_id' => 1,
4735
					'title' => 'Third Post',
4736
					'body' => 'Third Post Body',
4737
					'published' => 'N',
4738
					'created' => static::date(),
4739
					'updated' => static::date()
4740
			));
4741
		}
4742
		$this->assertEquals($expected, $result);
4743
 
4744
		$TestModel->validate = array('title' => 'notBlank');
4745
		$data = array(
4746
			array('author_id' => 1, 'title' => 'New Fourth Post'),
4747
			array('author_id' => 1, 'title' => 'New Fifth Post'),
4748
			array('author_id' => 1, 'title' => 'New Sixth Post')
4749
		);
4750
		$this->assertTrue($TestModel->saveAll($data));
4751
 
4752
		$result = $TestModel->find('all', array(
4753
			'recursive' => -1,
4754
			'fields' => array('author_id', 'title', 'body', 'published'),
4755
			'order' => array('Post.created' => 'ASC')
4756
		));
4757
 
4758
		$expected = array(
4759
			array('Post' => array(
4760
				'author_id' => 1,
4761
				'title' => 'First Post',
4762
				'body' => 'First Post Body',
4763
				'published' => 'Y'
4764
			)),
4765
			array('Post' => array(
4766
				'author_id' => 3,
4767
				'title' => 'Second Post',
4768
				'body' => 'Second Post Body',
4769
				'published' => 'Y'
4770
			)),
4771
			array('Post' => array(
4772
				'author_id' => 1,
4773
				'title' => 'Third Post',
4774
				'body' => 'Third Post Body',
4775
				'published' => 'Y'
4776
			)),
4777
			array('Post' => array(
4778
				'author_id' => 1,
4779
				'title' => 'New Fourth Post',
4780
				'body' => '',
4781
				'published' => 'N'
4782
			)),
4783
			array('Post' => array(
4784
				'author_id' => 1,
4785
				'title' => 'New Fifth Post',
4786
				'body' => '',
4787
				'published' => 'N'
4788
			)),
4789
			array('Post' => array(
4790
				'author_id' => 1,
4791
				'title' => 'New Sixth Post',
4792
				'body' => '',
4793
				'published' => 'N'
4794
		)));
4795
		$this->assertEquals($expected, $result);
4796
	}
4797
 
4798
/**
4799
 * testSaveAllValidation method
4800
 *
4801
 * @return void
4802
 */
4803
	public function testSaveAllValidation() {
4804
		$this->loadFixtures('Post', 'Author', 'Comment', 'Attachment');
4805
		$TestModel = new Post();
4806
 
4807
		$data = array(
4808
			array(
4809
				'id' => '1',
4810
				'title' => 'Baleeted First Post',
4811
				'body' => 'Baleeted!',
4812
				'published' => 'N'
4813
			),
4814
			array(
4815
				'id' => '2',
4816
				'title' => 'Just update the title'
4817
			),
4818
			array(
4819
				'title' => 'Creating a fourth post',
4820
				'body' => 'Fourth post body',
4821
				'author_id' => 2
4822
		));
4823
 
4824
		$this->assertTrue($TestModel->saveAll($data));
4825
 
4826
		$result = $TestModel->find('all', array('recursive' => -1, 'order' => 'Post.id ASC'));
4827
		$expected = array(
4828
			array(
4829
				'Post' => array(
4830
					'id' => '1',
4831
					'author_id' => '1',
4832
					'title' => 'Baleeted First Post',
4833
					'body' => 'Baleeted!',
4834
					'published' => 'N',
4835
					'created' => '2007-03-18 10:39:23'
4836
			)),
4837
			array(
4838
				'Post' => array(
4839
					'id' => '2',
4840
					'author_id' => '3',
4841
					'title' => 'Just update the title',
4842
					'body' => 'Second Post Body',
4843
					'published' => 'Y',
4844
					'created' => '2007-03-18 10:41:23'
4845
			)),
4846
			array(
4847
				'Post' => array(
4848
					'id' => '3',
4849
					'author_id' => '1',
4850
					'title' => 'Third Post',
4851
					'body' => 'Third Post Body',
4852
					'published' => 'Y',
4853
					'created' => '2007-03-18 10:43:23',
4854
					'updated' => '2007-03-18 10:45:31'
4855
			)),
4856
			array(
4857
				'Post' => array(
4858
					'id' => '4',
4859
					'author_id' => '2',
4860
					'title' => 'Creating a fourth post',
4861
					'body' => 'Fourth post body',
4862
					'published' => 'N'
4863
		)));
4864
		$this->assertEquals(static::date(), $result[0]['Post']['updated']);
4865
		$this->assertEquals(static::date(), $result[1]['Post']['updated']);
4866
		$this->assertEquals(static::date(), $result[3]['Post']['created']);
4867
		$this->assertEquals(static::date(), $result[3]['Post']['updated']);
4868
		unset($result[0]['Post']['updated'], $result[1]['Post']['updated']);
4869
		unset($result[3]['Post']['created'], $result[3]['Post']['updated']);
4870
		$this->assertEquals($expected, $result);
4871
 
4872
		$TestModel->validate = array('title' => 'notBlank', 'author_id' => 'numeric');
4873
		$data = array(
4874
			array(
4875
				'id' => '1',
4876
				'title' => 'Un-Baleeted First Post',
4877
				'body' => 'Not Baleeted!',
4878
				'published' => 'Y'
4879
			),
4880
			array(
4881
				'id' => '2',
4882
				'title' => '',
4883
				'body' => 'Trying to get away with an empty title'
4884
		));
4885
		$result = $TestModel->saveAll($data);
4886
		$this->assertFalse($result);
4887
 
4888
		$result = $TestModel->find('all', array('recursive' => -1, 'order' => 'Post.id ASC'));
4889
		$errors = array(1 => array('title' => array('This field cannot be left blank')));
4890
		$transactionWorked = Set::matches('/Post[1][title=Baleeted First Post]', $result);
4891
		if (!$transactionWorked) {
4892
			$this->assertTrue(Set::matches('/Post[1][title=Un-Baleeted First Post]', $result));
4893
			$this->assertTrue(Set::matches('/Post[2][title=Just update the title]', $result));
4894
		}
4895
 
4896
		$this->assertEquals($errors, $TestModel->validationErrors);
4897
 
4898
		$TestModel->validate = array('title' => 'notBlank', 'author_id' => 'numeric');
4899
		$data = array(
4900
			array(
4901
				'id' => '1',
4902
				'title' => 'Un-Baleeted First Post',
4903
				'body' => 'Not Baleeted!',
4904
				'published' => 'Y'
4905
			),
4906
			array(
4907
				'id' => '2',
4908
				'title' => '',
4909
				'body' => 'Trying to get away with an empty title'
4910
		));
4911
		$result = $TestModel->saveAll($data, array('validate' => true, 'atomic' => false));
4912
		$this->assertEquals(array(true, false), $result);
4913
		$result = $TestModel->find('all', array('recursive' => -1, 'order' => 'Post.id ASC'));
4914
		$errors = array(1 => array('title' => array('This field cannot be left blank')));
4915
		$expected = array(
4916
			array(
4917
				'Post' => array(
4918
					'id' => '1',
4919
					'author_id' => '1',
4920
					'title' => 'Un-Baleeted First Post',
4921
					'body' => 'Not Baleeted!',
4922
					'published' => 'Y',
4923
					'created' => '2007-03-18 10:39:23'
4924
				)
4925
			),
4926
			array(
4927
				'Post' => array(
4928
					'id' => '2',
4929
					'author_id' => '3',
4930
					'title' => 'Just update the title',
4931
					'body' => 'Second Post Body',
4932
					'published' => 'Y',
4933
					'created' => '2007-03-18 10:41:23'
4934
				)
4935
			),
4936
			array(
4937
				'Post' => array(
4938
					'id' => '3',
4939
					'author_id' => '1',
4940
					'title' => 'Third Post',
4941
					'body' => 'Third Post Body',
4942
					'published' => 'Y',
4943
					'created' => '2007-03-18 10:43:23',
4944
					'updated' => '2007-03-18 10:45:31'
4945
				)
4946
			),
4947
			array(
4948
				'Post' => array(
4949
					'id' => '4',
4950
					'author_id' => '2',
4951
					'title' => 'Creating a fourth post',
4952
					'body' => 'Fourth post body',
4953
					'published' => 'N'
4954
				)
4955
			)
4956
		);
4957
 
4958
		$this->assertEquals(static::date(), $result[0]['Post']['updated']);
4959
		$this->assertEquals(static::date(), $result[1]['Post']['updated']);
4960
		$this->assertEquals(static::date(), $result[3]['Post']['updated']);
4961
		$this->assertEquals(static::date(), $result[3]['Post']['created']);
4962
		unset(
4963
			$result[0]['Post']['updated'], $result[1]['Post']['updated'],
4964
			$result[3]['Post']['updated'], $result[3]['Post']['created']
4965
		);
4966
		$this->assertEquals($expected, $result);
4967
		$this->assertEquals($errors, $TestModel->validationErrors);
4968
 
4969
		$data = array(
4970
			array(
4971
				'id' => '1',
4972
				'title' => 'Re-Baleeted First Post',
4973
				'body' => 'Baleeted!',
4974
				'published' => 'N'
4975
			),
4976
			array(
4977
				'id' => '2',
4978
				'title' => '',
4979
				'body' => 'Trying to get away with an empty title'
4980
		));
4981
		$this->assertFalse($TestModel->saveAll($data, array('validate' => 'first')));
4982
 
4983
		$result = $TestModel->find('all', array('recursive' => -1, 'order' => 'Post.id ASC'));
4984
		unset(
4985
			$result[0]['Post']['updated'], $result[1]['Post']['updated'],
4986
			$result[3]['Post']['updated'], $result[3]['Post']['created']
4987
		);
4988
		$this->assertEquals($expected, $result);
4989
		$this->assertEquals($errors, $TestModel->validationErrors);
4990
	}
4991
 
4992
/**
4993
 * testSaveAllValidationOnly method
4994
 *
4995
 * @return void
4996
 */
4997
	public function testSaveAllValidationOnly() {
4998
		$this->loadFixtures('Comment', 'Attachment');
4999
		$TestModel = new Comment();
5000
		$TestModel->Attachment->validate = array('attachment' => 'notBlank');
5001
 
5002
		$data = array(
5003
			'Comment' => array(
5004
				'comment' => 'This is the comment'
5005
			),
5006
			'Attachment' => array(
5007
				'attachment' => ''
5008
			)
5009
		);
5010
 
5011
		$result = $TestModel->saveAll($data, array('validate' => 'only'));
5012
		$this->assertFalse($result);
5013
 
5014
		$TestModel = new Article();
5015
		$TestModel->validate = array('title' => 'notBlank');
5016
		$result = $TestModel->saveAll(
5017
			array(
5018
 
5019
				1 => array('title' => 'title 1'),
5020
				2 => array('title' => 'title 2'),
5021
			),
5022
			array('validate' => 'only')
5023
		);
5024
		$this->assertFalse($result);
5025
		$expected = array(
5026
 
5027
		);
5028
		$this->assertEquals($expected, $TestModel->validationErrors);
5029
 
5030
		$result = $TestModel->saveAll(
5031
			array(
5032
 
5033
				1 => array('title' => ''),
5034
				2 => array('title' => 'title 2'),
5035
			),
5036
			array('validate' => 'only')
5037
		);
5038
		$this->assertFalse($result);
5039
		$expected = array(
5040
			1 => array('title' => array('This field cannot be left blank')),
5041
		);
5042
		$this->assertEquals($expected, $TestModel->validationErrors);
5043
	}
5044
 
5045
/**
5046
 * testSaveAllValidateFirst method
5047
 *
5048
 * @return void
5049
 */
5050
	public function testSaveAllValidateFirst() {
5051
		$this->loadFixtures('Article', 'Comment', 'Attachment', 'User', 'ArticlesTag', 'Tag');
5052
		$model = new Article();
5053
		$model->deleteAll(true);
5054
 
5055
		$model->Comment->validate = array('comment' => 'notBlank');
5056
		$result = $model->saveAll(array(
5057
			'Article' => array(
5058
				'title' => 'Post with Author',
5059
				'body' => 'This post will be saved author'
5060
			),
5061
			'Comment' => array(
5062
				array('comment' => 'First new comment'),
5063
				array('comment' => '')
5064
			)
5065
		), array('validate' => 'first'));
5066
 
5067
		$this->assertFalse($result);
5068
 
5069
		$result = $model->find('all');
5070
		$this->assertSame(array(), $result);
5071
		$expected = array('Comment' => array(
5072
			1 => array('comment' => array('This field cannot be left blank'))
5073
		));
5074
 
5075
		$this->assertEquals($expected['Comment'], $model->Comment->validationErrors);
5076
 
5077
		$this->assertSame($model->Comment->find('count'), 0);
5078
 
5079
		$result = $model->saveAll(
5080
			array(
5081
				'Article' => array(
5082
					'title' => 'Post with Author',
5083
					'body' => 'This post will be saved with an author',
5084
					'user_id' => 2
5085
				),
5086
				'Comment' => array(
5087
					array(
5088
						'comment' => 'Only new comment',
5089
						'user_id' => 2
5090
			))),
5091
			array('validate' => 'first')
5092
		);
5093
 
5094
		$this->assertTrue($result);
5095
 
5096
		$result = $model->Comment->find('all');
5097
		$this->assertSame(count($result), 1);
5098
		$result = Hash::extract($result, '{n}.Comment.article_id');
5099
		$this->assertEquals(4, $result[0]);
5100
 
5101
		$model->deleteAll(true);
5102
		$data = array(
5103
			'Article' => array(
5104
				'title' => 'Post with Author saveAlled from comment',
5105
				'body' => 'This post will be saved with an author',
5106
				'user_id' => 2
5107
			),
5108
			'Comment' => array(
5109
				'comment' => 'Only new comment', 'user_id' => 2
5110
		));
5111
 
5112
		$result = $model->Comment->saveAll($data, array('validate' => 'first'));
5113
		$this->assertFalse(empty($result));
5114
 
5115
		$result = $model->find('all');
5116
		$this->assertEquals(
5117
			$result[0]['Article']['title'],
5118
			'Post with Author saveAlled from comment'
5119
		);
5120
		$this->assertEquals('Only new comment', $result[0]['Comment'][0]['comment']);
5121
	}
5122
 
5123
/**
5124
 * test saveAll()'s return is correct when using atomic = false and validate = first.
5125
 *
5126
 * @return void
5127
 */
5128
	public function testSaveAllValidateFirstAtomicFalse() {
5129
		$this->loadFixtures('Something');
5130
		$Something = new Something();
5131
		$invalidData = array(
5132
			array(
5133
				'title' => 'foo',
5134
				'body' => 'bar',
5135
				'published' => 'baz',
5136
			),
5137
			array(
5138
				'body' => 3,
5139
				'published' => 'sd',
5140
			),
5141
		);
5142
		$Something->create();
5143
		$Something->validate = array(
5144
			'title' => array(
5145
				'rule' => 'alphaNumeric',
5146
				'required' => true,
5147
			),
5148
			'body' => array(
5149
				'rule' => 'alphaNumeric',
5150
				'required' => true,
5151
				'allowEmpty' => true,
5152
			),
5153
		);
5154
		$result = $Something->saveAll($invalidData, array(
5155
			'atomic' => false,
5156
			'validate' => 'first',
5157
		));
5158
		$expected = array(true, false);
5159
		$this->assertEquals($expected, $result);
5160
 
5161
		$Something = new Something();
5162
		$validData = array(
5163
			array(
5164
				'title' => 'title value',
5165
				'body' => 'body value',
5166
				'published' => 'baz',
5167
			),
5168
			array(
5169
				'title' => 'valid',
5170
				'body' => 'this body',
5171
				'published' => 'sd',
5172
			),
5173
		);
5174
		$Something->create();
5175
		$result = $Something->saveAll($validData, array(
5176
			'atomic' => false,
5177
			'validate' => 'first',
5178
		));
5179
		$expected = array(true, true);
5180
		$this->assertEquals($expected, $result);
5181
	}
5182
 
5183
/**
5184
 * testSaveAllHasManyValidationOnly method
5185
 *
5186
 * @return void
5187
 */
5188
	public function testSaveAllHasManyValidationOnly() {
5189
		$this->loadFixtures('Article', 'Comment', 'Attachment');
5190
		$TestModel = new Article();
5191
		$TestModel->belongsTo = $TestModel->hasAndBelongsToMany = array();
5192
		$TestModel->Comment->validate = array('comment' => 'notBlank');
5193
 
5194
		$result = $TestModel->saveAll(
5195
			array(
5196
				'Article' => array('id' => 2),
5197
				'Comment' => array(
5198
					array(
5199
						'id' => 1,
5200
						'comment' => '',
5201
						'published' => 'Y',
5202
						'user_id' => 1),
5203
					array(
5204
						'id' => 2,
5205
						'comment' =>
5206
						'comment',
5207
						'published' => 'Y',
5208
						'user_id' => 1
5209
			))),
5210
			array('validate' => 'only')
5211
		);
5212
		$this->assertFalse($result);
5213
 
5214
		$result = $TestModel->saveAll(
5215
			array(
5216
				'Article' => array('id' => 2),
5217
				'Comment' => array(
5218
					array(
5219
						'id' => 1,
5220
						'comment' => '',
5221
						'published' => 'Y',
5222
						'user_id' => 1
5223
					),
5224
					array(
5225
						'id' => 2,
5226
						'comment' => 'comment',
5227
						'published' => 'Y',
5228
						'user_id' => 1
5229
					),
5230
					array(
5231
						'id' => 3,
5232
						'comment' => '',
5233
						'published' => 'Y',
5234
						'user_id' => 1
5235
			))),
5236
			array(
5237
				'validate' => 'only',
5238
				'atomic' => false
5239
		));
5240
		$expected = array(
5241
			'Article' => true,
5242
			'Comment' => array(false, true, false)
5243
		);
5244
		$this->assertSame($expected, $result);
5245
 
5246
		$expected = array('Comment' => array(
5247
 
5248
			2 => array('comment' => array('This field cannot be left blank'))
5249
		));
5250
		$this->assertEquals($expected, $TestModel->validationErrors);
5251
 
5252
		$expected = array(
5253
 
5254
			2 => array('comment' => array('This field cannot be left blank'))
5255
		);
5256
		$this->assertEquals($expected, $TestModel->Comment->validationErrors);
5257
	}
5258
 
5259
/**
5260
 * test that saveAll still behaves like previous versions (does not necessarily need a first argument)
5261
 *
5262
 * @return void
5263
 */
5264
	public function testSaveAllWithSet() {
5265
		$this->loadFixtures('Article', 'Tag', 'Comment', 'User', 'ArticlesTag');
5266
		$data = array(
5267
			'Article' => array(
5268
				'user_id' => 1,
5269
				'title' => 'Article Has and belongs to Many Tags'
5270
			),
5271
			'Tag' => array(
5272
				'Tag' => array(1, 2)
5273
			),
5274
			'Comment' => array(
5275
				array(
5276
					'comment' => 'Article comment',
5277
					'user_id' => 1
5278
		)));
5279
		$Article = new Article();
5280
		$Article->set($data);
5281
		$result = $Article->saveAll();
5282
		$this->assertFalse(empty($result));
5283
	}
5284
 
5285
/**
5286
 * test that saveAll behaves like plain save() when supplied empty data
5287
 *
5288
 * @link https://cakephp.lighthouseapp.com/projects/42648/tickets/277-test-saveall-with-validation-returns-incorrect-boolean-when-saving-empty-data
5289
 * @return void
5290
 */
5291
	public function testSaveAllEmptyData() {
5292
		$this->skipIf($this->db instanceof Sqlserver, 'This test is not compatible with SQL Server.');
5293
 
5294
		$this->loadFixtures('Article', 'ProductUpdateAll', 'Comment', 'Attachment');
5295
		$model = new Article();
5296
		$result = $model->saveAll(array(), array('validate' => 'first'));
5297
		$this->assertFalse(empty($result));
5298
 
5299
		$model = new ProductUpdateAll();
5300
		$result = $model->saveAll();
5301
		$this->assertFalse($result);
5302
	}
5303
 
5304
/**
5305
 * testSaveAssociated method
5306
 *
5307
 * @return void
5308
 */
5309
	public function testSaveAssociated() {
5310
		$this->loadFixtures('Post', 'Author', 'Comment', 'Attachment', 'Article', 'User');
5311
		$TestModel = new Post();
5312
 
5313
		$result = $TestModel->find('all');
5314
		$this->assertEquals(3, count($result));
5315
		$this->assertFalse(isset($result[3]));
5316
 
5317
		$TestModel->saveAssociated(array(
5318
			'Post' => array(
5319
				'title' => 'Post with Author',
5320
				'body' => 'This post will be saved with an author'
5321
			),
5322
			'Author' => array(
5323
				'user' => 'bob',
5324
				'password' => '5f4dcc3b5aa765d61d8327deb882cf90'
5325
		)));
5326
 
5327
		$result = $TestModel->find('all', array('order' => array('Post.id ' => 'ASC')));
5328
		$expected = array(
5329
			'Post' => array(
5330
				'id' => '4',
5331
				'author_id' => '5',
5332
				'title' => 'Post with Author',
5333
				'body' => 'This post will be saved with an author',
5334
				'published' => 'N'
5335
			),
5336
			'Author' => array(
5337
				'id' => '5',
5338
				'user' => 'bob',
5339
				'password' => '5f4dcc3b5aa765d61d8327deb882cf90',
5340
				'test' => 'working'
5341
		));
5342
		$this->assertEquals(static::date(), $result[3]['Post']['updated']);
5343
		$this->assertEquals(static::date(), $result[3]['Post']['created']);
5344
		$this->assertEquals(static::date(), $result[3]['Author']['created']);
5345
		$this->assertEquals(static::date(), $result[3]['Author']['updated']);
5346
		unset(
5347
			$result[3]['Post']['updated'], $result[3]['Post']['created'],
5348
			$result[3]['Author']['updated'], $result[3]['Author']['created']
5349
		);
5350
		$this->assertEquals($expected, $result[3]);
5351
		$this->assertEquals(4, count($result));
5352
 
5353
		$TestModel = new Comment();
5354
		$result = $TestModel->saveAssociated(array(
5355
			'Comment' => array(
5356
				'article_id' => 2,
5357
				'user_id' => 2,
5358
				'comment' => 'New comment with attachment',
5359
				'published' => 'Y'
5360
			),
5361
			'Attachment' => array(
5362
				'attachment' => 'some_file.tgz'
5363
			)));
5364
		$this->assertFalse(empty($result));
5365
 
5366
		$result = $TestModel->find('all');
5367
		$expected = array(
5368
			'id' => '7',
5369
			'article_id' => '2',
5370
			'user_id' => '2',
5371
			'comment' => 'New comment with attachment',
5372
			'published' => 'Y'
5373
		);
5374
		$this->assertEquals(static::date(), $result[6]['Comment']['updated']);
5375
		$this->assertEquals(static::date(), $result[6]['Comment']['created']);
5376
		unset($result[6]['Comment']['updated'], $result[6]['Comment']['created']);
5377
		$this->assertEquals($expected, $result[6]['Comment']);
5378
 
5379
		$expected = array(
5380
			'id' => '2',
5381
			'comment_id' => '7',
5382
			'attachment' => 'some_file.tgz'
5383
		);
5384
		$this->assertEquals(static::date(), $result[6]['Attachment']['updated']);
5385
		$this->assertEquals(static::date(), $result[6]['Attachment']['created']);
5386
		unset($result[6]['Attachment']['updated'], $result[6]['Attachment']['created']);
5387
		$this->assertEquals($expected, $result[6]['Attachment']);
5388
	}
5389
 
5390
/**
5391
 * Test that validate = first, atomic = false works when associated records
5392
 * fail validation.
5393
 *
5394
 * @return void
5395
 */
5396
	public function testSaveAssociatedAtomicFalseValidateFirstWithErrors() {
5397
		$this->loadFixtures('Comment', 'Article', 'User');
5398
		$Article = ClassRegistry::init('Article');
5399
		$Article->Comment->validator()->add('comment', array(
5400
			array('rule' => 'notBlank')
5401
		));
5402
 
5403
		$data = array(
5404
			'Article' => array(
5405
				'user_id' => 1,
5406
				'title' => 'Foo',
5407
				'body' => 'text',
5408
				'published' => 'N'
5409
			),
5410
			'Comment' => array(
5411
				array(
5412
					'user_id' => 1,
5413
					'comment' => '',
5414
					'published' => 'N',
5415
				)
5416
			),
5417
		);
5418
 
5419
		$Article->saveAssociated(
5420
			$data,
5421
			array('validate' => 'first', 'atomic' => false)
5422
		);
5423
 
5424
		$result = $Article->validationErrors;
5425
		$expected = array(
5426
			'Comment' => array(
5427
				array(
5428
					'comment' => array('This field cannot be left blank')
5429
				)
5430
			)
5431
		);
5432
		$this->assertEquals($expected, $result);
5433
	}
5434
 
5435
/**
5436
 * testSaveMany method
5437
 *
5438
 * @return void
5439
 */
5440
	public function testSaveMany() {
5441
		$this->loadFixtures('Post');
5442
		$TestModel = new Post();
5443
		$TestModel->deleteAll(true);
5444
		$this->assertEquals(array(), $TestModel->find('all'));
5445
 
5446
		// SQLite seems to reset the PK counter when that happens, so we need this to make the tests pass
5447
		$this->db->truncate($TestModel);
5448
 
5449
		$TestModel->saveMany(array(
5450
			array(
5451
				'title' => 'Multi-record post 1',
5452
				'body' => 'First multi-record post',
5453
				'author_id' => 2
5454
			),
5455
			array(
5456
				'title' => 'Multi-record post 2',
5457
				'body' => 'Second multi-record post',
5458
				'author_id' => 2
5459
		)));
5460
 
5461
		$result = $TestModel->find('all', array(
5462
			'recursive' => -1,
5463
			'order' => 'Post.id ASC'
5464
		));
5465
		$expected = array(
5466
			array(
5467
				'Post' => array(
5468
					'id' => '1',
5469
					'author_id' => '2',
5470
					'title' => 'Multi-record post 1',
5471
					'body' => 'First multi-record post',
5472
					'published' => 'N'
5473
				)
5474
			),
5475
			array(
5476
				'Post' => array(
5477
					'id' => '2',
5478
					'author_id' => '2',
5479
					'title' => 'Multi-record post 2',
5480
					'body' => 'Second multi-record post',
5481
					'published' => 'N'
5482
				)
5483
			)
5484
		);
5485
		$this->assertEquals(static::date(), $result[0]['Post']['updated']);
5486
		$this->assertEquals(static::date(), $result[0]['Post']['created']);
5487
		$this->assertEquals(static::date(), $result[1]['Post']['updated']);
5488
		$this->assertEquals(static::date(), $result[1]['Post']['created']);
5489
		unset($result[0]['Post']['updated'], $result[0]['Post']['created']);
5490
		unset($result[1]['Post']['updated'], $result[1]['Post']['created']);
5491
		$this->assertEquals($expected, $result);
5492
	}
5493
 
5494
/**
5495
 * Test SaveMany with validate=false.
5496
 *
5497
 * @return void
5498
 */
5499
	public function testSaveManyValidateFalse() {
5500
		$this->loadFixtures('Post');
5501
		$TestModel = new Post();
5502
		$TestModel->deleteAll(true);
5503
		$data = array(
5504
			array('id' => 1, 'author_id' => 1, 'title' => 'hi'),
5505
			array('id' => 2, 'author_id' => 1, 'title' => 'bye')
5506
		);
5507
		$result = $TestModel->saveAll($data, array('validate' => false));
5508
		$this->assertTrue($result);
5509
	}
5510
 
5511
/**
5512
 * Test SaveAssociated with Habtm relations
5513
 *
5514
 * @return void
5515
 */
5516
	public function testSaveAssociatedHabtm() {
5517
		$this->loadFixtures('Article', 'Tag', 'Comment', 'User', 'ArticlesTag');
5518
		$data = array(
5519
			'Article' => array(
5520
				'user_id' => 1,
5521
				'title' => 'Article Has and belongs to Many Tags'
5522
			),
5523
			'Tag' => array(
5524
				'Tag' => array(1, 2)
5525
			),
5526
			'Comment' => array(
5527
				array(
5528
					'comment' => 'Article comment',
5529
					'user_id' => 1
5530
		)));
5531
		$Article = new Article();
5532
		$result = $Article->saveAssociated($data);
5533
		$this->assertFalse(empty($result));
5534
 
5535
		$result = $Article->read();
5536
		$this->assertEquals(2, count($result['Tag']));
5537
		$this->assertEquals('tag1', $result['Tag'][0]['tag']);
5538
		$this->assertEquals(1, count($result['Comment']));
5539
		$this->assertEquals(1, count($result['Comment'][0]['comment']));
5540
	}
5541
 
5542
/**
5543
 * Test SaveAssociated with Habtm relations and extra join table fields
5544
 *
5545
 * @return void
5546
 */
5547
	public function testSaveAssociatedHabtmWithExtraJoinTableFields() {
5548
		$this->loadFixtures('Something', 'SomethingElse', 'JoinThing');
5549
 
5550
		$data = array(
5551
			'Something' => array(
5552
				'id' => 4,
5553
				'title' => 'Extra Fields',
5554
				'body' => 'Extra Fields Body',
5555
				'published' => '1'
5556
			),
5557
			'SomethingElse' => array(
5558
				array('something_else_id' => 1, 'doomed' => '1'),
5559
				array('something_else_id' => 2, 'doomed' => '0'),
5560
				array('something_else_id' => 3, 'doomed' => '1')
5561
			)
5562
		);
5563
 
5564
		$Something = new Something();
5565
		$result = $Something->saveAssociated($data);
5566
		$this->assertFalse(empty($result));
5567
		$result = $Something->read();
5568
 
5569
		$this->assertEquals(3, count($result['SomethingElse']));
5570
		$this->assertTrue(Set::matches('/Something[id=4]', $result));
5571
 
5572
		$this->assertTrue(Set::matches('/SomethingElse[id=1]', $result));
5573
		$this->assertTrue(Set::matches('/SomethingElse[id=1]/JoinThing[something_else_id=1]', $result));
5574
		$this->assertTrue(Set::matches('/SomethingElse[id=1]/JoinThing[doomed=1]', $result));
5575
 
5576
		$this->assertTrue(Set::matches('/SomethingElse[id=2]', $result));
5577
		$this->assertTrue(Set::matches('/SomethingElse[id=2]/JoinThing[something_else_id=2]', $result));
5578
		$this->assertTrue(Set::matches('/SomethingElse[id=2]/JoinThing[doomed=0]', $result));
5579
 
5580
		$this->assertTrue(Set::matches('/SomethingElse[id=3]', $result));
5581
		$this->assertTrue(Set::matches('/SomethingElse[id=3]/JoinThing[something_else_id=3]', $result));
5582
		$this->assertTrue(Set::matches('/SomethingElse[id=3]/JoinThing[doomed=1]', $result));
5583
	}
5584
 
5585
/**
5586
 * testSaveAssociatedHasOne method
5587
 *
5588
 * @return void
5589
 */
5590
	public function testSaveAssociatedHasOne() {
5591
		$model = new Comment();
5592
		$model->deleteAll(true);
5593
		$this->assertEquals(array(), $model->find('all'));
5594
 
5595
		$model->Attachment->deleteAll(true);
5596
		$this->assertEquals(array(), $model->Attachment->find('all'));
5597
 
5598
		$this->assertTrue($model->saveAssociated(array(
5599
			'Comment' => array(
5600
				'comment' => 'Comment with attachment',
5601
				'article_id' => 1,
5602
				'user_id' => 1
5603
			),
5604
			'Attachment' => array(
5605
				'attachment' => 'some_file.zip'
5606
		))));
5607
		$result = $model->find('all', array('fields' => array(
5608
			'Comment.id', 'Comment.comment', 'Attachment.id',
5609
			'Attachment.comment_id', 'Attachment.attachment'
5610
		)));
5611
		$expected = array(array(
5612
			'Comment' => array(
5613
				'id' => '1',
5614
				'comment' => 'Comment with attachment'
5615
			),
5616
			'Attachment' => array(
5617
				'id' => '1',
5618
				'comment_id' => '1',
5619
				'attachment' => 'some_file.zip'
5620
		)));
5621
		$this->assertEquals($expected, $result);
5622
 
5623
		$model->Attachment->bindModel(array('belongsTo' => array('Comment')), false);
5624
		$data = array(
5625
			'Comment' => array(
5626
				'comment' => 'Comment with attachment',
5627
				'article_id' => 1,
5628
				'user_id' => 1
5629
			),
5630
			'Attachment' => array(
5631
				'attachment' => 'some_file.zip'
5632
		));
5633
		$this->assertTrue($model->saveAssociated($data, array('validate' => 'first')));
5634
	}
5635
 
5636
/**
5637
 * testSaveAssociatedBelongsTo method
5638
 *
5639
 * @return void
5640
 */
5641
	public function testSaveAssociatedBelongsTo() {
5642
		$model = new Comment();
5643
		$model->deleteAll(true);
5644
		$this->assertEquals(array(), $model->find('all'));
5645
 
5646
		$model->Article->deleteAll(true);
5647
		$this->assertEquals(array(), $model->Article->find('all'));
5648
 
5649
		$this->assertTrue($model->saveAssociated(array(
5650
			'Comment' => array(
5651
				'comment' => 'Article comment',
5652
				'article_id' => 1,
5653
				'user_id' => 1
5654
			),
5655
			'Article' => array(
5656
				'title' => 'Model Associations 101',
5657
				'user_id' => 1
5658
		))));
5659
		$result = $model->find('all', array('fields' => array(
5660
			'Comment.id', 'Comment.comment', 'Comment.article_id', 'Article.id', 'Article.title'
5661
		)));
5662
		$expected = array(array(
5663
			'Comment' => array(
5664
				'id' => '1',
5665
				'article_id' => '1',
5666
				'comment' => 'Article comment'
5667
			),
5668
			'Article' => array(
5669
				'id' => '1',
5670
				'title' => 'Model Associations 101'
5671
		)));
5672
		$this->assertEquals($expected, $result);
5673
	}
5674
 
5675
/**
5676
 * testSaveAssociatedHasOneValidation method
5677
 *
5678
 * @return void
5679
 */
5680
	public function testSaveAssociatedHasOneValidation() {
5681
		$model = new Comment();
5682
		$model->deleteAll(true);
5683
		$this->assertEquals(array(), $model->find('all'));
5684
 
5685
		$model->Attachment->deleteAll(true);
5686
		$this->assertEquals(array(), $model->Attachment->find('all'));
5687
 
5688
		$model->validate = array('comment' => 'notBlank');
5689
		$model->Attachment->validate = array('attachment' => 'notBlank');
5690
		$model->Attachment->bindModel(array('belongsTo' => array('Comment')));
5691
 
5692
		$result = $model->saveAssociated(
5693
			array(
5694
				'Comment' => array(
5695
					'comment' => '',
5696
					'article_id' => 1,
5697
					'user_id' => 1
5698
				),
5699
				'Attachment' => array('attachment' => '')
5700
			)
5701
		);
5702
		$this->assertFalse($result);
5703
		$expected = array(
5704
			'comment' => array(
5705
				'This field cannot be left blank'
5706
			),
5707
			'Attachment' => array(
5708
				'attachment' => array(
5709
					'This field cannot be left blank'
5710
				)
5711
			)
5712
		);
5713
		$this->assertEquals($expected, $model->validationErrors);
5714
		$this->assertEquals($expected['Attachment'], $model->Attachment->validationErrors);
5715
	}
5716
 
5717
/**
5718
 * testSaveAssociatedAtomic method
5719
 *
5720
 * @return void
5721
 */
5722
	public function testSaveAssociatedAtomic() {
5723
		$this->loadFixtures('Article', 'User');
5724
		$TestModel = new Article();
5725
 
5726
		$result = $TestModel->saveAssociated(array(
5727
			'Article' => array(
5728
				'title' => 'Post with Author',
5729
				'body' => 'This post will be saved with an author',
5730
				'user_id' => 2
5731
			),
5732
			'Comment' => array(
5733
				array('comment' => 'First new comment', 'user_id' => 2))
5734
		), array('atomic' => false));
5735
 
5736
		$this->assertSame($result, array('Article' => true, 'Comment' => array(true)));
5737
 
5738
		$result = $TestModel->saveAssociated(array(
5739
			'Article' => array('id' => 2),
5740
			'Comment' => array(
5741
				array(
5742
					'comment' => 'First new comment',
5743
					'published' => 'Y',
5744
					'user_id' => 1
5745
				),
5746
				array(
5747
					'comment' => 'Second new comment',
5748
					'published' => 'Y',
5749
					'user_id' => 2
5750
			))
5751
		), array('validate' => true, 'atomic' => false));
5752
		$this->assertSame($result, array('Article' => true, 'Comment' => array(true, true)));
5753
	}
5754
 
5755
/**
5756
 * testSaveManyAtomic method
5757
 *
5758
 * @return void
5759
 */
5760
	public function testSaveManyAtomic() {
5761
		$this->loadFixtures('Article', 'User');
5762
		$TestModel = new Article();
5763
 
5764
		$result = $TestModel->saveMany(array(
5765
			array(
5766
				'id' => '1',
5767
				'title' => 'Baleeted First Post',
5768
				'body' => 'Baleeted!',
5769
				'published' => 'N'
5770
			),
5771
			array(
5772
				'id' => '2',
5773
				'title' => 'Just update the title'
5774
			),
5775
			array(
5776
				'title' => 'Creating a fourth post',
5777
				'body' => 'Fourth post body',
5778
				'user_id' => 2
5779
			)
5780
		), array('atomic' => false));
5781
		$this->assertSame($result, array(true, true, true));
5782
 
5783
		$TestModel->validate = array('title' => 'notBlank', 'author_id' => 'numeric');
5784
		$result = $TestModel->saveMany(array(
5785
			array(
5786
				'id' => '1',
5787
				'title' => 'Un-Baleeted First Post',
5788
				'body' => 'Not Baleeted!',
5789
				'published' => 'Y'
5790
			),
5791
			array(
5792
				'id' => '2',
5793
				'title' => '',
5794
				'body' => 'Trying to get away with an empty title'
5795
			)
5796
		), array('validate' => true, 'atomic' => false));
5797
 
5798
		$this->assertSame(array(true, false), $result);
5799
	}
5800
 
5801
/**
5802
 * testSaveAssociatedHasMany method
5803
 *
5804
 * @return void
5805
 */
5806
	public function testSaveAssociatedHasMany() {
5807
		$this->loadFixtures('Article', 'Comment');
5808
		$TestModel = new Article();
5809
		$TestModel->belongsTo = $TestModel->hasAndBelongsToMany = array();
5810
 
5811
		$result = $TestModel->saveAssociated(array(
5812
			'Article' => array('id' => 2),
5813
			'Comment' => array(
5814
				array('comment' => 'First new comment', 'published' => 'Y', 'user_id' => 1),
5815
				array('comment' => 'Second new comment', 'published' => 'Y', 'user_id' => 2)
5816
			)
5817
		));
5818
		$this->assertFalse(empty($result));
5819
 
5820
		$result = $TestModel->findById(2);
5821
		$expected = array(
5822
			'First Comment for Second Article',
5823
			'Second Comment for Second Article',
5824
			'First new comment',
5825
			'Second new comment'
5826
		);
5827
		$this->assertEquals($expected, Hash::extract($result['Comment'], '{n}.comment'));
5828
 
5829
		$result = $TestModel->saveAssociated(
5830
			array(
5831
				'Article' => array('id' => 2),
5832
				'Comment' => array(
5833
					array(
5834
						'comment' => 'Third new comment',
5835
						'published' => 'Y',
5836
						'user_id' => 1
5837
			))),
5838
			array('atomic' => false)
5839
		);
5840
		$this->assertFalse(empty($result));
5841
 
5842
		$result = $TestModel->findById(2);
5843
		$expected = array(
5844
			'First Comment for Second Article',
5845
			'Second Comment for Second Article',
5846
			'First new comment',
5847
			'Second new comment',
5848
			'Third new comment'
5849
		);
5850
		$this->assertEquals($expected, Hash::extract($result['Comment'], '{n}.comment'));
5851
 
5852
		$TestModel->beforeSaveReturn = false;
5853
		$result = $TestModel->saveAssociated(
5854
			array(
5855
				'Article' => array('id' => 2),
5856
				'Comment' => array(
5857
					array(
5858
						'comment' => 'Fourth new comment',
5859
						'published' => 'Y',
5860
						'user_id' => 1
5861
			))),
5862
			array('atomic' => false)
5863
		);
5864
		$this->assertEquals(array('Article' => false), $result);
5865
 
5866
		$result = $TestModel->findById(2);
5867
		$expected = array(
5868
			'First Comment for Second Article',
5869
			'Second Comment for Second Article',
5870
			'First new comment',
5871
			'Second new comment',
5872
			'Third new comment'
5873
		);
5874
		$this->assertEquals($expected, Hash::extract($result['Comment'], '{n}.comment'));
5875
	}
5876
 
5877
/**
5878
 * testSaveAssociatedHasManyEmpty method
5879
 *
5880
 * @return void
5881
 */
5882
	public function testSaveAssociatedHasManyEmpty() {
5883
		$this->loadFixtures('Article', 'Comment');
5884
		$TestModel = new Article();
5885
		$TestModel->belongsTo = $TestModel->hasAndBelongsToMany = array();
5886
		$TestModel->validate = $TestModel->Comment->validate = array('user_id' => array('notBlank' => array('rule' => 'notBlank', 'required' => true)));
5887
 
5888
		//empty hasMany data is ignored in save
5889
		$result = $TestModel->saveAssociated(array(
5890
			'Article' => array('title' => 'title', 'user_id' => 1),
5891
			'Comment' => array()
5892
		), array('validate' => true));
5893
		$this->assertTrue($result);
5894
 
5895
		$result = $TestModel->saveAssociated(array(
5896
			'Article' => array('title' => 'title', 'user_id' => 1),
5897
			'Comment' => array()
5898
		), array('validate' => true, 'atomic' => false));
5899
		$this->assertEquals(array('Article' => true), $result);
5900
 
5901
		//empty primary data is not ignored
5902
		$result = $TestModel->saveAssociated(array('Article' => array()), array('validate' => true));
5903
		$this->assertFalse($result);
5904
 
5905
		$result = $TestModel->saveAssociated(array('Article' => array()), array('validate' => true, 'atomic' => false));
5906
		$this->assertEquals(array('Article' => false), $result);
5907
	}
5908
 
5909
/**
5910
 * testSaveAssociatedHasManyValidation method
5911
 *
5912
 * @return void
5913
 */
5914
	public function testSaveAssociatedHasManyValidation() {
5915
		$this->loadFixtures('Article', 'Comment');
5916
		$TestModel = new Article();
5917
		$TestModel->belongsTo = $TestModel->hasAndBelongsToMany = array();
5918
		$TestModel->Comment->validate = array('comment' => 'notBlank');
5919
 
5920
		$result = $TestModel->saveAssociated(array(
5921
			'Article' => array('id' => 2),
5922
			'Comment' => array(
5923
				array('comment' => '', 'published' => 'Y', 'user_id' => 1),
5924
			)
5925
		), array('validate' => true));
5926
		$this->assertFalse($result);
5927
 
5928
		$expected = array('Comment' => array(
5929
			array('comment' => array('This field cannot be left blank'))
5930
		));
5931
		$this->assertEquals($expected, $TestModel->validationErrors);
5932
		$expected = array(
5933
			array('comment' => array('This field cannot be left blank'))
5934
		);
5935
		$this->assertEquals($expected, $TestModel->Comment->validationErrors);
5936
 
5937
		$result = $TestModel->saveAssociated(array(
5938
			'Article' => array('id' => 2),
5939
			'Comment' => array(
5940
				array(
5941
					'comment' => '',
5942
					'published' => 'Y',
5943
					'user_id' => 1
5944
			))
5945
		), array('validate' => 'first'));
5946
		$this->assertFalse($result);
5947
	}
5948
 
5949
/**
5950
 * test saveMany with transactions and ensure there is no missing rollback.
5951
 *
5952
 * @return void
5953
 */
5954
	public function testSaveManyTransactionNoRollback() {
5955
		$this->loadFixtures('Post');
5956
 
5957
		$Post = new TestPost();
5958
		$Post->validate = array(
5959
			'title' => array('rule' => array('notBlank'))
5960
		);
5961
 
5962
		// If validation error occurs, rollback() should be called.
5963
		$db = $this->_getMockDboSource(array('begin', 'commit', 'rollback'));
5964
		$db->expects($this->once())->method('begin')->will($this->returnValue(true));
5965
		$db->expects($this->never())->method('commit');
5966
		$db->expects($this->once())->method('rollback');
5967
 
5968
		$Post->setDataSourceObject($db);
5969
 
5970
		$data = array(
5971
			array('author_id' => 1, 'title' => 'New Fourth Post'),
5972
			array('author_id' => 1, 'title' => '')
5973
		);
5974
		$Post->saveMany($data, array('validate' => true));
5975
 
5976
		// If exception thrown, rollback() should be called too.
5977
		$db = $this->_getMockDboSource(array('begin', 'commit', 'rollback'));
5978
		$db->expects($this->once())->method('begin')->will($this->returnValue(true));
5979
		$db->expects($this->never())->method('commit');
5980
		$db->expects($this->once())->method('rollback');
5981
 
5982
		$Post->setDataSourceObject($db);
5983
 
5984
		$data = array(
5985
			array('author_id' => 1, 'title' => 'New Fourth Post'),
5986
			array('author_id' => 1, 'title' => 'New Fifth Post', 'body' => $db->expression('PDO_EXCEPTION()'))
5987
		);
5988
 
5989
		try {
5990
			$Post->saveMany($data, array('validate' => true));
5991
			$this->fail('No exception thrown');
5992
		} catch (PDOException $e) {
5993
		}
5994
 
5995
		// Otherwise, commit() should be called.
5996
		$db = $this->_getMockDboSource(array('begin', 'commit', 'rollback'));
5997
		$db->expects($this->once())->method('begin')->will($this->returnValue(true));
5998
		$db->expects($this->once())->method('commit');
5999
		$db->expects($this->never())->method('rollback');
6000
 
6001
		$Post->setDataSourceObject($db);
6002
 
6003
		$data = array(
6004
			array('author_id' => 1, 'title' => 'New Fourth Post'),
6005
			array('author_id' => 1, 'title' => 'New Fifth Post')
6006
		);
6007
		$Post->saveMany($data, array('validate' => true));
6008
	}
6009
 
6010
/**
6011
 * test saveAssociated with transactions and ensure there is no missing rollback.
6012
 *
6013
 * @return void
6014
 */
6015
	public function testSaveAssociatedTransactionNoRollback() {
6016
		$this->loadFixtures('Post', 'Author');
6017
 
6018
		$Post = new TestPost();
6019
		$Post->Author->validate = array(
6020
			'user' => array('rule' => array('notBlank'))
6021
		);
6022
 
6023
		// If validation error occurs, rollback() should be called.
6024
		$db = $this->_getMockDboSource(array('begin', 'commit', 'rollback'));
6025
		$db->expects($this->once())->method('begin')->will($this->returnValue(true));
6026
		$db->expects($this->never())->method('commit');
6027
		$db->expects($this->once())->method('rollback');
6028
 
6029
		$Post->setDataSourceObject($db);
6030
		$Post->Author->setDataSourceObject($db);
6031
 
6032
		$data = array(
6033
			'Post' => array(
6034
				'title' => 'New post',
6035
				'body' => 'Content',
6036
				'published' => 'Y'
6037
			),
6038
			'Author' => array(
6039
				'user' => '',
6040
				'password' => "sekret"
6041
			)
6042
		);
6043
		$Post->saveAssociated($data, array('validate' => true, 'atomic' => true));
6044
 
6045
		// If exception thrown, commit() should be called.
6046
		$db = $this->_getMockDboSource(array('begin', 'commit', 'rollback'));
6047
		$db->expects($this->once())->method('begin')->will($this->returnValue(true));
6048
		$db->expects($this->never())->method('commit');
6049
		$db->expects($this->once())->method('rollback');
6050
 
6051
		$Post->setDataSourceObject($db);
6052
		$Post->Author->setDataSourceObject($db);
6053
 
6054
		$data = array(
6055
			'Post' => array(
6056
				'title' => 'New post',
6057
				'body' => $db->expression('PDO_EXCEPTION()'),
6058
				'published' => 'Y'
6059
			),
6060
			'Author' => array(
6061
				'user' => 'New user',
6062
				'password' => "sekret"
6063
			)
6064
		);
6065
 
6066
		try {
6067
			$Post->saveAssociated($data, array('validate' => true, 'atomic' => true));
6068
			$this->fail('No exception thrown');
6069
		} catch (PDOException $e) {
6070
		}
6071
 
6072
		// Otherwise, commit() should be called.
6073
		$db = $this->_getMockDboSource(array('begin', 'commit', 'rollback'));
6074
		$db->expects($this->once())->method('begin')->will($this->returnValue(true));
6075
		$db->expects($this->once())->method('commit');
6076
		$db->expects($this->never())->method('rollback');
6077
 
6078
		$Post->setDataSourceObject($db);
6079
		$Post->Author->setDataSourceObject($db);
6080
 
6081
		$data = array(
6082
			'Post' => array(
6083
				'title' => 'New post',
6084
				'body' => 'Content',
6085
				'published' => 'Y'
6086
			),
6087
			'Author' => array(
6088
				'user' => 'New user',
6089
				'password' => "sekret"
6090
			)
6091
		);
6092
		$Post->saveAssociated($data, array('validate' => true, 'atomic' => true));
6093
	}
6094
 
6095
/**
6096
 * test saveMany with nested saveMany call.
6097
 *
6098
 * @return void
6099
 */
6100
	public function testSaveManyNestedSaveMany() {
6101
		$this->loadFixtures('Sample');
6102
		$TransactionManyTestModel = new TransactionManyTestModel();
6103
 
6104
		$data = array(
6105
			array('apple_id' => 1, 'name' => 'sample5'),
6106
		);
6107
 
6108
		$this->assertTrue($TransactionManyTestModel->saveMany($data, array('atomic' => true)));
6109
	}
6110
 
6111
/**
6112
 * testSaveManyTransaction method
6113
 *
6114
 * @return void
6115
 */
6116
	public function testSaveManyTransaction() {
6117
		$this->loadFixtures('Post', 'Author', 'Comment', 'Attachment');
6118
		$TestModel = new Post();
6119
 
6120
		$TestModel->validate = array('title' => 'notBlank');
6121
		$data = array(
6122
			array('author_id' => 1, 'title' => 'New Fourth Post'),
6123
			array('author_id' => 1, 'title' => 'New Fifth Post'),
6124
			array('author_id' => 1, 'title' => '')
6125
		);
6126
		$this->assertFalse($TestModel->saveMany($data));
6127
 
6128
		$result = $TestModel->find('all', array('recursive' => -1));
6129
		$expected = array(
6130
			array('Post' => array(
6131
				'id' => '1',
6132
				'author_id' => 1,
6133
				'title' => 'First Post',
6134
				'body' => 'First Post Body',
6135
				'published' => 'Y',
6136
				'created' => '2007-03-18 10:39:23',
6137
				'updated' => '2007-03-18 10:41:31'
6138
			)),
6139
			array('Post' => array(
6140
				'id' => '2',
6141
				'author_id' => 3,
6142
				'title' => 'Second Post',
6143
				'body' => 'Second Post Body',
6144
				'published' => 'Y',
6145
				'created' => '2007-03-18 10:41:23',
6146
				'updated' => '2007-03-18 10:43:31'
6147
			)),
6148
			array('Post' => array(
6149
				'id' => '3',
6150
				'author_id' => 1,
6151
				'title' => 'Third Post',
6152
				'body' => 'Third Post Body',
6153
				'published' => 'Y',
6154
				'created' => '2007-03-18 10:43:23',
6155
				'updated' => '2007-03-18 10:45:31'
6156
		)));
6157
 
6158
		if (count($result) != 3) {
6159
			// Database doesn't support transactions
6160
			$expected[] = array(
6161
				'Post' => array(
6162
					'id' => '4',
6163
					'author_id' => 1,
6164
					'title' => 'New Fourth Post',
6165
					'body' => null,
6166
					'published' => 'N'
6167
			));
6168
 
6169
			$expected[] = array(
6170
				'Post' => array(
6171
					'id' => '5',
6172
					'author_id' => 1,
6173
					'title' => 'New Fifth Post',
6174
					'body' => null,
6175
					'published' => 'N',
6176
			));
6177
 
6178
			$this->assertEquals(static::date(), $result[3]['Post']['created']);
6179
			$this->assertEquals(static::date(), $result[3]['Post']['updated']);
6180
			$this->assertEquals(static::date(), $result[4]['Post']['created']);
6181
			$this->assertEquals(static::date(), $result[4]['Post']['updated']);
6182
			unset($result[3]['Post']['created'], $result[3]['Post']['updated']);
6183
			unset($result[4]['Post']['created'], $result[4]['Post']['updated']);
6184
			$this->assertEquals($expected, $result);
6185
			// Skip the rest of the transactional tests
6186
			return;
6187
		}
6188
 
6189
		$this->assertEquals($expected, $result);
6190
 
6191
		$data = array(
6192
			array('author_id' => 1, 'title' => 'New Fourth Post'),
6193
			array('author_id' => 1, 'title' => ''),
6194
			array('author_id' => 1, 'title' => 'New Sixth Post')
6195
		);
6196
		$this->assertFalse($TestModel->saveMany($data));
6197
 
6198
		$result = $TestModel->find('all', array('recursive' => -1));
6199
		$expected = array(
6200
			array('Post' => array(
6201
				'id' => '1',
6202
				'author_id' => 1,
6203
				'title' => 'First Post',
6204
				'body' => 'First Post Body',
6205
				'published' => 'Y',
6206
				'created' => '2007-03-18 10:39:23',
6207
				'updated' => '2007-03-18 10:41:31'
6208
			)),
6209
			array('Post' => array(
6210
				'id' => '2',
6211
				'author_id' => 3,
6212
				'title' => 'Second Post',
6213
				'body' => 'Second Post Body',
6214
				'published' => 'Y',
6215
				'created' => '2007-03-18 10:41:23',
6216
				'updated' => '2007-03-18 10:43:31'
6217
			)),
6218
			array('Post' => array(
6219
				'id' => '3',
6220
				'author_id' => 1,
6221
				'title' => 'Third Post',
6222
				'body' => 'Third Post Body',
6223
				'published' => 'Y',
6224
				'created' => '2007-03-18 10:43:23',
6225
				'updated' => '2007-03-18 10:45:31'
6226
		)));
6227
 
6228
		if (count($result) != 3) {
6229
			// Database doesn't support transactions
6230
			$expected[] = array(
6231
				'Post' => array(
6232
					'id' => '4',
6233
					'author_id' => 1,
6234
					'title' => 'New Fourth Post',
6235
					'body' => 'Third Post Body',
6236
					'published' => 'N'
6237
			));
6238
 
6239
			$expected[] = array(
6240
				'Post' => array(
6241
					'id' => '5',
6242
					'author_id' => 1,
6243
					'title' => 'Third Post',
6244
					'body' => 'Third Post Body',
6245
					'published' => 'N'
6246
			));
6247
			$this->assertEquals(static::date(), $result[3]['Post']['created']);
6248
			$this->assertEquals(static::date(), $result[3]['Post']['updated']);
6249
			$this->assertEquals(static::date(), $result[4]['Post']['created']);
6250
			$this->assertEquals(static::date(), $result[4]['Post']['updated']);
6251
			unset($result[3]['Post']['created'], $result[3]['Post']['updated']);
6252
			unset($result[4]['Post']['created'], $result[4]['Post']['updated']);
6253
		}
6254
		$this->assertEquals($expected, $result);
6255
 
6256
		$TestModel->validate = array('title' => 'notBlank');
6257
		$data = array(
6258
			array('author_id' => 1, 'title' => 'New Fourth Post'),
6259
			array('author_id' => 1, 'title' => 'New Fifth Post'),
6260
			array('author_id' => 1, 'title' => 'New Sixth Post')
6261
		);
6262
		$this->assertTrue($TestModel->saveMany($data));
6263
 
6264
		$result = $TestModel->find('all', array(
6265
			'recursive' => -1,
6266
			'fields' => array('author_id', 'title', 'body', 'published'),
6267
			'order' => array('Post.created' => 'ASC')
6268
		));
6269
 
6270
		$expected = array(
6271
			array('Post' => array(
6272
				'author_id' => 1,
6273
				'title' => 'First Post',
6274
				'body' => 'First Post Body',
6275
				'published' => 'Y'
6276
			)),
6277
			array('Post' => array(
6278
				'author_id' => 3,
6279
				'title' => 'Second Post',
6280
				'body' => 'Second Post Body',
6281
				'published' => 'Y'
6282
			)),
6283
			array('Post' => array(
6284
				'author_id' => 1,
6285
				'title' => 'Third Post',
6286
				'body' => 'Third Post Body',
6287
				'published' => 'Y'
6288
			)),
6289
			array('Post' => array(
6290
				'author_id' => 1,
6291
				'title' => 'New Fourth Post',
6292
				'body' => '',
6293
				'published' => 'N'
6294
			)),
6295
			array('Post' => array(
6296
				'author_id' => 1,
6297
				'title' => 'New Fifth Post',
6298
				'body' => '',
6299
				'published' => 'N'
6300
			)),
6301
			array('Post' => array(
6302
				'author_id' => 1,
6303
				'title' => 'New Sixth Post',
6304
				'body' => '',
6305
				'published' => 'N'
6306
		)));
6307
		$this->assertEquals($expected, $result);
6308
	}
6309
 
6310
/**
6311
 * testSaveManyValidation method
6312
 *
6313
 * @return void
6314
 */
6315
	public function testSaveManyValidation() {
6316
		$this->loadFixtures('Post', 'Author', 'Comment', 'Attachment');
6317
		$TestModel = new Post();
6318
 
6319
		$data = array(
6320
			array(
6321
				'id' => '1',
6322
				'title' => 'Baleeted First Post',
6323
				'body' => 'Baleeted!',
6324
				'published' => 'N'
6325
			),
6326
			array(
6327
				'id' => '2',
6328
				'title' => 'Just update the title'
6329
			),
6330
			array(
6331
				'title' => 'Creating a fourth post',
6332
				'body' => 'Fourth post body',
6333
				'author_id' => 2
6334
		));
6335
 
6336
		$this->assertTrue($TestModel->saveMany($data));
6337
 
6338
		$result = $TestModel->find('all', array('recursive' => -1, 'order' => 'Post.id ASC'));
6339
		$expected = array(
6340
			array(
6341
				'Post' => array(
6342
					'id' => '1',
6343
					'author_id' => '1',
6344
					'title' => 'Baleeted First Post',
6345
					'body' => 'Baleeted!',
6346
					'published' => 'N',
6347
					'created' => '2007-03-18 10:39:23'
6348
				)
6349
			),
6350
			array(
6351
				'Post' => array(
6352
					'id' => '2',
6353
					'author_id' => '3',
6354
					'title' => 'Just update the title',
6355
					'body' => 'Second Post Body',
6356
					'published' => 'Y',
6357
					'created' => '2007-03-18 10:41:23'
6358
				)
6359
			),
6360
			array(
6361
				'Post' => array(
6362
					'id' => '3',
6363
					'author_id' => '1',
6364
					'title' => 'Third Post',
6365
					'body' => 'Third Post Body',
6366
					'published' => 'Y',
6367
					'created' => '2007-03-18 10:43:23',
6368
					'updated' => '2007-03-18 10:45:31'
6369
			)),
6370
			array(
6371
				'Post' => array(
6372
					'id' => '4',
6373
					'author_id' => '2',
6374
					'title' => 'Creating a fourth post',
6375
					'body' => 'Fourth post body',
6376
					'published' => 'N'
6377
				)
6378
			)
6379
		);
6380
 
6381
		$this->assertEquals(static::date(), $result[0]['Post']['updated']);
6382
		$this->assertEquals(static::date(), $result[1]['Post']['updated']);
6383
		$this->assertEquals(static::date(), $result[3]['Post']['created']);
6384
		$this->assertEquals(static::date(), $result[3]['Post']['updated']);
6385
		unset($result[0]['Post']['updated'], $result[1]['Post']['updated']);
6386
		unset($result[3]['Post']['created'], $result[3]['Post']['updated']);
6387
		$this->assertEquals($expected, $result);
6388
 
6389
		$TestModel->validate = array('title' => 'notBlank', 'author_id' => 'numeric');
6390
		$data = array(
6391
			array(
6392
				'id' => '1',
6393
				'title' => 'Un-Baleeted First Post',
6394
				'body' => 'Not Baleeted!',
6395
				'published' => 'Y'
6396
			),
6397
			array(
6398
				'id' => '2',
6399
				'title' => '',
6400
				'body' => 'Trying to get away with an empty title'
6401
		));
6402
		$result = $TestModel->saveMany($data);
6403
		$this->assertFalse($result);
6404
 
6405
		$result = $TestModel->find('all', array('recursive' => -1, 'order' => 'Post.id ASC'));
6406
		$errors = array(1 => array('title' => array('This field cannot be left blank')));
6407
		$transactionWorked = Set::matches('/Post[1][title=Baleeted First Post]', $result);
6408
		if (!$transactionWorked) {
6409
			$this->assertTrue(Set::matches('/Post[1][title=Un-Baleeted First Post]', $result));
6410
			$this->assertTrue(Set::matches('/Post[2][title=Just update the title]', $result));
6411
		}
6412
 
6413
		$this->assertEquals($errors, $TestModel->validationErrors);
6414
 
6415
		$TestModel->validate = array('title' => 'notBlank', 'author_id' => 'numeric');
6416
		$data = array(
6417
			array(
6418
				'id' => '1',
6419
				'title' => 'Un-Baleeted First Post',
6420
				'body' => 'Not Baleeted!',
6421
				'published' => 'Y'
6422
			),
6423
			array(
6424
				'id' => '2',
6425
				'title' => '',
6426
				'body' => 'Trying to get away with an empty title'
6427
		));
6428
		$result = $TestModel->saveMany($data, array('validate' => true, 'atomic' => false));
6429
		$this->assertEquals(array(true, false), $result);
6430
 
6431
		$result = $TestModel->find('all', array(
6432
			'fields' => array('id', 'author_id', 'title', 'body', 'published'),
6433
			'recursive' => -1,
6434
			'order' => 'Post.id ASC'
6435
		));
6436
		$errors = array(1 => array('title' => array('This field cannot be left blank')));
6437
		$expected = array(
6438
			array(
6439
				'Post' => array(
6440
					'id' => '1',
6441
					'author_id' => '1',
6442
					'title' => 'Un-Baleeted First Post',
6443
					'body' => 'Not Baleeted!',
6444
					'published' => 'Y',
6445
			)),
6446
			array(
6447
				'Post' => array(
6448
					'id' => '2',
6449
					'author_id' => '3',
6450
					'title' => 'Just update the title',
6451
					'body' => 'Second Post Body',
6452
					'published' => 'Y',
6453
			)),
6454
			array(
6455
				'Post' => array(
6456
					'id' => '3',
6457
					'author_id' => '1',
6458
					'title' => 'Third Post',
6459
					'body' => 'Third Post Body',
6460
					'published' => 'Y',
6461
			)),
6462
			array(
6463
				'Post' => array(
6464
					'id' => '4',
6465
					'author_id' => '2',
6466
					'title' => 'Creating a fourth post',
6467
					'body' => 'Fourth post body',
6468
					'published' => 'N',
6469
		)));
6470
		$this->assertEquals($expected, $result);
6471
		$this->assertEquals($errors, $TestModel->validationErrors);
6472
 
6473
		$data = array(
6474
			array(
6475
				'id' => '1',
6476
				'title' => 'Re-Baleeted First Post',
6477
				'body' => 'Baleeted!',
6478
				'published' => 'N'
6479
			),
6480
			array(
6481
				'id' => '2',
6482
				'title' => '',
6483
				'body' => 'Trying to get away with an empty title'
6484
		));
6485
		$this->assertFalse($TestModel->saveMany($data, array('validate' => 'first')));
6486
 
6487
		$result = $TestModel->find('all', array(
6488
			'fields' => array('id', 'author_id', 'title', 'body', 'published'),
6489
			'recursive' => -1,
6490
			'order' => 'Post.id ASC'
6491
		));
6492
		$this->assertEquals($expected, $result);
6493
		$this->assertEquals($errors, $TestModel->validationErrors);
6494
	}
6495
 
6496
/**
6497
 * testValidateMany method
6498
 *
6499
 * @return void
6500
 */
6501
	public function testValidateMany() {
6502
		$TestModel = new Article();
6503
		$TestModel->validate = array('title' => 'notBlank');
6504
		$data = array(
6505
 
6506
				1 => array('title' => 'title 1'),
6507
				2 => array('title' => 'title 2'),
6508
		);
6509
		$result = $TestModel->validateMany($data);
6510
		$this->assertFalse($result);
6511
		$expected = array(
6512
 
6513
		);
6514
		$this->assertEquals($expected, $TestModel->validationErrors);
6515
 
6516
		$data = array(
6517
 
6518
				1 => array('title' => ''),
6519
				2 => array('title' => 'title 2'),
6520
		);
6521
		$result = $TestModel->validateMany($data);
6522
		$this->assertFalse($result);
6523
		$expected = array(
6524
			1 => array('title' => array('This field cannot be left blank')),
6525
		);
6526
		$this->assertEquals($expected, $TestModel->validationErrors);
6527
	}
6528
 
6529
/**
6530
 * testSaveAssociatedValidateFirst method
6531
 *
6532
 * @return void
6533
 */
6534
	public function testSaveAssociatedValidateFirst() {
6535
		$this->loadFixtures('Article', 'Comment', 'Attachment');
6536
		$model = new Article();
6537
		$model->deleteAll(true);
6538
 
6539
		$model->Comment->validate = array('comment' => 'notBlank');
6540
		$result = $model->saveAssociated(array(
6541
			'Article' => array(
6542
				'title' => 'Post with Author',
6543
				'body' => 'This post will be saved author'
6544
			),
6545
			'Comment' => array(
6546
				array('comment' => 'First new comment'),
6547
				array('comment' => '')
6548
			)
6549
		), array('validate' => 'first'));
6550
 
6551
		$this->assertFalse($result);
6552
 
6553
		$result = $model->find('all');
6554
		$this->assertSame(array(), $result);
6555
		$expected = array('Comment' => array(
6556
			1 => array('comment' => array('This field cannot be left blank'))
6557
		));
6558
 
6559
		$this->assertEquals($expected['Comment'], $model->Comment->validationErrors);
6560
 
6561
		$this->assertSame($model->Comment->find('count'), 0);
6562
 
6563
		$result = $model->saveAssociated(
6564
			array(
6565
				'Article' => array(
6566
					'title' => 'Post with Author',
6567
					'body' => 'This post will be saved with an author',
6568
					'user_id' => 2
6569
				),
6570
				'Comment' => array(
6571
					array(
6572
						'comment' => 'Only new comment',
6573
						'user_id' => 2
6574
			))),
6575
			array('validate' => 'first')
6576
		);
6577
 
6578
		$this->assertTrue($result);
6579
 
6580
		$result = $model->Comment->find('all');
6581
		$this->assertSame(count($result), 1);
6582
		$result = Hash::extract($result, '{n}.Comment.article_id');
6583
		$this->assertEquals(4, $result[0]);
6584
 
6585
		$model->deleteAll(true);
6586
		$data = array(
6587
			'Article' => array(
6588
				'title' => 'Post with Author saveAlled from comment',
6589
				'body' => 'This post will be saved with an author',
6590
				'user_id' => 2
6591
			),
6592
			'Comment' => array(
6593
				'comment' => 'Only new comment', 'user_id' => 2
6594
		));
6595
 
6596
		$result = $model->Comment->saveAssociated($data, array('validate' => 'first'));
6597
		$this->assertFalse(empty($result));
6598
 
6599
		$result = $model->find('all');
6600
		$this->assertEquals(
6601
			'Post with Author saveAlled from comment',
6602
			$result[0]['Article']['title']
6603
		);
6604
		$this->assertEquals('Only new comment', $result[0]['Comment'][0]['comment']);
6605
	}
6606
 
6607
/**
6608
 * test saveMany()'s return is correct when using atomic = false and validate = first.
6609
 *
6610
 * @return void
6611
 */
6612
	public function testSaveManyValidateFirstAtomicFalse() {
6613
		$Something = new Something();
6614
		$invalidData = array(
6615
			array(
6616
				'title' => 'foo',
6617
				'body' => 'bar',
6618
				'published' => 'baz',
6619
			),
6620
			array(
6621
				'body' => 3,
6622
				'published' => 'sd',
6623
			),
6624
		);
6625
		$Something->create();
6626
		$Something->validate = array(
6627
			'title' => array(
6628
				'rule' => 'alphaNumeric',
6629
				'required' => true,
6630
			),
6631
			'body' => array(
6632
				'rule' => 'alphaNumeric',
6633
				'required' => true,
6634
				'allowEmpty' => true,
6635
			),
6636
		);
6637
		$result = $Something->saveMany($invalidData, array(
6638
			'atomic' => false,
6639
			'validate' => 'first',
6640
		));
6641
		$expected = array(true, false);
6642
		$this->assertEquals($expected, $result);
6643
 
6644
		$Something = new Something();
6645
		$validData = array(
6646
			array(
6647
				'title' => 'title value',
6648
				'body' => 'body value',
6649
				'published' => 'baz',
6650
			),
6651
			array(
6652
				'title' => 'valid',
6653
				'body' => 'this body',
6654
				'published' => 'sd',
6655
			),
6656
		);
6657
		$Something->create();
6658
		$result = $Something->saveMany($validData, array(
6659
			'atomic' => false,
6660
			'validate' => 'first',
6661
		));
6662
		$expected = array(true, true);
6663
		$this->assertEquals($expected, $result);
6664
	}
6665
 
6666
/**
6667
 * testValidateAssociated method
6668
 *
6669
 * @return void
6670
 */
6671
	public function testValidateAssociated() {
6672
		$this->loadFixtures('Attachment', 'Article', 'Comment');
6673
		$TestModel = new Comment();
6674
		$TestModel->Attachment->validate = array('attachment' => 'notBlank');
6675
 
6676
		$data = array(
6677
			'Comment' => array(
6678
				'comment' => 'This is the comment'
6679
			),
6680
			'Attachment' => array(
6681
				'attachment' => ''
6682
			)
6683
		);
6684
 
6685
		$result = $TestModel->validateAssociated($data);
6686
		$this->assertFalse($result);
6687
 
6688
		$TestModel = new Article();
6689
		$TestModel->belongsTo = $TestModel->hasAndBelongsToMany = array();
6690
		$TestModel->Comment->validate = array('comment' => 'notBlank');
6691
 
6692
		$data = array(
6693
			'Article' => array('id' => 2),
6694
			'Comment' => array(
6695
				array(
6696
					'id' => 1,
6697
					'comment' => '',
6698
					'published' => 'Y',
6699
					'user_id' => 1),
6700
				array(
6701
					'id' => 2,
6702
					'comment' =>
6703
					'comment',
6704
					'published' => 'Y',
6705
					'user_id' => 1
6706
		)));
6707
		$result = $TestModel->validateAssociated($data);
6708
		$this->assertFalse($result);
6709
 
6710
		$data = array(
6711
			'Article' => array('id' => 2),
6712
			'Comment' => array(
6713
				array(
6714
					'id' => 1,
6715
					'comment' => '',
6716
					'published' => 'Y',
6717
					'user_id' => 1
6718
				),
6719
				array(
6720
					'id' => 2,
6721
					'comment' => 'comment',
6722
					'published' => 'Y',
6723
					'user_id' => 1
6724
				),
6725
				array(
6726
					'id' => 3,
6727
					'comment' => '',
6728
					'published' => 'Y',
6729
					'user_id' => 1
6730
		)));
6731
		$result = $TestModel->validateAssociated($data, array(
6732
				'atomic' => false
6733
		));
6734
		$expected = array(
6735
			'Article' => true,
6736
			'Comment' => array(false, true, false)
6737
		);
6738
		$this->assertSame($expected, $result);
6739
 
6740
		$expected = array('Comment' => array(
6741
 
6742
			2 => array('comment' => array('This field cannot be left blank'))
6743
		));
6744
		$this->assertEquals($expected, $TestModel->validationErrors);
6745
 
6746
		$expected = array(
6747
 
6748
			2 => array('comment' => array('This field cannot be left blank'))
6749
		);
6750
		$this->assertEquals($expected, $TestModel->Comment->validationErrors);
6751
	}
6752
 
6753
/**
6754
 * test that saveMany behaves like plain save() when suplied empty data
6755
 *
6756
 * @link https://cakephp.lighthouseapp.com/projects/42648/tickets/277-test-saveall-with-validation-returns-incorrect-boolean-when-saving-empty-data
6757
 * @return void
6758
 */
6759
	public function testSaveManyEmptyData() {
6760
		$this->skipIf($this->db instanceof Sqlserver, 'This test is not compatible with SQL Server.');
6761
 
6762
		$this->loadFixtures('Article', 'ProductUpdateAll', 'Comment', 'Attachment');
6763
		$model = new Article();
6764
		$result = $model->saveMany(array(), array('validate' => true));
6765
		$this->assertFalse(empty($result));
6766
 
6767
		$model = new ProductUpdateAll();
6768
		$result = $model->saveMany(array());
6769
		$this->assertFalse($result);
6770
	}
6771
 
6772
/**
6773
 * test that saveAssociated behaves like plain save() when supplied empty data
6774
 *
6775
 * @link https://cakephp.lighthouseapp.com/projects/42648/tickets/277-test-saveall-with-validation-returns-incorrect-boolean-when-saving-empty-data
6776
 * @return void
6777
 */
6778
	public function testSaveAssociatedEmptyData() {
6779
		$this->skipIf($this->db instanceof Sqlserver, 'This test is not compatible with SQL Server.');
6780
 
6781
		$this->loadFixtures('Article', 'ProductUpdateAll', 'Comment', 'Attachment');
6782
		$model = new Article();
6783
		$result = $model->saveAssociated(array(), array('validate' => true));
6784
		$this->assertFalse(empty($result));
6785
 
6786
		$model = new ProductUpdateAll();
6787
		$result = $model->saveAssociated(array());
6788
		$this->assertFalse($result);
6789
	}
6790
 
6791
/**
6792
 * Test that saveAssociated will accept expression object values when saving.
6793
 *
6794
 * @return void
6795
 */
6796
	public function testSaveAssociatedExpressionObjects() {
6797
		$this->loadFixtures('Post', 'Author', 'Comment', 'Attachment', 'Article', 'User');
6798
		$TestModel = new Post();
6799
		$db = $TestModel->getDataSource();
6800
 
6801
		$TestModel->saveAssociated(array(
6802
			'Post' => array(
6803
				'title' => $db->expression("(SELECT 'Post with Author')"),
6804
				'body' => 'This post will be saved with an author'
6805
			),
6806
			'Author' => array(
6807
				'user' => 'bob',
6808
				'password' => '5f4dcc3b5aa765d61d8327deb882cf90'
6809
		)), array('atomic' => false));
6810
 
6811
		$result = $TestModel->find('first', array(
6812
			'order' => array('Post.id ' => 'DESC')
6813
		));
6814
		$this->assertEquals('Post with Author', $result['Post']['title']);
6815
	}
6816
 
6817
/**
6818
 * testUpdateWithCalculation method
6819
 *
6820
 * @return void
6821
 */
6822
	public function testUpdateWithCalculation() {
6823
		$this->loadFixtures('DataTest');
6824
		$model = new DataTest();
6825
		$model->deleteAll(true);
6826
		$result = $model->saveMany(array(
6827
			array('count' => 5, 'float' => 1.1),
6828
			array('count' => 3, 'float' => 1.2),
6829
			array('count' => 4, 'float' => 1.3),
6830
			array('count' => 1, 'float' => 2.0),
6831
		));
6832
		$this->assertFalse(empty($result));
6833
 
6834
		$result = Hash::extract($model->find('all', array('fields' => 'count')), '{n}.DataTest.count');
6835
		$this->assertEquals(array(5, 3, 4, 1), $result);
6836
 
6837
		$this->assertTrue($model->updateAll(array('count' => 'count + 2')));
6838
		$result = Hash::extract($model->find('all', array('fields' => 'count')), '{n}.DataTest.count');
6839
		$this->assertEquals(array(7, 5, 6, 3), $result);
6840
 
6841
		$this->assertTrue($model->updateAll(array('DataTest.count' => 'DataTest.count - 1')));
6842
		$result = Hash::extract($model->find('all', array('fields' => 'count')), '{n}.DataTest.count');
6843
		$this->assertEquals(array(6, 4, 5, 2), $result);
6844
	}
6845
 
6846
/**
6847
 * testToggleBoolFields method
6848
 *
6849
 * @return void
6850
 */
6851
	public function testToggleBoolFields() {
6852
		$this->loadFixtures('CounterCacheUser', 'CounterCachePost');
6853
		$Post = new CounterCachePost();
6854
		$Post->unbindModel(array('belongsTo' => array('User')), true);
6855
 
6856
		$true = array('Post' => array('published' => true, 'id' => 2));
6857
		$false = array('Post' => array('published' => false, 'id' => 2));
6858
		$fields = array('Post.published', 'Post.id');
6859
		$updateConditions = array('Post.id' => 2);
6860
 
6861
		// check its true
6862
		$result = $Post->find('first', array('conditions' => $updateConditions, 'fields' => $fields));
6863
		$this->assertEquals($true, $result);
6864
 
6865
		// Testing without the alias
6866
		$this->assertTrue($Post->updateAll(array('published' => 'NOT published'), $updateConditions));
6867
		$result = $Post->find('first', array('conditions' => $updateConditions, 'fields' => $fields));
6868
		$this->assertEquals($false, $result);
6869
 
6870
		$this->assertTrue($Post->updateAll(array('published' => 'NOT published'), $updateConditions));
6871
		$result = $Post->find('first', array('conditions' => $updateConditions, 'fields' => $fields));
6872
		$this->assertEquals($true, $result);
6873
 
6874
		$db = ConnectionManager::getDataSource('test');
6875
		$alias = $db->name('Post.published');
6876
 
6877
		// Testing with the alias
6878
		$this->assertTrue($Post->updateAll(array('Post.published' => "NOT $alias"), $updateConditions));
6879
		$result = $Post->find('first', array('conditions' => $updateConditions, 'fields' => $fields));
6880
		$this->assertEquals($false, $result);
6881
 
6882
		$this->assertTrue($Post->updateAll(array('Post.published' => "NOT $alias"), $updateConditions));
6883
		$result = $Post->find('first', array('conditions' => $updateConditions, 'fields' => $fields));
6884
		$this->assertEquals($true, $result);
6885
	}
6886
 
6887
/**
6888
 * TestFindAllWithoutForeignKey
6889
 *
6890
 * @return void
6891
 */
6892
	public function testFindAllForeignKey() {
6893
		$this->loadFixtures('ProductUpdateAll', 'GroupUpdateAll');
6894
		$ProductUpdateAll = new ProductUpdateAll();
6895
 
6896
		$conditions = array('Group.name' => 'group one');
6897
 
6898
		$ProductUpdateAll->bindModel(array(
6899
			'belongsTo' => array(
6900
				'Group' => array('className' => 'GroupUpdateAll')
6901
			)
6902
		));
6903
 
6904
		$ProductUpdateAll->belongsTo = array(
6905
			'Group' => array('className' => 'GroupUpdateAll', 'foreignKey' => 'group_id')
6906
		);
6907
 
6908
		$results = $ProductUpdateAll->find('all', compact('conditions'));
6909
		$this->assertTrue(!empty($results));
6910
 
6911
		$ProductUpdateAll->bindModel(array('belongsTo' => array('Group')));
6912
		$ProductUpdateAll->belongsTo = array(
6913
			'Group' => array(
6914
				'className' => 'GroupUpdateAll',
6915
				'foreignKey' => false,
6916
				'conditions' => 'ProductUpdateAll.groupcode = Group.code'
6917
			));
6918
 
6919
		$resultsFkFalse = $ProductUpdateAll->find('all', compact('conditions'));
6920
		$this->assertTrue(!empty($resultsFkFalse));
6921
		$expected = array(
6922
			'0' => array(
6923
				'ProductUpdateAll' => array(
6924
					'id' => 1,
6925
					'name'	=> 'product one',
6926
					'groupcode' => 120,
6927
					'group_id' => 1),
6928
				'Group' => array(
6929
					'id' => 1,
6930
					'name' => 'group one',
6931
					'code' => 120)
6932
				),
6933
			'1' => array(
6934
				'ProductUpdateAll' => array(
6935
					'id' => 2,
6936
					'name'	=> 'product two',
6937
					'groupcode'	=> 120,
6938
					'group_id'	=> 1),
6939
				'Group' => array(
6940
					'id' => 1,
6941
					'name' => 'group one',
6942
					'code' => 120)
6943
				)
6944
 
6945
			);
6946
		$this->assertEquals($expected, $results);
6947
		$this->assertEquals($expected, $resultsFkFalse);
6948
	}
6949
 
6950
/**
6951
 * test updateAll with empty values.
6952
 *
6953
 * @return void
6954
 */
6955
	public function testUpdateAllEmptyValues() {
6956
		$this->skipIf($this->db instanceof Sqlserver || $this->db instanceof Postgres, 'This test is not compatible with Postgres or SQL Server.');
6957
 
6958
		$this->loadFixtures('Author', 'Post');
6959
		$model = new Author();
6960
		$result = $model->updateAll(array('user' => '""'));
6961
		$this->assertTrue($result);
6962
	}
6963
 
6964
/**
6965
 * testUpdateAllWithJoins
6966
 *
6967
 * @return void
6968
 */
6969
	public function testUpdateAllWithJoins() {
6970
		$this->skipIf(!$this->db instanceof Mysql, 'Currently, there is no way of doing joins in an update statement in postgresql or sqlite');
6971
 
6972
		$this->loadFixtures('ProductUpdateAll', 'GroupUpdateAll');
6973
		$ProductUpdateAll = new ProductUpdateAll();
6974
 
6975
		$conditions = array('Group.name' => 'group one');
6976
 
6977
		$ProductUpdateAll->bindModel(array('belongsTo' => array(
6978
			'Group' => array('className' => 'GroupUpdateAll')))
6979
		);
6980
 
6981
		$ProductUpdateAll->updateAll(array('name' => "'new product'"), $conditions);
6982
		$results = $ProductUpdateAll->find('all', array(
6983
			'conditions' => array('ProductUpdateAll.name' => 'new product')
6984
		));
6985
		$expected = array(
6986
			'0' => array(
6987
				'ProductUpdateAll' => array(
6988
					'id' => 1,
6989
					'name' => 'new product',
6990
					'groupcode'	=> 120,
6991
					'group_id' => 1),
6992
				'Group' => array(
6993
					'id' => 1,
6994
					'name' => 'group one',
6995
					'code' => 120)
6996
				),
6997
			'1' => array(
6998
				'ProductUpdateAll' => array(
6999
					'id' => 2,
7000
					'name' => 'new product',
7001
					'groupcode' => 120,
7002
					'group_id' => 1),
7003
				'Group' => array(
7004
					'id' => 1,
7005
					'name' => 'group one',
7006
					'code' => 120)));
7007
 
7008
		$this->assertEquals($expected, $results);
7009
	}
7010
 
7011
/**
7012
 * testUpdateAllWithoutForeignKey
7013
 *
7014
 * @return void
7015
 */
7016
	public function testUpdateAllWithoutForeignKey() {
7017
		$this->skipIf(!$this->db instanceof Mysql, 'Currently, there is no way of doing joins in an update statement in postgresql');
7018
 
7019
		$this->loadFixtures('ProductUpdateAll', 'GroupUpdateAll');
7020
		$ProductUpdateAll = new ProductUpdateAll();
7021
 
7022
		$conditions = array('Group.name' => 'group one');
7023
 
7024
		$ProductUpdateAll->bindModel(array('belongsTo' => array(
7025
			'Group' => array('className' => 'GroupUpdateAll')
7026
		)));
7027
 
7028
		$ProductUpdateAll->belongsTo = array(
7029
			'Group' => array(
7030
				'className' => 'GroupUpdateAll',
7031
				'foreignKey' => false,
7032
				'conditions' => 'ProductUpdateAll.groupcode = Group.code'
7033
			)
7034
		);
7035
 
7036
		$ProductUpdateAll->updateAll(array('name' => "'new product'"), $conditions);
7037
		$resultsFkFalse = $ProductUpdateAll->find('all', array('conditions' => array('ProductUpdateAll.name' => 'new product')));
7038
		$expected = array(
7039
			'0' => array(
7040
				'ProductUpdateAll' => array(
7041
					'id' => 1,
7042
					'name' => 'new product',
7043
					'groupcode'	=> 120,
7044
					'group_id' => 1),
7045
				'Group' => array(
7046
					'id' => 1,
7047
					'name' => 'group one',
7048
					'code' => 120)
7049
				),
7050
			'1' => array(
7051
				'ProductUpdateAll' => array(
7052
					'id' => 2,
7053
					'name' => 'new product',
7054
					'groupcode' => 120,
7055
					'group_id' => 1),
7056
				'Group' => array(
7057
					'id' => 1,
7058
					'name' => 'group one',
7059
					'code' => 120)));
7060
		$this->assertEquals($expected, $resultsFkFalse);
7061
	}
7062
 
7063
/**
7064
 * test writing floats in german locale.
7065
 *
7066
 * @return void
7067
 */
7068
	public function testWriteFloatAsGerman() {
7069
		$restore = setlocale(LC_NUMERIC, 0);
7070
 
7071
		$this->skipIf(setlocale(LC_NUMERIC, 'de_DE') === false, "The German locale isn't available.");
7072
 
7073
		$model = new DataTest();
7074
		$result = $model->save(array(
7075
			'count' => 1,
7076
			'float' => 3.14593
7077
		));
7078
		$this->assertTrue((bool)$result);
7079
		setlocale(LC_NUMERIC, $restore);
7080
	}
7081
 
7082
/**
7083
 * Test returned array contains primary key when save creates a new record
7084
 *
7085
 * @return void
7086
 */
7087
	public function testPkInReturnArrayForCreate() {
7088
		$this->loadFixtures('Article');
7089
		$TestModel = new Article();
7090
 
7091
		$data = array('Article' => array(
7092
			'user_id' => '1',
7093
			'title' => 'Fourth Article',
7094
			'body' => 'Fourth Article Body',
7095
			'published' => 'Y'
7096
		));
7097
		$result = $TestModel->save($data);
7098
		$this->assertSame($result['Article']['id'], $TestModel->id);
7099
	}
7100
 
7101
/**
7102
 * testSaveAllFieldListValidateBelongsTo
7103
 *
7104
 * @return void
7105
 */
7106
	public function testSaveAllFieldListValidateBelongsTo() {
7107
		$this->loadFixtures('Post', 'Author', 'Comment', 'Attachment');
7108
		$TestModel = new Post();
7109
 
7110
		$result = $TestModel->find('all');
7111
		$this->assertEquals(3, count($result));
7112
		$this->assertFalse(isset($result[3]));
7113
 
7114
		// test belongsTo
7115
		$fieldList = array(
7116
			'Post' => array('title'),
7117
			'Author' => array('user')
7118
		);
7119
		$data = array(
7120
			'Post' => array(
7121
				'title' => 'Post without body',
7122
				'body' => 'This will not be saved',
7123
			),
7124
			'Author' => array(
7125
				'user' => 'bob',
7126
				'test' => 'This will not be saved',
7127
 
7128
		));
7129
		$TestModel->saveAll($data, array('fieldList' => $fieldList));
7130
 
7131
		$result = $TestModel->find('all', array(
7132
			'order' => 'Post.id ASC',
7133
		));
7134
		$expected = array(
7135
			'Post' => array(
7136
				'id' => '4',
7137
				'author_id' => '5',
7138
				'title' => 'Post without body',
7139
				'body' => null,
7140
				'published' => 'N',
7141
				'created' => static::date(),
7142
				'updated' => static::date(),
7143
			),
7144
			'Author' => array(
7145
				'id' => '5',
7146
				'user' => 'bob',
7147
				'password' => null,
7148
				'created' => static::date(),
7149
				'updated' => static::date(),
7150
				'test' => 'working',
7151
			),
7152
		);
7153
		$this->assertEquals($expected, $result[3]);
7154
		$this->assertEquals(4, count($result));
7155
		$this->assertEquals('', $result[3]['Post']['body']);
7156
		$this->assertEquals('working', $result[3]['Author']['test']);
7157
 
7158
		$fieldList = array(
7159
			'Post' => array('title')
7160
		);
7161
		$data = array(
7162
			'Post' => array(
7163
				'title' => 'Post without body 2',
7164
				'body' => 'This will not be saved'
7165
			),
7166
			'Author' => array(
7167
				'user' => 'jack'
7168
			)
7169
		);
7170
		$TestModel->saveAll($data, array('fieldList' => $fieldList));
7171
		$result = $TestModel->find('all', array(
7172
			'order' => 'Post.id ASC',
7173
		));
7174
		$this->assertNull($result[4]['Post']['body']);
7175
 
7176
		$fieldList = array(
7177
			'Author' => array('password')
7178
		);
7179
		$data = array(
7180
			'Post' => array(
7181
				'id' => '5',
7182
				'title' => 'Post title',
7183
				'body' => 'Post body'
7184
			),
7185
			'Author' => array(
7186
				'id' => '6',
7187
				'user' => 'will not change',
7188
				'password' => 'foobar'
7189
			)
7190
		);
7191
		$result = $TestModel->saveAll($data, array('fieldList' => $fieldList));
7192
		$this->assertTrue($result);
7193
 
7194
		$result = $TestModel->find('all', array(
7195
			'order' => 'Post.id ASC',
7196
		));
7197
		$expected = array(
7198
			'Post' => array(
7199
				'id' => '5',
7200
				'author_id' => '6',
7201
				'title' => 'Post title',
7202
				'body' => 'Post body',
7203
				'published' => 'N',
7204
				'created' => static::date(),
7205
				'updated' => static::date()
7206
			),
7207
			'Author' => array(
7208
				'id' => '6',
7209
				'user' => 'jack',
7210
				'password' => 'foobar',
7211
				'created' => static::date(),
7212
				'updated' => static::date(),
7213
				'test' => 'working'
7214
			),
7215
		);
7216
		$this->assertEquals($expected, $result[4]);
7217
 
7218
		// test multirecord
7219
		$this->db->truncate($TestModel);
7220
 
7221
		$fieldList = array('title', 'author_id');
7222
		$TestModel->saveAll(array(
7223
			array(
7224
				'title' => 'Multi-record post 1',
7225
				'body' => 'First multi-record post',
7226
				'author_id' => 2
7227
			),
7228
			array(
7229
				'title' => 'Multi-record post 2',
7230
				'body' => 'Second multi-record post',
7231
				'author_id' => 2
7232
		)), array('fieldList' => $fieldList));
7233
 
7234
		$result = $TestModel->find('all', array(
7235
			'recursive' => -1,
7236
			'order' => 'Post.id ASC'
7237
		));
7238
		$expected = array(
7239
			array(
7240
				'Post' => array(
7241
					'id' => '1',
7242
					'author_id' => '2',
7243
					'title' => 'Multi-record post 1',
7244
					'body' => '',
7245
					'published' => 'N',
7246
					'created' => static::date(),
7247
					'updated' => static::date()
7248
				)
7249
			),
7250
			array(
7251
				'Post' => array(
7252
					'id' => '2',
7253
					'author_id' => '2',
7254
					'title' => 'Multi-record post 2',
7255
					'body' => '',
7256
					'published' => 'N',
7257
					'created' => static::date(),
7258
					'updated' => static::date()
7259
				)
7260
			)
7261
		);
7262
		$this->assertEquals($expected, $result);
7263
	}
7264
 
7265
/**
7266
 * testSaveAllFieldListHasMany method
7267
 *
7268
 * @return void
7269
 */
7270
	public function testSaveAllFieldListHasMany() {
7271
		$this->loadFixtures('Article', 'Comment');
7272
		$TestModel = new Article();
7273
		$TestModel->belongsTo = $TestModel->hasAndBelongsToMany = array();
7274
 
7275
		$this->db->truncate($TestModel);
7276
		$this->db->truncate(new Comment());
7277
 
7278
		$data = array(
7279
			'Article' => array('title' => 'I will not save'),
7280
			'Comment' => array(
7281
				array('comment' => 'First new comment', 'published' => 'Y', 'user_id' => 1),
7282
				array('comment' => 'Second new comment', 'published' => 'Y', 'user_id' => 2)
7283
			)
7284
		);
7285
 
7286
		$fieldList = array(
7287
			'Article' => array('id'),
7288
			'Comment' => array('article_id', 'user_id')
7289
		);
7290
		$TestModel->saveAll($data, array('fieldList' => $fieldList));
7291
 
7292
		$result = $TestModel->find('all');
7293
		$this->assertEquals('', $result[0]['Article']['title']);
7294
		$this->assertEquals('', $result[0]['Comment'][0]['comment']);
7295
		$this->assertEquals('', $result[0]['Comment'][1]['comment']);
7296
 
7297
		$fieldList = array(
7298
			'Article' => array('id'),
7299
			'Comment' => array('user_id')
7300
		);
7301
		$TestModel->saveAll($data, array('fieldList' => $fieldList));
7302
		$result = $TestModel->find('all');
7303
 
7304
		$this->assertEquals('', $result[1]['Article']['title']);
7305
		$this->assertEquals(2, count($result[1]['Comment']));
7306
 
7307
		$TestModel->whitelist = array('id');
7308
		$TestModel->Comment->whitelist = array('user_id');
7309
		$TestModel->saveAll($data);
7310
		$result = $TestModel->find('all');
7311
 
7312
		$this->assertEquals('', $result[2]['Article']['title']);
7313
		$this->assertEquals(2, count($result[2]['Comment']));
7314
	}
7315
 
7316
/**
7317
 * testSaveAllFieldListHasOne method
7318
 *
7319
 * @return void
7320
 */
7321
	public function testSaveAllFieldListHasOne() {
7322
		$this->loadFixtures('Attachment', 'Comment', 'Article', 'User');
7323
		$TestModel = new Comment();
7324
 
7325
		$TestModel->validate = array('comment' => 'notBlank');
7326
		$TestModel->Attachment->validate = array('attachment' => 'notBlank');
7327
 
7328
		$record = array(
7329
			'Comment' => array(
7330
				'user_id' => 1,
7331
				'article_id' => 1,
7332
				'comment' => '',
7333
			),
7334
			'Attachment' => array(
7335
				'attachment' => ''
7336
			)
7337
		);
7338
		$result = $TestModel->saveAll($record, array('validate' => 'only'));
7339
		$this->assertFalse($result);
7340
 
7341
		$fieldList = array(
7342
			'Comment' => array('id', 'article_id', 'user_id'),
7343
			'Attachment' => array('comment_id')
7344
		);
7345
		$result = $TestModel->saveAll($record, array(
7346
			'fieldList' => $fieldList, 'validate' => 'only'
7347
		));
7348
		$this->assertTrue($result);
7349
		$this->assertEmpty($TestModel->validationErrors);
7350
	}
7351
 
7352
/**
7353
 * testSaveAllFieldListHasOneAddFkToWhitelist method
7354
 *
7355
 * @return void
7356
 */
7357
	public function testSaveAllFieldListHasOneAddFkToWhitelist() {
7358
		$this->loadFixtures('ArticleFeatured', 'Featured');
7359
		$Article = new ArticleFeatured();
7360
		$Article->belongsTo = $Article->hasMany = array();
7361
		$Article->Featured->validate = array('end_date' => 'notBlank');
7362
 
7363
		$record = array(
7364
			'ArticleFeatured' => array(
7365
				'user_id' => 1,
7366
				'title' => 'First Article',
7367
				'body' => '',
7368
				'published' => 'Y'
7369
			),
7370
			'Featured' => array(
7371
				'category_id' => 1,
7372
				'end_date' => ''
7373
			)
7374
		);
7375
		$result = $Article->saveAll($record, array('validate' => 'only'));
7376
		$this->assertFalse($result);
7377
		$expected = array(
7378
			'body' => array(
7379
				'This field cannot be left blank'
7380
			),
7381
			'Featured' => array(
7382
				'end_date' => array(
7383
					'This field cannot be left blank'
7384
				)
7385
			)
7386
		);
7387
		$this->assertEquals($expected, $Article->validationErrors);
7388
 
7389
		$fieldList = array(
7390
			'ArticleFeatured' => array('user_id', 'title'),
7391
			'Featured' => array('category_id')
7392
		);
7393
 
7394
		$result = $Article->saveAll($record, array(
7395
			'fieldList' => $fieldList, 'validate' => 'first'
7396
		));
7397
		$this->assertTrue($result);
7398
		$this->assertEmpty($Article->validationErrors);
7399
 
7400
		$Article->recursive = 0;
7401
		$result = $Article->find('first', array('order' => array('ArticleFeatured.created' => 'DESC')));
7402
		$this->assertSame($result['ArticleFeatured']['id'], $result['Featured']['article_featured_id']);
7403
	}
7404
 
7405
/**
7406
 * testSaveAllDeepFieldListValidateBelongsTo
7407
 *
7408
 * @return void
7409
 */
7410
	public function testSaveAllDeepFieldListValidateBelongsTo() {
7411
		$this->loadFixtures('Post', 'Author', 'Comment', 'Attachment', 'Article', 'User');
7412
		$TestModel = new Post();
7413
		$TestModel->Author->bindModel(array('hasMany' => array('Comment' => array('foreignKey' => 'user_id'))), false);
7414
		$TestModel->recursive = 2;
7415
 
7416
		$result = $TestModel->find('all');
7417
		$this->assertEquals(3, count($result));
7418
		$this->assertFalse(isset($result[3]));
7419
 
7420
		// test belongsTo
7421
		$fieldList = array(
7422
			'Post' => array('title', 'author_id'),
7423
			'Author' => array('user'),
7424
			'Comment' => array('comment')
7425
		);
7426
		$TestModel->saveAll(array(
7427
			'Post' => array(
7428
				'title' => 'Post without body',
7429
				'body' => 'This will not be saved',
7430
			),
7431
			'Author' => array(
7432
				'user' => 'bob',
7433
				'test' => 'This will not be saved',
7434
				'Comment' => array(
7435
					array('id' => 5, 'comment' => 'I am still published', 'published' => 'N'))
7436
 
7437
		)), array('fieldList' => $fieldList, 'deep' => true));
7438
 
7439
		$result = $TestModel->Author->Comment->find('first', array(
7440
			'conditions' => array('Comment.id' => 5),
7441
			'fields' => array('comment', 'published')
7442
		));
7443
		$expected = array(
7444
			'Comment' => array(
7445
				'comment' => 'I am still published',
7446
				'published' => 'Y'
7447
			)
7448
		);
7449
		$this->assertEquals($expected, $result);
7450
	}
7451
 
7452
/**
7453
 * testSaveAllDeepFieldListHasMany method
7454
 *
7455
 * @return void
7456
 */
7457
	public function testSaveAllDeepFieldListHasMany() {
7458
		$this->loadFixtures('Article', 'Comment', 'User');
7459
		$TestModel = new Article();
7460
		$TestModel->belongsTo = $TestModel->hasAndBelongsToMany = array();
7461
 
7462
		$this->db->truncate($TestModel);
7463
		$this->db->truncate(new Comment());
7464
 
7465
		$fieldList = array(
7466
			'Article' => array('id'),
7467
			'Comment' => array('article_id', 'user_id'),
7468
			'User' => array('user')
7469
		);
7470
 
7471
		$result = $TestModel->saveAll(array(
7472
			'Article' => array('id' => 2, 'title' => 'I will not save'),
7473
			'Comment' => array(
7474
				array('comment' => 'First new comment', 'published' => 'Y', 'user_id' => 1),
7475
				array(
7476
					'comment' => 'Second new comment', 'published' => 'Y', 'user_id' => 2,
7477
					'User' => array('user' => 'nopassword', 'password' => 'not saved')
7478
				)
7479
			)
7480
		), array('fieldList' => $fieldList, 'deep' => true));
7481
 
7482
		$result = $TestModel->Comment->User->find('first', array(
7483
			'conditions' => array('User.user' => 'nopassword'),
7484
			'fields' => array('user', 'password')
7485
		));
7486
		$expected = array(
7487
			'User' => array(
7488
				'user' => 'nopassword',
7489
				'password' => ''
7490
			)
7491
		);
7492
		$this->assertEquals($expected, $result);
7493
	}
7494
 
7495
/**
7496
 * testSaveAllDeepHasManyBelongsTo method
7497
 *
7498
 * @return void
7499
 */
7500
	public function testSaveAllDeepHasManyBelongsTo() {
7501
		$this->loadFixtures('Article', 'Comment', 'User');
7502
		$TestModel = new Article();
7503
		$TestModel->belongsTo = $TestModel->hasAndBelongsToMany = array();
7504
 
7505
		$this->db->truncate($TestModel);
7506
		$this->db->truncate(new Comment());
7507
 
7508
		$result = $TestModel->saveAll(array(
7509
			'Article' => array('id' => 2, 'title' => 'The title'),
7510
			'Comment' => array(
7511
				array('comment' => 'First new comment', 'published' => 'Y', 'user_id' => 1),
7512
				array(
7513
					'comment' => 'belongsto', 'published' => 'Y',
7514
					'User' => array('user' => 'findme', 'password' => 'somepass')
7515
				)
7516
			)
7517
		), array('deep' => true));
7518
 
7519
		$result = $TestModel->Comment->User->find('first', array(
7520
			'conditions' => array('User.user' => 'findme'),
7521
			'fields' => array('id', 'user', 'password')
7522
		));
7523
		$expected = array(
7524
			'User' => array(
7525
				'id' => 5,
7526
				'user' => 'findme',
7527
				'password' => 'somepass',
7528
			)
7529
		);
7530
		$this->assertEquals($expected, $result);
7531
 
7532
		$result = $TestModel->Comment->find('first', array(
7533
			'conditions' => array('Comment.user_id' => 5),
7534
			'fields' => array('id', 'comment', 'published', 'user_id')
7535
		));
7536
		$expected = array(
7537
			'Comment' => array(
7538
				'id' => 2,
7539
				'comment' => 'belongsto',
7540
				'published' => 'Y',
7541
				'user_id' => 5
7542
			)
7543
		);
7544
		$this->assertEquals($expected, $result);
7545
	}
7546
 
7547
/**
7548
 * testSaveAllDeepHasManyhasMany method
7549
 *
7550
 * @return void
7551
 */
7552
	public function testSaveAllDeepHasManyHasMany() {
7553
		$this->loadFixtures('Article', 'Comment', 'User', 'Attachment');
7554
		$TestModel = new Article();
7555
		$TestModel->belongsTo = $TestModel->hasAndBelongsToMany = $TestModel->Comment->belongsTo = array();
7556
		$TestModel->Comment->unbindModel(array('hasOne' => array('Attachment')), false);
7557
		$TestModel->Comment->bindModel(array('hasMany' => array('Attachment')), false);
7558
 
7559
		$this->db->truncate($TestModel);
7560
		$this->db->truncate(new Comment());
7561
		$this->db->truncate(new Attachment());
7562
 
7563
		$result = $TestModel->saveAll(array(
7564
			'Article' => array('id' => 2, 'title' => 'The title'),
7565
			'Comment' => array(
7566
				array('comment' => 'First new comment', 'published' => 'Y', 'user_id' => 1),
7567
				array(
7568
					'comment' => 'hasmany', 'published' => 'Y', 'user_id' => 5,
7569
					'Attachment' => array(
7570
						array('attachment' => 'first deep attachment'),
7571
						array('attachment' => 'second deep attachment'),
7572
					)
7573
				)
7574
			)
7575
		), array('deep' => true));
7576
 
7577
		$result = $TestModel->Comment->find('first', array(
7578
			'conditions' => array('Comment.comment' => 'hasmany'),
7579
			'fields' => array('id', 'comment', 'published', 'user_id'),
7580
			'recursive' => -1
7581
		));
7582
		$expected = array(
7583
			'Comment' => array(
7584
				'id' => 2,
7585
				'comment' => 'hasmany',
7586
				'published' => 'Y',
7587
				'user_id' => 5
7588
			)
7589
		);
7590
		$this->assertEquals($expected, $result);
7591
 
7592
		$result = $TestModel->Comment->Attachment->find('all', array(
7593
			'fields' => array('attachment', 'comment_id'),
7594
			'order' => array('Attachment.id' => 'ASC')
7595
		));
7596
		$expected = array(
7597
			array('Attachment' => array('attachment' => 'first deep attachment', 'comment_id' => 2)),
7598
			array('Attachment' => array('attachment' => 'second deep attachment', 'comment_id' => 2)),
7599
		);
7600
		$this->assertEquals($expected, $result);
7601
	}
7602
 
7603
/**
7604
 * testSaveAllDeepOrderHasManyHasMany method
7605
 *
7606
 * @return void
7607
 */
7608
	public function testSaveAllDeepOrderHasManyHasMany() {
7609
		$this->loadFixtures('Article', 'Comment', 'User', 'Attachment');
7610
		$TestModel = new Article();
7611
		$TestModel->belongsTo = $TestModel->hasAndBelongsToMany = $TestModel->Comment->belongsTo = array();
7612
		$TestModel->Comment->unbindModel(array('hasOne' => array('Attachment')), false);
7613
		$TestModel->Comment->bindModel(array('hasMany' => array('Attachment')), false);
7614
 
7615
		$this->db->truncate($TestModel);
7616
		$this->db->truncate(new Comment());
7617
		$this->db->truncate(new Attachment());
7618
 
7619
		$result = $TestModel->saveAll(array(
7620
			'Article' => array('id' => 2, 'title' => 'Comment has its data after Attachment'),
7621
			'Comment' => array(
7622
				array(
7623
					'Attachment' => array(
7624
						array('attachment' => 'attachment should be created with comment_id'),
7625
						array('attachment' => 'comment should be created with article_id'),
7626
					),
7627
					'comment' => 'after associated data',
7628
					'user_id' => 1
7629
				)
7630
			)
7631
		), array('deep' => true));
7632
		$result = $TestModel->Comment->find('first', array(
7633
			'conditions' => array('Comment.article_id' => 2),
7634
		));
7635
 
7636
		$this->assertEquals(2, $result['Comment']['article_id']);
7637
		$this->assertEquals(2, count($result['Attachment']));
7638
	}
7639
 
7640
/**
7641
 * testSaveAllDeepEmptyHasManyHasMany method
7642
 *
7643
 * @return void
7644
 */
7645
	public function testSaveAllDeepEmptyHasManyHasMany() {
7646
		$this->skipIf(!$this->db instanceof Mysql, 'This test is only compatible with Mysql.');
7647
 
7648
		$this->loadFixtures('Article', 'Comment', 'User', 'Attachment');
7649
		$TestModel = new Article();
7650
		$TestModel->belongsTo = $TestModel->hasAndBelongsToMany = $TestModel->Comment->belongsTo = array();
7651
		$TestModel->Comment->unbindModel(array('hasOne' => array('Attachment')), false);
7652
		$TestModel->Comment->bindModel(array('hasMany' => array('Attachment')), false);
7653
 
7654
		$this->db->truncate($TestModel);
7655
		$this->db->truncate(new Comment());
7656
		$this->db->truncate(new Attachment());
7657
 
7658
		$result = $TestModel->saveAll(array(
7659
			'Article' => array('id' => 3, 'user_id' => 1, 'title' => 'Comment has no data'),
7660
			'Comment' => array(
7661
				array(
7662
					'user_id' => 1,
7663
					'Attachment' => array(
7664
						array('attachment' => 'attachment should be created with comment_id'),
7665
						array('attachment' => 'comment should be created with article_id'),
7666
					),
7667
				)
7668
			)
7669
		), array('deep' => true));
7670
		$result = $TestModel->Comment->find('first', array(
7671
			'conditions' => array('Comment.article_id' => 3),
7672
		));
7673
 
7674
		$this->assertEquals(3, $result['Comment']['article_id']);
7675
		$this->assertEquals(2, count($result['Attachment']));
7676
	}
7677
 
7678
/**
7679
 * Test that boolean fields don't cause saveMany to fail
7680
 *
7681
 * @return void
7682
 */
7683
	public function testSaveManyBooleanFields() {
7684
		$this->loadFixtures('Item', 'Syfile', 'Image');
7685
		$data = array(
7686
			array(
7687
				'Item' => array(
7688
					'name' => 'testing',
7689
					'syfile_id' => 1,
7690
					'published' => false
7691
				)
7692
			),
7693
			array(
7694
				'Item' => array(
7695
					'name' => 'testing 2',
7696
					'syfile_id' => 1,
7697
					'published' => true
7698
				)
7699
			),
7700
		);
7701
		$item = ClassRegistry::init('Item');
7702
		$result = $item->saveMany($data, array('atomic' => false));
7703
 
7704
		$this->assertCount(2, $result, '2 records should have been saved.');
7705
		$this->assertTrue($result[0], 'Both should have succeded');
7706
		$this->assertTrue($result[1], 'Both should have succeded');
7707
	}
7708
 
7709
/**
7710
 * testSaveManyDeepHasManyValidationFailure method
7711
 *
7712
 * @return void
7713
 */
7714
	public function testSaveManyDeepHasManyValidationFailure() {
7715
		$this->loadFixtures('Article', 'Comment');
7716
		$TestModel = new Article();
7717
		$TestModel->Comment->validate = array(
7718
			'comment' => array(
7719
				'notBlank' => array(
7720
					'rule' => array('notBlank'),
7721
				)
7722
			)
7723
		);
7724
 
7725
		$result = $TestModel->saveMany(array(
7726
			array(
7727
				'user_id' => 1,
7728
				'title' => 'New Article',
7729
				'body' => 'This article contains a invalid comment',
7730
				'Comment' => array(
7731
					array(
7732
						'user_id' => 1,
7733
						'comment' => ''
7734
					)
7735
				)
7736
			)
7737
		), array('deep' => true));
7738
		$this->assertFalse($result);
7739
		$this->assertEquals(array(
7740
			array(
7741
				'Comment' => array(
7742
					array('comment' => array('notBlank'))
7743
				)
7744
			)
7745
		), $TestModel->validationErrors);
7746
	}
7747
 
7748
/**
7749
 * testSaveAssociatedDeepHasOneHasManyValidateTrueValidationFailure method
7750
 *
7751
 * @return void
7752
 */
7753
	public function testSaveAssociatedDeepHasOneHasManyValidateTrueValidationFailure() {
7754
		$this->loadFixtures('User', 'Article', 'Comment');
7755
		$TestModel = new UserHasOneArticle();
7756
		$TestModel->Article->Comment->validate = array(
7757
			'comment' => array(
7758
				'notBlank' => array(
7759
					'rule' => array('notBlank'),
7760
				)
7761
			)
7762
		);
7763
 
7764
		$result = $TestModel->saveAssociated(array(
7765
			'User' => array(
7766
				'user' => 'hiromi',
7767
				'password' => '5f4dcc3b5aa765d61d8327deb882cf99',
7768
			),
7769
			'Article' => array(
7770
				'title' => 'Article with User',
7771
				'body' => 'This article will be saved with an user and contains a invalid comment',
7772
				'Comment' => array(
7773
					array(
7774
						'user_id' => 1,
7775
						'comment' => ''
7776
					)
7777
				)
7778
			)
7779
		), array('deep' => true, 'validate' => true));
7780
		$this->assertFalse($result);
7781
		$this->assertEquals(array(
7782
			'Article' => array(
7783
				'Comment' => array(
7784
					array('comment' => array('notBlank'))
7785
				)
7786
			)
7787
		), $TestModel->validationErrors);
7788
	}
7789
 
7790
/**
7791
 * testSaveAssociatedDeepBelongsToHasManyValidateTrueValidationFailure method
7792
 *
7793
 * @return void
7794
 */
7795
	public function testSaveAssociatedDeepBelongsToHasManyValidateTrueValidationFailure() {
7796
		$this->loadFixtures('ArticlesTag', 'Article', 'Comment');
7797
		$TestModel = new ArticlesTagBelongsToArticle();
7798
		$TestModel->Article->Comment->validate = array(
7799
			'comment' => array(
7800
				'notBlank' => array(
7801
					'rule' => array('notBlank'),
7802
				)
7803
			)
7804
		);
7805
 
7806
		$result = $TestModel->saveAssociated(array(
7807
			'ArticlesTagBelongsToArticle' => array(
7808
				'tag_id' => 1,
7809
			),
7810
			'Article' => array(
7811
				'title' => 'Article with User',
7812
				'body' => 'This article will be saved with an user and contains a invalid comment',
7813
				'Comment' => array(
7814
					array(
7815
						'user_id' => 1,
7816
						'comment' => ''
7817
					)
7818
				)
7819
			)
7820
		), array('deep' => true, 'validate' => true));
7821
		$this->assertFalse($result);
7822
		$this->assertEquals(array(
7823
			'Article' => array(
7824
				'Comment' => array(
7825
					array('comment' => array('notBlank'))
7826
				)
7827
			)
7828
		), $TestModel->validationErrors);
7829
	}
7830
 
7831
/**
7832
 * Test that boolean fields don't cause saveAssociated to fail
7833
 *
7834
 * @return void
7835
 */
7836
	public function testSaveAssociatedHasOneBooleanFields() {
7837
		$this->loadFixtures('Item', 'Syfile', 'Image');
7838
		$data = array(
7839
			'Syfile' => array(
7840
				'image_id' => 1,
7841
				'name' => 'Some file',
7842
			),
7843
			'Item' => array(
7844
				'name' => 'testing',
7845
				'published' => false
7846
			),
7847
		);
7848
		$syfile = ClassRegistry::init('Syfile');
7849
		$syfile->bindModel(array('hasOne' => array('Item')), false);
7850
		$result = $syfile->saveAssociated($data, array('atomic' => false));
7851
 
7852
		$this->assertCount(2, $result, '2 records should have been saved.');
7853
		$this->assertTrue($result['Syfile'], 'Both should have succeded');
7854
		$this->assertTrue($result['Item'], 'Both should have succeded');
7855
	}
7856
 
7857
/**
7858
 * Test that boolean fields don't cause saveAssociated to fail
7859
 *
7860
 * @return void
7861
 */
7862
	public function testSaveAssociatedBelongsToBooleanFields() {
7863
		$this->loadFixtures('Item', 'Syfile', 'Image');
7864
		$data = array(
7865
			'Syfile' => array(
7866
				'image_id' => 1,
7867
				'name' => 'Some file',
7868
			),
7869
			'Item' => array(
7870
				'name' => 'testing',
7871
				'syfile_id' => 2,
7872
				'published' => false
7873
			),
7874
		);
7875
		$item = ClassRegistry::init('Item');
7876
		$item->bindModel(array(
7877
			'belongsTo' => array(
7878
				'Item' => array(
7879
					'foreignKey' => 'image_id'
7880
				)
7881
			)
7882
		), false);
7883
		$result = $item->saveAssociated($data, array('atomic' => false));
7884
 
7885
		$this->assertCount(2, $result, '2 records should have been saved.');
7886
		$this->assertTrue($result['Syfile'], 'Both should have succeded');
7887
		$this->assertTrue($result['Item'], 'Both should have succeded');
7888
	}
7889
 
7890
/**
7891
 * testUpdateAllBoolean
7892
 *
7893
 * @return void
7894
 */
7895
	public function testUpdateAllBoolean() {
7896
		$this->loadFixtures('Item', 'Syfile', 'Portfolio', 'Image', 'ItemsPortfolio');
7897
		$TestModel = new Item();
7898
		$result = $TestModel->updateAll(array('published' => true));
7899
		$this->assertTrue($result);
7900
 
7901
		$result = $TestModel->find('first', array('fields' => array('id', 'published')));
7902
		$this->assertEquals(true, $result['Item']['published']);
7903
	}
7904
 
7905
/**
7906
 * testUpdateAllBooleanConditions
7907
 *
7908
 * @return void
7909
 */
7910
	public function testUpdateAllBooleanConditions() {
7911
		$this->loadFixtures('Item', 'Syfile', 'Portfolio', 'Image', 'ItemsPortfolio');
7912
		$TestModel = new Item();
7913
 
7914
		$result = $TestModel->updateAll(array('published' => true), array('Item.id' => 1));
7915
		$this->assertTrue($result);
7916
		$result = $TestModel->find('first', array(
7917
			'fields' => array('id', 'published'),
7918
			'conditions' => array('Item.id' => 1)));
7919
		$this->assertEquals(true, $result['Item']['published']);
7920
	}
7921
 
7922
/**
7923
 * testUpdateBoolean
7924
 *
7925
 * @return void
7926
 */
7927
	public function testUpdateBoolean() {
7928
		$this->loadFixtures('Item', 'Syfile', 'Portfolio', 'Image', 'ItemsPortfolio');
7929
		$TestModel = new Item();
7930
 
7931
		$result = $TestModel->save(array('published' => true, 'id' => 1));
7932
		$this->assertTrue((bool)$result);
7933
		$result = $TestModel->find('first', array(
7934
			'fields' => array('id', 'published'),
7935
			'conditions' => array('Item.id' => 1)));
7936
		$this->assertEquals(true, $result['Item']['published']);
7937
	}
7938
 
7939
/**
7940
 * Test the clear() method.
7941
 *
7942
 * @return void
7943
 */
7944
	public function testClear() {
7945
		$this->loadFixtures('Bid');
7946
		$model = ClassRegistry::init('Bid');
7947
		$model->set(array('name' => 'Testing', 'message_id' => 3));
7948
		$this->assertTrue(isset($model->data['Bid']['name']));
7949
		$this->assertTrue($model->clear());
7950
		$this->assertFalse(isset($model->data['Bid']['name']));
7951
		$this->assertFalse(isset($model->data['Bid']['message_id']));
7952
	}
7953
 
7954
/**
7955
 * Test that Model::save() doesn't generate a query with WHERE 1 = 1 on race condition.
7956
 *
7957
 * @link https://github.com/cakephp/cakephp/issues/3857
7958
 * @return void
7959
 */
7960
	public function testSafeUpdateMode() {
7961
		$this->loadFixtures('User');
7962
 
7963
		$User = ClassRegistry::init('User');
7964
		$this->assertFalse($User->__safeUpdateMode);
7965
 
7966
		$User->getEventManager()->attach(array($this, 'deleteMe'), 'Model.beforeSave');
7967
 
7968
		$User->id = 1;
7969
		$User->set(array('user' => 'nobody'));
7970
		$User->save();
7971
 
7972
		$users = $User->find('list', array('fields' => 'User.user'));
7973
 
7974
		$expected = array(
7975
			2 => 'nate',
7976
			3 => 'larry',
7977
			4 => 'garrett',
7978
		);
7979
		$this->assertEquals($expected, $users);
7980
		$this->assertFalse($User->__safeUpdateMode);
7981
 
7982
		$User->id = 2;
7983
		$User->set(array('user' => $User->getDataSource()->expression('PDO_EXCEPTION()')));
7984
		try {
7985
			$User->save(null, false);
7986
			$this->fail('No exception thrown');
7987
		} catch (PDOException $e) {
7988
			$this->assertFalse($User->__safeUpdateMode);
7989
		}
7990
	}
7991
 
7992
/**
7993
 * Emulates race condition
7994
 *
7995
 * @param CakeEvent $event containing the Model
7996
 * @return void
7997
 */
7998
	public function deleteMe($event) {
7999
		$Model = $event->subject;
8000
		$Model->getDataSource()->delete($Model, array($Model->alias . '.' . $Model->primaryKey => $Model->id));
8001
	}
8002
 
8003
/**
8004
 * Creates a convenient mock DboSource
8005
 *
8006
 * We cannot call several methods via mock DboSource, such as DboSource::value()
8007
 * because mock DboSource has no $_connection.
8008
 * This method helps us to avoid this problem.
8009
 *
8010
 * @param array $methods Configurable method names.
8011
 * @return DboSource
8012
 */
8013
	protected function _getMockDboSource($methods = array()) {
8014
		$testDb = ConnectionManager::getDataSource('test');
8015
 
8016
		$passthrough = array_diff(array('value', 'begin', 'rollback', 'commit', 'describe', 'lastInsertId', 'execute'), $methods);
8017
 
8018
		$methods = array_merge($methods, $passthrough);
8019
		if (!in_array('connect', $methods)) {
8020
			$methods[] = 'connect'; // This will be called by DboSource::__construct().
8021
		}
8022
 
8023
		$db = $this->getMock('DboSource', $methods);
8024
		$db->columns = $testDb->columns;
8025
		$db->startQuote = $testDb->startQuote;
8026
		$db->endQuote = $testDb->endQuote;
8027
 
8028
		foreach ($passthrough as $method) {
8029
			$db->expects($this->any())
8030
				->method($method)
8031
				->will($this->returnCallback(array($testDb, $method)));
8032
		}
8033
 
8034
		return $db;
8035
	}
8036
 
8037
/**
8038
 * Test that transactions behave correctly on nested saveMany calls.
8039
 *
8040
 * @return void
8041
 */
8042
	public function testTransactionOnNestedSaveMany() {
8043
		$this->loadFixtures('Post');
8044
		$Post = new TestPost();
8045
		$Post->getEventManager()->attach(array($this, 'nestedSaveMany'), 'Model.afterSave');
8046
 
8047
		// begin -> [ begin -> commit ] -> commit
8048
		$db = $this->_getMockDboSource(array('begin', 'commit', 'rollback'));
8049
		$db->expects($this->exactly(2))->method('begin')->will($this->returnValue(true));
8050
		$db->expects($this->exactly(2))->method('commit');
8051
		$db->expects($this->never())->method('rollback');
8052
		$Post->setDataSourceObject($db);
8053
 
8054
		$data = array(
8055
			array('author_id' => 1, 'title' => 'Outer Post'),
8056
		);
8057
		$Post->dataForAfterSave = array(
8058
			array('author_id' => 1, 'title' => 'Inner Post'),
8059
		);
8060
		$this->assertTrue($Post->saveMany($data));
8061
 
8062
		// begin -> [  begin(false) ] -> commit
8063
		$db = $this->_getMockDboSource(array('begin', 'commit', 'rollback'));
8064
		$db->expects($this->at(0))->method('begin')->will($this->returnValue(true));
8065
		$db->expects($this->at(1))->method('begin')->will($this->returnValue(false));
8066
		$db->expects($this->once())->method('commit');
8067
		$db->expects($this->never())->method('rollback');
8068
		$Post->setDataSourceObject($db);
8069
 
8070
		$data = array(
8071
			array('author_id' => 1, 'title' => 'Outer Post'),
8072
		);
8073
		$Post->dataForAfterSave = array(
8074
			array('author_id' => 1, 'title' => 'Inner Post'),
8075
		);
8076
		$this->assertTrue($Post->saveMany($data));
8077
 
8078
		// begin -> [ begin -> rollback ] -> rollback
8079
		$db = $this->_getMockDboSource(array('begin', 'commit', 'rollback'));
8080
		$db->expects($this->exactly(2))->method('begin')->will($this->returnValue(true));
8081
		$db->expects($this->never())->method('commit');
8082
		$db->expects($this->exactly(2))->method('rollback');
8083
		$Post->setDataSourceObject($db);
8084
		$data = array(
8085
			array('author_id' => 1, 'title' => 'Outer Post'),
8086
		);
8087
		$Post->dataForAfterSave = array(
8088
			array('author_id' => 1, 'title' => 'Inner Post', 'body' => $db->expression('PDO_EXCEPTION()')),
8089
		);
8090
 
8091
		try {
8092
			$Post->saveMany($data);
8093
			$this->fail('No exception thrown');
8094
		} catch(Exception $e) {
8095
		}
8096
	}
8097
 
8098
/**
8099
 * Test that transaction behaves correctly on nested saveAssociated calls.
8100
 *
8101
 * @return void
8102
 */
8103
	public function testTransactionOnNestedSaveAssociated() {
8104
		$this->loadFixtures('Author', 'Post');
8105
 
8106
		$Author = new TestAuthor();
8107
		$Author->getEventManager()->attach(array($this, 'nestedSaveAssociated'), 'Model.afterSave');
8108
 
8109
		// begin -> [ begin -> commit ] -> commit
8110
		$db = $this->_getMockDboSource(array('begin', 'commit', 'rollback'));
8111
		$db->expects($this->exactly(2))->method('begin')->will($this->returnValue(true));
8112
		$db->expects($this->exactly(2))->method('commit');
8113
		$db->expects($this->never())->method('rollback');
8114
		$Author->setDataSourceObject($db);
8115
		$Author->Post->setDataSourceObject($db);
8116
 
8117
		$data = array(
8118
			'Author' => array('user' => 'outer'),
8119
			'Post' => array(
8120
				array('title' => 'Outer Post'),
8121
			)
8122
		);
8123
		$Author->dataForAfterSave = array(
8124
			'Author' => array('user' => 'inner'),
8125
			'Post' => array(
8126
				array('title' => 'Inner Post'),
8127
			)
8128
		);
8129
		$this->assertTrue($Author->saveAssociated($data));
8130
 
8131
		// begin -> [  begin(false) ] -> commit
8132
		$db = $this->_getMockDboSource(array('begin', 'commit', 'rollback'));
8133
		$db->expects($this->at(0))->method('begin')->will($this->returnValue(true));
8134
		$db->expects($this->at(1))->method('begin')->will($this->returnValue(false));
8135
		$db->expects($this->once())->method('commit');
8136
		$db->expects($this->never())->method('rollback');
8137
		$Author->setDataSourceObject($db);
8138
		$Author->Post->setDataSourceObject($db);
8139
		$data = array(
8140
			'Author' => array('user' => 'outer'),
8141
			'Post' => array(
8142
				array('title' => 'Outer Post'),
8143
			)
8144
		);
8145
		$Author->dataForAfterSave = array(
8146
			'Author' => array('user' => 'inner'),
8147
			'Post' => array(
8148
				array('title' => 'Inner Post'),
8149
			)
8150
		);
8151
		$this->assertTrue($Author->saveAssociated($data));
8152
 
8153
		// begin -> [ begin -> rollback ] -> rollback
8154
		$db = $this->_getMockDboSource(array('begin', 'commit', 'rollback'));
8155
		$db->expects($this->exactly(2))->method('begin')->will($this->returnValue(true));
8156
		$db->expects($this->never())->method('commit');
8157
		$db->expects($this->exactly(2))->method('rollback');
8158
		$Author->setDataSourceObject($db);
8159
		$Author->Post->setDataSourceObject($db);
8160
		$data = array(
8161
			'Author' => array('user' => 'outer'),
8162
			'Post' => array(
8163
				array('title' => 'Outer Post'),
8164
			)
8165
		);
8166
		$Author->dataForAfterSave = array(
8167
			'Author' => array('user' => 'inner', 'password' => $db->expression('PDO_EXCEPTION()')),
8168
			'Post' => array(
8169
				array('title' => 'Inner Post'),
8170
			)
8171
		);
8172
 
8173
		try {
8174
			$Author->saveAssociated($data);
8175
			$this->fail('No exception thrown');
8176
		} catch(Exception $e) {
8177
		}
8178
	}
8179
 
8180
/**
8181
 * A callback for testing nested saveMany.
8182
 *
8183
 * @param CakeEvent $event containing the Model
8184
 * @return void
8185
 */
8186
	public function nestedSaveMany($event) {
8187
		$Model = $event->subject;
8188
		$Model->saveMany($Model->dataForAfterSave, array('callbacks' => false));
8189
	}
8190
 
8191
/**
8192
 * A callback for testing nested saveAssociated.
8193
 *
8194
 * @param CakeEvent $event containing the Model
8195
 * @return void
8196
 */
8197
	public function nestedSaveAssociated($event) {
8198
		$Model = $event->subject;
8199
		$Model->saveAssociated($Model->dataForAfterSave, array('callbacks' => false));
8200
	}
8201
}