ModelWriteTest::testSaveAllNotDeepAssociated()   B
last analyzed

Complexity

Conditions 1
Paths 1

Size

Total Lines 82
Code Lines 61

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
cc 1
eloc 61
c 0
b 0
f 0
nc 1
nop 0
dl 0
loc 82
rs 8.7769

How to fix   Long Method   

Long Method

Small methods make your code easier to understand, in particular if combined with a good name. Besides, if your method is small, finding a good name is usually much easier.

For example, if you find yourself adding comments to a method's body, this is usually a good sign to extract the commented part to a new method, and use the comment as a starting point when coming up with a good name for this new method.

Commonly applied refactorings include:

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 View Code Duplication
class TestAuthor extends Author {
0 ignored issues
show
Duplication introduced by
This class seems to be duplicated in your project.

Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation.

You can also find more detailed suggestions in the “Code” section of your repository.

Loading history...
30
31
	public $hasMany = array(
32
		'Post' => array(
33
			'className' => 'TestPost'
34
		)
35
	);
36
37
	protected $_dataSourceObject;
38
39
/**
40
 * Helper method to set a datasource object
41
 *
42
 * @param Object $object The datasource object
43
 * @return void
44
 */
45
	public function setDataSourceObject($object) {
46
		$this->_dataSourceObject = $object;
47
	}
48
49
/**
50
 * Overwritten in order to return the directly set datasource object if
51
 * available
52
 *
53
 * @return DataSource
54
 */
55
	public function getDataSource() {
56
		if ($this->_dataSourceObject !== null) {
57
			return $this->_dataSourceObject;
58
		}
59
		return parent::getDataSource();
60
	}
61
62
}
63
64
/**
65
 * Helper class for testing with mocked datasources
66
 */
67 View Code Duplication
class TestPost extends Post {
0 ignored issues
show
Duplication introduced by
This class seems to be duplicated in your project.

Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation.

You can also find more detailed suggestions in the “Code” section of your repository.

Loading history...
68
69
	public $belongsTo = array(
70
		'Author' => array(
71
			'className' => 'TestAuthor'
72
		)
73
	);
74
75
	protected $_dataSourceObject;
76
77
/**
78
 * Helper method to set a datasource object
79
 *
80
 * @param Object $object The datasource object
81
 * @return void
82
 */
83
	public function setDataSourceObject($object) {
84
		$this->_dataSourceObject = $object;
85
	}
86
87
/**
88
 * Overwritten in order to return the directly set datasource object if
89
 * available
90
 *
91
 * @return DataSource
92
 */
93
	public function getDataSource() {
94
		if ($this->_dataSourceObject !== null) {
95
			return $this->_dataSourceObject;
96
		}
97
		return parent::getDataSource();
98
	}
99
100
}
101
102
/**
103
 * ModelWriteTest
104
 *
105
 * @package       Cake.Test.Case.Model
106
 */
107
class ModelWriteTest extends BaseModelTest {
108
109
/**
110
 * override locale to the default (eng).
111
 *
112
 * @return void
113
 */
114
	public function setUp() {
115
		parent::setUp();
116
		Configure::write('Config.language', 'eng');
117
	}
118
119
/**
120
 * Test save() failing when there is no data.
121
 *
122
 * @return void
123
 */
124
	public function testInsertNoData() {
125
		$this->loadFixtures('Bid');
126
		$Bid = ClassRegistry::init('Bid');
127
128
		$this->assertFalse($Bid->save());
129
130
		$result = $Bid->save(array('Bid' => array()));
131
		$this->assertFalse($result);
132
133
		$result = $Bid->save(array('Bid' => array('not in schema' => 1)));
134
		$this->assertFalse($result);
135
	}
136
137
/**
138
 * testInsertAnotherHabtmRecordWithSameForeignKey method
139
 *
140
 * @return void
141
 */
142
	public function testInsertAnotherHabtmRecordWithSameForeignKey() {
143
		$this->loadFixtures('JoinA', 'JoinB', 'JoinAB', 'JoinC', 'JoinAC');
144
		$TestModel = new JoinA();
145
146
		$result = $TestModel->JoinAsJoinB->findById(1);
147
		$expected = array(
148
			'JoinAsJoinB' => array(
149
				'id' => 1,
150
				'join_a_id' => 1,
151
				'join_b_id' => 2,
152
				'other' => 'Data for Join A 1 Join B 2',
153
				'created' => '2008-01-03 10:56:33',
154
				'updated' => '2008-01-03 10:56:33'
155
		));
156
		$this->assertEquals($expected, $result);
157
158
		$TestModel->JoinAsJoinB->create();
159
		$data = array(
160
			'join_a_id' => 1,
161
			'join_b_id' => 1,
162
			'other' => 'Data for Join A 1 Join B 1',
163
			'created' => '2008-01-03 10:56:44',
164
			'updated' => '2008-01-03 10:56:44'
165
		);
166
		$result = $TestModel->JoinAsJoinB->save($data);
167
		$lastInsertId = $TestModel->JoinAsJoinB->getLastInsertID();
168
		$data['id'] = $lastInsertId;
169
		$this->assertEquals(array('JoinAsJoinB' => $data), $result);
170
		$this->assertTrue($lastInsertId > 0);
171
172
		$result = $TestModel->JoinAsJoinB->findById(1);
173
		$expected = array(
174
			'JoinAsJoinB' => array(
175
				'id' => 1,
176
				'join_a_id' => 1,
177
				'join_b_id' => 2,
178
				'other' => 'Data for Join A 1 Join B 2',
179
				'created' => '2008-01-03 10:56:33',
180
				'updated' => '2008-01-03 10:56:33'
181
		));
182
		$this->assertEquals($expected, $result);
183
184
		$updatedValue = 'UPDATED Data for Join A 1 Join B 2';
185
		$TestModel->JoinAsJoinB->id = 1;
186
		$result = $TestModel->JoinAsJoinB->saveField('other', $updatedValue, false);
187
		$this->assertFalse(empty($result));
188
189
		$result = $TestModel->JoinAsJoinB->findById(1);
190
		$this->assertEquals($updatedValue, $result['JoinAsJoinB']['other']);
191
	}
192
193
/**
194
 * testSaveDateAsFirstEntry method
195
 *
196
 * @return void
197
 */
198
	public function testSaveDateAsFirstEntry() {
199
		$this->loadFixtures('Article', 'User', 'Comment', 'Attachment', 'Tag', 'ArticlesTag');
200
201
		$Article = new Article();
202
203
		$data = array(
204
			'Article' => array(
205
				'created' => array(
206
					'day' => '1',
207
					'month' => '1',
208
					'year' => '2008'
209
				),
210
				'title' => 'Test Title',
211
				'user_id' => 1
212
		));
213
		$Article->create();
214
		$result = $Article->save($data);
215
		$this->assertFalse(empty($result));
216
217
		$testResult = $Article->find('first', array('conditions' => array('Article.title' => 'Test Title')));
218
219
		$this->assertEquals($data['Article']['title'], $testResult['Article']['title']);
220
		$this->assertEquals('2008-01-01 00:00:00', $testResult['Article']['created']);
221
	}
222
223
/**
224
 * testUnderscoreFieldSave method
225
 *
226
 * @return void
227
 */
228
	public function testUnderscoreFieldSave() {
229
		$this->loadFixtures('UnderscoreField');
230
		$UnderscoreField = new UnderscoreField();
231
232
		$currentCount = $UnderscoreField->find('count');
233
		$this->assertEquals(3, $currentCount);
234
		$data = array('UnderscoreField' => array(
235
			'user_id' => '1',
236
			'my_model_has_a_field' => 'Content here',
237
			'body' => 'Body',
238
			'published' => 'Y',
239
			'another_field' => 4
240
		));
241
		$ret = $UnderscoreField->save($data);
242
		$this->assertFalse(empty($ret));
243
244
		$currentCount = $UnderscoreField->find('count');
245
		$this->assertEquals(4, $currentCount);
246
	}
247
248
/**
249
 * testAutoSaveUuid method
250
 *
251
 * @return void
252
 */
253 View Code Duplication
	public function testAutoSaveUuid() {
254
		// SQLite does not support non-integer primary keys
255
		$this->skipIf($this->db instanceof Sqlite, 'This test is not compatible with SQLite.');
256
257
		$this->loadFixtures('Uuid');
258
		$TestModel = new Uuid();
259
260
		$TestModel->save(array('title' => 'Test record'));
261
		$result = $TestModel->findByTitle('Test record');
0 ignored issues
show
Documentation Bug introduced by
The method findByTitle does not exist on object<Uuid>? Since you implemented __call, maybe consider adding a @method annotation.

If you implement __call and you know which methods are available, you can improve IDE auto-completion and static analysis by adding a @method annotation to the class.

This is often the case, when __call is implemented by a parent class and only the child class knows which methods exist:

class ParentClass {
    private $data = array();

    public function __call($method, array $args) {
        if (0 === strpos($method, 'get')) {
            return $this->data[strtolower(substr($method, 3))];
        }

        throw new \LogicException(sprintf('Unsupported method: %s', $method));
    }
}

/**
 * If this class knows which fields exist, you can specify the methods here:
 *
 * @method string getName()
 */
class SomeClass extends ParentClass { }
Loading history...
262
		$this->assertEquals(
263
			array('id', 'title', 'count', 'created', 'updated'),
264
			array_keys($result['Uuid'])
265
		);
266
		$this->assertEquals(36, strlen($result['Uuid']['id']));
267
	}
268
269
/**
270
 * Ensure that if the id key is null but present the save doesn't fail (with an
271
 * x sql error: "Column id specified twice")
272
 *
273
 * @return void
274
 */
275 View Code Duplication
	public function testSaveUuidNull() {
276
		// SQLite does not support non-integer primary keys
277
		$this->skipIf($this->db instanceof Sqlite, 'This test is not compatible with SQLite.');
278
279
		$this->loadFixtures('Uuid');
280
		$TestModel = new Uuid();
281
282
		$TestModel->save(array('title' => 'Test record', 'id' => null));
283
		$result = $TestModel->findByTitle('Test record');
0 ignored issues
show
Documentation Bug introduced by
The method findByTitle does not exist on object<Uuid>? Since you implemented __call, maybe consider adding a @method annotation.

If you implement __call and you know which methods are available, you can improve IDE auto-completion and static analysis by adding a @method annotation to the class.

This is often the case, when __call is implemented by a parent class and only the child class knows which methods exist:

class ParentClass {
    private $data = array();

    public function __call($method, array $args) {
        if (0 === strpos($method, 'get')) {
            return $this->data[strtolower(substr($method, 3))];
        }

        throw new \LogicException(sprintf('Unsupported method: %s', $method));
    }
}

/**
 * If this class knows which fields exist, you can specify the methods here:
 *
 * @method string getName()
 */
class SomeClass extends ParentClass { }
Loading history...
284
		$this->assertEquals(
285
			array('id', 'title', 'count', 'created', 'updated'),
286
			array_keys($result['Uuid'])
287
		);
288
		$this->assertEquals(36, strlen($result['Uuid']['id']));
289
	}
290
291
/**
292
 * testZeroDefaultFieldValue method
293
 *
294
 * @return void
295
 */
296
	public function testZeroDefaultFieldValue() {
297
		$this->skipIf($this->db instanceof Sqlite, 'SQLite uses loose typing, this operation is unsupported.');
298
299
		$this->loadFixtures('DataTest');
300
		$TestModel = new DataTest();
301
302
		$TestModel->create(array());
303
		$TestModel->save();
304
		$result = $TestModel->findById($TestModel->id);
0 ignored issues
show
Documentation Bug introduced by
The method findById does not exist on object<DataTest>? Since you implemented __call, maybe consider adding a @method annotation.

If you implement __call and you know which methods are available, you can improve IDE auto-completion and static analysis by adding a @method annotation to the class.

This is often the case, when __call is implemented by a parent class and only the child class knows which methods exist:

class ParentClass {
    private $data = array();

    public function __call($method, array $args) {
        if (0 === strpos($method, 'get')) {
            return $this->data[strtolower(substr($method, 3))];
        }

        throw new \LogicException(sprintf('Unsupported method: %s', $method));
    }
}

/**
 * If this class knows which fields exist, you can specify the methods here:
 *
 * @method string getName()
 */
class SomeClass extends ParentClass { }
Loading history...
305
		$this->assertEquals(0, $result['DataTest']['count']);
306
		$this->assertEquals(0, $result['DataTest']['float']);
307
	}
308
309
/**
310
 * Tests validation parameter order in custom validation methods
311
 *
312
 * @return void
313
 */
314
	public function testAllowSimulatedFields() {
315
		$TestModel = new ValidationTest1();
316
317
		$TestModel->create(array(
318
			'title' => 'foo',
319
			'bar' => 'baz'
320
		));
321
		$expected = array(
322
			'ValidationTest1' => array(
323
				'title' => 'foo',
324
				'bar' => 'baz'
325
		));
326
		$this->assertEquals($expected, $TestModel->data);
327
	}
328
329
/**
330
 * test that Caches are getting cleared on save().
331
 * ensure that both inflections of controller names are getting cleared
332
 * as URL for controller could be either overallFavorites/index or overall_favorites/index
333
 *
334
 * @return void
335
 */
336
	public function testCacheClearOnSave() {
337
		$_back = array(
338
			'check' => Configure::read('Cache.check'),
339
			'disable' => Configure::read('Cache.disable'),
340
		);
341
		Configure::write('Cache.check', true);
342
		Configure::write('Cache.disable', false);
343
344
		$this->loadFixtures('OverallFavorite');
345
		$OverallFavorite = new OverallFavorite();
346
347
		touch(CACHE . 'views' . DS . 'some_dir_overallfavorites_index.php');
348
		touch(CACHE . 'views' . DS . 'some_dir_overall_favorites_index.php');
349
350
		$data = array(
351
			'OverallFavorite' => array(
352
				'id' => 22,
353
				'model_type' => '8-track',
354
				'model_id' => '3',
355
				'priority' => '1'
356
			)
357
		);
358
		$OverallFavorite->create($data);
359
		$OverallFavorite->save();
360
361
		$this->assertFalse(file_exists(CACHE . 'views' . DS . 'some_dir_overallfavorites_index.php'));
362
		$this->assertFalse(file_exists(CACHE . 'views' . DS . 'some_dir_overall_favorites_index.php'));
363
364
		Configure::write('Cache.check', $_back['check']);
365
		Configure::write('Cache.disable', $_back['disable']);
366
	}
367
368
/**
369
 * test that save() resets whitelist on failed save
370
 *
371
 * @return void
372
 */
373
	public function testSaveFieldListResetsWhitelistOnFailedSave() {
374
		$this->loadFixtures('Bidding');
375
		$model = new Bidding();
376
		$whitelist = array('title');
377
		$model->whitelist = $whitelist;
378
		$result = $model->save(
379
			array(),
380
			array('fieldList' => array('body'))
381
		);
382
		$this->assertFalse($result);
383
		$this->assertEquals($whitelist, $model->whitelist);
384
	}
385
386
/**
387
 * testSaveWithCounterCache method
388
 *
389
 * @return void
390
 */
391
	public function testSaveWithCounterCache() {
392
		$this->loadFixtures('Syfile', 'Item', 'Image', 'Portfolio', 'ItemsPortfolio');
393
		$TestModel = new Syfile();
394
		$TestModel2 = new Item();
395
396
		$result = $TestModel->findById(1);
0 ignored issues
show
Documentation Bug introduced by
The method findById does not exist on object<Syfile>? Since you implemented __call, maybe consider adding a @method annotation.

If you implement __call and you know which methods are available, you can improve IDE auto-completion and static analysis by adding a @method annotation to the class.

This is often the case, when __call is implemented by a parent class and only the child class knows which methods exist:

class ParentClass {
    private $data = array();

    public function __call($method, array $args) {
        if (0 === strpos($method, 'get')) {
            return $this->data[strtolower(substr($method, 3))];
        }

        throw new \LogicException(sprintf('Unsupported method: %s', $method));
    }
}

/**
 * If this class knows which fields exist, you can specify the methods here:
 *
 * @method string getName()
 */
class SomeClass extends ParentClass { }
Loading history...
397
		$this->assertNull($result['Syfile']['item_count']);
398
399
		$TestModel2->save(array(
400
			'name' => 'Item 7',
401
			'syfile_id' => 1,
402
			'published' => false
403
		));
404
405
		$result = $TestModel->findById(1);
0 ignored issues
show
Documentation Bug introduced by
The method findById does not exist on object<Syfile>? Since you implemented __call, maybe consider adding a @method annotation.

If you implement __call and you know which methods are available, you can improve IDE auto-completion and static analysis by adding a @method annotation to the class.

This is often the case, when __call is implemented by a parent class and only the child class knows which methods exist:

class ParentClass {
    private $data = array();

    public function __call($method, array $args) {
        if (0 === strpos($method, 'get')) {
            return $this->data[strtolower(substr($method, 3))];
        }

        throw new \LogicException(sprintf('Unsupported method: %s', $method));
    }
}

/**
 * If this class knows which fields exist, you can specify the methods here:
 *
 * @method string getName()
 */
class SomeClass extends ParentClass { }
Loading history...
406
		$this->assertEquals(2, $result['Syfile']['item_count']);
407
408
		$TestModel2->delete(1);
409
		$result = $TestModel->findById(1);
0 ignored issues
show
Documentation Bug introduced by
The method findById does not exist on object<Syfile>? Since you implemented __call, maybe consider adding a @method annotation.

If you implement __call and you know which methods are available, you can improve IDE auto-completion and static analysis by adding a @method annotation to the class.

This is often the case, when __call is implemented by a parent class and only the child class knows which methods exist:

class ParentClass {
    private $data = array();

    public function __call($method, array $args) {
        if (0 === strpos($method, 'get')) {
            return $this->data[strtolower(substr($method, 3))];
        }

        throw new \LogicException(sprintf('Unsupported method: %s', $method));
    }
}

/**
 * If this class knows which fields exist, you can specify the methods here:
 *
 * @method string getName()
 */
class SomeClass extends ParentClass { }
Loading history...
410
		$this->assertEquals(1, $result['Syfile']['item_count']);
411
412
		$TestModel2->id = 2;
413
		$TestModel2->saveField('syfile_id', 1);
414
415
		$result = $TestModel->findById(1);
0 ignored issues
show
Documentation Bug introduced by
The method findById does not exist on object<Syfile>? Since you implemented __call, maybe consider adding a @method annotation.

If you implement __call and you know which methods are available, you can improve IDE auto-completion and static analysis by adding a @method annotation to the class.

This is often the case, when __call is implemented by a parent class and only the child class knows which methods exist:

class ParentClass {
    private $data = array();

    public function __call($method, array $args) {
        if (0 === strpos($method, 'get')) {
            return $this->data[strtolower(substr($method, 3))];
        }

        throw new \LogicException(sprintf('Unsupported method: %s', $method));
    }
}

/**
 * If this class knows which fields exist, you can specify the methods here:
 *
 * @method string getName()
 */
class SomeClass extends ParentClass { }
Loading history...
416
		$this->assertEquals(2, $result['Syfile']['item_count']);
417
418
		$result = $TestModel->findById(2);
0 ignored issues
show
Documentation Bug introduced by
The method findById does not exist on object<Syfile>? Since you implemented __call, maybe consider adding a @method annotation.

If you implement __call and you know which methods are available, you can improve IDE auto-completion and static analysis by adding a @method annotation to the class.

This is often the case, when __call is implemented by a parent class and only the child class knows which methods exist:

class ParentClass {
    private $data = array();

    public function __call($method, array $args) {
        if (0 === strpos($method, 'get')) {
            return $this->data[strtolower(substr($method, 3))];
        }

        throw new \LogicException(sprintf('Unsupported method: %s', $method));
    }
}

/**
 * If this class knows which fields exist, you can specify the methods here:
 *
 * @method string getName()
 */
class SomeClass extends ParentClass { }
Loading history...
419
		$this->assertEquals(0, $result['Syfile']['item_count']);
420
	}
421
422
/**
423
 * Tests that counter caches are updated when records are added
424
 *
425
 * @return void
426
 */
427
	public function testCounterCacheIncrease() {
428
		$this->loadFixtures('CounterCacheUser', 'CounterCachePost');
429
		$User = new CounterCacheUser();
430
		$Post = new CounterCachePost();
431
		$data = array('Post' => array(
432
			'id' => 22,
433
			'title' => 'New Post',
434
			'user_id' => 66
435
		));
436
437
		$Post->save($data);
438
		$user = $User->find('first', array(
439
			'conditions' => array('id' => 66),
440
			'recursive' => -1
441
		));
442
443
		$result = $user[$User->alias]['post_count'];
444
		$expected = 3;
445
		$this->assertEquals($expected, $result);
446
	}
447
448
/**
449
 * Tests that counter caches are updated when records are deleted
450
 *
451
 * @return void
452
 */
453
	public function testCounterCacheDecrease() {
454
		$this->loadFixtures('CounterCacheUser', 'CounterCachePost');
455
		$User = new CounterCacheUser();
456
		$Post = new CounterCachePost();
457
458
		$Post->delete(2);
459
		$user = $User->find('first', array(
460
			'conditions' => array('id' => 66),
461
			'recursive' => -1
462
		));
463
464
		$result = $user[$User->alias]['post_count'];
465
		$expected = 1;
466
		$this->assertEquals($expected, $result);
467
	}
468
469
/**
470
 * Tests that counter caches are updated when foreign keys of counted records change
471
 *
472
 * @return void
473
 */
474 View Code Duplication
	public function testCounterCacheUpdated() {
475
		$this->loadFixtures('CounterCacheUser', 'CounterCachePost');
476
		$User = new CounterCacheUser();
477
		$Post = new CounterCachePost();
478
479
		$data = $Post->find('first', array(
480
			'conditions' => array('id' => 1),
481
			'recursive' => -1
482
		));
483
		$data[$Post->alias]['user_id'] = 301;
484
		$Post->save($data);
485
486
		$users = $User->find('all', array('order' => 'User.id'));
487
		$this->assertEquals(1, $users[0]['User']['post_count']);
488
		$this->assertEquals(2, $users[1]['User']['post_count']);
489
	}
490
491
/**
492
 * Test counter cache with models that use a non-standard (i.e. not using 'id')
493
 * as their primary key.
494
 *
495
 * @return void
496
 */
497 View Code Duplication
	public function testCounterCacheWithNonstandardPrimaryKey() {
498
		$this->loadFixtures(
499
			'CounterCacheUserNonstandardPrimaryKey',
500
			'CounterCachePostNonstandardPrimaryKey'
501
		);
502
503
		$User = new CounterCacheUserNonstandardPrimaryKey();
504
		$Post = new CounterCachePostNonstandardPrimaryKey();
505
506
		$data = $Post->find('first', array(
507
			'conditions' => array('pid' => 1),
508
			'recursive' => -1
509
		));
510
		$data[$Post->alias]['uid'] = 301;
511
		$Post->save($data);
512
513
		$users = $User->find('all', array('order' => 'User.uid'));
514
		$this->assertEquals(1, $users[0]['User']['post_count']);
515
		$this->assertEquals(2, $users[1]['User']['post_count']);
516
	}
517
518
/**
519
 * test Counter Cache With Self Joining table
520
 *
521
 * @return void
522
 */
523
	public function testCounterCacheWithSelfJoin() {
524
		$this->skipIf($this->db instanceof Sqlite, 'SQLite 2.x does not support ALTER TABLE ADD COLUMN');
525
526
		$this->loadFixtures('CategoryThread');
527
		$column = 'COLUMN ';
528
		if ($this->db instanceof Sqlserver) {
529
			$column = '';
530
		}
531
		$column .= $this->db->buildColumn(array('name' => 'child_count', 'type' => 'integer'));
532
		$this->db->query('ALTER TABLE ' . $this->db->fullTableName('category_threads') . ' ADD ' . $column);
533
		$this->db->flushMethodCache();
534
		$Category = new CategoryThread();
535
		$result = $Category->updateAll(array('CategoryThread.name' => "'updated'"), array('CategoryThread.parent_id' => 5));
536
		$this->assertFalse(empty($result));
537
538
		$Category = new CategoryThread();
539
		$Category->belongsTo['ParentCategory']['counterCache'] = 'child_count';
540
		$Category->updateCounterCache(array('parent_id' => 5));
541
		$result = Hash::extract($Category->find('all', array('conditions' => array('CategoryThread.id' => 5))), '{n}.CategoryThread.child_count');
0 ignored issues
show
Bug introduced by
It seems like $Category->find('all', a...egoryThread.id' => 5))) targeting Model::find() can also be of type null; however, Hash::extract() does only seem to accept array, maybe add an additional type check?

This check looks at variables that are passed out again to other methods.

If the outgoing method call has stricter type requirements than the method itself, an issue is raised.

An additional type check may prevent trouble.

Loading history...
542
		$expected = array(1);
543
		$this->assertEquals($expected, $result);
544
	}
545
546
/**
547
 * testSaveWithCounterCacheScope method
548
 *
549
 * @return void
550
 */
551
	public function testSaveWithCounterCacheScope() {
552
		$this->loadFixtures('Syfile', 'Item', 'Image', 'ItemsPortfolio', 'Portfolio');
553
		$TestModel = new Syfile();
554
		$TestModel2 = new Item();
555
		$TestModel2->belongsTo['Syfile']['counterCache'] = true;
556
		$TestModel2->belongsTo['Syfile']['counterScope'] = array('published' => true);
557
558
		$result = $TestModel->findById(1);
0 ignored issues
show
Documentation Bug introduced by
The method findById does not exist on object<Syfile>? Since you implemented __call, maybe consider adding a @method annotation.

If you implement __call and you know which methods are available, you can improve IDE auto-completion and static analysis by adding a @method annotation to the class.

This is often the case, when __call is implemented by a parent class and only the child class knows which methods exist:

class ParentClass {
    private $data = array();

    public function __call($method, array $args) {
        if (0 === strpos($method, 'get')) {
            return $this->data[strtolower(substr($method, 3))];
        }

        throw new \LogicException(sprintf('Unsupported method: %s', $method));
    }
}

/**
 * If this class knows which fields exist, you can specify the methods here:
 *
 * @method string getName()
 */
class SomeClass extends ParentClass { }
Loading history...
559
		$this->assertNull($result['Syfile']['item_count']);
560
561
		$TestModel2->save(array(
562
			'name' => 'Item 7',
563
			'syfile_id' => 1,
564
			'published' => true
565
		));
566
567
		$result = $TestModel->findById(1);
0 ignored issues
show
Documentation Bug introduced by
The method findById does not exist on object<Syfile>? Since you implemented __call, maybe consider adding a @method annotation.

If you implement __call and you know which methods are available, you can improve IDE auto-completion and static analysis by adding a @method annotation to the class.

This is often the case, when __call is implemented by a parent class and only the child class knows which methods exist:

class ParentClass {
    private $data = array();

    public function __call($method, array $args) {
        if (0 === strpos($method, 'get')) {
            return $this->data[strtolower(substr($method, 3))];
        }

        throw new \LogicException(sprintf('Unsupported method: %s', $method));
    }
}

/**
 * If this class knows which fields exist, you can specify the methods here:
 *
 * @method string getName()
 */
class SomeClass extends ParentClass { }
Loading history...
568
569
		$this->assertEquals(1, $result['Syfile']['item_count']);
570
571
		$TestModel2->id = 1;
572
		$TestModel2->saveField('published', true);
573
		$result = $TestModel->findById(1);
0 ignored issues
show
Documentation Bug introduced by
The method findById does not exist on object<Syfile>? Since you implemented __call, maybe consider adding a @method annotation.

If you implement __call and you know which methods are available, you can improve IDE auto-completion and static analysis by adding a @method annotation to the class.

This is often the case, when __call is implemented by a parent class and only the child class knows which methods exist:

class ParentClass {
    private $data = array();

    public function __call($method, array $args) {
        if (0 === strpos($method, 'get')) {
            return $this->data[strtolower(substr($method, 3))];
        }

        throw new \LogicException(sprintf('Unsupported method: %s', $method));
    }
}

/**
 * If this class knows which fields exist, you can specify the methods here:
 *
 * @method string getName()
 */
class SomeClass extends ParentClass { }
Loading history...
574
		$this->assertEquals(2, $result['Syfile']['item_count']);
575
576
		$TestModel2->save(array(
577
			'id' => 1,
578
			'syfile_id' => 1,
579
			'published' => false
580
		));
581
582
		$result = $TestModel->findById(1);
0 ignored issues
show
Documentation Bug introduced by
The method findById does not exist on object<Syfile>? Since you implemented __call, maybe consider adding a @method annotation.

If you implement __call and you know which methods are available, you can improve IDE auto-completion and static analysis by adding a @method annotation to the class.

This is often the case, when __call is implemented by a parent class and only the child class knows which methods exist:

class ParentClass {
    private $data = array();

    public function __call($method, array $args) {
        if (0 === strpos($method, 'get')) {
            return $this->data[strtolower(substr($method, 3))];
        }

        throw new \LogicException(sprintf('Unsupported method: %s', $method));
    }
}

/**
 * If this class knows which fields exist, you can specify the methods here:
 *
 * @method string getName()
 */
class SomeClass extends ParentClass { }
Loading history...
583
		$this->assertEquals(1, $result['Syfile']['item_count']);
584
	}
585
586
/**
587
 * Tests having multiple counter caches for an associated model
588
 *
589
 * @return void
590
 */
591
	public function testCounterCacheMultipleCaches() {
592
		$this->loadFixtures('CounterCacheUser', 'CounterCachePost');
593
		$User = new CounterCacheUser();
594
		$Post = new CounterCachePost();
595
		$Post->unbindModel(array('belongsTo' => array('User')), false);
596
		$Post->bindModel(array(
597
			'belongsTo' => array(
598
				'User' => array(
599
					'className' => 'CounterCacheUser',
600
					'foreignKey' => 'user_id',
601
					'counterCache' => array(
602
						true,
603
						'posts_published' => array('Post.published' => true)
604
					)
605
				)
606
			)
607
		), false);
608
609
		// Count Increase
610
		$data = array('Post' => array(
611
			'id' => 22,
612
			'title' => 'New Post',
613
			'user_id' => 66,
614
			'published' => true
615
		));
616
		$Post->save($data);
617
		$result = $User->find('first', array(
618
			'conditions' => array('id' => 66),
619
			'recursive' => -1
620
		));
621
		$this->assertEquals(3, $result[$User->alias]['post_count']);
622
		$this->assertEquals(2, $result[$User->alias]['posts_published']);
623
624
		// Count decrease
625
		$Post->delete(1);
626
		$result = $User->find('first', array(
627
			'conditions' => array('id' => 66),
628
			'recursive' => -1
629
		));
630
		$this->assertEquals(2, $result[$User->alias]['post_count']);
631
		$this->assertEquals(2, $result[$User->alias]['posts_published']);
632
633
		// Count update
634
		$data = $Post->find('first', array(
635
			'conditions' => array('id' => 1),
636
			'recursive' => -1
637
		));
638
		$data[$Post->alias]['user_id'] = 301;
639
		$Post->save($data);
640
		$result = $User->find('all', array('order' => 'User.id'));
641
		$this->assertEquals(2, $result[0]['User']['post_count']);
642
		$this->assertEquals(1, $result[1]['User']['posts_published']);
643
	}
644
645
/**
646
 * Tests that counter caches are unchanged when using 'counterCache' => false
647
 *
648
 * @return void
649
 */
650 View Code Duplication
	public function testCounterCacheSkip() {
651
		$this->loadFixtures('CounterCacheUser', 'CounterCachePost');
652
		$User = new CounterCacheUser();
653
		$Post = new CounterCachePost();
654
655
		$data = $Post->find('first', array(
656
			'conditions' => array('id' => 1),
657
			'recursive' => -1
658
		));
659
		$data[$Post->alias]['user_id'] = 301;
660
		$Post->save($data, array('counterCache' => false));
661
662
		$users = $User->find('all', array('order' => 'User.id'));
663
		$this->assertEquals(2, $users[0]['User']['post_count']);
664
		$this->assertEquals(1, $users[1]['User']['post_count']);
665
	}
666
667
/**
668
 * test that beforeValidate returning false can abort saves.
669
 *
670
 * @return void
671
 */
672 View Code Duplication
	public function testBeforeValidateSaveAbortion() {
673
		$this->loadFixtures('Post');
674
		$Model = new CallbackPostTestModel();
675
		$Model->beforeValidateReturn = false;
676
677
		$data = array(
678
			'title' => 'new article',
679
			'body' => 'this is some text.'
680
		);
681
		$Model->create();
682
		$result = $Model->save($data);
683
		$this->assertFalse($result);
684
	}
685
686
/**
687
 * test that beforeSave returning false can abort saves.
688
 *
689
 * @return void
690
 */
691 View Code Duplication
	public function testBeforeSaveSaveAbortion() {
692
		$this->loadFixtures('Post');
693
		$Model = new CallbackPostTestModel();
694
		$Model->beforeSaveReturn = false;
695
696
		$data = array(
697
			'title' => 'new article',
698
			'body' => 'this is some text.'
699
		);
700
		$Model->create();
701
		$result = $Model->save($data);
702
		$this->assertFalse($result);
703
	}
704
705
/**
706
 * testSaveField method
707
 *
708
 * @return void
709
 */
710
	public function testSaveField() {
711
		$this->loadFixtures('Article');
712
		$TestModel = new Article();
713
714
		$TestModel->id = 1;
715
		$result = $TestModel->saveField('title', 'New First Article');
716
		$this->assertFalse(empty($result));
717
718
		$TestModel->recursive = -1;
719
		$result = $TestModel->read(array('id', 'user_id', 'title', 'body'), 1);
720
		$expected = array('Article' => array(
721
			'id' => '1',
722
			'user_id' => '1',
723
			'title' => 'New First Article',
724
			'body' => 'First Article Body'
725
		));
726
		$this->assertEquals($expected, $result);
727
728
		$TestModel->id = 1;
729
		$result = $TestModel->saveField('title', '');
730
		$this->assertFalse(empty($result));
731
732
		$TestModel->recursive = -1;
733
		$result = $TestModel->read(array('id', 'user_id', 'title', 'body'), 1);
734
		$expected = array('Article' => array(
735
			'id' => '1',
736
			'user_id' => '1',
737
			'title' => '',
738
			'body' => 'First Article Body'
739
		));
740
		$result['Article']['title'] = trim($result['Article']['title']);
741
		$this->assertEquals($expected, $result);
742
743
		$TestModel->id = 1;
744
		$TestModel->set('body', 'Messed up data');
745
		$result = $TestModel->saveField('title', 'First Article');
746
		$this->assertFalse(empty($result));
747
		$result = $TestModel->read(array('id', 'user_id', 'title', 'body'), 1);
748
		$expected = array('Article' => array(
749
			'id' => '1',
750
			'user_id' => '1',
751
			'title' => 'First Article',
752
			'body' => 'First Article Body'
753
		));
754
		$this->assertEquals($expected, $result);
755
756
		$TestModel->recursive = -1;
757
		$TestModel->read(array('id', 'user_id', 'title', 'body'), 1);
758
759
		$TestModel->id = 1;
760
		$result = $TestModel->saveField('title', '', true);
761
		$this->assertFalse($result);
762
763
		$TestModel->recursive = -1;
764
		$TestModel->id = 1;
765
		$result = $TestModel->saveField('user_id', 9999);
766
		$this->assertTrue((bool)$result);
767
768
		$result = $TestModel->read(array('id', 'user_id'), 1);
769
		$expected = array('Article' => array(
770
			'id' => '1',
771
			'user_id' => '9999',
772
		));
773
		$this->assertEquals($expected, $result);
774
775
		$this->loadFixtures('Node', 'Dependency');
776
		$Node = new Node();
777
		$Node->set('id', 1);
778
		$result = $Node->read();
779
		$this->assertEquals(array('Second'), Hash::extract($result, 'ParentNode.{n}.name'));
0 ignored issues
show
Bug introduced by
It seems like $result defined by $Node->read() on line 778 can also be of type false or null; however, Hash::extract() does only seem to accept array, maybe add an additional type check?

If a method or function can return multiple different values and unless you are sure that you only can receive a single value in this context, we recommend to add an additional type check:

/**
 * @return array|string
 */
function returnsDifferentValues($x) {
    if ($x) {
        return 'foo';
    }

    return array();
}

$x = returnsDifferentValues($y);
if (is_array($x)) {
    // $x is an array.
}

If this a common case that PHP Analyzer should handle natively, please let us know by opening an issue.

Loading history...
780
781
		$Node->saveField('state', 10);
782
		$result = $Node->read();
783
		$this->assertEquals(array('Second'), Hash::extract($result, 'ParentNode.{n}.name'));
0 ignored issues
show
Bug introduced by
It seems like $result defined by $Node->read() on line 782 can also be of type false or null; however, Hash::extract() does only seem to accept array, maybe add an additional type check?

If a method or function can return multiple different values and unless you are sure that you only can receive a single value in this context, we recommend to add an additional type check:

/**
 * @return array|string
 */
function returnsDifferentValues($x) {
    if ($x) {
        return 'foo';
    }

    return array();
}

$x = returnsDifferentValues($y);
if (is_array($x)) {
    // $x is an array.
}

If this a common case that PHP Analyzer should handle natively, please let us know by opening an issue.

Loading history...
784
	}
785
786
/**
787
 * testSaveWithCreate method
788
 *
789
 * @return void
790
 */
791
	public function testSaveWithCreate() {
792
		$this->loadFixtures(
793
			'User',
794
			'Article',
795
			'User',
796
			'Comment',
797
			'Tag',
798
			'ArticlesTag',
799
			'Attachment'
800
		);
801
		$TestModel = new User();
802
803
		$data = array('User' => array(
804
			'user' => 'user',
805
			'password' => ''
806
		));
807
		$result = $TestModel->save($data);
808
		$this->assertFalse($result);
809
		$this->assertTrue(!empty($TestModel->validationErrors));
810
811
		$TestModel = new Article();
812
813
		$data = array('Article' => array(
814
			'user_id' => '',
815
			'title' => '',
816
			'body' => ''
817
		));
818
		$result = $TestModel->create($data) && $TestModel->save();
819
		$this->assertFalse($result);
820
		$this->assertTrue(!empty($TestModel->validationErrors));
821
822
		$data = array('Article' => array(
823
			'id' => 1,
824
			'user_id' => '1',
825
			'title' => 'New First Article',
826
			'body' => ''
827
		));
828
		$result = $TestModel->create($data) && $TestModel->save();
829
		$this->assertFalse($result);
830
831
		$data = array('Article' => array(
832
			'id' => 1,
833
			'title' => 'New First Article'
834
		));
835
		$result = $TestModel->create() && $TestModel->save($data, false);
836
		$this->assertFalse(empty($result));
837
838
		$TestModel->recursive = -1;
839
		$result = $TestModel->read(array('id', 'user_id', 'title', 'body', 'published'), 1);
840
		$expected = array('Article' => array(
841
			'id' => '1',
842
			'user_id' => '1',
843
			'title' => 'New First Article',
844
			'body' => 'First Article Body',
845
			'published' => 'N'
846
		));
847
		$this->assertEquals($expected, $result);
848
849
		$data = array('Article' => array(
850
			'id' => 1,
851
			'user_id' => '2',
852
			'title' => 'First Article',
853
			'body' => 'New First Article Body',
854
			'published' => 'Y'
855
		));
856
		$result = $TestModel->create() && $TestModel->save($data, true, array('id', 'title', 'published'));
857
		$this->assertFalse(empty($result));
858
859
		$TestModel->recursive = -1;
860
		$result = $TestModel->read(array('id', 'user_id', 'title', 'body', 'published'), 1);
861
		$expected = array('Article' => array(
862
			'id' => '1',
863
			'user_id' => '1',
864
			'title' => 'First Article',
865
			'body' => 'First Article Body',
866
			'published' => 'Y'
867
		));
868
		$this->assertEquals($expected, $result);
869
870
		$data = array(
871
			'Article' => array(
872
				'user_id' => '2',
873
				'title' => 'New Article',
874
				'body' => 'New Article Body',
875
				'created' => '2007-03-18 14:55:23',
876
				'updated' => '2007-03-18 14:57:31'
877
			),
878
			'Tag' => array('Tag' => array(1, 3))
879
		);
880
		$TestModel->create();
881
		$result = $TestModel->create() && $TestModel->save($data);
882
		$this->assertFalse(empty($result));
883
884
		$TestModel->recursive = 2;
885
		$result = $TestModel->read(null, 4);
886
		$expected = array(
887
			'Article' => array(
888
				'id' => '4',
889
				'user_id' => '2',
890
				'title' => 'New Article',
891
				'body' => 'New Article Body',
892
				'published' => 'N',
893
				'created' => '2007-03-18 14:55:23',
894
				'updated' => '2007-03-18 14:57:31'
895
			),
896
			'User' => array(
897
				'id' => '2',
898
				'user' => 'nate',
899
				'password' => '5f4dcc3b5aa765d61d8327deb882cf99',
900
				'created' => '2007-03-17 01:18:23',
901
				'updated' => '2007-03-17 01:20:31'
902
			),
903
			'Comment' => array(),
904
			'Tag' => array(
905
				array(
906
					'id' => '1',
907
					'tag' => 'tag1',
908
					'created' => '2007-03-18 12:22:23',
909
					'updated' => '2007-03-18 12:24:31'
910
				),
911
				array(
912
					'id' => '3',
913
					'tag' => 'tag3',
914
					'created' => '2007-03-18 12:26:23',
915
					'updated' => '2007-03-18 12:28:31'
916
		)));
917
		$this->assertEquals($expected, $result);
918
919
		$data = array('Comment' => array(
920
			'article_id' => '4',
921
			'user_id' => '1',
922
			'comment' => 'Comment New Article',
923
			'published' => 'Y',
924
			'created' => '2007-03-18 14:57:23',
925
			'updated' => '2007-03-18 14:59:31'
926
		));
927
		$result = $TestModel->Comment->create() && $TestModel->Comment->save($data);
928
		$this->assertFalse(empty($result));
929
930
		$data = array('Attachment' => array(
931
			'comment_id' => '7',
932
			'attachment' => 'newattachment.zip',
933
			'created' => '2007-03-18 15:02:23',
934
			'updated' => '2007-03-18 15:04:31'
935
		));
936
		$result = $TestModel->Comment->Attachment->save($data);
937
		$this->assertFalse(empty($result));
938
939
		$TestModel->recursive = 2;
940
		$result = $TestModel->read(null, 4);
941
		$expected = array(
942
			'Article' => array(
943
				'id' => '4',
944
				'user_id' => '2',
945
				'title' => 'New Article',
946
				'body' => 'New Article Body',
947
				'published' => 'N',
948
				'created' => '2007-03-18 14:55:23',
949
				'updated' => '2007-03-18 14:57:31'
950
			),
951
			'User' => array(
952
				'id' => '2',
953
				'user' => 'nate',
954
				'password' => '5f4dcc3b5aa765d61d8327deb882cf99',
955
				'created' => '2007-03-17 01:18:23',
956
				'updated' => '2007-03-17 01:20:31'
957
			),
958
			'Comment' => array(
959
				array(
960
					'id' => '7',
961
					'article_id' => '4',
962
					'user_id' => '1',
963
					'comment' => 'Comment New Article',
964
					'published' => 'Y',
965
					'created' => '2007-03-18 14:57:23',
966
					'updated' => '2007-03-18 14:59:31',
967
					'Article' => array(
968
						'id' => '4',
969
						'user_id' => '2',
970
						'title' => 'New Article',
971
						'body' => 'New Article Body',
972
						'published' => 'N',
973
						'created' => '2007-03-18 14:55:23',
974
						'updated' => '2007-03-18 14:57:31'
975
					),
976
					'User' => array(
977
						'id' => '1',
978
						'user' => 'mariano',
979
						'password' => '5f4dcc3b5aa765d61d8327deb882cf99',
980
						'created' => '2007-03-17 01:16:23',
981
						'updated' => '2007-03-17 01:18:31'
982
					),
983
					'Attachment' => array(
984
						'id' => '2',
985
						'comment_id' => '7',
986
						'attachment' => 'newattachment.zip',
987
						'created' => '2007-03-18 15:02:23',
988
						'updated' => '2007-03-18 15:04:31'
989
			))),
990
			'Tag' => array(
991
				array(
992
					'id' => '1',
993
					'tag' => 'tag1',
994
					'created' => '2007-03-18 12:22:23',
995
					'updated' => '2007-03-18 12:24:31'
996
				),
997
				array(
998
					'id' => '3',
999
					'tag' => 'tag3',
1000
					'created' => '2007-03-18 12:26:23',
1001
					'updated' => '2007-03-18 12:28:31'
1002
		)));
1003
1004
		$this->assertEquals($expected, $result);
1005
	}
1006
1007
/**
1008
 * test that a null Id doesn't cause errors
1009
 *
1010
 * @return void
1011
 */
1012
	public function testSaveWithNullId() {
1013
		$this->loadFixtures('User');
1014
		$User = new User();
1015
		$User->read(null, 1);
1016
		$User->data['User']['id'] = null;
1017
		$result = $User->save(array('password' => 'test'));
1018
		$this->assertFalse(empty($result));
1019
		$this->assertTrue($User->id > 0);
1020
1021
		$User->read(null, 2);
1022
		$User->data['User']['id'] = null;
1023
		$result = $User->save(array('password' => 'test'));
1024
		$this->assertFalse(empty($result));
1025
		$this->assertTrue($User->id > 0);
1026
1027
		$User->data['User'] = array('password' => 'something');
1028
		$result = $User->save();
1029
		$this->assertFalse(empty($result));
1030
		$result = $User->read();
1031
		$this->assertEquals('something', $User->data['User']['password']);
1032
	}
1033
1034
/**
1035
 * testSaveWithSet method
1036
 *
1037
 * @return void
1038
 */
1039
	public function testSaveWithSet() {
1040
		$this->loadFixtures('Article');
1041
		$TestModel = new Article();
1042
1043
		// Create record we will be updating later
1044
1045
		$data = array('Article' => array(
1046
			'user_id' => '1',
1047
			'title' => 'Fourth Article',
1048
			'body' => 'Fourth Article Body',
1049
			'published' => 'Y'
1050
		));
1051
		$result = $TestModel->create() && $TestModel->save($data);
1052
		$this->assertFalse(empty($result));
1053
1054
		// Check record we created
1055
1056
		$TestModel->recursive = -1;
1057
		$result = $TestModel->read(array('id', 'user_id', 'title', 'body', 'published'), 4);
1058
		$expected = array('Article' => array(
1059
			'id' => '4',
1060
			'user_id' => '1',
1061
			'title' => 'Fourth Article',
1062
			'body' => 'Fourth Article Body',
1063
			'published' => 'Y'
1064
		));
1065
		$this->assertEquals($expected, $result);
1066
1067
		// Create new record just to overlap Model->id on previously created record
1068
1069
		$data = array('Article' => array(
1070
			'user_id' => '4',
1071
			'title' => 'Fifth Article',
1072
			'body' => 'Fifth Article Body',
1073
			'published' => 'Y'
1074
		));
1075
		$result = $TestModel->create() && $TestModel->save($data);
1076
		$this->assertFalse(empty($result));
1077
1078
		$TestModel->recursive = -1;
1079
		$result = $TestModel->read(array('id', 'user_id', 'title', 'body', 'published'), 5);
1080
		$expected = array('Article' => array(
1081
			'id' => '5',
1082
			'user_id' => '4',
1083
			'title' => 'Fifth Article',
1084
			'body' => 'Fifth Article Body',
1085
			'published' => 'Y'
1086
		));
1087
		$this->assertEquals($expected, $result);
1088
1089
		// Go back and edit the first article we created, starting by checking it's still there
1090
1091
		$TestModel->recursive = -1;
1092
		$result = $TestModel->read(array('id', 'user_id', 'title', 'body', 'published'), 4);
1093
		$expected = array('Article' => array(
1094
			'id' => '4',
1095
			'user_id' => '1',
1096
			'title' => 'Fourth Article',
1097
			'body' => 'Fourth Article Body',
1098
			'published' => 'Y'
1099
		));
1100
		$this->assertEquals($expected, $result);
1101
1102
		// And now do the update with set()
1103
1104
		$data = array('Article' => array(
1105
			'id' => '4',
1106
			'title' => 'Fourth Article - New Title',
1107
			'published' => 'N'
1108
		));
1109
		$result = $TestModel->set($data) && $TestModel->save();
1110
		$this->assertFalse(empty($result));
1111
1112
		$TestModel->recursive = -1;
1113
		$result = $TestModel->read(array('id', 'user_id', 'title', 'body', 'published'), 4);
1114
		$expected = array('Article' => array(
1115
			'id' => '4',
1116
			'user_id' => '1',
1117
			'title' => 'Fourth Article - New Title',
1118
			'body' => 'Fourth Article Body',
1119
			'published' => 'N'
1120
		));
1121
		$this->assertEquals($expected, $result);
1122
1123
		$TestModel->recursive = -1;
1124
		$result = $TestModel->read(array('id', 'user_id', 'title', 'body', 'published'), 5);
1125
		$expected = array('Article' => array(
1126
			'id' => '5',
1127
			'user_id' => '4',
1128
			'title' => 'Fifth Article',
1129
			'body' => 'Fifth Article Body',
1130
			'published' => 'Y'
1131
		));
1132
		$this->assertEquals($expected, $result);
1133
1134
		$data = array('Article' => array('id' => '5', 'title' => 'Fifth Article - New Title 5'));
1135
		$result = ($TestModel->set($data) && $TestModel->save());
1136
		$this->assertFalse(empty($result));
1137
1138
		$TestModel->recursive = -1;
1139
		$result = $TestModel->read(array('id', 'user_id', 'title', 'body', 'published'), 5);
1140
		$expected = array('Article' => array(
1141
			'id' => '5',
1142
			'user_id' => '4',
1143
			'title' => 'Fifth Article - New Title 5',
1144
			'body' => 'Fifth Article Body',
1145
			'published' => 'Y'
1146
		));
1147
		$this->assertEquals($expected, $result);
1148
1149
		$TestModel->recursive = -1;
1150
		$result = $TestModel->find('all', array(
1151
			'fields' => array('id', 'title'),
1152
			'order' => array('Article.id' => 'ASC')
1153
		));
1154
		$expected = array(
1155
			array('Article' => array('id' => 1, 'title' => 'First Article')),
1156
			array('Article' => array('id' => 2, 'title' => 'Second Article')),
1157
			array('Article' => array('id' => 3, 'title' => 'Third Article')),
1158
			array('Article' => array('id' => 4, 'title' => 'Fourth Article - New Title')),
1159
			array('Article' => array('id' => 5, 'title' => 'Fifth Article - New Title 5'))
1160
		);
1161
		$this->assertEquals($expected, $result);
1162
	}
1163
1164
/**
1165
 * testSaveWithNonExistentFields method
1166
 *
1167
 * @return void
1168
 */
1169
	public function testSaveWithNonExistentFields() {
1170
		$this->loadFixtures('Article');
1171
		$TestModel = new Article();
1172
		$TestModel->recursive = -1;
1173
1174
		$data = array(
1175
			'non_existent' => 'This field does not exist',
1176
			'user_id' => '1',
1177
			'title' => 'Fourth Article - New Title',
1178
			'body' => 'Fourth Article Body',
1179
			'published' => 'N'
1180
		);
1181
		$result = $TestModel->create() && $TestModel->save($data);
1182
		$this->assertFalse(empty($result));
1183
1184
		$expected = array('Article' => array(
1185
			'id' => '4',
1186
			'user_id' => '1',
1187
			'title' => 'Fourth Article - New Title',
1188
			'body' => 'Fourth Article Body',
1189
			'published' => 'N'
1190
		));
1191
		$result = $TestModel->read(array('id', 'user_id', 'title', 'body', 'published'), 4);
1192
		$this->assertEquals($expected, $result);
1193
1194
		$data = array(
1195
			'user_id' => '1',
1196
			'non_existent' => 'This field does not exist',
1197
			'title' => 'Fifth Article - New Title',
1198
			'body' => 'Fifth Article Body',
1199
			'published' => 'N'
1200
		);
1201
		$result = $TestModel->create() && $TestModel->save($data);
1202
		$this->assertFalse(empty($result));
1203
1204
		$expected = array('Article' => array(
1205
			'id' => '5',
1206
			'user_id' => '1',
1207
			'title' => 'Fifth Article - New Title',
1208
			'body' => 'Fifth Article Body',
1209
			'published' => 'N'
1210
		));
1211
		$result = $TestModel->read(array('id', 'user_id', 'title', 'body', 'published'), 5);
1212
		$this->assertEquals($expected, $result);
1213
	}
1214
1215
/**
1216
 * testSaveFromXml method
1217
 *
1218
 * @return void
1219
 */
1220
	public function testSaveFromXml() {
1221
		$this->markTestSkipped('This feature needs to be fixed or dropped');
1222
		$this->loadFixtures('Article');
1223
		App::uses('Xml', 'Utility');
1224
1225
		$Article = new Article();
1226
		$result = $Article->save(Xml::build('<article title="test xml" user_id="5" />'));
1227
		$this->assertFalse(empty($result));
1228
		$results = $Article->find('first', array('conditions' => array('Article.title' => 'test xml')));
1229
		$this->assertFalse(empty($results));
1230
1231
		$result = $Article->save(Xml::build('<article><title>testing</title><user_id>6</user_id></article>'));
1232
		$this->assertFalse(empty($result));
1233
		$results = $Article->find('first', array('conditions' => array('Article.title' => 'testing')));
1234
		$this->assertFalse(empty($results));
1235
1236
		$result = $Article->save(Xml::build('<article><title>testing with DOMDocument</title><user_id>7</user_id></article>', array('return' => 'domdocument')));
1237
		$this->assertFalse(empty($result));
1238
		$results = $Article->find('first', array('conditions' => array('Article.title' => 'testing with DOMDocument')));
1239
		$this->assertFalse(empty($results));
1240
	}
1241
1242
/**
1243
 * testSaveHabtm method
1244
 *
1245
 * @return void
1246
 */
1247
	public function testSaveHabtm() {
1248
		$this->loadFixtures('Article', 'User', 'Comment', 'Tag', 'ArticlesTag');
1249
		$TestModel = new Article();
1250
1251
		$result = $TestModel->findById(2);
0 ignored issues
show
Documentation Bug introduced by
The method findById does not exist on object<Article>? Since you implemented __call, maybe consider adding a @method annotation.

If you implement __call and you know which methods are available, you can improve IDE auto-completion and static analysis by adding a @method annotation to the class.

This is often the case, when __call is implemented by a parent class and only the child class knows which methods exist:

class ParentClass {
    private $data = array();

    public function __call($method, array $args) {
        if (0 === strpos($method, 'get')) {
            return $this->data[strtolower(substr($method, 3))];
        }

        throw new \LogicException(sprintf('Unsupported method: %s', $method));
    }
}

/**
 * If this class knows which fields exist, you can specify the methods here:
 *
 * @method string getName()
 */
class SomeClass extends ParentClass { }
Loading history...
1252
		$expected = array(
1253
			'Article' => array(
1254
				'id' => '2',
1255
				'user_id' => '3',
1256
				'title' => 'Second Article',
1257
				'body' => 'Second Article Body',
1258
				'published' => 'Y',
1259
				'created' => '2007-03-18 10:41:23',
1260
				'updated' => '2007-03-18 10:43:31'
1261
			),
1262
			'User' => array(
1263
				'id' => '3',
1264
				'user' => 'larry',
1265
				'password' => '5f4dcc3b5aa765d61d8327deb882cf99',
1266
				'created' => '2007-03-17 01:20:23',
1267
				'updated' => '2007-03-17 01:22:31'
1268
			),
1269
			'Comment' => array(
1270
				array(
1271
					'id' => '5',
1272
					'article_id' => '2',
1273
					'user_id' => '1',
1274
					'comment' => 'First Comment for Second Article',
1275
					'published' => 'Y',
1276
					'created' => '2007-03-18 10:53:23',
1277
					'updated' => '2007-03-18 10:55:31'
1278
				),
1279
				array(
1280
					'id' => '6',
1281
					'article_id' => '2',
1282
					'user_id' => '2',
1283
					'comment' => 'Second Comment for Second Article',
1284
					'published' => 'Y',
1285
					'created' => '2007-03-18 10:55:23',
1286
					'updated' => '2007-03-18 10:57:31'
1287
			)),
1288
			'Tag' => array(
1289
				array(
1290
					'id' => '1',
1291
					'tag' => 'tag1',
1292
					'created' => '2007-03-18 12:22:23',
1293
					'updated' => '2007-03-18 12:24:31'
1294
				),
1295
				array(
1296
					'id' => '3',
1297
					'tag' => 'tag3',
1298
					'created' => '2007-03-18 12:26:23',
1299
					'updated' => '2007-03-18 12:28:31'
1300
				)
1301
			)
1302
		);
1303
		$this->assertEquals($expected, $result);
1304
1305
		$data = array(
1306
			'Article' => array(
1307
				'id' => '2',
1308
				'title' => 'New Second Article'
1309
			),
1310
			'Tag' => array('Tag' => array(1, 2))
1311
		);
1312
1313
		$result = $TestModel->set($data);
1314
		$this->assertFalse(empty($result));
1315
		$result = $TestModel->save();
1316
		$this->assertFalse(empty($result));
1317
		$this->assertEquals($data['Tag'], $result['Tag']);
1318
1319
		$TestModel->unbindModel(array('belongsTo' => array('User'), 'hasMany' => array('Comment')));
1320
		$result = $TestModel->find('first', array('fields' => array('id', 'user_id', 'title', 'body'), 'conditions' => array('Article.id' => 2)));
1321
		$expected = array(
1322
			'Article' => array(
1323
				'id' => '2',
1324
				'user_id' => '3',
1325
				'title' => 'New Second Article',
1326
				'body' => 'Second Article Body'
1327
			),
1328
			'Tag' => array(
1329
				array(
1330
					'id' => '1',
1331
					'tag' => 'tag1',
1332
					'created' => '2007-03-18 12:22:23',
1333
					'updated' => '2007-03-18 12:24:31'
1334
				),
1335
				array(
1336
					'id' => '2',
1337
					'tag' => 'tag2',
1338
					'created' => '2007-03-18 12:24:23',
1339
					'updated' => '2007-03-18 12:26:31'
1340
		)));
1341
		$this->assertEquals($expected, $result);
1342
1343
		$data = array('Article' => array('id' => '2'), 'Tag' => array('Tag' => array(2, 3)));
1344
		$result = $TestModel->set($data);
1345
		$this->assertFalse(empty($result));
1346
1347
		$result = $TestModel->save();
1348
		$this->assertFalse(empty($result));
1349
1350
		$TestModel->unbindModel(array(
1351
			'belongsTo' => array('User'),
1352
			'hasMany' => array('Comment')
1353
		));
1354
		$result = $TestModel->find('first', array('fields' => array('id', 'user_id', 'title', 'body'), 'conditions' => array('Article.id' => 2)));
1355
		$expected = array(
1356
			'Article' => array(
1357
				'id' => '2',
1358
				'user_id' => '3',
1359
				'title' => 'New Second Article',
1360
				'body' => 'Second Article Body'
1361
			),
1362
			'Tag' => array(
1363
				array(
1364
					'id' => '2',
1365
					'tag' => 'tag2',
1366
					'created' => '2007-03-18 12:24:23',
1367
					'updated' => '2007-03-18 12:26:31'
1368
				),
1369
				array(
1370
					'id' => '3',
1371
					'tag' => 'tag3',
1372
					'created' => '2007-03-18 12:26:23',
1373
					'updated' => '2007-03-18 12:28:31'
1374
		)));
1375
		$this->assertEquals($expected, $result);
1376
1377
		$data = array('Tag' => array('Tag' => array(1, 2, 3)));
1378
1379
		$result = $TestModel->set($data);
1380
		$this->assertFalse(empty($result));
1381
1382
		$result = $TestModel->save();
1383
		$this->assertFalse(empty($result));
1384
1385
		$TestModel->unbindModel(array(
1386
			'belongsTo' => array('User'),
1387
			'hasMany' => array('Comment')
1388
		));
1389
		$result = $TestModel->find('first', array('fields' => array('id', 'user_id', 'title', 'body'), 'conditions' => array('Article.id' => 2)));
1390
		$expected = array(
1391
			'Article' => array(
1392
				'id' => '2',
1393
				'user_id' => '3',
1394
				'title' => 'New Second Article',
1395
				'body' => 'Second Article Body'
1396
			),
1397
			'Tag' => array(
1398
				array(
1399
					'id' => '1',
1400
					'tag' => 'tag1',
1401
					'created' => '2007-03-18 12:22:23',
1402
					'updated' => '2007-03-18 12:24:31'
1403
				),
1404
				array(
1405
					'id' => '2',
1406
					'tag' => 'tag2',
1407
					'created' => '2007-03-18 12:24:23',
1408
					'updated' => '2007-03-18 12:26:31'
1409
				),
1410
				array(
1411
					'id' => '3',
1412
					'tag' => 'tag3',
1413
					'created' => '2007-03-18 12:26:23',
1414
					'updated' => '2007-03-18 12:28:31'
1415
		)));
1416
		$this->assertEquals($expected, $result);
1417
1418
		$data = array('Tag' => array('Tag' => array()));
1419
		$result = $TestModel->set($data);
1420
		$this->assertFalse(empty($result));
1421
1422
		$result = $TestModel->save();
1423
		$this->assertFalse(empty($result));
1424
1425
		$data = array('Tag' => array('Tag' => ''));
1426
		$result = $TestModel->set($data);
1427
		$this->assertFalse(empty($result));
1428
1429
		$result = $TestModel->save();
1430
		$this->assertFalse(empty($result));
1431
1432
		$TestModel->unbindModel(array(
1433
			'belongsTo' => array('User'),
1434
			'hasMany' => array('Comment')
1435
		));
1436
		$result = $TestModel->find('first', array('fields' => array('id', 'user_id', 'title', 'body'), 'conditions' => array('Article.id' => 2)));
1437
		$expected = array(
1438
			'Article' => array(
1439
				'id' => '2',
1440
				'user_id' => '3',
1441
				'title' => 'New Second Article',
1442
				'body' => 'Second Article Body'
1443
			),
1444
			'Tag' => array()
1445
		);
1446
		$this->assertEquals($expected, $result);
1447
1448
		$data = array('Tag' => array('Tag' => array(2, 3)));
1449
		$result = $TestModel->set($data);
1450
		$this->assertFalse(empty($result));
1451
1452
		$result = $TestModel->save();
1453
		$this->assertFalse(empty($result));
1454
1455
		$TestModel->unbindModel(array(
1456
			'belongsTo' => array('User'),
1457
			'hasMany' => array('Comment')
1458
		));
1459
		$result = $TestModel->find('first', array('fields' => array('id', 'user_id', 'title', 'body'), 'conditions' => array('Article.id' => 2)));
1460
		$expected = array(
1461
			'Article' => array(
1462
				'id' => '2',
1463
				'user_id' => '3',
1464
				'title' => 'New Second Article',
1465
				'body' => 'Second Article Body'
1466
			),
1467
			'Tag' => array(
1468
				array(
1469
					'id' => '2',
1470
					'tag' => 'tag2',
1471
					'created' => '2007-03-18 12:24:23',
1472
					'updated' => '2007-03-18 12:26:31'
1473
				),
1474
				array(
1475
					'id' => '3',
1476
					'tag' => 'tag3',
1477
					'created' => '2007-03-18 12:26:23',
1478
					'updated' => '2007-03-18 12:28:31'
1479
		)));
1480
		$this->assertEquals($expected, $result);
1481
1482
		$data = array(
1483
			'Tag' => array(
1484
				'Tag' => array(1, 2)
1485
			),
1486
			'Article' => array(
1487
				'id' => '2',
1488
				'title' => 'New Second Article'
1489
		));
1490
		$result = $TestModel->set($data);
1491
		$this->assertFalse(empty($result));
1492
		$result = $TestModel->save();
1493
		$this->assertFalse(empty($result));
1494
1495
		$TestModel->unbindModel(array(
1496
			'belongsTo' => array('User'),
1497
			'hasMany' => array('Comment')
1498
		));
1499
		$result = $TestModel->find('first', array('fields' => array('id', 'user_id', 'title', 'body'), 'conditions' => array('Article.id' => 2)));
1500
		$expected = array(
1501
			'Article' => array(
1502
				'id' => '2',
1503
				'user_id' => '3',
1504
				'title' => 'New Second Article',
1505
				'body' => 'Second Article Body'
1506
			),
1507
			'Tag' => array(
1508
				array(
1509
					'id' => '1',
1510
					'tag' => 'tag1',
1511
					'created' => '2007-03-18 12:22:23',
1512
					'updated' => '2007-03-18 12:24:31'
1513
				),
1514
				array(
1515
					'id' => '2',
1516
					'tag' => 'tag2',
1517
					'created' => '2007-03-18 12:24:23',
1518
					'updated' => '2007-03-18 12:26:31'
1519
		)));
1520
		$this->assertEquals($expected, $result);
1521
1522
		$data = array(
1523
			'Tag' => array(
1524
				'Tag' => array(1, 2)
1525
			),
1526
			'Article' => array(
1527
				'id' => '2',
1528
				'title' => 'New Second Article Title'
1529
		));
1530
		$result = $TestModel->set($data);
1531
		$this->assertFalse(empty($result));
1532
		$result = $TestModel->save();
1533
		$this->assertFalse(empty($result));
1534
1535
		$TestModel->unbindModel(array(
1536
			'belongsTo' => array('User'),
1537
			'hasMany' => array('Comment')
1538
		));
1539
		$result = $TestModel->find('first', array('fields' => array('id', 'user_id', 'title', 'body'), 'conditions' => array('Article.id' => 2)));
1540
		$expected = array(
1541
			'Article' => array(
1542
				'id' => '2',
1543
				'user_id' => '3',
1544
				'title' => 'New Second Article Title',
1545
				'body' => 'Second Article Body'
1546
			),
1547
			'Tag' => array(
1548
				array(
1549
					'id' => '1',
1550
					'tag' => 'tag1',
1551
					'created' => '2007-03-18 12:22:23',
1552
					'updated' => '2007-03-18 12:24:31'
1553
				),
1554
				array(
1555
					'id' => '2',
1556
					'tag' => 'tag2',
1557
					'created' => '2007-03-18 12:24:23',
1558
					'updated' => '2007-03-18 12:26:31'
1559
				)
1560
			)
1561
		);
1562
		$this->assertEquals($expected, $result);
1563
1564
		$data = array(
1565
			'Tag' => array(
1566
				'Tag' => array(2, 3)
1567
			),
1568
			'Article' => array(
1569
				'id' => '2',
1570
				'title' => 'Changed Second Article'
1571
		));
1572
		$result = $TestModel->set($data);
1573
		$this->assertFalse(empty($result));
1574
		$result = $TestModel->save();
1575
		$this->assertFalse(empty($result));
1576
1577
		$TestModel->unbindModel(array(
1578
			'belongsTo' => array('User'),
1579
			'hasMany' => array('Comment')
1580
		));
1581
		$result = $TestModel->find('first', array('fields' => array('id', 'user_id', 'title', 'body'), 'conditions' => array('Article.id' => 2)));
1582
		$expected = array(
1583
			'Article' => array(
1584
				'id' => '2',
1585
				'user_id' => '3',
1586
				'title' => 'Changed Second Article',
1587
				'body' => 'Second Article Body'
1588
			),
1589
			'Tag' => array(
1590
				array(
1591
					'id' => '2',
1592
					'tag' => 'tag2',
1593
					'created' => '2007-03-18 12:24:23',
1594
					'updated' => '2007-03-18 12:26:31'
1595
				),
1596
				array(
1597
					'id' => '3',
1598
					'tag' => 'tag3',
1599
					'created' => '2007-03-18 12:26:23',
1600
					'updated' => '2007-03-18 12:28:31'
1601
				)
1602
			)
1603
		);
1604
		$this->assertEquals($expected, $result);
1605
1606
		$data = array(
1607
			'Tag' => array(
1608
				'Tag' => array(1, 3)
1609
			),
1610
			'Article' => array('id' => '2'),
1611
		);
1612
1613
		$result = $TestModel->set($data);
1614
		$this->assertFalse(empty($result));
1615
1616
		$result = $TestModel->save();
1617
		$this->assertFalse(empty($result));
1618
1619
		$TestModel->unbindModel(array(
1620
			'belongsTo' => array('User'),
1621
			'hasMany' => array('Comment')
1622
		));
1623
		$result = $TestModel->find('first', array('fields' => array('id', 'user_id', 'title', 'body'), 'conditions' => array('Article.id' => 2)));
1624
		$expected = array(
1625
			'Article' => array(
1626
				'id' => '2',
1627
				'user_id' => '3',
1628
				'title' => 'Changed Second Article',
1629
				'body' => 'Second Article Body'
1630
			),
1631
			'Tag' => array(
1632
				array(
1633
					'id' => '1',
1634
					'tag' => 'tag1',
1635
					'created' => '2007-03-18 12:22:23',
1636
					'updated' => '2007-03-18 12:24:31'
1637
				),
1638
				array(
1639
					'id' => '3',
1640
					'tag' => 'tag3',
1641
					'created' => '2007-03-18 12:26:23',
1642
					'updated' => '2007-03-18 12:28:31'
1643
		)));
1644
		$this->assertEquals($expected, $result);
1645
1646
		$data = array(
1647
			'Article' => array(
1648
				'id' => 10,
1649
				'user_id' => '2',
1650
				'title' => 'New Article With Tags and fieldList',
1651
				'body' => 'New Article Body with Tags and fieldList',
1652
				'created' => '2007-03-18 14:55:23',
1653
				'updated' => '2007-03-18 14:57:31'
1654
			),
1655
			'Tag' => array(
1656
				'Tag' => array(1, 2, 3)
1657
			)
1658
		);
1659
		$result = $TestModel->create()
1660
				&& $TestModel->save($data, true, array('user_id', 'title', 'published'));
1661
		$this->assertFalse(empty($result));
1662
1663
		$TestModel->unbindModel(array(
1664
			'belongsTo' => array('User'),
1665
			'hasMany' => array('Comment')
1666
		));
1667
		$result = $TestModel->read();
1668
		$expected = array(
1669
			'Article' => array(
1670
				'id' => 4,
1671
				'user_id' => 2,
1672
				'title' => 'New Article With Tags and fieldList',
1673
				'body' => '',
1674
				'published' => 'N',
1675
				'created' => '',
1676
				'updated' => ''
1677
			),
1678
			'Tag' => array(
1679
				0 => array(
1680
					'id' => 1,
1681
					'tag' => 'tag1',
1682
					'created' => '2007-03-18 12:22:23',
1683
					'updated' => '2007-03-18 12:24:31'
1684
				),
1685
				1 => array(
1686
					'id' => 2,
1687
					'tag' => 'tag2',
1688
					'created' => '2007-03-18 12:24:23',
1689
					'updated' => '2007-03-18 12:26:31'
1690
				),
1691
				2 => array(
1692
					'id' => 3,
1693
					'tag' => 'tag3',
1694
					'created' => '2007-03-18 12:26:23',
1695
					'updated' => '2007-03-18 12:28:31'
1696
		)));
1697
		$this->assertEquals($expected, $result);
1698
1699
		$this->loadFixtures('JoinA', 'JoinC', 'JoinAC', 'JoinB', 'JoinAB');
1700
		$TestModel = new JoinA();
1701
		$TestModel->hasBelongsToMany = array('JoinC' => array('unique' => true));
1702
		$data = array(
1703
			'JoinA' => array(
1704
				'id' => 1,
1705
				'name' => 'Join A 1',
1706
				'body' => 'Join A 1 Body',
1707
			),
1708
			'JoinC' => array(
1709
				'JoinC' => array(
1710
					array('join_c_id' => 2, 'other' => 'new record'),
1711
					array('join_c_id' => 3, 'other' => 'new record')
1712
				)
1713
			)
1714
		);
1715
		$TestModel->save($data);
1716
		$result = $TestModel->read(null, 1);
1717
		$expected = array(4, 5);
1718
		$this->assertEquals($expected, Hash::extract($result, 'JoinC.{n}.JoinAsJoinC.id'));
0 ignored issues
show
Bug introduced by
It seems like $result defined by $TestModel->read(null, 1) on line 1716 can also be of type false or null; however, Hash::extract() does only seem to accept array, maybe add an additional type check?

If a method or function can return multiple different values and unless you are sure that you only can receive a single value in this context, we recommend to add an additional type check:

/**
 * @return array|string
 */
function returnsDifferentValues($x) {
    if ($x) {
        return 'foo';
    }

    return array();
}

$x = returnsDifferentValues($y);
if (is_array($x)) {
    // $x is an array.
}

If this a common case that PHP Analyzer should handle natively, please let us know by opening an issue.

Loading history...
1719
		$expected = array('new record', 'new record');
1720
		$this->assertEquals($expected, Hash::extract($result, 'JoinC.{n}.JoinAsJoinC.other'));
0 ignored issues
show
Bug introduced by
It seems like $result defined by $TestModel->read(null, 1) on line 1716 can also be of type false or null; however, Hash::extract() does only seem to accept array, maybe add an additional type check?

If a method or function can return multiple different values and unless you are sure that you only can receive a single value in this context, we recommend to add an additional type check:

/**
 * @return array|string
 */
function returnsDifferentValues($x) {
    if ($x) {
        return 'foo';
    }

    return array();
}

$x = returnsDifferentValues($y);
if (is_array($x)) {
    // $x is an array.
}

If this a common case that PHP Analyzer should handle natively, please let us know by opening an issue.

Loading history...
1721
	}
1722
1723
/**
1724
 * testSaveHabtmNoPrimaryData method
1725
 *
1726
 * @return void
1727
 */
1728
	public function testSaveHabtmNoPrimaryData() {
1729
		$this->loadFixtures('Article', 'User', 'Comment', 'Tag', 'ArticlesTag');
1730
		$TestModel = new Article();
1731
1732
		$TestModel->unbindModel(array('belongsTo' => array('User'), 'hasMany' => array('Comment')), false);
1733
		$result = $TestModel->findById(2);
0 ignored issues
show
Documentation Bug introduced by
The method findById does not exist on object<Article>? Since you implemented __call, maybe consider adding a @method annotation.

If you implement __call and you know which methods are available, you can improve IDE auto-completion and static analysis by adding a @method annotation to the class.

This is often the case, when __call is implemented by a parent class and only the child class knows which methods exist:

class ParentClass {
    private $data = array();

    public function __call($method, array $args) {
        if (0 === strpos($method, 'get')) {
            return $this->data[strtolower(substr($method, 3))];
        }

        throw new \LogicException(sprintf('Unsupported method: %s', $method));
    }
}

/**
 * If this class knows which fields exist, you can specify the methods here:
 *
 * @method string getName()
 */
class SomeClass extends ParentClass { }
Loading history...
1734
		$expected = array(
1735
			'Article' => array(
1736
				'id' => '2',
1737
				'user_id' => '3',
1738
				'title' => 'Second Article',
1739
				'body' => 'Second Article Body',
1740
				'published' => 'Y',
1741
				'created' => '2007-03-18 10:41:23',
1742
				'updated' => '2007-03-18 10:43:31'
1743
			),
1744
			'Tag' => array(
1745
				array(
1746
					'id' => '1',
1747
					'tag' => 'tag1',
1748
					'created' => '2007-03-18 12:22:23',
1749
					'updated' => '2007-03-18 12:24:31'
1750
				),
1751
				array(
1752
					'id' => '3',
1753
					'tag' => 'tag3',
1754
					'created' => '2007-03-18 12:26:23',
1755
					'updated' => '2007-03-18 12:28:31'
1756
				)
1757
			)
1758
		);
1759
		$this->assertEquals($expected, $result);
1760
1761
		$TestModel->id = 2;
1762
		$data = array('Tag' => array('Tag' => array(2)));
1763
		$result = $TestModel->save($data);
1764
1765
		$this->assertEquals($data['Tag'], $result['Tag']);
1766
1767
		$result = $TestModel->findById(2);
0 ignored issues
show
Documentation Bug introduced by
The method findById does not exist on object<Article>? Since you implemented __call, maybe consider adding a @method annotation.

If you implement __call and you know which methods are available, you can improve IDE auto-completion and static analysis by adding a @method annotation to the class.

This is often the case, when __call is implemented by a parent class and only the child class knows which methods exist:

class ParentClass {
    private $data = array();

    public function __call($method, array $args) {
        if (0 === strpos($method, 'get')) {
            return $this->data[strtolower(substr($method, 3))];
        }

        throw new \LogicException(sprintf('Unsupported method: %s', $method));
    }
}

/**
 * If this class knows which fields exist, you can specify the methods here:
 *
 * @method string getName()
 */
class SomeClass extends ParentClass { }
Loading history...
1768
		$expected = array(
1769
			'Article' => array(
1770
				'id' => '2',
1771
				'user_id' => '3',
1772
				'title' => 'Second Article',
1773
				'body' => 'Second Article Body',
1774
				'published' => 'Y',
1775
				'created' => '2007-03-18 10:41:23',
1776
				'updated' => self::date()
1777
			),
1778
			'Tag' => array(
1779
				array(
1780
					'id' => '2',
1781
					'tag' => 'tag2',
1782
					'created' => '2007-03-18 12:24:23',
1783
					'updated' => '2007-03-18 12:26:31'
1784
				)
1785
			)
1786
		);
1787
		$this->assertEquals($expected, $result);
1788
1789
		$this->loadFixtures('Portfolio', 'Item', 'ItemsPortfolio');
1790
		$TestModel = new Portfolio();
1791
		$result = $TestModel->findById(2);
0 ignored issues
show
Documentation Bug introduced by
The method findById does not exist on object<Portfolio>? Since you implemented __call, maybe consider adding a @method annotation.

If you implement __call and you know which methods are available, you can improve IDE auto-completion and static analysis by adding a @method annotation to the class.

This is often the case, when __call is implemented by a parent class and only the child class knows which methods exist:

class ParentClass {
    private $data = array();

    public function __call($method, array $args) {
        if (0 === strpos($method, 'get')) {
            return $this->data[strtolower(substr($method, 3))];
        }

        throw new \LogicException(sprintf('Unsupported method: %s', $method));
    }
}

/**
 * If this class knows which fields exist, you can specify the methods here:
 *
 * @method string getName()
 */
class SomeClass extends ParentClass { }
Loading history...
1792
		$expected = array(
1793
			'Portfolio' => array(
1794
				'id' => 2,
1795
				'seller_id' => 1,
1796
				'name' => 'Portfolio 2'
1797
			),
1798
			'Item' => array(
1799
				array(
1800
					'id' => 2,
1801
					'syfile_id' => 2,
1802
					'published' => '',
1803
					'name' => 'Item 2',
1804
					'ItemsPortfolio' => array(
1805
						'id' => 2,
1806
						'item_id' => 2,
1807
						'portfolio_id' => 2
1808
					)
1809
				),
1810
				array(
1811
					'id' => 6,
1812
					'syfile_id' => 6,
1813
					'published' => '',
1814
					'name' => 'Item 6',
1815
					'ItemsPortfolio' => array(
1816
						'id' => 6,
1817
						'item_id' => 6,
1818
						'portfolio_id' => 2
1819
					)
1820
				)
1821
			)
1822
		);
1823
		$this->assertEquals($expected, $result);
1824
1825
		$data = array('Item' => array('Item' => array(1, 2)));
1826
		$TestModel->id = 2;
1827
		$TestModel->save($data);
1828
		$result = $TestModel->findById(2);
0 ignored issues
show
Documentation Bug introduced by
The method findById does not exist on object<Portfolio>? Since you implemented __call, maybe consider adding a @method annotation.

If you implement __call and you know which methods are available, you can improve IDE auto-completion and static analysis by adding a @method annotation to the class.

This is often the case, when __call is implemented by a parent class and only the child class knows which methods exist:

class ParentClass {
    private $data = array();

    public function __call($method, array $args) {
        if (0 === strpos($method, 'get')) {
            return $this->data[strtolower(substr($method, 3))];
        }

        throw new \LogicException(sprintf('Unsupported method: %s', $method));
    }
}

/**
 * If this class knows which fields exist, you can specify the methods here:
 *
 * @method string getName()
 */
class SomeClass extends ParentClass { }
Loading history...
1829
		$result['Item'] = Hash::sort($result['Item'], '{n}.id', 'asc');
1830
		$expected = array(
1831
			'Portfolio' => array(
1832
				'id' => 2,
1833
				'seller_id' => 1,
1834
				'name' => 'Portfolio 2'
1835
			),
1836
			'Item' => array(
1837
				array(
1838
					'id' => 1,
1839
					'syfile_id' => 1,
1840
					'published' => '',
1841
					'name' => 'Item 1',
1842
					'ItemsPortfolio' => array(
1843
						'id' => 7,
1844
						'item_id' => 1,
1845
						'portfolio_id' => 2
1846
					)
1847
				),
1848
				array(
1849
					'id' => 2,
1850
					'syfile_id' => 2,
1851
					'published' => '',
1852
					'name' => 'Item 2',
1853
					'ItemsPortfolio' => array(
1854
						'id' => 8,
1855
						'item_id' => 2,
1856
						'portfolio_id' => 2
1857
					)
1858
				)
1859
			)
1860
		);
1861
		$this->assertEquals($expected, $result);
1862
	}
1863
1864
/**
1865
 * testSaveHabtmCustomKeys method
1866
 *
1867
 * @return void
1868
 */
1869
	public function testSaveHabtmCustomKeys() {
1870
		$this->loadFixtures('Story', 'StoriesTag', 'Tag');
1871
		$Story = new Story();
1872
1873
		$data = array(
1874
			'Story' => array('story' => '1'),
1875
			'Tag' => array(
1876
				'Tag' => array(2, 3)
1877
		));
1878
		$result = $Story->set($data);
1879
		$this->assertFalse(empty($result));
1880
1881
		$result = $Story->save();
1882
		$this->assertFalse(empty($result));
1883
1884
		$result = $Story->find('all', array('order' => array('Story.story')));
1885
		$expected = array(
1886
			array(
1887
				'Story' => array(
1888
					'story' => 1,
1889
					'title' => 'First Story'
1890
				),
1891
				'Tag' => array(
1892
					array(
1893
						'id' => 2,
1894
						'tag' => 'tag2',
1895
						'created' => '2007-03-18 12:24:23',
1896
						'updated' => '2007-03-18 12:26:31'
1897
					),
1898
					array(
1899
						'id' => 3,
1900
						'tag' => 'tag3',
1901
						'created' => '2007-03-18 12:26:23',
1902
						'updated' => '2007-03-18 12:28:31'
1903
			))),
1904
			array(
1905
				'Story' => array(
1906
					'story' => 2,
1907
					'title' => 'Second Story'
1908
				),
1909
				'Tag' => array()
1910
		));
1911
		$this->assertEquals($expected, $result);
1912
	}
1913
1914
/**
1915
 * test that saving habtm records respects conditions set in the 'conditions' key
1916
 * for the association.
1917
 *
1918
 * @return void
1919
 */
1920
	public function testHabtmSaveWithConditionsInAssociation() {
1921
		$this->loadFixtures('JoinThing', 'Something', 'SomethingElse');
1922
		$Something = new Something();
1923
		$Something->unbindModel(array('hasAndBelongsToMany' => array('SomethingElse')), false);
1924
1925
		$Something->bindModel(array(
1926
			'hasAndBelongsToMany' => array(
1927
				'DoomedSomethingElse' => array(
1928
					'className' => 'SomethingElse',
1929
					'joinTable' => 'join_things',
1930
					'conditions' => array('JoinThing.doomed' => true),
1931
					'unique' => true
1932
				),
1933
				'NotDoomedSomethingElse' => array(
1934
					'className' => 'SomethingElse',
1935
					'joinTable' => 'join_things',
1936
					'conditions' => array('JoinThing.doomed' => 0),
1937
					'unique' => true
1938
				)
1939
			)
1940
		), false);
1941
		$result = $Something->read(null, 1);
1942
		$this->assertTrue(empty($result['NotDoomedSomethingElse']));
1943
		$this->assertEquals(1, count($result['DoomedSomethingElse']));
1944
1945
		$data = array(
1946
			'Something' => array('id' => 1),
1947
			'NotDoomedSomethingElse' => array(
1948
				'NotDoomedSomethingElse' => array(
1949
					array('something_else_id' => 2, 'doomed' => 0),
1950
					array('something_else_id' => 3, 'doomed' => 0)
1951
				)
1952
			)
1953
		);
1954
		$Something->create($data);
1955
		$result = $Something->save();
1956
		$this->assertFalse(empty($result));
1957
1958
		$result = $Something->read(null, 1);
1959
		$this->assertEquals(2, count($result['NotDoomedSomethingElse']));
1960
		$this->assertEquals(1, count($result['DoomedSomethingElse']));
1961
	}
1962
1963
/**
1964
 * testHabtmSaveKeyResolution method
1965
 *
1966
 * @return void
1967
 */
1968
	public function testHabtmSaveKeyResolution() {
1969
		$this->loadFixtures('Apple', 'Device', 'ThePaperMonkies');
1970
		$ThePaper = new ThePaper();
1971
1972
		$ThePaper->id = 1;
1973
		$ThePaper->save(array('Monkey' => array(2, 3)));
1974
1975
		$result = $ThePaper->findById(1);
0 ignored issues
show
Documentation Bug introduced by
The method findById does not exist on object<ThePaper>? Since you implemented __call, maybe consider adding a @method annotation.

If you implement __call and you know which methods are available, you can improve IDE auto-completion and static analysis by adding a @method annotation to the class.

This is often the case, when __call is implemented by a parent class and only the child class knows which methods exist:

class ParentClass {
    private $data = array();

    public function __call($method, array $args) {
        if (0 === strpos($method, 'get')) {
            return $this->data[strtolower(substr($method, 3))];
        }

        throw new \LogicException(sprintf('Unsupported method: %s', $method));
    }
}

/**
 * If this class knows which fields exist, you can specify the methods here:
 *
 * @method string getName()
 */
class SomeClass extends ParentClass { }
Loading history...
1976
		$expected = array(
1977
			array(
1978
				'id' => '2',
1979
				'device_type_id' => '1',
1980
				'name' => 'Device 2',
1981
				'typ' => '1'
1982
			),
1983
			array(
1984
				'id' => '3',
1985
				'device_type_id' => '1',
1986
				'name' => 'Device 3',
1987
				'typ' => '2'
1988
		));
1989
		$this->assertEquals($expected, $result['Monkey']);
1990
1991
		$ThePaper->id = 2;
1992
		$ThePaper->save(array('Monkey' => array(1, 2, 3)));
1993
1994
		$result = $ThePaper->findById(2);
0 ignored issues
show
Documentation Bug introduced by
The method findById does not exist on object<ThePaper>? Since you implemented __call, maybe consider adding a @method annotation.

If you implement __call and you know which methods are available, you can improve IDE auto-completion and static analysis by adding a @method annotation to the class.

This is often the case, when __call is implemented by a parent class and only the child class knows which methods exist:

class ParentClass {
    private $data = array();

    public function __call($method, array $args) {
        if (0 === strpos($method, 'get')) {
            return $this->data[strtolower(substr($method, 3))];
        }

        throw new \LogicException(sprintf('Unsupported method: %s', $method));
    }
}

/**
 * If this class knows which fields exist, you can specify the methods here:
 *
 * @method string getName()
 */
class SomeClass extends ParentClass { }
Loading history...
1995
		$expected = array(
1996
			array(
1997
				'id' => '1',
1998
				'device_type_id' => '1',
1999
				'name' => 'Device 1',
2000
				'typ' => '1'
2001
			),
2002
			array(
2003
				'id' => '2',
2004
				'device_type_id' => '1',
2005
				'name' => 'Device 2',
2006
				'typ' => '1'
2007
			),
2008
			array(
2009
				'id' => '3',
2010
				'device_type_id' => '1',
2011
				'name' => 'Device 3',
2012
				'typ' => '2'
2013
		));
2014
		$this->assertEquals($expected, $result['Monkey']);
2015
2016
		$ThePaper->id = 2;
2017
		$ThePaper->save(array('Monkey' => array(1, 3)));
2018
2019
		$result = $ThePaper->findById(2);
0 ignored issues
show
Documentation Bug introduced by
The method findById does not exist on object<ThePaper>? Since you implemented __call, maybe consider adding a @method annotation.

If you implement __call and you know which methods are available, you can improve IDE auto-completion and static analysis by adding a @method annotation to the class.

This is often the case, when __call is implemented by a parent class and only the child class knows which methods exist:

class ParentClass {
    private $data = array();

    public function __call($method, array $args) {
        if (0 === strpos($method, 'get')) {
            return $this->data[strtolower(substr($method, 3))];
        }

        throw new \LogicException(sprintf('Unsupported method: %s', $method));
    }
}

/**
 * If this class knows which fields exist, you can specify the methods here:
 *
 * @method string getName()
 */
class SomeClass extends ParentClass { }
Loading history...
2020
		$expected = array(
2021
			array(
2022
				'id' => '1',
2023
				'device_type_id' => '1',
2024
				'name' => 'Device 1',
2025
				'typ' => '1'
2026
			),
2027
			array(
2028
				'id' => '3',
2029
				'device_type_id' => '1',
2030
				'name' => 'Device 3',
2031
				'typ' => '2'
2032
			));
2033
		$this->assertEquals($expected, $result['Monkey']);
2034
2035
		$result = $ThePaper->findById(1);
0 ignored issues
show
Documentation Bug introduced by
The method findById does not exist on object<ThePaper>? Since you implemented __call, maybe consider adding a @method annotation.

If you implement __call and you know which methods are available, you can improve IDE auto-completion and static analysis by adding a @method annotation to the class.

This is often the case, when __call is implemented by a parent class and only the child class knows which methods exist:

class ParentClass {
    private $data = array();

    public function __call($method, array $args) {
        if (0 === strpos($method, 'get')) {
            return $this->data[strtolower(substr($method, 3))];
        }

        throw new \LogicException(sprintf('Unsupported method: %s', $method));
    }
}

/**
 * If this class knows which fields exist, you can specify the methods here:
 *
 * @method string getName()
 */
class SomeClass extends ParentClass { }
Loading history...
2036
		$expected = array(
2037
			array(
2038
				'id' => '2',
2039
				'device_type_id' => '1',
2040
				'name' => 'Device 2',
2041
				'typ' => '1'
2042
			),
2043
			array(
2044
				'id' => '3',
2045
				'device_type_id' => '1',
2046
				'name' => 'Device 3',
2047
				'typ' => '2'
2048
		));
2049
		$this->assertEquals($expected, $result['Monkey']);
2050
	}
2051
2052
/**
2053
 * testCreationOfEmptyRecord method
2054
 *
2055
 * @return void
2056
 */
2057
	public function testCreationOfEmptyRecord() {
2058
		$this->loadFixtures('Author');
2059
		$TestModel = new Author();
2060
		$this->assertEquals(4, $TestModel->find('count'));
2061
2062
		$TestModel->deleteAll(true, false, false);
2063
		$this->assertEquals(0, $TestModel->find('count'));
2064
2065
		$result = $TestModel->save();
2066
		$this->assertTrue(isset($result['Author']['created']));
2067
		$this->assertTrue(isset($result['Author']['updated']));
2068
		$this->assertEquals(1, $TestModel->find('count'));
2069
	}
2070
2071
/**
2072
 * testCreateWithPKFiltering method
2073
 *
2074
 * @return void
2075
 */
2076
	public function testCreateWithPKFiltering() {
2077
		$TestModel = new Article();
2078
		$data = array(
2079
			'id' => 5,
2080
			'user_id' => 2,
2081
			'title' => 'My article',
2082
			'body' => 'Some text'
2083
		);
2084
2085
		$result = $TestModel->create($data);
2086
		$expected = array(
2087
			'Article' => array(
2088
				'published' => 'N',
2089
				'id' => 5,
2090
				'user_id' => 2,
2091
				'title' => 'My article',
2092
				'body' => 'Some text'
2093
		));
2094
2095
		$this->assertEquals($expected, $result);
2096
		$this->assertEquals(5, $TestModel->id);
2097
2098
		$result = $TestModel->create($data, true);
2099
		$expected = array(
2100
			'Article' => array(
2101
				'published' => 'N',
2102
				'id' => false,
2103
				'user_id' => 2,
2104
				'title' => 'My article',
2105
				'body' => 'Some text'
2106
		));
2107
2108
		$this->assertEquals($expected, $result);
2109
		$this->assertFalse($TestModel->id);
2110
2111
		$result = $TestModel->create(array('Article' => $data), true);
2112
		$expected = array(
2113
			'Article' => array(
2114
				'published' => 'N',
2115
				'id' => false,
2116
				'user_id' => 2,
2117
				'title' => 'My article',
2118
				'body' => 'Some text'
2119
		));
2120
2121
		$this->assertEquals($expected, $result);
2122
		$this->assertFalse($TestModel->id);
2123
2124
		$data = array(
2125
			'id' => 6,
2126
			'user_id' => 2,
2127
			'title' => 'My article',
2128
			'body' => 'Some text',
2129
			'created' => '1970-01-01 00:00:00',
2130
			'updated' => '1970-01-01 12:00:00',
2131
			'modified' => '1970-01-01 12:00:00'
2132
		);
2133
2134
		$result = $TestModel->create($data);
2135
		$expected = array(
2136
			'Article' => array(
2137
				'published' => 'N',
2138
				'id' => 6,
2139
				'user_id' => 2,
2140
				'title' => 'My article',
2141
				'body' => 'Some text',
2142
				'created' => '1970-01-01 00:00:00',
2143
				'updated' => '1970-01-01 12:00:00',
2144
				'modified' => '1970-01-01 12:00:00'
2145
		));
2146
		$this->assertEquals($expected, $result);
2147
		$this->assertEquals(6, $TestModel->id);
2148
2149
		$result = $TestModel->create(array(
2150
			'Article' => array_diff_key($data, array(
2151
				'created' => true,
2152
				'updated' => true,
2153
				'modified' => true
2154
		))), true);
2155
		$expected = array(
2156
			'Article' => array(
2157
				'published' => 'N',
2158
				'id' => false,
2159
				'user_id' => 2,
2160
				'title' => 'My article',
2161
				'body' => 'Some text'
2162
		));
2163
		$this->assertEquals($expected, $result);
2164
		$this->assertFalse($TestModel->id);
2165
	}
2166
2167
/**
2168
 * testCreationWithMultipleData method
2169
 *
2170
 * @return void
2171
 */
2172
	public function testCreationWithMultipleData() {
2173
		$this->loadFixtures('Article', 'Comment');
2174
		$Article = new Article();
2175
		$Comment = new Comment();
2176
2177
		$articles = $Article->find('all', array(
2178
			'fields' => array('id', 'title'),
2179
			'recursive' => -1,
2180
			'order' => array('Article.id' => 'ASC')
2181
		));
2182
		$expected = array(
2183
			array('Article' => array(
2184
				'id' => 1,
2185
				'title' => 'First Article'
2186
			)),
2187
			array('Article' => array(
2188
				'id' => 2,
2189
				'title' => 'Second Article'
2190
			)),
2191
			array('Article' => array(
2192
				'id' => 3,
2193
				'title' => 'Third Article'
2194
		)));
2195
		$this->assertEquals($expected, $articles);
2196
2197
		$comments = $Comment->find('all', array(
2198
			'fields' => array('id', 'article_id', 'user_id', 'comment', 'published'),
2199
			'recursive' => -1,
2200
			'order' => array('Comment.id' => 'ASC')
2201
		));
2202
		$expected = array(
2203
			array('Comment' => array(
2204
				'id' => 1,
2205
				'article_id' => 1,
2206
				'user_id' => 2,
2207
				'comment' => 'First Comment for First Article',
2208
				'published' => 'Y'
2209
			)),
2210
			array('Comment' => array(
2211
				'id' => 2,
2212
				'article_id' => 1,
2213
				'user_id' => 4,
2214
				'comment' => 'Second Comment for First Article',
2215
				'published' => 'Y'
2216
			)),
2217
			array('Comment' => array(
2218
				'id' => 3,
2219
				'article_id' => 1,
2220
				'user_id' => 1,
2221
				'comment' => 'Third Comment for First Article',
2222
				'published' => 'Y'
2223
			)),
2224
			array('Comment' => array(
2225
				'id' => 4,
2226
				'article_id' => 1,
2227
				'user_id' => 1,
2228
				'comment' => 'Fourth Comment for First Article',
2229
				'published' => 'N'
2230
			)),
2231
			array('Comment' => array(
2232
				'id' => 5,
2233
				'article_id' => 2,
2234
				'user_id' => 1,
2235
				'comment' => 'First Comment for Second Article',
2236
				'published' => 'Y'
2237
			)),
2238
			array('Comment' => array(
2239
				'id' => 6,
2240
				'article_id' => 2,
2241
				'user_id' => 2,
2242
				'comment' => 'Second Comment for Second Article',
2243
				'published' => 'Y'
2244
		)));
2245
		$this->assertEquals($expected, $comments);
2246
2247
		$data = array(
2248
			'Comment' => array(
2249
				'article_id' => 2,
2250
				'user_id' => 4,
2251
				'comment' => 'Brand New Comment',
2252
				'published' => 'N'
2253
			),
2254
			'Article' => array(
2255
				'id' => 2,
2256
				'title' => 'Second Article Modified'
2257
		));
2258
		$result = $Comment->create($data);
2259
		$this->assertFalse(empty($result));
2260
2261
		$result = $Comment->save();
2262
		$this->assertFalse(empty($result));
2263
2264
		$articles = $Article->find('all', array(
2265
			'fields' => array('id', 'title'),
2266
			'recursive' => -1,
2267
			'order' => array('Article.id' => 'ASC')
2268
		));
2269
		$expected = array(
2270
			array('Article' => array(
2271
				'id' => 1,
2272
				'title' => 'First Article'
2273
			)),
2274
			array('Article' => array(
2275
				'id' => 2,
2276
				'title' => 'Second Article'
2277
			)),
2278
			array('Article' => array(
2279
				'id' => 3,
2280
				'title' => 'Third Article'
2281
		)));
2282
		$this->assertEquals($expected, $articles);
2283
2284
		$comments = $Comment->find('all', array(
2285
			'fields' => array('id', 'article_id', 'user_id', 'comment', 'published'),
2286
			'recursive' => -1,
2287
			'order' => array('Comment.id' => 'ASC')
2288
		));
2289
		$expected = array(
2290
			array('Comment' => array(
2291
				'id' => 1,
2292
				'article_id' => 1,
2293
				'user_id' => 2,
2294
				'comment' => 'First Comment for First Article',
2295
				'published' => 'Y'
2296
			)),
2297
			array('Comment' => array(
2298
				'id' => 2,
2299
				'article_id' => 1,
2300
				'user_id' => 4,
2301
				'comment' => 'Second Comment for First Article',
2302
				'published' => 'Y'
2303
			)),
2304
			array('Comment' => array(
2305
				'id' => 3,
2306
				'article_id' => 1,
2307
				'user_id' => 1,
2308
				'comment' => 'Third Comment for First Article',
2309
				'published' => 'Y'
2310
			)),
2311
			array('Comment' => array(
2312
				'id' => 4,
2313
				'article_id' => 1,
2314
				'user_id' => 1,
2315
				'comment' => 'Fourth Comment for First Article',
2316
				'published' => 'N'
2317
			)),
2318
			array('Comment' => array(
2319
				'id' => 5,
2320
				'article_id' => 2,
2321
				'user_id' => 1,
2322
				'comment' => 'First Comment for Second Article',
2323
				'published' => 'Y'
2324
			)),
2325
			array('Comment' => array(
2326
				'id' => 6,
2327
				'article_id' => 2,
2328
				'user_id' => 2, 'comment' =>
2329
				'Second Comment for Second Article',
2330
				'published' => 'Y'
2331
			)),
2332
			array('Comment' => array(
2333
				'id' => 7,
2334
				'article_id' => 2,
2335
				'user_id' => 4,
2336
				'comment' => 'Brand New Comment',
2337
				'published' => 'N'
2338
		)));
2339
		$this->assertEquals($expected, $comments);
2340
	}
2341
2342
/**
2343
 * testCreationWithMultipleDataSameModel method
2344
 *
2345
 * @return void
2346
 */
2347
	public function testCreationWithMultipleDataSameModel() {
2348
		$this->loadFixtures('Article');
2349
		$Article = new Article();
2350
2351
		$result = $Article->field('title', array('id' => 1));
2352
		$this->assertEquals('First Article', $result);
2353
2354
		$data = array(
2355
			'Article' => array(
2356
				'user_id' => 2,
2357
				'title' => 'Brand New Article',
2358
				'body' => 'Brand New Article Body',
2359
				'published' => 'Y'
2360
			),
2361
			'SecondaryArticle' => array(
2362
				'id' => 1
2363
		));
2364
2365
		$Article->create();
2366
		$result = $Article->save($data);
2367
		$this->assertFalse(empty($result));
2368
2369
		$result = $Article->getInsertID();
2370
		$this->assertTrue(!empty($result));
2371
2372
		$result = $Article->field('title', array('id' => 1));
2373
		$this->assertEquals('First Article', $result);
2374
2375
		$articles = $Article->find('all', array(
2376
			'fields' => array('id', 'title'),
2377
			'recursive' => -1,
2378
			'order' => array('Article.id' => 'ASC')
2379
		));
2380
		$expected = array(
2381
			array('Article' => array(
2382
				'id' => 1,
2383
				'title' => 'First Article'
2384
			)),
2385
			array('Article' => array(
2386
				'id' => 2,
2387
				'title' => 'Second Article'
2388
			)),
2389
			array('Article' => array(
2390
				'id' => 3,
2391
				'title' => 'Third Article'
2392
			)),
2393
			array('Article' => array(
2394
				'id' => 4,
2395
				'title' => 'Brand New Article'
2396
		)));
2397
2398
		$this->assertEquals($expected, $articles);
2399
	}
2400
2401
/**
2402
 * testCreationWithMultipleDataSameModelManualInstances method
2403
 *
2404
 * @return void
2405
 */
2406
	public function testCreationWithMultipleDataSameModelManualInstances() {
2407
		$this->loadFixtures('PrimaryModel');
2408
		$Primary = new PrimaryModel();
2409
2410
		$result = $Primary->field('primary_name', array('id' => 1));
2411
		$this->assertEquals('Primary Name Existing', $result);
2412
2413
		$data = array(
2414
			'PrimaryModel' => array(
2415
				'primary_name' => 'Primary Name New'
2416
			),
2417
			'SecondaryModel' => array(
2418
				'id' => array(1)
2419
		));
2420
2421
		$Primary->create();
2422
		$result = $Primary->save($data);
2423
		$this->assertFalse(empty($result));
2424
2425
		$result = $Primary->field('primary_name', array('id' => 1));
2426
		$this->assertEquals('Primary Name Existing', $result);
2427
2428
		$result = $Primary->getInsertID();
2429
		$this->assertTrue(!empty($result));
2430
2431
		$result = $Primary->field('primary_name', array('id' => $result));
2432
		$this->assertEquals('Primary Name New', $result);
2433
2434
		$result = $Primary->find('count');
2435
		$this->assertEquals(2, $result);
2436
	}
2437
2438
/**
2439
 * testRecordExists method
2440
 *
2441
 * @return void
2442
 */
2443
	public function testRecordExists() {
2444
		$this->loadFixtures('User');
2445
		$TestModel = new User();
2446
2447
		$this->assertFalse($TestModel->exists());
2448
		$TestModel->read(null, 1);
2449
		$this->assertTrue($TestModel->exists());
2450
		$TestModel->create();
2451
		$this->assertFalse($TestModel->exists());
2452
		$TestModel->id = 4;
2453
		$this->assertTrue($TestModel->exists());
2454
2455
		$TestModel = new TheVoid();
2456
		$this->assertFalse($TestModel->exists());
2457
	}
2458
2459
/**
2460
 * testRecordExistsMissingTable method
2461
 *
2462
 * @expectedException PDOException
2463
 * @return void
2464
 */
2465
	public function testRecordExistsMissingTable() {
2466
		$TestModel = new TheVoid();
2467
		$TestModel->id = 5;
2468
		$TestModel->exists();
2469
	}
2470
2471
/**
2472
 * testUpdateExisting method
2473
 *
2474
 * @return void
2475
 */
2476
	public function testUpdateExisting() {
2477
		$this->loadFixtures('User', 'Article', 'Comment');
2478
		$TestModel = new User();
2479
		$TestModel->create();
2480
2481
		$TestModel->save(array(
2482
			'User' => array(
2483
				'user' => 'some user',
2484
				'password' => 'some password'
2485
		)));
2486
		$this->assertTrue(is_int($TestModel->id) || (intval($TestModel->id) === 5));
2487
		$id = $TestModel->id;
2488
2489
		$TestModel->save(array(
2490
			'User' => array(
2491
				'user' => 'updated user'
2492
		)));
2493
		$this->assertEquals($id, $TestModel->id);
2494
2495
		$result = $TestModel->findById($id);
0 ignored issues
show
Documentation Bug introduced by
The method findById does not exist on object<User>? Since you implemented __call, maybe consider adding a @method annotation.

If you implement __call and you know which methods are available, you can improve IDE auto-completion and static analysis by adding a @method annotation to the class.

This is often the case, when __call is implemented by a parent class and only the child class knows which methods exist:

class ParentClass {
    private $data = array();

    public function __call($method, array $args) {
        if (0 === strpos($method, 'get')) {
            return $this->data[strtolower(substr($method, 3))];
        }

        throw new \LogicException(sprintf('Unsupported method: %s', $method));
    }
}

/**
 * If this class knows which fields exist, you can specify the methods here:
 *
 * @method string getName()
 */
class SomeClass extends ParentClass { }
Loading history...
2496
		$this->assertEquals('updated user', $result['User']['user']);
2497
		$this->assertEquals('some password', $result['User']['password']);
2498
2499
		$Article = new Article();
2500
		$Comment = new Comment();
2501
		$data = array(
2502
			'Comment' => array(
2503
				'id' => 1,
2504
				'comment' => 'First Comment for First Article'
2505
			),
2506
			'Article' => array(
2507
				'id' => 2,
2508
				'title' => 'Second Article'
2509
		));
2510
2511
		$result = $Article->save($data);
2512
		$this->assertFalse(empty($result));
2513
2514
		$result = $Comment->save($data);
2515
		$this->assertFalse(empty($result));
2516
	}
2517
2518
/**
2519
 * test updating records and saving blank values.
2520
 *
2521
 * @return void
2522
 */
2523
	public function testUpdateSavingBlankValues() {
2524
		$this->loadFixtures('Article');
2525
		$Article = new Article();
2526
		$Article->validate = array();
2527
		$Article->create();
2528
		$result = $Article->save(array(
2529
			'id' => 1,
2530
			'title' => '',
2531
			'body' => ''
2532
		));
2533
		$this->assertTrue((bool)$result);
2534
		$result = $Article->find('first', array('conditions' => array('Article.id' => 1)));
2535
		$this->assertEquals('', $result['Article']['title'], 'Title is not blank');
2536
		$this->assertEquals('', $result['Article']['body'], 'Body is not blank');
2537
	}
2538
2539
/**
2540
 * testUpdateMultiple method
2541
 *
2542
 * @return void
2543
 */
2544
	public function testUpdateMultiple() {
2545
		$this->loadFixtures('Comment', 'Article', 'User', 'CategoryThread');
2546
		$TestModel = new Comment();
2547
		$result = Hash::extract($TestModel->find('all'), '{n}.Comment.user_id');
0 ignored issues
show
Bug introduced by
It seems like $TestModel->find('all') targeting Model::find() can also be of type null; however, Hash::extract() does only seem to accept array, maybe add an additional type check?

This check looks at variables that are passed out again to other methods.

If the outgoing method call has stricter type requirements than the method itself, an issue is raised.

An additional type check may prevent trouble.

Loading history...
2548
		$expected = array('2', '4', '1', '1', '1', '2');
2549
		$this->assertEquals($expected, $result);
2550
2551
		$TestModel->updateAll(array('Comment.user_id' => 5), array('Comment.user_id' => 2));
2552
		$result = Hash::combine($TestModel->find('all'), '{n}.Comment.id', '{n}.Comment.user_id');
0 ignored issues
show
Bug introduced by
It seems like $TestModel->find('all') targeting Model::find() can also be of type null; however, Hash::combine() does only seem to accept array, maybe add an additional type check?

This check looks at variables that are passed out again to other methods.

If the outgoing method call has stricter type requirements than the method itself, an issue is raised.

An additional type check may prevent trouble.

Loading history...
2553
		$expected = array(1 => 5, 2 => 4, 3 => 1, 4 => 1, 5 => 1, 6 => 5);
2554
		$this->assertEquals($expected, $result);
2555
2556
		$result = $TestModel->updateAll(
2557
			array('Comment.comment' => "'Updated today'"),
2558
			array('Comment.user_id' => 5)
2559
		);
2560
		$this->assertFalse(empty($result));
2561
		$result = Hash::extract(
2562
			$TestModel->find('all', array(
0 ignored issues
show
Bug introduced by
It seems like $TestModel->find('all', ...omment.user_id' => 5))) targeting Model::find() can also be of type null; however, Hash::extract() does only seem to accept array, maybe add an additional type check?

This check looks at variables that are passed out again to other methods.

If the outgoing method call has stricter type requirements than the method itself, an issue is raised.

An additional type check may prevent trouble.

Loading history...
2563
				'conditions' => array(
2564
					'Comment.user_id' => 5
2565
			))),
2566
			'{n}.Comment.comment'
2567
		);
2568
		$expected = array_fill(0, 2, 'Updated today');
2569
		$this->assertEquals($expected, $result);
2570
	}
2571
2572
/**
2573
 * testHabtmUuidWithUuidId method
2574
 *
2575
 * @return void
2576
 */
2577
	public function testHabtmUuidWithUuidId() {
2578
		$this->loadFixtures('Uuidportfolio', 'Uuiditem', 'UuiditemsUuidportfolio', 'UuiditemsUuidportfolioNumericid');
2579
		$TestModel = new Uuidportfolio();
2580
2581
		$data = array('Uuidportfolio' => array('name' => 'Portfolio 3'));
2582
		$data['Uuiditem']['Uuiditem'] = array('483798c8-c7cc-430e-8cf9-4fcc40cf8569');
2583
		$TestModel->create($data);
2584
		$TestModel->save();
2585
		$id = $TestModel->id;
2586
		$result = $TestModel->read(null, $id);
2587
		$this->assertEquals(1, count($result['Uuiditem']));
2588
		$this->assertEquals(36, strlen($result['Uuiditem'][0]['UuiditemsUuidportfolio']['id']));
2589
	}
2590
2591
/**
2592
 * test HABTM saving when join table has no primary key and only 2 columns.
2593
 *
2594
 * @return void
2595
 */
2596 View Code Duplication
	public function testHabtmSavingWithNoPrimaryKeyUuidJoinTable() {
2597
		$this->loadFixtures('UuidTag', 'Fruit', 'FruitsUuidTag');
2598
		$Fruit = new Fruit();
2599
		$Fruit->FruitsUuidTag->order = null;
2600
		$data = array(
2601
			'Fruit' => array(
2602
				'color' => 'Red',
2603
				'shape' => 'Heart-shaped',
2604
				'taste' => 'sweet',
2605
				'name' => 'Strawberry',
2606
			),
2607
			'UuidTag' => array(
2608
				'UuidTag' => array(
2609
					'481fc6d0-b920-43e0-e50f-6d1740cf8569'
2610
				)
2611
			)
2612
		);
2613
		$result = $Fruit->save($data);
2614
		$this->assertFalse(empty($result));
2615
	}
2616
2617
/**
2618
 * test HABTM saving when join table has no primary key and only 2 columns, no with model is used.
2619
 *
2620
 * @return void
2621
 */
2622 View Code Duplication
	public function testHabtmSavingWithNoPrimaryKeyUuidJoinTableNoWith() {
2623
		$this->loadFixtures('UuidTag', 'Fruit', 'FruitsUuidTag');
2624
		$Fruit = new FruitNoWith();
2625
		$data = array(
2626
			'Fruit' => array(
2627
				'color' => 'Red',
2628
				'shape' => 'Heart-shaped',
2629
				'taste' => 'sweet',
2630
				'name' => 'Strawberry',
2631
			),
2632
			'UuidTag' => array(
2633
				'UuidTag' => array(
2634
					'481fc6d0-b920-43e0-e50f-6d1740cf8569'
2635
				)
2636
			)
2637
		);
2638
		$result = $Fruit->save($data);
2639
		$this->assertFalse(empty($result));
2640
	}
2641
2642
/**
2643
 * testHabtmUuidWithNumericId method
2644
 *
2645
 * @return void
2646
 */
2647
	public function testHabtmUuidWithNumericId() {
2648
		$this->loadFixtures('Uuidportfolio', 'Uuiditem', 'UuiditemsUuidportfolioNumericid');
2649
		$TestModel = new Uuiditem();
2650
2651
		$data = array('Uuiditem' => array('name' => 'Item 7', 'published' => 0));
2652
		$data['Uuidportfolio']['Uuidportfolio'] = array('480af662-eb8c-47d3-886b-230540cf8569');
2653
		$TestModel->create($data);
2654
		$TestModel->save();
2655
		$id = $TestModel->id;
2656
		$result = $TestModel->read(null, $id);
2657
		$this->assertEquals(1, count($result['Uuidportfolio']));
2658
	}
2659
2660
/**
2661
 * testSaveMultipleHabtm method
2662
 *
2663
 * @return void
2664
 */
2665
	public function testSaveMultipleHabtm() {
2666
		$this->loadFixtures('JoinA', 'JoinB', 'JoinC', 'JoinAB', 'JoinAC');
2667
		$TestModel = new JoinA();
2668
		$result = $TestModel->findById(1);
0 ignored issues
show
Documentation Bug introduced by
The method findById does not exist on object<JoinA>? Since you implemented __call, maybe consider adding a @method annotation.

If you implement __call and you know which methods are available, you can improve IDE auto-completion and static analysis by adding a @method annotation to the class.

This is often the case, when __call is implemented by a parent class and only the child class knows which methods exist:

class ParentClass {
    private $data = array();

    public function __call($method, array $args) {
        if (0 === strpos($method, 'get')) {
            return $this->data[strtolower(substr($method, 3))];
        }

        throw new \LogicException(sprintf('Unsupported method: %s', $method));
    }
}

/**
 * If this class knows which fields exist, you can specify the methods here:
 *
 * @method string getName()
 */
class SomeClass extends ParentClass { }
Loading history...
2669
2670
		$expected = array(
2671
			'JoinA' => array(
2672
				'id' => 1,
2673
				'name' => 'Join A 1',
2674
				'body' => 'Join A 1 Body',
2675
				'created' => '2008-01-03 10:54:23',
2676
				'updated' => '2008-01-03 10:54:23'
2677
			),
2678
			'JoinB' => array(
2679
				0 => array(
2680
					'id' => 2,
2681
					'name' => 'Join B 2',
2682
					'created' => '2008-01-03 10:55:02',
2683
					'updated' => '2008-01-03 10:55:02',
2684
					'JoinAsJoinB' => array(
2685
						'id' => 1,
2686
						'join_a_id' => 1,
2687
						'join_b_id' => 2,
2688
						'other' => 'Data for Join A 1 Join B 2',
2689
						'created' => '2008-01-03 10:56:33',
2690
						'updated' => '2008-01-03 10:56:33'
2691
			))),
2692
			'JoinC' => array(
2693
				0 => array(
2694
					'id' => 2,
2695
					'name' => 'Join C 2',
2696
					'created' => '2008-01-03 10:56:12',
2697
					'updated' => '2008-01-03 10:56:12',
2698
					'JoinAsJoinC' => array(
2699
						'id' => 1,
2700
						'join_a_id' => 1,
2701
						'join_c_id' => 2,
2702
						'other' => 'Data for Join A 1 Join C 2',
2703
						'created' => '2008-01-03 10:57:22',
2704
						'updated' => '2008-01-03 10:57:22'
2705
		))));
2706
2707
		$this->assertEquals($expected, $result);
2708
2709
		$TestModel->id = 1;
2710
		$data = array(
2711
			'JoinA' => array(
2712
				'id' => '1',
2713
				'name' => 'New name for Join A 1',
2714
				'updated' => self::date()
2715
			),
2716
			'JoinB' => array(
2717
				array(
2718
					'id' => 1,
2719
					'join_b_id' => 2,
2720
					'other' => 'New data for Join A 1 Join B 2',
2721
					'created' => self::date(),
2722
					'updated' => self::date()
2723
			)),
2724
			'JoinC' => array(
2725
				array(
2726
					'id' => 1,
2727
					'join_c_id' => 2,
2728
					'other' => 'New data for Join A 1 Join C 2',
2729
					'created' => self::date(),
2730
					'updated' => self::date()
2731
		)));
2732
2733
		$TestModel->set($data);
2734
		$TestModel->save();
2735
2736
		$result = $TestModel->findById(1);
0 ignored issues
show
Documentation Bug introduced by
The method findById does not exist on object<JoinA>? Since you implemented __call, maybe consider adding a @method annotation.

If you implement __call and you know which methods are available, you can improve IDE auto-completion and static analysis by adding a @method annotation to the class.

This is often the case, when __call is implemented by a parent class and only the child class knows which methods exist:

class ParentClass {
    private $data = array();

    public function __call($method, array $args) {
        if (0 === strpos($method, 'get')) {
            return $this->data[strtolower(substr($method, 3))];
        }

        throw new \LogicException(sprintf('Unsupported method: %s', $method));
    }
}

/**
 * If this class knows which fields exist, you can specify the methods here:
 *
 * @method string getName()
 */
class SomeClass extends ParentClass { }
Loading history...
2737
		$expected = array(
2738
			'JoinA' => array(
2739
				'id' => 1,
2740
				'name' => 'New name for Join A 1',
2741
				'body' => 'Join A 1 Body',
2742
				'created' => '2008-01-03 10:54:23',
2743
				'updated' => self::date()
2744
			),
2745
			'JoinB' => array(
2746
				0 => array(
2747
					'id' => 2,
2748
					'name' => 'Join B 2',
2749
					'created' => '2008-01-03 10:55:02',
2750
					'updated' => '2008-01-03 10:55:02',
2751
					'JoinAsJoinB' => array(
2752
						'id' => 1,
2753
						'join_a_id' => 1,
2754
						'join_b_id' => 2,
2755
						'other' => 'New data for Join A 1 Join B 2',
2756
						'created' => self::date(),
2757
						'updated' => self::date()
2758
			))),
2759
			'JoinC' => array(
2760
				0 => array(
2761
					'id' => 2,
2762
					'name' => 'Join C 2',
2763
					'created' => '2008-01-03 10:56:12',
2764
					'updated' => '2008-01-03 10:56:12',
2765
					'JoinAsJoinC' => array(
2766
						'id' => 1,
2767
						'join_a_id' => 1,
2768
						'join_c_id' => 2,
2769
						'other' => 'New data for Join A 1 Join C 2',
2770
						'created' => self::date(),
2771
						'updated' => self::date()
2772
		))));
2773
2774
		$this->assertEquals($expected, $result);
2775
	}
2776
2777
/**
2778
 * testSaveAll method
2779
 *
2780
 * @return void
2781
 */
2782
	public function testSaveAll() {
2783
		$this->loadFixtures('Post', 'Author', 'Comment', 'Attachment', 'Article', 'User');
2784
		$TestModel = new Post();
2785
2786
		$result = $TestModel->find('all');
2787
		$this->assertEquals(3, count($result));
2788
		$this->assertFalse(isset($result[3]));
2789
2790
		$TestModel->saveAll(array(
2791
			'Post' => array(
2792
				'title' => 'Post with Author',
2793
				'body' => 'This post will be saved with an author'
2794
			),
2795
			'Author' => array(
2796
				'user' => 'bob',
2797
				'password' => '5f4dcc3b5aa765d61d8327deb882cf90'
2798
		)));
2799
2800
		$result = $TestModel->find('all');
2801
		$expected = array(
2802
			'Post' => array(
2803
				'id' => '4',
2804
				'author_id' => '5',
2805
				'title' => 'Post with Author',
2806
				'body' => 'This post will be saved with an author',
2807
				'published' => 'N'
2808
			),
2809
			'Author' => array(
2810
				'id' => '5',
2811
				'user' => 'bob',
2812
				'password' => '5f4dcc3b5aa765d61d8327deb882cf90',
2813
				'test' => 'working'
2814
		));
2815
		$this->assertEquals(self::date(), $result[3]['Post']['created']);
2816
		$this->assertEquals(self::date(), $result[3]['Post']['updated']);
2817
		$this->assertEquals(self::date(), $result[3]['Author']['created']);
2818
		$this->assertEquals(self::date(), $result[3]['Author']['updated']);
2819
		unset($result[3]['Post']['created'], $result[3]['Post']['updated']);
2820
		unset($result[3]['Author']['created'], $result[3]['Author']['updated']);
2821
		$this->assertEquals($expected, $result[3]);
2822
		$this->assertEquals(4, count($result));
2823
2824
		$TestModel->deleteAll(true);
2825
		$this->assertEquals(array(), $TestModel->find('all'));
2826
2827
		// SQLite seems to reset the PK counter when that happens, so we need this to make the tests pass
2828
		$this->db->truncate($TestModel);
2829
2830
		$TestModel->saveAll(array(
2831
			array(
2832
				'title' => 'Multi-record post 1',
2833
				'body' => 'First multi-record post',
2834
				'author_id' => 2
2835
			),
2836
			array(
2837
				'title' => 'Multi-record post 2',
2838
				'body' => 'Second multi-record post',
2839
				'author_id' => 2
2840
		)));
2841
2842
		$result = $TestModel->find('all', array(
2843
			'recursive' => -1,
2844
			'order' => 'Post.id ASC'
2845
		));
2846
		$expected = array(
2847
			array(
2848
				'Post' => array(
2849
					'id' => '1',
2850
					'author_id' => '2',
2851
					'title' => 'Multi-record post 1',
2852
					'body' => 'First multi-record post',
2853
					'published' => 'N'
2854
			)),
2855
			array(
2856
				'Post' => array(
2857
					'id' => '2',
2858
					'author_id' => '2',
2859
					'title' => 'Multi-record post 2',
2860
					'body' => 'Second multi-record post',
2861
					'published' => 'N'
2862
		)));
2863
		$this->assertEquals(self::date(), $result[0]['Post']['created']);
2864
		$this->assertEquals(self::date(), $result[0]['Post']['updated']);
2865
		$this->assertEquals(self::date(), $result[1]['Post']['created']);
2866
		$this->assertEquals(self::date(), $result[1]['Post']['updated']);
2867
		unset($result[0]['Post']['created'], $result[0]['Post']['updated']);
2868
		unset($result[1]['Post']['created'], $result[1]['Post']['updated']);
2869
		$this->assertEquals($expected, $result);
2870
2871
		$TestModel = new Comment();
2872
		$result = $TestModel->saveAll(array(
2873
			'Comment' => array(
2874
				'article_id' => 2,
2875
				'user_id' => 2,
2876
				'comment' => 'New comment with attachment',
2877
				'published' => 'Y'
2878
			),
2879
			'Attachment' => array(
2880
				'attachment' => 'some_file.tgz'
2881
			)));
2882
		$this->assertFalse(empty($result));
2883
2884
		$result = $TestModel->find('all');
2885
		$expected = array(
2886
			'id' => '7',
2887
			'article_id' => '2',
2888
			'user_id' => '2',
2889
			'comment' => 'New comment with attachment',
2890
			'published' => 'Y'
2891
		);
2892
		$this->assertEquals(self::date(), $result[6]['Comment']['created']);
2893
		$this->assertEquals(self::date(), $result[6]['Comment']['updated']);
2894
		unset($result[6]['Comment']['created'], $result[6]['Comment']['updated']);
2895
		$this->assertEquals($expected, $result[6]['Comment']);
2896
2897
		$expected = array(
2898
			'id' => '2',
2899
			'comment_id' => '7',
2900
			'attachment' => 'some_file.tgz'
2901
		);
2902
		$this->assertEquals(self::date(), $result[6]['Attachment']['created']);
2903
		$this->assertEquals(self::date(), $result[6]['Attachment']['updated']);
2904
		unset($result[6]['Attachment']['created'], $result[6]['Attachment']['updated']);
2905
		$this->assertEquals($expected, $result[6]['Attachment']);
2906
	}
2907
2908
/**
2909
 * Test SaveAll with Habtm relations
2910
 *
2911
 * @return void
2912
 */
2913 View Code Duplication
	public function testSaveAllHabtm() {
2914
		$this->loadFixtures('Article', 'Tag', 'Comment', 'User', 'ArticlesTag');
2915
		$data = array(
2916
			'Article' => array(
2917
				'user_id' => 1,
2918
				'title' => 'Article Has and belongs to Many Tags'
2919
			),
2920
			'Tag' => array(
2921
				'Tag' => array(1, 2)
2922
			),
2923
			'Comment' => array(
2924
				array(
2925
					'comment' => 'Article comment',
2926
					'user_id' => 1
2927
		)));
2928
		$Article = new Article();
2929
		$result = $Article->saveAll($data);
2930
		$this->assertFalse(empty($result));
2931
2932
		$result = $Article->read();
2933
		$this->assertEquals(2, count($result['Tag']));
2934
		$this->assertEquals('tag1', $result['Tag'][0]['tag']);
2935
		$this->assertEquals(1, count($result['Comment']));
2936
		$this->assertEquals(1, count($result['Comment'][0]['comment']));
2937
	}
2938
2939
/**
2940
 * Test SaveAll with Habtm relations and extra join table fields
2941
 *
2942
 * @return void
2943
 */
2944 View Code Duplication
	public function testSaveAllHabtmWithExtraJoinTableFields() {
2945
		$this->loadFixtures('Something', 'SomethingElse', 'JoinThing');
2946
2947
		$data = array(
2948
			'Something' => array(
2949
				'id' => 4,
2950
				'title' => 'Extra Fields',
2951
				'body' => 'Extra Fields Body',
2952
				'published' => '1'
2953
			),
2954
			'SomethingElse' => array(
2955
				array('something_else_id' => 1, 'doomed' => '1'),
2956
				array('something_else_id' => 2, 'doomed' => '0'),
2957
				array('something_else_id' => 3, 'doomed' => '1')
2958
			)
2959
		);
2960
2961
		$Something = new Something();
2962
		$result = $Something->saveAll($data);
2963
		$this->assertFalse(empty($result));
2964
		$result = $Something->read();
2965
2966
		$this->assertEquals(3, count($result['SomethingElse']));
2967
		$this->assertTrue(Set::matches('/Something[id=4]', $result));
0 ignored issues
show
Security Bug introduced by
It seems like $result defined by $Something->read() on line 2964 can also be of type false; however, Set::matches() does only seem to accept array, did you maybe forget to handle an error condition?

This check looks for type mismatches where the missing type is false. This is usually indicative of an error condtion.

Consider the follow example

<?php

function getDate($date)
{
    if ($date !== null) {
        return new DateTime($date);
    }

    return false;
}

This function either returns a new DateTime object or false, if there was an error. This is a typical pattern in PHP programming to show that an error has occurred without raising an exception. The calling code should check for this returned false before passing on the value to another function or method that may not be able to handle a false.

Loading history...
2968
2969
		$this->assertTrue(Set::matches('/SomethingElse[id=1]', $result));
0 ignored issues
show
Security Bug introduced by
It seems like $result defined by $Something->read() on line 2964 can also be of type false; however, Set::matches() does only seem to accept array, did you maybe forget to handle an error condition?

This check looks for type mismatches where the missing type is false. This is usually indicative of an error condtion.

Consider the follow example

<?php

function getDate($date)
{
    if ($date !== null) {
        return new DateTime($date);
    }

    return false;
}

This function either returns a new DateTime object or false, if there was an error. This is a typical pattern in PHP programming to show that an error has occurred without raising an exception. The calling code should check for this returned false before passing on the value to another function or method that may not be able to handle a false.

Loading history...
2970
		$this->assertTrue(Set::matches('/SomethingElse[id=1]/JoinThing[something_else_id=1]', $result));
0 ignored issues
show
Security Bug introduced by
It seems like $result defined by $Something->read() on line 2964 can also be of type false; however, Set::matches() does only seem to accept array, did you maybe forget to handle an error condition?

This check looks for type mismatches where the missing type is false. This is usually indicative of an error condtion.

Consider the follow example

<?php

function getDate($date)
{
    if ($date !== null) {
        return new DateTime($date);
    }

    return false;
}

This function either returns a new DateTime object or false, if there was an error. This is a typical pattern in PHP programming to show that an error has occurred without raising an exception. The calling code should check for this returned false before passing on the value to another function or method that may not be able to handle a false.

Loading history...
2971
		$this->assertTrue(Set::matches('/SomethingElse[id=1]/JoinThing[doomed=1]', $result));
0 ignored issues
show
Security Bug introduced by
It seems like $result defined by $Something->read() on line 2964 can also be of type false; however, Set::matches() does only seem to accept array, did you maybe forget to handle an error condition?

This check looks for type mismatches where the missing type is false. This is usually indicative of an error condtion.

Consider the follow example

<?php

function getDate($date)
{
    if ($date !== null) {
        return new DateTime($date);
    }

    return false;
}

This function either returns a new DateTime object or false, if there was an error. This is a typical pattern in PHP programming to show that an error has occurred without raising an exception. The calling code should check for this returned false before passing on the value to another function or method that may not be able to handle a false.

Loading history...
2972
2973
		$this->assertTrue(Set::matches('/SomethingElse[id=2]', $result));
0 ignored issues
show
Security Bug introduced by
It seems like $result defined by $Something->read() on line 2964 can also be of type false; however, Set::matches() does only seem to accept array, did you maybe forget to handle an error condition?

This check looks for type mismatches where the missing type is false. This is usually indicative of an error condtion.

Consider the follow example

<?php

function getDate($date)
{
    if ($date !== null) {
        return new DateTime($date);
    }

    return false;
}

This function either returns a new DateTime object or false, if there was an error. This is a typical pattern in PHP programming to show that an error has occurred without raising an exception. The calling code should check for this returned false before passing on the value to another function or method that may not be able to handle a false.

Loading history...
2974
		$this->assertTrue(Set::matches('/SomethingElse[id=2]/JoinThing[something_else_id=2]', $result));
0 ignored issues
show
Security Bug introduced by
It seems like $result defined by $Something->read() on line 2964 can also be of type false; however, Set::matches() does only seem to accept array, did you maybe forget to handle an error condition?

This check looks for type mismatches where the missing type is false. This is usually indicative of an error condtion.

Consider the follow example

<?php

function getDate($date)
{
    if ($date !== null) {
        return new DateTime($date);
    }

    return false;
}

This function either returns a new DateTime object or false, if there was an error. This is a typical pattern in PHP programming to show that an error has occurred without raising an exception. The calling code should check for this returned false before passing on the value to another function or method that may not be able to handle a false.

Loading history...
2975
		$this->assertTrue(Set::matches('/SomethingElse[id=2]/JoinThing[doomed=0]', $result));
0 ignored issues
show
Security Bug introduced by
It seems like $result defined by $Something->read() on line 2964 can also be of type false; however, Set::matches() does only seem to accept array, did you maybe forget to handle an error condition?

This check looks for type mismatches where the missing type is false. This is usually indicative of an error condtion.

Consider the follow example

<?php

function getDate($date)
{
    if ($date !== null) {
        return new DateTime($date);
    }

    return false;
}

This function either returns a new DateTime object or false, if there was an error. This is a typical pattern in PHP programming to show that an error has occurred without raising an exception. The calling code should check for this returned false before passing on the value to another function or method that may not be able to handle a false.

Loading history...
2976
2977
		$this->assertTrue(Set::matches('/SomethingElse[id=3]', $result));
0 ignored issues
show
Security Bug introduced by
It seems like $result defined by $Something->read() on line 2964 can also be of type false; however, Set::matches() does only seem to accept array, did you maybe forget to handle an error condition?

This check looks for type mismatches where the missing type is false. This is usually indicative of an error condtion.

Consider the follow example

<?php

function getDate($date)
{
    if ($date !== null) {
        return new DateTime($date);
    }

    return false;
}

This function either returns a new DateTime object or false, if there was an error. This is a typical pattern in PHP programming to show that an error has occurred without raising an exception. The calling code should check for this returned false before passing on the value to another function or method that may not be able to handle a false.

Loading history...
2978
		$this->assertTrue(Set::matches('/SomethingElse[id=3]/JoinThing[something_else_id=3]', $result));
0 ignored issues
show
Security Bug introduced by
It seems like $result defined by $Something->read() on line 2964 can also be of type false; however, Set::matches() does only seem to accept array, did you maybe forget to handle an error condition?

This check looks for type mismatches where the missing type is false. This is usually indicative of an error condtion.

Consider the follow example

<?php

function getDate($date)
{
    if ($date !== null) {
        return new DateTime($date);
    }

    return false;
}

This function either returns a new DateTime object or false, if there was an error. This is a typical pattern in PHP programming to show that an error has occurred without raising an exception. The calling code should check for this returned false before passing on the value to another function or method that may not be able to handle a false.

Loading history...
2979
		$this->assertTrue(Set::matches('/SomethingElse[id=3]/JoinThing[doomed=1]', $result));
0 ignored issues
show
Security Bug introduced by
It seems like $result defined by $Something->read() on line 2964 can also be of type false; however, Set::matches() does only seem to accept array, did you maybe forget to handle an error condition?

This check looks for type mismatches where the missing type is false. This is usually indicative of an error condtion.

Consider the follow example

<?php

function getDate($date)
{
    if ($date !== null) {
        return new DateTime($date);
    }

    return false;
}

This function either returns a new DateTime object or false, if there was an error. This is a typical pattern in PHP programming to show that an error has occurred without raising an exception. The calling code should check for this returned false before passing on the value to another function or method that may not be able to handle a false.

Loading history...
2980
	}
2981
2982
/**
2983
 * testSaveAllHasOne method
2984
 *
2985
 * @return void
2986
 */
2987 View Code Duplication
	public function testSaveAllHasOne() {
2988
		$model = new Comment();
2989
		$model->deleteAll(true);
2990
		$this->assertEquals(array(), $model->find('all'));
2991
2992
		$model->Attachment->deleteAll(true);
2993
		$this->assertEquals(array(), $model->Attachment->find('all'));
2994
2995
		$this->assertTrue($model->saveAll(array(
2996
			'Comment' => array(
2997
				'comment' => 'Comment with attachment',
2998
				'article_id' => 1,
2999
				'user_id' => 1
3000
			),
3001
			'Attachment' => array(
3002
				'attachment' => 'some_file.zip'
3003
		))));
3004
		$result = $model->find('all', array('fields' => array(
3005
			'Comment.id', 'Comment.comment', 'Attachment.id',
3006
			'Attachment.comment_id', 'Attachment.attachment'
3007
		)));
3008
		$expected = array(array(
3009
			'Comment' => array(
3010
				'id' => '1',
3011
				'comment' => 'Comment with attachment'
3012
			),
3013
			'Attachment' => array(
3014
				'id' => '1',
3015
				'comment_id' => '1',
3016
				'attachment' => 'some_file.zip'
3017
		)));
3018
		$this->assertEquals($expected, $result);
3019
3020
		$model->Attachment->bindModel(array('belongsTo' => array('Comment')), false);
3021
		$data = array(
3022
			'Comment' => array(
3023
				'comment' => 'Comment with attachment',
3024
				'article_id' => 1,
3025
				'user_id' => 1
3026
			),
3027
			'Attachment' => array(
3028
				'attachment' => 'some_file.zip'
3029
		));
3030
		$this->assertTrue($model->saveAll($data, array('validate' => 'first')));
3031
	}
3032
3033
/**
3034
 * testSaveAllBelongsTo method
3035
 *
3036
 * @return void
3037
 */
3038 View Code Duplication
	public function testSaveAllBelongsTo() {
3039
		$model = new Comment();
3040
		$model->deleteAll(true);
3041
		$this->assertEquals(array(), $model->find('all'));
3042
3043
		$model->Article->deleteAll(true);
3044
		$this->assertEquals(array(), $model->Article->find('all'));
3045
3046
		$this->assertTrue($model->saveAll(array(
3047
			'Comment' => array(
3048
				'comment' => 'Article comment',
3049
				'article_id' => 1,
3050
				'user_id' => 1
3051
			),
3052
			'Article' => array(
3053
				'title' => 'Model Associations 101',
3054
				'user_id' => 1
3055
		))));
3056
		$result = $model->find('all', array('fields' => array(
3057
			'Comment.id', 'Comment.comment', 'Comment.article_id', 'Article.id', 'Article.title'
3058
		)));
3059
		$expected = array(array(
3060
			'Comment' => array(
3061
				'id' => '1',
3062
				'article_id' => '1',
3063
				'comment' => 'Article comment'
3064
			),
3065
			'Article' => array(
3066
				'id' => '1',
3067
				'title' => 'Model Associations 101'
3068
		)));
3069
		$this->assertEquals($expected, $result);
3070
	}
3071
3072
/**
3073
 * testSaveAllHasOneValidation method
3074
 *
3075
 * @return void
3076
 */
3077 View Code Duplication
	public function testSaveAllHasOneValidation() {
3078
		$model = new Comment();
3079
		$model->deleteAll(true);
3080
		$this->assertEquals(array(), $model->find('all'));
3081
3082
		$model->Attachment->deleteAll(true);
3083
		$this->assertEquals(array(), $model->Attachment->find('all'));
3084
3085
		$model->validate = array('comment' => 'notEmpty');
3086
		$model->Attachment->validate = array('attachment' => 'notEmpty');
3087
		$model->Attachment->bindModel(array('belongsTo' => array('Comment')));
3088
3089
		$result = $model->saveAll(
3090
			array(
3091
				'Comment' => array(
3092
					'comment' => '',
3093
					'article_id' => 1,
3094
					'user_id' => 1
3095
				),
3096
				'Attachment' => array('attachment' => '')
3097
			),
3098
			array('validate' => 'first')
3099
		);
3100
		$this->assertEquals(false, $result);
3101
		$expected = array(
3102
			'comment' => array('This field cannot be left blank'),
3103
			'Attachment' => array(
3104
				'attachment' => array('This field cannot be left blank')
3105
			)
3106
		);
3107
		$this->assertEquals($expected, $model->validationErrors);
3108
		$this->assertEquals($expected['Attachment'], $model->Attachment->validationErrors);
3109
	}
3110
3111
/**
3112
 * testSaveAllAtomic method
3113
 *
3114
 * @return void
3115
 */
3116
	public function testSaveAllAtomic() {
3117
		$this->loadFixtures('Article', 'User', 'Comment');
3118
		$TestModel = new Article();
3119
3120
		$result = $TestModel->saveAll(array(
3121
			'Article' => array(
3122
				'title' => 'Post with Author',
3123
				'body' => 'This post will be saved with an author',
3124
				'user_id' => 2
3125
			),
3126
			'Comment' => array(
3127
				array('comment' => 'First new comment', 'user_id' => 2))
3128
		), array('atomic' => false));
3129
3130
		$this->assertSame($result, array('Article' => true, 'Comment' => array(true)));
3131
3132
		$result = $TestModel->saveAll(array(
3133
			array(
3134
				'id' => '1',
3135
				'title' => 'Baleeted First Post',
3136
				'body' => 'Baleeted!',
3137
				'published' => 'N'
3138
			),
3139
			array(
3140
				'id' => '2',
3141
				'title' => 'Just update the title'
3142
			),
3143
			array(
3144
				'title' => 'Creating a fourth post',
3145
				'body' => 'Fourth post body',
3146
				'user_id' => 2
3147
			)
3148
		), array('atomic' => false));
3149
		$this->assertSame($result, array(true, true, true));
3150
3151
		$result = $TestModel->saveAll(array(
3152
			'Article' => array('id' => 2),
3153
			'Comment' => array(
3154
				array(
3155
					'comment' => 'First new comment',
3156
					'published' => 'Y',
3157
					'user_id' => 1
3158
				),
3159
				array(
3160
					'comment' => 'Second new comment',
3161
					'published' => 'Y',
3162
					'user_id' => 2
3163
			))
3164
		), array('validate' => true, 'atomic' => false));
3165
		$this->assertSame($result, array('Article' => true, 'Comment' => array(true, true)));
3166
3167
		$TestModel->validate = array(
3168
			'title' => 'notEmpty',
3169
			'author_id' => 'numeric'
3170
		);
3171
		$result = $TestModel->saveAll(array(
3172
			array(
3173
				'id' => '1',
3174
				'title' => 'Un-Baleeted First Post',
3175
				'body' => 'Not Baleeted!',
3176
				'published' => 'Y'
3177
			),
3178
			array(
3179
				'id' => '2',
3180
				'title' => '',
3181
				'body' => 'Trying to get away with an empty title'
3182
			)
3183
		), array('validate' => true, 'atomic' => false));
3184
		$this->assertSame(array(true, false), $result);
3185
	}
3186
3187
/**
3188
 * testSaveAllDeepAssociated method
3189
 *
3190
 * @return void
3191
 */
3192
	public function testSaveAllDeepAssociated() {
3193
		$this->loadFixtures('Article', 'Comment', 'User', 'Attachment');
3194
		$TestModel = new Article();
3195
		$TestModel->hasMany['Comment']['order'] = array('Comment.created' => 'ASC');
3196
		$TestModel->hasAndBelongsToMany = array();
3197
3198
		$result = $TestModel->saveAll(array(
3199
			'Article' => array('id' => 2),
3200
			'Comment' => array(
3201
				array('comment' => 'First new comment', 'published' => 'Y', 'User' => array('user' => 'newuser', 'password' => 'newuserpass')),
3202
				array('comment' => 'Second new comment', 'published' => 'Y', 'user_id' => 2)
3203
			)
3204
		), array('deep' => true));
3205
		$this->assertTrue($result);
3206
3207
		$result = $TestModel->findById(2);
0 ignored issues
show
Documentation Bug introduced by
The method findById does not exist on object<Article>? Since you implemented __call, maybe consider adding a @method annotation.

If you implement __call and you know which methods are available, you can improve IDE auto-completion and static analysis by adding a @method annotation to the class.

This is often the case, when __call is implemented by a parent class and only the child class knows which methods exist:

class ParentClass {
    private $data = array();

    public function __call($method, array $args) {
        if (0 === strpos($method, 'get')) {
            return $this->data[strtolower(substr($method, 3))];
        }

        throw new \LogicException(sprintf('Unsupported method: %s', $method));
    }
}

/**
 * If this class knows which fields exist, you can specify the methods here:
 *
 * @method string getName()
 */
class SomeClass extends ParentClass { }
Loading history...
3208
		$expected = array(
3209
			'First Comment for Second Article',
3210
			'Second Comment for Second Article',
3211
			'First new comment',
3212
			'Second new comment'
3213
		);
3214
		$result = Hash::extract(Hash::sort($result['Comment'], '{n}.id', 'ASC'), '{n}.comment');
3215
		$this->assertEquals($expected, $result);
3216
3217
		$result = $TestModel->Comment->User->field('id', array('user' => 'newuser', 'password' => 'newuserpass'));
3218
		$this->assertEquals(5, $result);
3219
		$result = $TestModel->saveAll(array(
3220
			'Article' => array('id' => 2),
3221
			'Comment' => array(
3222
				array('comment' => 'Third new comment', 'published' => 'Y', 'user_id' => 5),
3223
				array('comment' => 'Fourth new comment', 'published' => 'Y', 'user_id' => 2, 'Attachment' => array('attachment' => 'deepsaved'))
3224
			)
3225
		), array('deep' => true));
3226
		$this->assertTrue($result);
3227
3228
		$result = $TestModel->findById(2);
0 ignored issues
show
Documentation Bug introduced by
The method findById does not exist on object<Article>? Since you implemented __call, maybe consider adding a @method annotation.

If you implement __call and you know which methods are available, you can improve IDE auto-completion and static analysis by adding a @method annotation to the class.

This is often the case, when __call is implemented by a parent class and only the child class knows which methods exist:

class ParentClass {
    private $data = array();

    public function __call($method, array $args) {
        if (0 === strpos($method, 'get')) {
            return $this->data[strtolower(substr($method, 3))];
        }

        throw new \LogicException(sprintf('Unsupported method: %s', $method));
    }
}

/**
 * If this class knows which fields exist, you can specify the methods here:
 *
 * @method string getName()
 */
class SomeClass extends ParentClass { }
Loading history...
3229
		$expected = array(
3230
			'First Comment for Second Article',
3231
			'Second Comment for Second Article',
3232
			'First new comment',
3233
			'Second new comment',
3234
			'Third new comment',
3235
			'Fourth new comment'
3236
		);
3237
		$result = Hash::extract(Hash::sort($result['Comment'], '{n}.id', 'ASC'), '{n}.comment');
3238
		$this->assertEquals($expected, $result);
3239
3240
		$result = $TestModel->Comment->Attachment->field('id', array('attachment' => 'deepsaved'));
3241
		$this->assertEquals(2, $result);
3242
		$data = array(
3243
			'Attachment' => array(
3244
				'attachment' => 'deepsave insert',
3245
			),
3246
			'Comment' => array(
3247
				'comment' => 'First comment deepsave insert',
3248
				'published' => 'Y',
3249
				'user_id' => 5,
3250
				'Article' => array(
3251
					'title' => 'First Article deepsave insert',
3252
					'body' => 'First Article Body deepsave insert',
3253
					'User' => array(
3254
						'user' => '',
3255
						'password' => 'magic'
3256
					),
3257
				),
3258
			)
3259
		);
3260
3261
		$TestModel->Comment->Attachment->create();
3262
		$result = $TestModel->Comment->Attachment->saveAll($data, array('deep' => true));
3263
		$this->assertFalse($result);
3264
3265
		$expected = array('User' => array('user' => array('This field cannot be left blank')));
3266
		$this->assertEquals($expected, $TestModel->validationErrors);
3267
3268
		$data['Comment']['Article']['User']['user'] = 'deepsave';
3269
		$TestModel->Comment->Attachment->create();
3270
		$result = $TestModel->Comment->Attachment->saveAll($data, array('deep' => true));
3271
		$this->assertTrue($result);
3272
3273
		$result = $TestModel->Comment->Attachment->findById($TestModel->Comment->Attachment->id);
3274
		$expected = array(
3275
			'Attachment' => array(
3276
				'id' => '3',
3277
				'comment_id' => '11',
3278
				'attachment' => 'deepsave insert',
3279
			),
3280
			'Comment' => array(
3281
				'id' => '11',
3282
				'article_id' => '4',
3283
				'user_id' => '5',
3284
				'comment' => 'First comment deepsave insert',
3285
				'published' => 'Y',
3286
			)
3287
		);
3288
		unset($result['Attachment']['created'], $result['Attachment']['updated']);
3289
		$this->assertEquals($expected['Attachment'], $result['Attachment']);
3290
3291
		unset($result['Comment']['created'], $result['Comment']['updated']);
3292
		$this->assertEquals($expected['Comment'], $result['Comment']);
3293
3294
		$result = $TestModel->findById($result['Comment']['article_id']);
0 ignored issues
show
Documentation Bug introduced by
The method findById does not exist on object<Article>? Since you implemented __call, maybe consider adding a @method annotation.

If you implement __call and you know which methods are available, you can improve IDE auto-completion and static analysis by adding a @method annotation to the class.

This is often the case, when __call is implemented by a parent class and only the child class knows which methods exist:

class ParentClass {
    private $data = array();

    public function __call($method, array $args) {
        if (0 === strpos($method, 'get')) {
            return $this->data[strtolower(substr($method, 3))];
        }

        throw new \LogicException(sprintf('Unsupported method: %s', $method));
    }
}

/**
 * If this class knows which fields exist, you can specify the methods here:
 *
 * @method string getName()
 */
class SomeClass extends ParentClass { }
Loading history...
3295
		$expected = array(
3296
			'Article' => array(
3297
				'id' => '4',
3298
				'user_id' => '6',
3299
				'title' => 'First Article deepsave insert',
3300
				'body' => 'First Article Body deepsave insert',
3301
				'published' => 'N',
3302
			),
3303
			'User' => array(
3304
				'id' => '6',
3305
				'user' => 'deepsave',
3306
				'password' => 'magic',
3307
			),
3308
			'Comment' => array(
3309
				array(
3310
					'id' => '11',
3311
					'article_id' => '4',
3312
					'user_id' => '5',
3313
					'comment' => 'First comment deepsave insert',
3314
					'published' => 'Y',
3315
				)
3316
			)
3317
		);
3318
		unset(
3319
			$result['Article']['created'], $result['Article']['updated'],
3320
			$result['User']['created'], $result['User']['updated'],
3321
			$result['Comment'][0]['created'], $result['Comment'][0]['updated']
3322
		);
3323
		$this->assertEquals($expected, $result);
3324
	}
3325
3326
/**
3327
 * testSaveAllDeepMany
3328
 * tests the validate methods with deeper recursive data
3329
 *
3330
 * @return void
3331
 */
3332
	public function testSaveAllDeepMany() {
3333
		$this->loadFixtures('Article', 'Comment', 'User', 'Attachment');
3334
		$TestModel = new Article();
3335
		$TestModel->hasMany['Comment']['order'] = array('Comment.created' => 'ASC');
3336
		$TestModel->hasAndBelongsToMany = array();
3337
3338
		$data = array(
3339
			array(
3340
				'Article' => array('id' => 1),
3341
				'Comment' => array(
3342
					array('comment' => 'First comment deepsaved article 1', 'published' => 'Y', 'User' => array('user' => 'savemany', 'password' => 'manysaved')),
3343
					array('comment' => 'Second comment deepsaved article 1', 'published' => 'Y', 'user_id' => 2)
3344
				)
3345
			),
3346
			array(
3347
				'Article' => array('id' => 2),
3348
				'Comment' => array(
3349
					array('comment' => 'First comment deepsaved article 2', 'published' => 'Y', 'User' => array('user' => 'savemore', 'password' => 'moresaved')),
3350
					array('comment' => 'Second comment deepsaved article 2', 'published' => 'Y', 'user_id' => 2)
3351
				)
3352
			)
3353
		);
3354
		$result = $TestModel->saveAll($data, array('deep' => true));
3355
		$this->assertTrue($result);
3356
3357
		$data = array(
3358
			array(
3359
				'id' => 1, 'body' => '',
3360
				'Comment' => array(
3361
					array('comment' => '', 'published' => 'Y', 'User' => array('user' => '', 'password' => 'manysaved')),
3362
					array('comment' => 'Second comment deepsaved article 1', 'published' => 'Y', 'user_id' => 2)
3363
				)
3364
			),
3365
			array(
3366
				'Article' => array('id' => 2),
3367
				'Comment' => array(
3368
					array('comment' => 'First comment deepsaved article 2', 'published' => 'Y', 'User' => array('user' => 'savemore', 'password' => '')),
3369
					array('comment' => '', 'published' => 'Y', 'user_id' => 2)
3370
				)
3371
			)
3372
		);
3373
		$TestModel->Comment->validate['comment'] = 'notEmpty';
3374
		$result = $TestModel->saveAll($data, array('deep' => true));
3375
		$this->assertFalse($result);
3376
3377
		$expected = array(
3378
			0 => array(
3379
				'body' => array('This field cannot be left blank'),
3380
				'Comment' => array(
3381
					0 => array(
3382
						'comment' => array('This field cannot be left blank'),
3383
						'User' => array(
3384
							'user' => array('This field cannot be left blank')
3385
						)
3386
					)
3387
				)
3388
			),
3389
			1 => array(
3390
				'Comment' => array(
3391
					0 => array(
3392
						'User' => array(
3393
							'password' => array('This field cannot be left blank')
3394
						)
3395
					),
3396
					1 => array(
3397
						'comment' => array('This field cannot be left blank')
3398
					)
3399
				)
3400
			)
3401
		);
3402
		$result = $TestModel->validationErrors;
3403
		$this->assertSame($expected, $result);
3404
	}
3405
/**
3406
 * testSaveAllDeepValidateOnly
3407
 * tests the validate methods with deeper recursive data
3408
 *
3409
 * @return void
3410
 */
3411
	public function testSaveAllDeepValidateOnly() {
3412
		$this->loadFixtures('Article', 'Comment', 'User', 'Attachment');
3413
		$TestModel = new Article();
3414
		$TestModel->hasMany['Comment']['order'] = array('Comment.created' => 'ASC');
3415
		$TestModel->hasAndBelongsToMany = array();
3416
		$TestModel->Comment->Attachment->validate['attachment'] = 'notEmpty';
3417
		$TestModel->Comment->validate['comment'] = 'notEmpty';
3418
3419
		$result = $TestModel->saveAll(
3420
			array(
3421
				'Article' => array('id' => 2),
3422
				'Comment' => array(
3423
					array('comment' => 'First new comment', 'published' => 'Y', 'User' => array('user' => 'newuser', 'password' => 'newuserpass')),
3424
					array('comment' => 'Second new comment', 'published' => 'Y', 'user_id' => 2)
3425
				)
3426
			),
3427
			array('validate' => 'only', 'deep' => true)
3428
		);
3429
		$this->assertTrue($result);
3430
3431
		$result = $TestModel->saveAll(
3432
			array(
3433
				'Article' => array('id' => 2),
3434
				'Comment' => array(
3435
					array('comment' => 'First new comment', 'published' => 'Y', 'User' => array('user' => '', 'password' => 'newuserpass')),
3436
					array('comment' => 'Second new comment', 'published' => 'Y', 'user_id' => 2)
3437
				)
3438
			),
3439
			array('validate' => 'only', 'deep' => true)
3440
		);
3441
		$this->assertFalse($result);
3442
3443
		$result = $TestModel->saveAll(
3444
			array(
3445
				'Article' => array('id' => 2),
3446
				'Comment' => array(
3447
					array('comment' => 'First new comment', 'published' => 'Y', 'User' => array('user' => 'newuser', 'password' => 'newuserpass')),
3448
					array('comment' => 'Second new comment', 'published' => 'Y', 'user_id' => 2)
3449
				)
3450
			),
3451
			array('validate' => 'only', 'atomic' => false, 'deep' => true)
3452
		);
3453
		$expected = array(
3454
			'Article' => true,
3455
			'Comment' => array(
3456
				true,
3457
				true
3458
			)
3459
		);
3460
		$this->assertSame($expected, $result);
3461
3462
		$result = $TestModel->saveAll(
3463
			array(
3464
				'Article' => array('id' => 2),
3465
				'Comment' => array(
3466
					array('comment' => 'First new comment', 'published' => 'Y', 'User' => array('user' => '', 'password' => 'newuserpass')),
3467
					array('comment' => 'Second new comment', 'published' => 'Y', 'user_id' => 2)
3468
				)
3469
			),
3470
			array('validate' => 'only', 'atomic' => false, 'deep' => true)
3471
		);
3472
		$expected = array(
3473
			'Article' => true,
3474
			'Comment' => array(
3475
				false,
3476
				true
3477
			)
3478
		);
3479
		$this->assertSame($expected, $result);
3480
3481
		$result = $TestModel->saveAll(array(
3482
			'Article' => array('id' => 2),
3483
			'Comment' => array(
3484
				array('comment' => 'Third new comment', 'published' => 'Y', 'user_id' => 5),
3485
				array('comment' => 'Fourth new comment', 'published' => 'Y', 'user_id' => 2, 'Attachment' => array('attachment' => 'deepsaved'))
3486
			)
3487
		),
3488
		array('validate' => 'only', 'deep' => true)
3489
		);
3490
		$this->assertTrue($result);
3491
3492
		$result = $TestModel->saveAll(array(
3493
			'Article' => array('id' => 2),
3494
			'Comment' => array(
3495
				array('comment' => 'Third new comment', 'published' => 'Y', 'user_id' => 5),
3496
				array('comment' => 'Fourth new comment', 'published' => 'Y', 'user_id' => 2, 'Attachment' => array('attachment' => ''))
3497
			)
3498
		),
3499
		array('validate' => 'only', 'deep' => true)
3500
		);
3501
		$this->assertFalse($result);
3502
3503
		$result = $TestModel->saveAll(array(
3504
			'Article' => array('id' => 2),
3505
			'Comment' => array(
3506
				array('comment' => 'Third new comment', 'published' => 'Y', 'user_id' => 5),
3507
				array('comment' => 'Fourth new comment', 'published' => 'Y', 'user_id' => 2, 'Attachment' => array('attachment' => 'deepsave'))
3508
			)
3509
		),
3510
		array('validate' => 'only', 'atomic' => false, 'deep' => true)
3511
		);
3512
		$expected = array(
3513
			'Article' => true,
3514
			'Comment' => array(
3515
				true,
3516
				true
3517
			)
3518
		);
3519
		$this->assertSame($expected, $result);
3520
3521
		$result = $TestModel->saveAll(array(
3522
			'Article' => array('id' => 2),
3523
			'Comment' => array(
3524
				array('comment' => 'Third new comment', 'published' => 'Y', 'user_id' => 5),
3525
				array('comment' => 'Fourth new comment', 'published' => 'Y', 'user_id' => 2, 'Attachment' => array('attachment' => ''))
3526
			)
3527
		),
3528
		array('validate' => 'only', 'atomic' => false, 'deep' => true)
3529
		);
3530
		$expected = array(
3531
			'Article' => true,
3532
			'Comment' => array(
3533
				true,
3534
				false
3535
			)
3536
		);
3537
		$this->assertSame($expected, $result);
3538
3539
		$expected = array(
3540
			'Comment' => array(
3541
				1 => array(
3542
					'Attachment' => array(
3543
						'attachment' => array('This field cannot be left blank')
3544
					)
3545
				)
3546
			)
3547
		);
3548
		$result = $TestModel->validationErrors;
3549
		$this->assertSame($expected, $result);
3550
3551
		$data = array(
3552
			'Attachment' => array(
3553
				'attachment' => 'deepsave insert',
3554
			),
3555
			'Comment' => array(
3556
				'comment' => 'First comment deepsave insert',
3557
				'published' => 'Y',
3558
				'user_id' => 5,
3559
				'Article' => array(
3560
					'title' => 'First Article deepsave insert',
3561
					'body' => 'First Article Body deepsave insert',
3562
					'User' => array(
3563
						'user' => 'deepsave',
3564
						'password' => 'magic'
3565
					),
3566
				),
3567
			)
3568
		);
3569
3570
		$result = $TestModel->Comment->Attachment->saveAll($data, array('validate' => 'only', 'deep' => true));
3571
		$this->assertTrue($result);
3572
3573
		$result = $TestModel->Comment->Attachment->saveAll($data, array('validate' => 'only', 'atomic' => false, 'deep' => true));
3574
		$expected = array(
3575
			'Attachment' => true,
3576
			'Comment' => true
3577
		);
3578
		$this->assertSame($expected, $result);
3579
3580
		$data = array(
3581
			'Attachment' => array(
3582
				'attachment' => 'deepsave insert',
3583
			),
3584
			'Comment' => array(
3585
				'comment' => 'First comment deepsave insert',
3586
				'published' => 'Y',
3587
				'user_id' => 5,
3588
				'Article' => array(
3589
					'title' => 'First Article deepsave insert',
3590
					'body' => 'First Article Body deepsave insert',
3591
					'User' => array(
3592
						'user' => '',
3593
						'password' => 'magic'
3594
					),
3595
				),
3596
			)
3597
		);
3598
3599
		$result = $TestModel->Comment->Attachment->saveAll($data, array('validate' => 'only', 'deep' => true));
3600
		$this->assertFalse($result);
3601
3602
		$result = $TestModel->Comment->Attachment->validationErrors;
3603
		$expected = array(
3604
			'Comment' => array(
3605
				'Article' => array(
3606
					'User' => array(
3607
						'user' => array('This field cannot be left blank')
3608
					)
3609
				)
3610
			)
3611
		);
3612
		$this->assertSame($expected, $result);
3613
3614
		$result = $TestModel->Comment->Attachment->saveAll($data, array('validate' => 'only', 'atomic' => false, 'deep' => true));
3615
		$expected = array(
3616
			'Attachment' => true,
3617
			'Comment' => false
3618
		);
3619
		$this->assertEquals($expected, $result);
3620
3621
		$data['Comment']['Article']['body'] = '';
3622
		$result = $TestModel->Comment->Attachment->saveAll($data, array('validate' => 'only', 'deep' => true));
3623
		$this->assertFalse($result);
3624
3625
		$result = $TestModel->Comment->Attachment->validationErrors;
3626
		$expected = array(
3627
			'Comment' => array(
3628
				'Article' => array(
3629
					'body' => array('This field cannot be left blank'),
3630
					'User' => array(
3631
						'user' => array('This field cannot be left blank')
3632
					)
3633
				)
3634
			)
3635
		);
3636
		$this->assertSame($expected, $result);
3637
3638
		$result = $TestModel->Comment->Attachment->saveAll($data, array('validate' => 'only', 'atomic' => false, 'deep' => true));
3639
		$expected = array(
3640
			'Attachment' => true,
3641
			'Comment' => false
3642
		);
3643
		$this->assertEquals($expected, $result);
3644
3645
		$data['Comment']['comment'] = '';
3646
		$result = $TestModel->Comment->Attachment->saveAll($data, array('validate' => 'only', 'deep' => true));
3647
		$this->assertFalse($result);
3648
3649
		$result = $TestModel->Comment->Attachment->validationErrors;
3650
		$expected = array(
3651
			'Comment' => array(
3652
				'comment' => array('This field cannot be left blank'),
3653
				'Article' => array(
3654
					'body' => array('This field cannot be left blank'),
3655
					'User' => array(
3656
						'user' => array('This field cannot be left blank')
3657
					)
3658
				)
3659
			)
3660
		);
3661
		$this->assertSame($expected, $result);
3662
3663
		$result = $TestModel->Comment->Attachment->saveAll($data, array('validate' => 'only', 'atomic' => false, 'deep' => true));
3664
		$expected = array(
3665
			'Attachment' => true,
3666
			'Comment' => false
3667
		);
3668
		$this->assertEquals($expected, $result);
3669
3670
		$data['Attachment']['attachment'] = '';
3671
		$result = $TestModel->Comment->Attachment->saveAll($data, array('validate' => 'only', 'deep' => true));
3672
		$this->assertFalse($result);
3673
3674
		$result = $TestModel->Comment->Attachment->validationErrors;
3675
		$expected = array(
3676
			'attachment' => array('This field cannot be left blank'),
3677
			'Comment' => array(
3678
				'comment' => array('This field cannot be left blank'),
3679
				'Article' => array(
3680
					'body' => array('This field cannot be left blank'),
3681
					'User' => array(
3682
						'user' => array('This field cannot be left blank')
3683
					)
3684
				)
3685
			)
3686
		);
3687
		$this->assertSame($expected, $result);
3688
3689
		$result = $TestModel->Comment->validationErrors;
3690
		$expected = array(
3691
			'comment' => array('This field cannot be left blank'),
3692
			'Article' => array(
3693
				'body' => array('This field cannot be left blank'),
3694
				'User' => array(
3695
					'user' => array('This field cannot be left blank')
3696
				)
3697
			)
3698
		);
3699
		$this->assertSame($expected, $result);
3700
3701
		$result = $TestModel->Comment->Attachment->saveAll($data, array('validate' => 'only', 'atomic' => false, 'deep' => true));
3702
		$expected = array(
3703
			'Attachment' => false,
3704
			'Comment' => false
3705
		);
3706
		$this->assertEquals($expected, $result);
3707
	}
3708
3709
/**
3710
 * testSaveAllNotDeepAssociated method
3711
 * test that only directly associated data gets saved
3712
 *
3713
 * @return void
3714
 */
3715
	public function testSaveAllNotDeepAssociated() {
3716
		$this->loadFixtures('Article', 'Comment', 'User', 'Attachment');
3717
		$TestModel = new Article();
3718
		$TestModel->hasMany['Comment']['order'] = array('Comment.created' => 'ASC');
3719
		$TestModel->hasAndBelongsToMany = array();
3720
3721
		$result = $TestModel->saveAll(array(
3722
			'Article' => array('id' => 2),
3723
			'Comment' => array(
3724
				array(
3725
					'comment' => 'First new comment', 'published' => 'Y', 'user_id' => 2,
3726
					'User' => array('user' => 'newuser', 'password' => 'newuserpass')
3727
				),
3728
				array('comment' => 'Second new comment', 'published' => 'Y', 'user_id' => 2)
3729
			)
3730
		), array('deep' => false));
3731
		$this->assertTrue($result);
3732
3733
		$result = $TestModel->Comment->User->field('id', array('user' => 'newuser', 'password' => 'newuserpass'));
3734
		$this->assertFalse($result);
3735
3736
		$result = $TestModel->saveAll(array(
3737
			'Article' => array('id' => 2),
3738
			'Comment' => array(
3739
				array('comment' => 'Third new comment', 'published' => 'Y', 'user_id' => 4),
3740
				array('comment' => 'Fourth new comment', 'published' => 'Y', 'user_id' => 2, 'Attachment' => array('attachment' => 'deepsaved'))
3741
			)
3742
		), array('deep' => false));
3743
		$this->assertTrue($result);
3744
3745
		$result = $TestModel->Comment->Attachment->field('id', array('attachment' => 'deepsaved'));
3746
		$this->assertFalse($result);
3747
3748
		$data = array(
3749
			'Attachment' => array(
3750
				'attachment' => 'deepsave insert',
3751
			),
3752
			'Comment' => array(
3753
				'comment' => 'First comment deepsave insert',
3754
				'published' => 'Y',
3755
				'user_id' => 4,
3756
				'article_id' => 1,
3757
				'Article' => array(
3758
					'title' => 'First Article deepsave insert',
3759
					'body' => 'First Article Body deepsave insert',
3760
					'User' => array(
3761
						'user' => 'deepsave',
3762
						'password' => 'magic'
3763
					),
3764
				),
3765
			)
3766
		);
3767
		$expected = $TestModel->User->find('count');
3768
3769
		$TestModel->Comment->Attachment->create();
3770
		$result = $TestModel->Comment->Attachment->saveAll($data, array('deep' => false));
3771
		$this->assertTrue($result);
3772
3773
		$result = $TestModel->User->find('count');
3774
		$this->assertEquals($expected, $result);
3775
3776
		$result = $TestModel->Comment->Attachment->findById($TestModel->Comment->Attachment->id);
3777
		$expected = array(
3778
			'Attachment' => array(
3779
				'id' => '2',
3780
				'comment_id' => '11',
3781
				'attachment' => 'deepsave insert',
3782
			),
3783
			'Comment' => array(
3784
				'id' => '11',
3785
				'article_id' => 1,
3786
				'user_id' => '4',
3787
				'comment' => 'First comment deepsave insert',
3788
				'published' => 'Y',
3789
			)
3790
		);
3791
		unset($result['Attachment']['created'], $result['Attachment']['updated']);
3792
		$this->assertEquals($expected['Attachment'], $result['Attachment']);
3793
3794
		unset($result['Comment']['created'], $result['Comment']['updated']);
3795
		$this->assertEquals($expected['Comment'], $result['Comment']);
3796
	}
3797
3798
/**
3799
 * testSaveAllNotDeepMany
3800
 * tests the save methods to not save deeper recursive data
3801
 *
3802
 * @return void
3803
 */
3804
	public function testSaveAllNotDeepMany() {
3805
		$this->loadFixtures('Article', 'Comment', 'User', 'Attachment');
3806
		$TestModel = new Article();
3807
		$TestModel->hasMany['Comment']['order'] = array('Comment.created' => 'ASC');
3808
		$TestModel->hasAndBelongsToMany = array();
3809
3810
		$data = array(
3811
			array(
3812
				'id' => 1,
3813
				'body' => '',
3814
				'Comment' => array(
3815
					array('comment' => '', 'published' => 'Y', 'User' => array('user' => '', 'password' => 'manysaved')),
3816
					array('comment' => 'Second comment deepsaved article 1', 'published' => 'Y', 'user_id' => 2)
3817
				)
3818
			),
3819
			array(
3820
				'Article' => array('id' => 2),
3821
				'Comment' => array(
3822
					array('comment' => 'First comment deepsaved article 2', 'published' => 'Y', 'User' => array('user' => 'savemore', 'password' => '')),
3823
					array('comment' => '', 'published' => 'Y', 'user_id' => 2)
3824
				)
3825
			)
3826
		);
3827
		$TestModel->Comment->validate['comment'] = 'notEmpty';
3828
		$result = $TestModel->saveAll($data, array('deep' => false));
3829
		$this->assertFalse($result);
3830
3831
		$expected = array(
3832
			0 => array(
3833
				'body' => array('This field cannot be left blank')
3834
			)
3835
		);
3836
		$result = $TestModel->validationErrors;
3837
		$this->assertSame($expected, $result);
3838
3839
		$data = array(
3840
			array(
3841
				'Article' => array('id' => 1, 'body' => 'Ignore invalid comment'),
3842
				'Comment' => array(
3843
					array('comment' => '', 'published' => 'Y', 'user_id' => 2)
3844
				)
3845
			),
3846
			array(
3847
				'Article' => array('id' => 2),
3848
				'Comment' => array(
3849
					array('comment' => '', 'published' => 'Y', 'user_id' => 2)
3850
				)
3851
			)
3852
		);
3853
		$result = $TestModel->saveAll($data, array('deep' => false));
3854
		$this->assertTrue($result);
3855
	}
3856
/**
3857
 * testSaveAllNotDeepValidateOnly
3858
 * tests the validate methods to not validate deeper recursive data
3859
 *
3860
 * @return void
3861
 */
3862
	public function testSaveAllNotDeepValidateOnly() {
3863
		$this->loadFixtures('Article', 'Comment', 'User', 'Attachment');
3864
		$TestModel = new Article();
3865
		$TestModel->hasMany['Comment']['order'] = array('Comment.created' => 'ASC');
3866
		$TestModel->hasAndBelongsToMany = array();
3867
		$TestModel->Comment->Attachment->validate['attachment'] = 'notEmpty';
3868
		$TestModel->Comment->validate['comment'] = 'notEmpty';
3869
3870
		$result = $TestModel->saveAll(
3871
			array(
3872
				'Article' => array('id' => 2, 'body' => ''),
3873
				'Comment' => array(
3874
					array('comment' => 'First new comment', 'published' => 'Y', 'User' => array('user' => '', 'password' => 'newuserpass')),
3875
					array('comment' => 'Second new comment', 'published' => 'Y', 'user_id' => 2)
3876
				)
3877
			),
3878
			array('validate' => 'only', 'deep' => false)
3879
		);
3880
		$this->assertFalse($result);
3881
3882
		$expected = array('body' => array('This field cannot be left blank'));
3883
		$result = $TestModel->validationErrors;
3884
		$this->assertSame($expected, $result);
3885
3886
		$result = $TestModel->saveAll(
3887
			array(
3888
				'Article' => array('id' => 2, 'body' => 'Ignore invalid user data'),
3889
				'Comment' => array(
3890
					array('comment' => 'First new comment', 'published' => 'Y', 'User' => array('user' => '', 'password' => 'newuserpass')),
3891
					array('comment' => 'Second new comment', 'published' => 'Y', 'user_id' => 2)
3892
				)
3893
			),
3894
			array('validate' => 'only', 'deep' => false)
3895
		);
3896
		$this->assertTrue($result);
3897
3898
		$result = $TestModel->saveAll(
3899
			array(
3900
				'Article' => array('id' => 2, 'body' => 'Ignore invalid user data'),
3901
				'Comment' => array(
3902
					array('comment' => 'First new comment', 'published' => 'Y', 'User' => array('user' => '', 'password' => 'newuserpass')),
3903
					array('comment' => 'Second new comment', 'published' => 'Y', 'user_id' => 2)
3904
				)
3905
			),
3906
			array('validate' => 'only', 'atomic' => false, 'deep' => false)
3907
		);
3908
		$expected = array(
3909
			'Article' => true,
3910
			'Comment' => array(
3911
				true,
3912
				true
3913
			)
3914
		);
3915
		$this->assertSame($expected, $result);
3916
3917
		$result = $TestModel->saveAll(array(
3918
			'Article' => array('id' => 2, 'body' => 'Ignore invalid attachment data'),
3919
			'Comment' => array(
3920
				array('comment' => 'Third new comment', 'published' => 'Y', 'user_id' => 5),
3921
				array('comment' => 'Fourth new comment', 'published' => 'Y', 'user_id' => 2, 'Attachment' => array('attachment' => ''))
3922
			)
3923
		),
3924
		array('validate' => 'only', 'deep' => false)
3925
		);
3926
		$this->assertTrue($result);
3927
3928
		$result = $TestModel->saveAll(array(
3929
			'Article' => array('id' => 2, 'body' => 'Ignore invalid attachment data'),
3930
			'Comment' => array(
3931
				array('comment' => 'Third new comment', 'published' => 'Y', 'user_id' => 5),
3932
				array('comment' => 'Fourth new comment', 'published' => 'Y', 'user_id' => 2, 'Attachment' => array('attachment' => ''))
3933
			)
3934
		),
3935
		array('validate' => 'only', 'atomic' => false, 'deep' => false)
3936
		);
3937
		$expected = array(
3938
			'Article' => true,
3939
			'Comment' => array(
3940
				true,
3941
				true
3942
			)
3943
		);
3944
		$this->assertSame($expected, $result);
3945
3946
		$expected = array();
3947
		$result = $TestModel->validationErrors;
3948
		$this->assertSame($expected, $result);
3949
3950
		$data = array(
3951
			'Attachment' => array(
3952
				'attachment' => 'deepsave insert',
3953
			),
3954
			'Comment' => array(
3955
				'comment' => 'First comment deepsave insert',
3956
				'published' => 'Y',
3957
				'user_id' => 5,
3958
				'Article' => array(
3959
					'title' => 'First Article deepsave insert ignored',
3960
					'body' => 'First Article Body deepsave insert',
3961
					'User' => array(
3962
						'user' => '',
3963
						'password' => 'magic'
3964
					),
3965
				),
3966
			)
3967
		);
3968
3969
		$result = $TestModel->Comment->Attachment->saveAll($data, array('validate' => 'only', 'deep' => false));
3970
		$this->assertTrue($result);
3971
3972
		$result = $TestModel->Comment->Attachment->validationErrors;
3973
		$expected = array();
3974
		$this->assertSame($expected, $result);
3975
3976
		$result = $TestModel->Comment->Attachment->saveAll($data, array('validate' => 'only', 'atomic' => false, 'deep' => false));
3977
		$expected = array(
3978
			'Attachment' => true,
3979
			'Comment' => true
3980
		);
3981
		$this->assertEquals($expected, $result);
3982
3983
		$data['Comment']['Article']['body'] = '';
3984
		$result = $TestModel->Comment->Attachment->saveAll($data, array('validate' => 'only', 'deep' => false));
3985
		$this->assertTrue($result);
3986
3987
		$result = $TestModel->Comment->Attachment->validationErrors;
3988
		$expected = array();
3989
		$this->assertSame($expected, $result);
3990
3991
		$result = $TestModel->Comment->Attachment->saveAll($data, array('validate' => 'only', 'atomic' => false, 'deep' => false));
3992
		$expected = array(
3993
			'Attachment' => true,
3994
			'Comment' => true
3995
		);
3996
		$this->assertEquals($expected, $result);
3997
	}
3998
3999
/**
4000
 * testSaveAllHasMany method
4001
 *
4002
 * @return void
4003
 */
4004
	public function testSaveAllHasMany() {
4005
		$this->loadFixtures('Article', 'Comment');
4006
		$TestModel = new Article();
4007
		$TestModel->hasMany['Comment']['order'] = array('Comment.created' => 'ASC');
4008
		$TestModel->belongsTo = $TestModel->hasAndBelongsToMany = array();
4009
4010
		$result = $TestModel->saveAll(array(
4011
			'Article' => array('id' => 2),
4012
			'Comment' => array(
4013
				array('comment' => 'First new comment', 'published' => 'Y', 'user_id' => 1),
4014
				array('comment' => 'Second new comment', 'published' => 'Y', 'user_id' => 2)
4015
			)
4016
		));
4017
		$this->assertFalse(empty($result));
4018
4019
		$result = $TestModel->findById(2);
0 ignored issues
show
Documentation Bug introduced by
The method findById does not exist on object<Article>? Since you implemented __call, maybe consider adding a @method annotation.

If you implement __call and you know which methods are available, you can improve IDE auto-completion and static analysis by adding a @method annotation to the class.

This is often the case, when __call is implemented by a parent class and only the child class knows which methods exist:

class ParentClass {
    private $data = array();

    public function __call($method, array $args) {
        if (0 === strpos($method, 'get')) {
            return $this->data[strtolower(substr($method, 3))];
        }

        throw new \LogicException(sprintf('Unsupported method: %s', $method));
    }
}

/**
 * If this class knows which fields exist, you can specify the methods here:
 *
 * @method string getName()
 */
class SomeClass extends ParentClass { }
Loading history...
4020
		$expected = array(
4021
			'First Comment for Second Article',
4022
			'Second Comment for Second Article',
4023
			'First new comment',
4024
			'Second new comment'
4025
		);
4026
		$result = Hash::extract(Hash::sort($result['Comment'], '{n}.id', 'ASC'), '{n}.comment');
4027
		$this->assertEquals($expected, $result);
4028
4029
		$result = $TestModel->saveAll(
4030
			array(
4031
				'Article' => array('id' => 2),
4032
				'Comment' => array(
4033
					array(
4034
						'comment' => 'Third new comment',
4035
						'published' => 'Y',
4036
						'user_id' => 1
4037
			))),
4038
			array('atomic' => false)
4039
		);
4040
		$this->assertFalse(empty($result));
4041
4042
		$result = $TestModel->findById(2);
0 ignored issues
show
Documentation Bug introduced by
The method findById does not exist on object<Article>? Since you implemented __call, maybe consider adding a @method annotation.

If you implement __call and you know which methods are available, you can improve IDE auto-completion and static analysis by adding a @method annotation to the class.

This is often the case, when __call is implemented by a parent class and only the child class knows which methods exist:

class ParentClass {
    private $data = array();

    public function __call($method, array $args) {
        if (0 === strpos($method, 'get')) {
            return $this->data[strtolower(substr($method, 3))];
        }

        throw new \LogicException(sprintf('Unsupported method: %s', $method));
    }
}

/**
 * If this class knows which fields exist, you can specify the methods here:
 *
 * @method string getName()
 */
class SomeClass extends ParentClass { }
Loading history...
4043
		$expected = array(
4044
			'First Comment for Second Article',
4045
			'Second Comment for Second Article',
4046
			'First new comment',
4047
			'Second new comment',
4048
			'Third new comment'
4049
		);
4050
		$result = Hash::extract(Hash::sort($result['Comment'], '{n}.id', 'ASC'), '{n}.comment');
4051
		$this->assertEquals($expected, $result);
4052
4053
		$TestModel->beforeSaveReturn = false;
4054
		$result = $TestModel->saveAll(
4055
			array(
4056
				'Article' => array('id' => 2),
4057
				'Comment' => array(
4058
					array(
4059
						'comment' => 'Fourth new comment',
4060
						'published' => 'Y',
4061
						'user_id' => 1
4062
			))),
4063
			array('atomic' => false)
4064
		);
4065
		$this->assertEquals(array('Article' => false), $result);
4066
4067
		$result = $TestModel->findById(2);
0 ignored issues
show
Documentation Bug introduced by
The method findById does not exist on object<Article>? Since you implemented __call, maybe consider adding a @method annotation.

If you implement __call and you know which methods are available, you can improve IDE auto-completion and static analysis by adding a @method annotation to the class.

This is often the case, when __call is implemented by a parent class and only the child class knows which methods exist:

class ParentClass {
    private $data = array();

    public function __call($method, array $args) {
        if (0 === strpos($method, 'get')) {
            return $this->data[strtolower(substr($method, 3))];
        }

        throw new \LogicException(sprintf('Unsupported method: %s', $method));
    }
}

/**
 * If this class knows which fields exist, you can specify the methods here:
 *
 * @method string getName()
 */
class SomeClass extends ParentClass { }
Loading history...
4068
		$expected = array(
4069
			'First Comment for Second Article',
4070
			'Second Comment for Second Article',
4071
			'First new comment',
4072
			'Second new comment',
4073
			'Third new comment'
4074
		);
4075
		$result = Hash::extract(Hash::sort($result['Comment'], '{n}.id', 'ASC'), '{n}.comment');
4076
		$this->assertEquals($expected, $result);
4077
	}
4078
4079
/**
4080
 * testSaveAllHasManyValidation method
4081
 *
4082
 * @return void
4083
 */
4084 View Code Duplication
	public function testSaveAllHasManyValidation() {
4085
		$this->loadFixtures('Article', 'Comment');
4086
		$TestModel = new Article();
4087
		$TestModel->belongsTo = $TestModel->hasAndBelongsToMany = array();
4088
		$TestModel->Comment->validate = array('comment' => 'notEmpty');
4089
4090
		$result = $TestModel->saveAll(array(
4091
			'Article' => array('id' => 2),
4092
			'Comment' => array(
4093
				array('comment' => '', 'published' => 'Y', 'user_id' => 1),
4094
			)
4095
		), array('validate' => true));
4096
		$this->assertFalse($result);
4097
4098
		$expected = array('Comment' => array(
4099
			array('comment' => array('This field cannot be left blank'))
4100
		));
4101
		$this->assertEquals($expected, $TestModel->validationErrors);
4102
		$expected = array(
4103
			array('comment' => array('This field cannot be left blank'))
4104
		);
4105
		$this->assertEquals($expected, $TestModel->Comment->validationErrors);
4106
4107
		$result = $TestModel->saveAll(array(
4108
			'Article' => array('id' => 2),
4109
			'Comment' => array(
4110
				array(
4111
					'comment' => '',
4112
					'published' => 'Y',
4113
					'user_id' => 1
4114
			))
4115
		), array('validate' => 'first'));
4116
		$this->assertFalse($result);
4117
	}
4118
4119
/**
4120
 * test saveAll with transactions and ensure there is no missing rollback.
4121
 *
4122
 * @return void
4123
 */
4124 View Code Duplication
	public function testSaveAllManyRowsTransactionNoRollback() {
4125
		$this->loadFixtures('Post');
4126
4127
		$db = $this->getMock('DboSource', array('begin', 'connect', 'rollback', 'describe'));
4128
4129
		$db->expects($this->once())
4130
			->method('describe')
4131
			->will($this->returnValue(array()));
4132
		$db->expects($this->once())->method('rollback');
4133
4134
		$Post = new TestPost();
4135
		$Post->setDataSourceObject($db);
4136
4137
		$Post->validate = array(
4138
			'title' => array('rule' => array('notEmpty'))
4139
		);
4140
4141
		$data = array(
4142
			array('author_id' => 1, 'title' => 'New Fourth Post'),
4143
			array('author_id' => 1, 'title' => '')
4144
		);
4145
		$Post->saveAll($data, array('atomic' => true, 'validate' => true));
4146
	}
4147
4148
/**
4149
 * test saveAll with transactions and ensure there is no missing rollback.
4150
 *
4151
 * @return void
4152
 */
4153 View Code Duplication
	public function testSaveAllAssociatedTransactionNoRollback() {
4154
		$testDb = ConnectionManager::getDataSource('test');
4155
4156
		$db = $this->getMock('DboSource', array('connect', 'rollback', 'describe', 'create', 'update', 'begin'));
4157
		$db->columns = $testDb->columns;
0 ignored issues
show
Bug introduced by
The property columns does not seem to exist in DataSource.

An attempt at access to an undefined property has been detected. This may either be a typographical error or the property has been renamed but there are still references to its old name.

If you really want to allow access to undefined properties, you can define magic methods to allow access. See the php core documentation on Overloading.

Loading history...
4158
4159
		$db->expects($this->once())->method('rollback');
4160
		$db->expects($this->any())->method('describe')
4161
			->will($this->returnValue(array(
4162
				'id' => array('type' => 'integer', 'length' => 11),
4163
				'title' => array('type' => 'string'),
4164
				'body' => array('type' => 'text'),
4165
				'published' => array('type' => 'string')
4166
			)));
4167
4168
		$Post = new TestPost();
4169
		$Post->setDataSourceObject($db);
4170
		$Post->Author->setDataSourceObject($db);
4171
4172
		$Post->Author->validate = array(
4173
			'user' => array('rule' => array('notEmpty'))
4174
		);
4175
4176
		$data = array(
4177
			'Post' => array(
4178
				'title' => 'New post',
4179
				'body' => 'Content',
4180
				'published' => 'Y'
4181
			),
4182
			'Author' => array(
4183
				'user' => '',
4184
				'password' => "sekret"
4185
			)
4186
		);
4187
		$Post->saveAll($data, array('validate' => true));
4188
	}
4189
4190
/**
4191
 * test saveAll with nested saveAll call.
4192
 *
4193
 * @return void
4194
 */
4195 View Code Duplication
	public function testSaveAllNestedSaveAll() {
4196
		$this->loadFixtures('Sample');
4197
		$TransactionTestModel = new TransactionTestModel();
4198
4199
		$data = array(
4200
			array('apple_id' => 1, 'name' => 'sample5'),
4201
		);
4202
4203
		$this->assertTrue($TransactionTestModel->saveAll($data, array('atomic' => true)));
4204
	}
4205
4206
/**
4207
 * testSaveAllTransaction method
4208
 *
4209
 * @return void
4210
 */
4211
	public function testSaveAllTransaction() {
4212
		$this->loadFixtures('Post', 'Author', 'Comment', 'Attachment');
4213
		$TestModel = new Post();
4214
4215
		$TestModel->validate = array('title' => 'notEmpty');
4216
		$data = array(
4217
			array('author_id' => 1, 'title' => 'New Fourth Post'),
4218
			array('author_id' => 1, 'title' => 'New Fifth Post'),
4219
			array('author_id' => 1, 'title' => '')
4220
		);
4221
		$this->assertFalse($TestModel->saveAll($data));
4222
4223
		$result = $TestModel->find('all', array('recursive' => -1));
4224
		$expected = array(
4225
			array('Post' => array(
4226
				'id' => '1',
4227
				'author_id' => 1,
4228
				'title' => 'First Post',
4229
				'body' => 'First Post Body',
4230
				'published' => 'Y',
4231
				'created' => '2007-03-18 10:39:23',
4232
				'updated' => '2007-03-18 10:41:31'
4233
			)),
4234
			array('Post' => array(
4235
				'id' => '2',
4236
				'author_id' => 3,
4237
				'title' => 'Second Post',
4238
				'body' => 'Second Post Body',
4239
				'published' => 'Y',
4240
				'created' => '2007-03-18 10:41:23',
4241
				'updated' => '2007-03-18 10:43:31'
4242
			)),
4243
			array('Post' => array(
4244
				'id' => '3',
4245
				'author_id' => 1,
4246
				'title' => 'Third Post',
4247
				'body' => 'Third Post Body',
4248
				'published' => 'Y',
4249
				'created' => '2007-03-18 10:43:23',
4250
				'updated' => '2007-03-18 10:45:31'
4251
		)));
4252
4253
		if (count($result) != 3) {
4254
			// Database doesn't support transactions
4255
			$expected[] = array(
4256
				'Post' => array(
4257
					'id' => '4',
4258
					'author_id' => 1,
4259
					'title' => 'New Fourth Post',
4260
					'body' => null,
4261
					'published' => 'N',
4262
					'created' => self::date(),
4263
					'updated' => self::date()
4264
			));
4265
4266
			$expected[] = array(
4267
				'Post' => array(
4268
					'id' => '5',
4269
					'author_id' => 1,
4270
					'title' => 'New Fifth Post',
4271
					'body' => null,
4272
					'published' => 'N',
4273
					'created' => self::date(),
4274
					'updated' => self::date()
4275
			));
4276
4277
			$this->assertEquals($expected, $result);
4278
			// Skip the rest of the transactional tests
4279
			return;
4280
		}
4281
4282
		$this->assertEquals($expected, $result);
4283
4284
		$data = array(
4285
			array('author_id' => 1, 'title' => 'New Fourth Post'),
4286
			array('author_id' => 1, 'title' => ''),
4287
			array('author_id' => 1, 'title' => 'New Sixth Post')
4288
		);
4289
		$this->assertFalse($TestModel->saveAll($data));
4290
4291
		$result = $TestModel->find('all', array('recursive' => -1));
4292
		$expected = array(
4293
			array('Post' => array(
4294
				'id' => '1',
4295
				'author_id' => 1,
4296
				'title' => 'First Post',
4297
				'body' => 'First Post Body',
4298
				'published' => 'Y',
4299
				'created' => '2007-03-18 10:39:23',
4300
				'updated' => '2007-03-18 10:41:31'
4301
			)),
4302
			array('Post' => array(
4303
				'id' => '2',
4304
				'author_id' => 3,
4305
				'title' => 'Second Post',
4306
				'body' => 'Second Post Body',
4307
				'published' => 'Y',
4308
				'created' => '2007-03-18 10:41:23',
4309
				'updated' => '2007-03-18 10:43:31'
4310
			)),
4311
			array('Post' => array(
4312
				'id' => '3',
4313
				'author_id' => 1,
4314
				'title' => 'Third Post',
4315
				'body' => 'Third Post Body',
4316
				'published' => 'Y',
4317
				'created' => '2007-03-18 10:43:23',
4318
				'updated' => '2007-03-18 10:45:31'
4319
		)));
4320
4321
		if (count($result) != 3) {
4322
			// Database doesn't support transactions
4323
			$expected[] = array(
4324
				'Post' => array(
4325
					'id' => '4',
4326
					'author_id' => 1,
4327
					'title' => 'New Fourth Post',
4328
					'body' => 'Third Post Body',
4329
					'published' => 'N',
4330
					'created' => self::date(),
4331
					'updated' => self::date()
4332
			));
4333
4334
			$expected[] = array(
4335
				'Post' => array(
4336
					'id' => '5',
4337
					'author_id' => 1,
4338
					'title' => 'Third Post',
4339
					'body' => 'Third Post Body',
4340
					'published' => 'N',
4341
					'created' => self::date(),
4342
					'updated' => self::date()
4343
			));
4344
		}
4345
		$this->assertEquals($expected, $result);
4346
4347
		$TestModel->validate = array('title' => 'notEmpty');
4348
		$data = array(
4349
			array('author_id' => 1, 'title' => 'New Fourth Post'),
4350
			array('author_id' => 1, 'title' => 'New Fifth Post'),
4351
			array('author_id' => 1, 'title' => 'New Sixth Post')
4352
		);
4353
		$this->assertTrue($TestModel->saveAll($data));
4354
4355
		$result = $TestModel->find('all', array(
4356
			'recursive' => -1,
4357
			'fields' => array('author_id', 'title', 'body', 'published'),
4358
			'order' => array('Post.created' => 'ASC')
4359
		));
4360
4361
		$expected = array(
4362
			array('Post' => array(
4363
				'author_id' => 1,
4364
				'title' => 'First Post',
4365
				'body' => 'First Post Body',
4366
				'published' => 'Y'
4367
			)),
4368
			array('Post' => array(
4369
				'author_id' => 3,
4370
				'title' => 'Second Post',
4371
				'body' => 'Second Post Body',
4372
				'published' => 'Y'
4373
			)),
4374
			array('Post' => array(
4375
				'author_id' => 1,
4376
				'title' => 'Third Post',
4377
				'body' => 'Third Post Body',
4378
				'published' => 'Y'
4379
			)),
4380
			array('Post' => array(
4381
				'author_id' => 1,
4382
				'title' => 'New Fourth Post',
4383
				'body' => '',
4384
				'published' => 'N'
4385
			)),
4386
			array('Post' => array(
4387
				'author_id' => 1,
4388
				'title' => 'New Fifth Post',
4389
				'body' => '',
4390
				'published' => 'N'
4391
			)),
4392
			array('Post' => array(
4393
				'author_id' => 1,
4394
				'title' => 'New Sixth Post',
4395
				'body' => '',
4396
				'published' => 'N'
4397
		)));
4398
		$this->assertEquals($expected, $result);
4399
	}
4400
4401
/**
4402
 * testSaveAllValidation method
4403
 *
4404
 * @return void
4405
 */
4406
	public function testSaveAllValidation() {
4407
		$this->loadFixtures('Post', 'Author', 'Comment', 'Attachment');
4408
		$TestModel = new Post();
4409
4410
		$data = array(
4411
			array(
4412
				'id' => '1',
4413
				'title' => 'Baleeted First Post',
4414
				'body' => 'Baleeted!',
4415
				'published' => 'N'
4416
			),
4417
			array(
4418
				'id' => '2',
4419
				'title' => 'Just update the title'
4420
			),
4421
			array(
4422
				'title' => 'Creating a fourth post',
4423
				'body' => 'Fourth post body',
4424
				'author_id' => 2
4425
		));
4426
4427
		$this->assertTrue($TestModel->saveAll($data));
4428
4429
		$result = $TestModel->find('all', array('recursive' => -1, 'order' => 'Post.id ASC'));
4430
		$expected = array(
4431
			array(
4432
				'Post' => array(
4433
					'id' => '1',
4434
					'author_id' => '1',
4435
					'title' => 'Baleeted First Post',
4436
					'body' => 'Baleeted!',
4437
					'published' => 'N',
4438
					'created' => '2007-03-18 10:39:23'
4439
			)),
4440
			array(
4441
				'Post' => array(
4442
					'id' => '2',
4443
					'author_id' => '3',
4444
					'title' => 'Just update the title',
4445
					'body' => 'Second Post Body',
4446
					'published' => 'Y',
4447
					'created' => '2007-03-18 10:41:23'
4448
			)),
4449
			array(
4450
				'Post' => array(
4451
					'id' => '3',
4452
					'author_id' => '1',
4453
					'title' => 'Third Post',
4454
					'body' => 'Third Post Body',
4455
					'published' => 'Y',
4456
					'created' => '2007-03-18 10:43:23',
4457
					'updated' => '2007-03-18 10:45:31'
4458
			)),
4459
			array(
4460
				'Post' => array(
4461
					'id' => '4',
4462
					'author_id' => '2',
4463
					'title' => 'Creating a fourth post',
4464
					'body' => 'Fourth post body',
4465
					'published' => 'N'
4466
		)));
4467
		$this->assertEquals(self::date(), $result[0]['Post']['updated']);
4468
		$this->assertEquals(self::date(), $result[1]['Post']['updated']);
4469
		$this->assertEquals(self::date(), $result[3]['Post']['created']);
4470
		$this->assertEquals(self::date(), $result[3]['Post']['updated']);
4471
		unset($result[0]['Post']['updated'], $result[1]['Post']['updated']);
4472
		unset($result[3]['Post']['created'], $result[3]['Post']['updated']);
4473
		$this->assertEquals($expected, $result);
4474
4475
		$TestModel->validate = array('title' => 'notEmpty', 'author_id' => 'numeric');
4476
		$data = array(
4477
			array(
4478
				'id' => '1',
4479
				'title' => 'Un-Baleeted First Post',
4480
				'body' => 'Not Baleeted!',
4481
				'published' => 'Y'
4482
			),
4483
			array(
4484
				'id' => '2',
4485
				'title' => '',
4486
				'body' => 'Trying to get away with an empty title'
4487
		));
4488
		$result = $TestModel->saveAll($data);
4489
		$this->assertFalse($result);
4490
4491
		$result = $TestModel->find('all', array('recursive' => -1, 'order' => 'Post.id ASC'));
4492
		$errors = array(1 => array('title' => array('This field cannot be left blank')));
4493
		$transactionWorked = Set::matches('/Post[1][title=Baleeted First Post]', $result);
0 ignored issues
show
Bug introduced by
It seems like $result defined by $TestModel->find('all', ...der' => 'Post.id ASC')) on line 4491 can also be of type null; however, Set::matches() does only seem to accept array, maybe add an additional type check?

If a method or function can return multiple different values and unless you are sure that you only can receive a single value in this context, we recommend to add an additional type check:

/**
 * @return array|string
 */
function returnsDifferentValues($x) {
    if ($x) {
        return 'foo';
    }

    return array();
}

$x = returnsDifferentValues($y);
if (is_array($x)) {
    // $x is an array.
}

If this a common case that PHP Analyzer should handle natively, please let us know by opening an issue.

Loading history...
4494
		if (!$transactionWorked) {
4495
			$this->assertTrue(Set::matches('/Post[1][title=Un-Baleeted First Post]', $result));
0 ignored issues
show
Bug introduced by
It seems like $result defined by $TestModel->find('all', ...der' => 'Post.id ASC')) on line 4491 can also be of type null; however, Set::matches() does only seem to accept array, maybe add an additional type check?

If a method or function can return multiple different values and unless you are sure that you only can receive a single value in this context, we recommend to add an additional type check:

/**
 * @return array|string
 */
function returnsDifferentValues($x) {
    if ($x) {
        return 'foo';
    }

    return array();
}

$x = returnsDifferentValues($y);
if (is_array($x)) {
    // $x is an array.
}

If this a common case that PHP Analyzer should handle natively, please let us know by opening an issue.

Loading history...
4496
			$this->assertTrue(Set::matches('/Post[2][title=Just update the title]', $result));
0 ignored issues
show
Bug introduced by
It seems like $result defined by $TestModel->find('all', ...der' => 'Post.id ASC')) on line 4491 can also be of type null; however, Set::matches() does only seem to accept array, maybe add an additional type check?

If a method or function can return multiple different values and unless you are sure that you only can receive a single value in this context, we recommend to add an additional type check:

/**
 * @return array|string
 */
function returnsDifferentValues($x) {
    if ($x) {
        return 'foo';
    }

    return array();
}

$x = returnsDifferentValues($y);
if (is_array($x)) {
    // $x is an array.
}

If this a common case that PHP Analyzer should handle natively, please let us know by opening an issue.

Loading history...
4497
		}
4498
4499
		$this->assertEquals($errors, $TestModel->validationErrors);
4500
4501
		$TestModel->validate = array('title' => 'notEmpty', 'author_id' => 'numeric');
4502
		$data = array(
4503
			array(
4504
				'id' => '1',
4505
				'title' => 'Un-Baleeted First Post',
4506
				'body' => 'Not Baleeted!',
4507
				'published' => 'Y'
4508
			),
4509
			array(
4510
				'id' => '2',
4511
				'title' => '',
4512
				'body' => 'Trying to get away with an empty title'
4513
		));
4514
		$result = $TestModel->saveAll($data, array('validate' => true, 'atomic' => false));
4515
		$this->assertEquals(array(true, false), $result);
4516
		$result = $TestModel->find('all', array('recursive' => -1, 'order' => 'Post.id ASC'));
4517
		$errors = array(1 => array('title' => array('This field cannot be left blank')));
4518
		$expected = array(
4519
			array(
4520
				'Post' => array(
4521
					'id' => '1',
4522
					'author_id' => '1',
4523
					'title' => 'Un-Baleeted First Post',
4524
					'body' => 'Not Baleeted!',
4525
					'published' => 'Y',
4526
					'created' => '2007-03-18 10:39:23'
4527
				)
4528
			),
4529
			array(
4530
				'Post' => array(
4531
					'id' => '2',
4532
					'author_id' => '3',
4533
					'title' => 'Just update the title',
4534
					'body' => 'Second Post Body',
4535
					'published' => 'Y',
4536
					'created' => '2007-03-18 10:41:23'
4537
				)
4538
			),
4539
			array(
4540
				'Post' => array(
4541
					'id' => '3',
4542
					'author_id' => '1',
4543
					'title' => 'Third Post',
4544
					'body' => 'Third Post Body',
4545
					'published' => 'Y',
4546
					'created' => '2007-03-18 10:43:23',
4547
					'updated' => '2007-03-18 10:45:31'
4548
				)
4549
			),
4550
			array(
4551
				'Post' => array(
4552
					'id' => '4',
4553
					'author_id' => '2',
4554
					'title' => 'Creating a fourth post',
4555
					'body' => 'Fourth post body',
4556
					'published' => 'N'
4557
				)
4558
			)
4559
		);
4560
4561
		$this->assertEquals(self::date(), $result[0]['Post']['updated']);
4562
		$this->assertEquals(self::date(), $result[1]['Post']['updated']);
4563
		$this->assertEquals(self::date(), $result[3]['Post']['updated']);
4564
		$this->assertEquals(self::date(), $result[3]['Post']['created']);
4565
		unset(
4566
			$result[0]['Post']['updated'], $result[1]['Post']['updated'],
4567
			$result[3]['Post']['updated'], $result[3]['Post']['created']
4568
		);
4569
		$this->assertEquals($expected, $result);
4570
		$this->assertEquals($errors, $TestModel->validationErrors);
4571
4572
		$data = array(
4573
			array(
4574
				'id' => '1',
4575
				'title' => 'Re-Baleeted First Post',
4576
				'body' => 'Baleeted!',
4577
				'published' => 'N'
4578
			),
4579
			array(
4580
				'id' => '2',
4581
				'title' => '',
4582
				'body' => 'Trying to get away with an empty title'
4583
		));
4584
		$this->assertFalse($TestModel->saveAll($data, array('validate' => 'first')));
4585
4586
		$result = $TestModel->find('all', array('recursive' => -1, 'order' => 'Post.id ASC'));
4587
		unset(
4588
			$result[0]['Post']['updated'], $result[1]['Post']['updated'],
4589
			$result[3]['Post']['updated'], $result[3]['Post']['created']
4590
		);
4591
		$this->assertEquals($expected, $result);
4592
		$this->assertEquals($errors, $TestModel->validationErrors);
4593
	}
4594
4595
/**
4596
 * testSaveAllValidationOnly method
4597
 *
4598
 * @return void
4599
 */
4600
	public function testSaveAllValidationOnly() {
4601
		$this->loadFixtures('Comment', 'Attachment');
4602
		$TestModel = new Comment();
4603
		$TestModel->Attachment->validate = array('attachment' => 'notEmpty');
4604
4605
		$data = array(
4606
			'Comment' => array(
4607
				'comment' => 'This is the comment'
4608
			),
4609
			'Attachment' => array(
4610
				'attachment' => ''
4611
			)
4612
		);
4613
4614
		$result = $TestModel->saveAll($data, array('validate' => 'only'));
4615
		$this->assertFalse($result);
4616
4617
		$TestModel = new Article();
4618
		$TestModel->validate = array('title' => 'notEmpty');
4619
		$result = $TestModel->saveAll(
4620
			array(
4621
				0 => array('title' => ''),
4622
				1 => array('title' => 'title 1'),
4623
				2 => array('title' => 'title 2'),
4624
			),
4625
			array('validate' => 'only')
4626
		);
4627
		$this->assertFalse($result);
4628
		$expected = array(
4629
			0 => array('title' => array('This field cannot be left blank')),
4630
		);
4631
		$this->assertEquals($expected, $TestModel->validationErrors);
4632
4633
		$result = $TestModel->saveAll(
4634
			array(
4635
				0 => array('title' => 'title 0'),
4636
				1 => array('title' => ''),
4637
				2 => array('title' => 'title 2'),
4638
			),
4639
			array('validate' => 'only')
4640
		);
4641
		$this->assertFalse($result);
4642
		$expected = array(
4643
			1 => array('title' => array('This field cannot be left blank')),
4644
		);
4645
		$this->assertEquals($expected, $TestModel->validationErrors);
4646
	}
4647
4648
/**
4649
 * testSaveAllValidateFirst method
4650
 *
4651
 * @return void
4652
 */
4653 View Code Duplication
	public function testSaveAllValidateFirst() {
4654
		$this->loadFixtures('Article', 'Comment', 'Attachment', 'User', 'ArticlesTag', 'Tag');
4655
		$model = new Article();
4656
		$model->deleteAll(true);
4657
4658
		$model->Comment->validate = array('comment' => 'notEmpty');
4659
		$result = $model->saveAll(array(
4660
			'Article' => array(
4661
				'title' => 'Post with Author',
4662
				'body' => 'This post will be saved author'
4663
			),
4664
			'Comment' => array(
4665
				array('comment' => 'First new comment'),
4666
				array('comment' => '')
4667
			)
4668
		), array('validate' => 'first'));
4669
4670
		$this->assertFalse($result);
4671
4672
		$result = $model->find('all');
4673
		$this->assertSame(array(), $result);
4674
		$expected = array('Comment' => array(
4675
			1 => array('comment' => array('This field cannot be left blank'))
4676
		));
4677
4678
		$this->assertEquals($expected['Comment'], $model->Comment->validationErrors);
4679
4680
		$this->assertSame($model->Comment->find('count'), 0);
4681
4682
		$result = $model->saveAll(
4683
			array(
4684
				'Article' => array(
4685
					'title' => 'Post with Author',
4686
					'body' => 'This post will be saved with an author',
4687
					'user_id' => 2
4688
				),
4689
				'Comment' => array(
4690
					array(
4691
						'comment' => 'Only new comment',
4692
						'user_id' => 2
4693
			))),
4694
			array('validate' => 'first')
4695
		);
4696
4697
		$this->assertTrue($result);
4698
4699
		$result = $model->Comment->find('all');
4700
		$this->assertSame(count($result), 1);
4701
		$result = Hash::extract($result, '{n}.Comment.article_id');
4702
		$this->assertEquals(4, $result[0]);
4703
4704
		$model->deleteAll(true);
4705
		$data = array(
4706
			'Article' => array(
4707
				'title' => 'Post with Author saveAlled from comment',
4708
				'body' => 'This post will be saved with an author',
4709
				'user_id' => 2
4710
			),
4711
			'Comment' => array(
4712
				'comment' => 'Only new comment', 'user_id' => 2
4713
		));
4714
4715
		$result = $model->Comment->saveAll($data, array('validate' => 'first'));
4716
		$this->assertFalse(empty($result));
4717
4718
		$result = $model->find('all');
4719
		$this->assertEquals(
4720
			$result[0]['Article']['title'],
4721
			'Post with Author saveAlled from comment'
4722
		);
4723
		$this->assertEquals('Only new comment', $result[0]['Comment'][0]['comment']);
4724
	}
4725
4726
/**
4727
 * test saveAll()'s return is correct when using atomic = false and validate = first.
4728
 *
4729
 * @return void
4730
 */
4731
	public function testSaveAllValidateFirstAtomicFalse() {
4732
		$this->loadFixtures('Something');
4733
		$Something = new Something();
4734
		$invalidData = array(
4735
			array(
4736
				'title' => 'foo',
4737
				'body' => 'bar',
4738
				'published' => 'baz',
4739
			),
4740
			array(
4741
				'body' => 3,
4742
				'published' => 'sd',
4743
			),
4744
		);
4745
		$Something->create();
4746
		$Something->validate = array(
4747
			'title' => array(
4748
				'rule' => 'alphaNumeric',
4749
				'required' => true,
4750
			),
4751
			'body' => array(
4752
				'rule' => 'alphaNumeric',
4753
				'required' => true,
4754
				'allowEmpty' => true,
4755
			),
4756
		);
4757
		$result = $Something->saveAll($invalidData, array(
4758
			'atomic' => false,
4759
			'validate' => 'first',
4760
		));
4761
		$expected = array(true, false);
4762
		$this->assertEquals($expected, $result);
4763
4764
		$Something = new Something();
4765
		$validData = array(
4766
			array(
4767
				'title' => 'title value',
4768
				'body' => 'body value',
4769
				'published' => 'baz',
4770
			),
4771
			array(
4772
				'title' => 'valid',
4773
				'body' => 'this body',
4774
				'published' => 'sd',
4775
			),
4776
		);
4777
		$Something->create();
4778
		$result = $Something->saveAll($validData, array(
4779
			'atomic' => false,
4780
			'validate' => 'first',
4781
		));
4782
		$expected = array(true, true);
4783
		$this->assertEquals($expected, $result);
4784
	}
4785
4786
/**
4787
 * testSaveAllHasManyValidationOnly method
4788
 *
4789
 * @return void
4790
 */
4791
	public function testSaveAllHasManyValidationOnly() {
4792
		$this->loadFixtures('Article', 'Comment', 'Attachment');
4793
		$TestModel = new Article();
4794
		$TestModel->belongsTo = $TestModel->hasAndBelongsToMany = array();
4795
		$TestModel->Comment->validate = array('comment' => 'notEmpty');
4796
4797
		$result = $TestModel->saveAll(
4798
			array(
4799
				'Article' => array('id' => 2),
4800
				'Comment' => array(
4801
					array(
4802
						'id' => 1,
4803
						'comment' => '',
4804
						'published' => 'Y',
4805
						'user_id' => 1),
4806
					array(
4807
						'id' => 2,
4808
						'comment' =>
4809
						'comment',
4810
						'published' => 'Y',
4811
						'user_id' => 1
4812
			))),
4813
			array('validate' => 'only')
4814
		);
4815
		$this->assertFalse($result);
4816
4817
		$result = $TestModel->saveAll(
4818
			array(
4819
				'Article' => array('id' => 2),
4820
				'Comment' => array(
4821
					array(
4822
						'id' => 1,
4823
						'comment' => '',
4824
						'published' => 'Y',
4825
						'user_id' => 1
4826
					),
4827
					array(
4828
						'id' => 2,
4829
						'comment' => 'comment',
4830
						'published' => 'Y',
4831
						'user_id' => 1
4832
					),
4833
					array(
4834
						'id' => 3,
4835
						'comment' => '',
4836
						'published' => 'Y',
4837
						'user_id' => 1
4838
			))),
4839
			array(
4840
				'validate' => 'only',
4841
				'atomic' => false
4842
		));
4843
		$expected = array(
4844
			'Article' => true,
4845
			'Comment' => array(false, true, false)
4846
		);
4847
		$this->assertSame($expected, $result);
4848
4849
		$expected = array('Comment' => array(
4850
			0 => array('comment' => array('This field cannot be left blank')),
4851
			2 => array('comment' => array('This field cannot be left blank'))
4852
		));
4853
		$this->assertEquals($expected, $TestModel->validationErrors);
4854
4855
		$expected = array(
4856
			0 => array('comment' => array('This field cannot be left blank')),
4857
			2 => array('comment' => array('This field cannot be left blank'))
4858
		);
4859
		$this->assertEquals($expected, $TestModel->Comment->validationErrors);
4860
	}
4861
4862
/**
4863
 * test that saveAll still behaves like previous versions (does not necessarily need a first argument)
4864
 *
4865
 * @return void
4866
 */
4867
	public function testSaveAllWithSet() {
4868
		$this->loadFixtures('Article', 'Tag', 'Comment', 'User', 'ArticlesTag');
4869
		$data = array(
4870
			'Article' => array(
4871
				'user_id' => 1,
4872
				'title' => 'Article Has and belongs to Many Tags'
4873
			),
4874
			'Tag' => array(
4875
				'Tag' => array(1, 2)
4876
			),
4877
			'Comment' => array(
4878
				array(
4879
					'comment' => 'Article comment',
4880
					'user_id' => 1
4881
		)));
4882
		$Article = new Article();
4883
		$Article->set($data);
4884
		$result = $Article->saveAll();
4885
		$this->assertFalse(empty($result));
4886
	}
4887
4888
/**
4889
 * test that saveAll behaves like plain save() when supplied empty data
4890
 *
4891
 * @link https://cakephp.lighthouseapp.com/projects/42648/tickets/277-test-saveall-with-validation-returns-incorrect-boolean-when-saving-empty-data
4892
 * @return void
4893
 */
4894 View Code Duplication
	public function testSaveAllEmptyData() {
4895
		$this->skipIf($this->db instanceof Sqlserver, 'This test is not compatible with SQL Server.');
4896
4897
		$this->loadFixtures('Article', 'ProductUpdateAll', 'Comment', 'Attachment');
4898
		$model = new Article();
4899
		$result = $model->saveAll(array(), array('validate' => 'first'));
4900
		$this->assertFalse(empty($result));
4901
4902
		$model = new ProductUpdateAll();
4903
		$result = $model->saveAll();
4904
		$this->assertFalse($result);
4905
	}
4906
4907
/**
4908
 * testSaveAssociated method
4909
 *
4910
 * @return void
4911
 */
4912
	public function testSaveAssociated() {
4913
		$this->loadFixtures('Post', 'Author', 'Comment', 'Attachment', 'Article', 'User');
4914
		$TestModel = new Post();
4915
4916
		$result = $TestModel->find('all');
4917
		$this->assertEquals(3, count($result));
4918
		$this->assertFalse(isset($result[3]));
4919
4920
		$TestModel->saveAssociated(array(
4921
			'Post' => array(
4922
				'title' => 'Post with Author',
4923
				'body' => 'This post will be saved with an author'
4924
			),
4925
			'Author' => array(
4926
				'user' => 'bob',
4927
				'password' => '5f4dcc3b5aa765d61d8327deb882cf90'
4928
		)));
4929
4930
		$result = $TestModel->find('all', array('order' => array('Post.id ' => 'ASC')));
4931
		$expected = array(
4932
			'Post' => array(
4933
				'id' => '4',
4934
				'author_id' => '5',
4935
				'title' => 'Post with Author',
4936
				'body' => 'This post will be saved with an author',
4937
				'published' => 'N'
4938
			),
4939
			'Author' => array(
4940
				'id' => '5',
4941
				'user' => 'bob',
4942
				'password' => '5f4dcc3b5aa765d61d8327deb882cf90',
4943
				'test' => 'working'
4944
		));
4945
		$this->assertEquals(self::date(), $result[3]['Post']['updated']);
4946
		$this->assertEquals(self::date(), $result[3]['Post']['created']);
4947
		$this->assertEquals(self::date(), $result[3]['Author']['created']);
4948
		$this->assertEquals(self::date(), $result[3]['Author']['updated']);
4949
		unset(
4950
			$result[3]['Post']['updated'], $result[3]['Post']['created'],
4951
			$result[3]['Author']['updated'], $result[3]['Author']['created']
4952
		);
4953
		$this->assertEquals($expected, $result[3]);
4954
		$this->assertEquals(4, count($result));
4955
4956
		$TestModel = new Comment();
4957
		$result = $TestModel->saveAssociated(array(
4958
			'Comment' => array(
4959
				'article_id' => 2,
4960
				'user_id' => 2,
4961
				'comment' => 'New comment with attachment',
4962
				'published' => 'Y'
4963
			),
4964
			'Attachment' => array(
4965
				'attachment' => 'some_file.tgz'
4966
			)));
4967
		$this->assertFalse(empty($result));
4968
4969
		$result = $TestModel->find('all');
4970
		$expected = array(
4971
			'id' => '7',
4972
			'article_id' => '2',
4973
			'user_id' => '2',
4974
			'comment' => 'New comment with attachment',
4975
			'published' => 'Y'
4976
		);
4977
		$this->assertEquals(self::date(), $result[6]['Comment']['updated']);
4978
		$this->assertEquals(self::date(), $result[6]['Comment']['created']);
4979
		unset($result[6]['Comment']['updated'], $result[6]['Comment']['created']);
4980
		$this->assertEquals($expected, $result[6]['Comment']);
4981
4982
		$expected = array(
4983
			'id' => '2',
4984
			'comment_id' => '7',
4985
			'attachment' => 'some_file.tgz'
4986
		);
4987
		$this->assertEquals(self::date(), $result[6]['Attachment']['updated']);
4988
		$this->assertEquals(self::date(), $result[6]['Attachment']['created']);
4989
		unset($result[6]['Attachment']['updated'], $result[6]['Attachment']['created']);
4990
		$this->assertEquals($expected, $result[6]['Attachment']);
4991
	}
4992
4993
/**
4994
 * Test that validate = first, atomic = false works when associated records
4995
 * fail validation.
4996
 *
4997
 * @return void
4998
 */
4999
	public function testSaveAssociatedAtomicFalseValidateFirstWithErrors() {
5000
		$this->loadFixtures('Comment', 'Article', 'User');
5001
		$Article = ClassRegistry::init('Article');
5002
		$Article->Comment->validator()->add('comment', array(
5003
			array('rule' => 'notEmpty')
5004
		));
5005
5006
		$data = array(
5007
			'Article' => array(
5008
				'user_id' => 1,
5009
				'title' => 'Foo',
5010
				'body' => 'text',
5011
				'published' => 'N'
5012
			),
5013
			'Comment' => array(
5014
				array(
5015
					'user_id' => 1,
5016
					'comment' => '',
5017
					'published' => 'N',
5018
				)
5019
			),
5020
		);
5021
5022
		$Article->saveAssociated(
5023
			$data,
5024
			array('validate' => 'first', 'atomic' => false)
5025
		);
5026
5027
		$result = $Article->validationErrors;
5028
		$expected = array(
5029
			'Comment' => array(
5030
				array(
5031
					'comment' => array('This field cannot be left blank')
5032
				)
5033
			)
5034
		);
5035
		$this->assertEquals($expected, $result);
5036
	}
5037
5038
/**
5039
 * testSaveMany method
5040
 *
5041
 * @return void
5042
 */
5043
	public function testSaveMany() {
5044
		$this->loadFixtures('Post');
5045
		$TestModel = new Post();
5046
		$TestModel->deleteAll(true);
5047
		$this->assertEquals(array(), $TestModel->find('all'));
5048
5049
		// SQLite seems to reset the PK counter when that happens, so we need this to make the tests pass
5050
		$this->db->truncate($TestModel);
5051
5052
		$TestModel->saveMany(array(
5053
			array(
5054
				'title' => 'Multi-record post 1',
5055
				'body' => 'First multi-record post',
5056
				'author_id' => 2
5057
			),
5058
			array(
5059
				'title' => 'Multi-record post 2',
5060
				'body' => 'Second multi-record post',
5061
				'author_id' => 2
5062
		)));
5063
5064
		$result = $TestModel->find('all', array(
5065
			'recursive' => -1,
5066
			'order' => 'Post.id ASC'
5067
		));
5068
		$expected = array(
5069
			array(
5070
				'Post' => array(
5071
					'id' => '1',
5072
					'author_id' => '2',
5073
					'title' => 'Multi-record post 1',
5074
					'body' => 'First multi-record post',
5075
					'published' => 'N'
5076
				)
5077
			),
5078
			array(
5079
				'Post' => array(
5080
					'id' => '2',
5081
					'author_id' => '2',
5082
					'title' => 'Multi-record post 2',
5083
					'body' => 'Second multi-record post',
5084
					'published' => 'N'
5085
				)
5086
			)
5087
		);
5088
		$this->assertEquals(self::date(), $result[0]['Post']['updated']);
5089
		$this->assertEquals(self::date(), $result[0]['Post']['created']);
5090
		$this->assertEquals(self::date(), $result[1]['Post']['updated']);
5091
		$this->assertEquals(self::date(), $result[1]['Post']['created']);
5092
		unset($result[0]['Post']['updated'], $result[0]['Post']['created']);
5093
		unset($result[1]['Post']['updated'], $result[1]['Post']['created']);
5094
		$this->assertEquals($expected, $result);
5095
	}
5096
5097
/**
5098
 * Test SaveMany with validate=false.
5099
 *
5100
 * @return void
5101
 */
5102
	public function testSaveManyValidateFalse() {
5103
		$this->loadFixtures('Post');
5104
		$TestModel = new Post();
5105
		$TestModel->deleteAll(true);
5106
		$data = array(
5107
			array('id' => 1, 'author_id' => 1, 'title' => 'hi'),
5108
			array('id' => 2, 'author_id' => 1, 'title' => 'bye')
5109
		);
5110
		$result = $TestModel->saveAll($data, array('validate' => false));
5111
		$this->assertTrue($result);
5112
	}
5113
5114
/**
5115
 * Test SaveAssociated with Habtm relations
5116
 *
5117
 * @return void
5118
 */
5119 View Code Duplication
	public function testSaveAssociatedHabtm() {
5120
		$this->loadFixtures('Article', 'Tag', 'Comment', 'User', 'ArticlesTag');
5121
		$data = array(
5122
			'Article' => array(
5123
				'user_id' => 1,
5124
				'title' => 'Article Has and belongs to Many Tags'
5125
			),
5126
			'Tag' => array(
5127
				'Tag' => array(1, 2)
5128
			),
5129
			'Comment' => array(
5130
				array(
5131
					'comment' => 'Article comment',
5132
					'user_id' => 1
5133
		)));
5134
		$Article = new Article();
5135
		$result = $Article->saveAssociated($data);
5136
		$this->assertFalse(empty($result));
5137
5138
		$result = $Article->read();
5139
		$this->assertEquals(2, count($result['Tag']));
5140
		$this->assertEquals('tag1', $result['Tag'][0]['tag']);
5141
		$this->assertEquals(1, count($result['Comment']));
5142
		$this->assertEquals(1, count($result['Comment'][0]['comment']));
5143
	}
5144
5145
/**
5146
 * Test SaveAssociated with Habtm relations and extra join table fields
5147
 *
5148
 * @return void
5149
 */
5150 View Code Duplication
	public function testSaveAssociatedHabtmWithExtraJoinTableFields() {
5151
		$this->loadFixtures('Something', 'SomethingElse', 'JoinThing');
5152
5153
		$data = array(
5154
			'Something' => array(
5155
				'id' => 4,
5156
				'title' => 'Extra Fields',
5157
				'body' => 'Extra Fields Body',
5158
				'published' => '1'
5159
			),
5160
			'SomethingElse' => array(
5161
				array('something_else_id' => 1, 'doomed' => '1'),
5162
				array('something_else_id' => 2, 'doomed' => '0'),
5163
				array('something_else_id' => 3, 'doomed' => '1')
5164
			)
5165
		);
5166
5167
		$Something = new Something();
5168
		$result = $Something->saveAssociated($data);
5169
		$this->assertFalse(empty($result));
5170
		$result = $Something->read();
5171
5172
		$this->assertEquals(3, count($result['SomethingElse']));
5173
		$this->assertTrue(Set::matches('/Something[id=4]', $result));
0 ignored issues
show
Security Bug introduced by
It seems like $result defined by $Something->read() on line 5170 can also be of type false; however, Set::matches() does only seem to accept array, did you maybe forget to handle an error condition?

This check looks for type mismatches where the missing type is false. This is usually indicative of an error condtion.

Consider the follow example

<?php

function getDate($date)
{
    if ($date !== null) {
        return new DateTime($date);
    }

    return false;
}

This function either returns a new DateTime object or false, if there was an error. This is a typical pattern in PHP programming to show that an error has occurred without raising an exception. The calling code should check for this returned false before passing on the value to another function or method that may not be able to handle a false.

Loading history...
5174
5175
		$this->assertTrue(Set::matches('/SomethingElse[id=1]', $result));
0 ignored issues
show
Security Bug introduced by
It seems like $result defined by $Something->read() on line 5170 can also be of type false; however, Set::matches() does only seem to accept array, did you maybe forget to handle an error condition?

This check looks for type mismatches where the missing type is false. This is usually indicative of an error condtion.

Consider the follow example

<?php

function getDate($date)
{
    if ($date !== null) {
        return new DateTime($date);
    }

    return false;
}

This function either returns a new DateTime object or false, if there was an error. This is a typical pattern in PHP programming to show that an error has occurred without raising an exception. The calling code should check for this returned false before passing on the value to another function or method that may not be able to handle a false.

Loading history...
5176
		$this->assertTrue(Set::matches('/SomethingElse[id=1]/JoinThing[something_else_id=1]', $result));
0 ignored issues
show
Security Bug introduced by
It seems like $result defined by $Something->read() on line 5170 can also be of type false; however, Set::matches() does only seem to accept array, did you maybe forget to handle an error condition?

This check looks for type mismatches where the missing type is false. This is usually indicative of an error condtion.

Consider the follow example

<?php

function getDate($date)
{
    if ($date !== null) {
        return new DateTime($date);
    }

    return false;
}

This function either returns a new DateTime object or false, if there was an error. This is a typical pattern in PHP programming to show that an error has occurred without raising an exception. The calling code should check for this returned false before passing on the value to another function or method that may not be able to handle a false.

Loading history...
5177
		$this->assertTrue(Set::matches('/SomethingElse[id=1]/JoinThing[doomed=1]', $result));
0 ignored issues
show
Security Bug introduced by
It seems like $result defined by $Something->read() on line 5170 can also be of type false; however, Set::matches() does only seem to accept array, did you maybe forget to handle an error condition?

This check looks for type mismatches where the missing type is false. This is usually indicative of an error condtion.

Consider the follow example

<?php

function getDate($date)
{
    if ($date !== null) {
        return new DateTime($date);
    }

    return false;
}

This function either returns a new DateTime object or false, if there was an error. This is a typical pattern in PHP programming to show that an error has occurred without raising an exception. The calling code should check for this returned false before passing on the value to another function or method that may not be able to handle a false.

Loading history...
5178
5179
		$this->assertTrue(Set::matches('/SomethingElse[id=2]', $result));
0 ignored issues
show
Security Bug introduced by
It seems like $result defined by $Something->read() on line 5170 can also be of type false; however, Set::matches() does only seem to accept array, did you maybe forget to handle an error condition?

This check looks for type mismatches where the missing type is false. This is usually indicative of an error condtion.

Consider the follow example

<?php

function getDate($date)
{
    if ($date !== null) {
        return new DateTime($date);
    }

    return false;
}

This function either returns a new DateTime object or false, if there was an error. This is a typical pattern in PHP programming to show that an error has occurred without raising an exception. The calling code should check for this returned false before passing on the value to another function or method that may not be able to handle a false.

Loading history...
5180
		$this->assertTrue(Set::matches('/SomethingElse[id=2]/JoinThing[something_else_id=2]', $result));
0 ignored issues
show
Security Bug introduced by
It seems like $result defined by $Something->read() on line 5170 can also be of type false; however, Set::matches() does only seem to accept array, did you maybe forget to handle an error condition?

This check looks for type mismatches where the missing type is false. This is usually indicative of an error condtion.

Consider the follow example

<?php

function getDate($date)
{
    if ($date !== null) {
        return new DateTime($date);
    }

    return false;
}

This function either returns a new DateTime object or false, if there was an error. This is a typical pattern in PHP programming to show that an error has occurred without raising an exception. The calling code should check for this returned false before passing on the value to another function or method that may not be able to handle a false.

Loading history...
5181
		$this->assertTrue(Set::matches('/SomethingElse[id=2]/JoinThing[doomed=0]', $result));
0 ignored issues
show
Security Bug introduced by
It seems like $result defined by $Something->read() on line 5170 can also be of type false; however, Set::matches() does only seem to accept array, did you maybe forget to handle an error condition?

This check looks for type mismatches where the missing type is false. This is usually indicative of an error condtion.

Consider the follow example

<?php

function getDate($date)
{
    if ($date !== null) {
        return new DateTime($date);
    }

    return false;
}

This function either returns a new DateTime object or false, if there was an error. This is a typical pattern in PHP programming to show that an error has occurred without raising an exception. The calling code should check for this returned false before passing on the value to another function or method that may not be able to handle a false.

Loading history...
5182
5183
		$this->assertTrue(Set::matches('/SomethingElse[id=3]', $result));
0 ignored issues
show
Security Bug introduced by
It seems like $result defined by $Something->read() on line 5170 can also be of type false; however, Set::matches() does only seem to accept array, did you maybe forget to handle an error condition?

This check looks for type mismatches where the missing type is false. This is usually indicative of an error condtion.

Consider the follow example

<?php

function getDate($date)
{
    if ($date !== null) {
        return new DateTime($date);
    }

    return false;
}

This function either returns a new DateTime object or false, if there was an error. This is a typical pattern in PHP programming to show that an error has occurred without raising an exception. The calling code should check for this returned false before passing on the value to another function or method that may not be able to handle a false.

Loading history...
5184
		$this->assertTrue(Set::matches('/SomethingElse[id=3]/JoinThing[something_else_id=3]', $result));
0 ignored issues
show
Security Bug introduced by
It seems like $result defined by $Something->read() on line 5170 can also be of type false; however, Set::matches() does only seem to accept array, did you maybe forget to handle an error condition?

This check looks for type mismatches where the missing type is false. This is usually indicative of an error condtion.

Consider the follow example

<?php

function getDate($date)
{
    if ($date !== null) {
        return new DateTime($date);
    }

    return false;
}

This function either returns a new DateTime object or false, if there was an error. This is a typical pattern in PHP programming to show that an error has occurred without raising an exception. The calling code should check for this returned false before passing on the value to another function or method that may not be able to handle a false.

Loading history...
5185
		$this->assertTrue(Set::matches('/SomethingElse[id=3]/JoinThing[doomed=1]', $result));
0 ignored issues
show
Security Bug introduced by
It seems like $result defined by $Something->read() on line 5170 can also be of type false; however, Set::matches() does only seem to accept array, did you maybe forget to handle an error condition?

This check looks for type mismatches where the missing type is false. This is usually indicative of an error condtion.

Consider the follow example

<?php

function getDate($date)
{
    if ($date !== null) {
        return new DateTime($date);
    }

    return false;
}

This function either returns a new DateTime object or false, if there was an error. This is a typical pattern in PHP programming to show that an error has occurred without raising an exception. The calling code should check for this returned false before passing on the value to another function or method that may not be able to handle a false.

Loading history...
5186
	}
5187
5188
/**
5189
 * testSaveAssociatedHasOne method
5190
 *
5191
 * @return void
5192
 */
5193 View Code Duplication
	public function testSaveAssociatedHasOne() {
5194
		$model = new Comment();
5195
		$model->deleteAll(true);
5196
		$this->assertEquals(array(), $model->find('all'));
5197
5198
		$model->Attachment->deleteAll(true);
5199
		$this->assertEquals(array(), $model->Attachment->find('all'));
5200
5201
		$this->assertTrue($model->saveAssociated(array(
5202
			'Comment' => array(
5203
				'comment' => 'Comment with attachment',
5204
				'article_id' => 1,
5205
				'user_id' => 1
5206
			),
5207
			'Attachment' => array(
5208
				'attachment' => 'some_file.zip'
5209
		))));
5210
		$result = $model->find('all', array('fields' => array(
5211
			'Comment.id', 'Comment.comment', 'Attachment.id',
5212
			'Attachment.comment_id', 'Attachment.attachment'
5213
		)));
5214
		$expected = array(array(
5215
			'Comment' => array(
5216
				'id' => '1',
5217
				'comment' => 'Comment with attachment'
5218
			),
5219
			'Attachment' => array(
5220
				'id' => '1',
5221
				'comment_id' => '1',
5222
				'attachment' => 'some_file.zip'
5223
		)));
5224
		$this->assertEquals($expected, $result);
5225
5226
		$model->Attachment->bindModel(array('belongsTo' => array('Comment')), false);
5227
		$data = array(
5228
			'Comment' => array(
5229
				'comment' => 'Comment with attachment',
5230
				'article_id' => 1,
5231
				'user_id' => 1
5232
			),
5233
			'Attachment' => array(
5234
				'attachment' => 'some_file.zip'
5235
		));
5236
		$this->assertTrue($model->saveAssociated($data, array('validate' => 'first')));
5237
	}
5238
5239
/**
5240
 * testSaveAssociatedBelongsTo method
5241
 *
5242
 * @return void
5243
 */
5244 View Code Duplication
	public function testSaveAssociatedBelongsTo() {
5245
		$model = new Comment();
5246
		$model->deleteAll(true);
5247
		$this->assertEquals(array(), $model->find('all'));
5248
5249
		$model->Article->deleteAll(true);
5250
		$this->assertEquals(array(), $model->Article->find('all'));
5251
5252
		$this->assertTrue($model->saveAssociated(array(
5253
			'Comment' => array(
5254
				'comment' => 'Article comment',
5255
				'article_id' => 1,
5256
				'user_id' => 1
5257
			),
5258
			'Article' => array(
5259
				'title' => 'Model Associations 101',
5260
				'user_id' => 1
5261
		))));
5262
		$result = $model->find('all', array('fields' => array(
5263
			'Comment.id', 'Comment.comment', 'Comment.article_id', 'Article.id', 'Article.title'
5264
		)));
5265
		$expected = array(array(
5266
			'Comment' => array(
5267
				'id' => '1',
5268
				'article_id' => '1',
5269
				'comment' => 'Article comment'
5270
			),
5271
			'Article' => array(
5272
				'id' => '1',
5273
				'title' => 'Model Associations 101'
5274
		)));
5275
		$this->assertEquals($expected, $result);
5276
	}
5277
5278
/**
5279
 * testSaveAssociatedHasOneValidation method
5280
 *
5281
 * @return void
5282
 */
5283 View Code Duplication
	public function testSaveAssociatedHasOneValidation() {
5284
		$model = new Comment();
5285
		$model->deleteAll(true);
5286
		$this->assertEquals(array(), $model->find('all'));
5287
5288
		$model->Attachment->deleteAll(true);
5289
		$this->assertEquals(array(), $model->Attachment->find('all'));
5290
5291
		$model->validate = array('comment' => 'notEmpty');
5292
		$model->Attachment->validate = array('attachment' => 'notEmpty');
5293
		$model->Attachment->bindModel(array('belongsTo' => array('Comment')));
5294
5295
		$result = $model->saveAssociated(
5296
			array(
5297
				'Comment' => array(
5298
					'comment' => '',
5299
					'article_id' => 1,
5300
					'user_id' => 1
5301
				),
5302
				'Attachment' => array('attachment' => '')
5303
			)
5304
		);
5305
		$this->assertFalse($result);
5306
		$expected = array(
5307
			'comment' => array(
5308
				'This field cannot be left blank'
5309
			),
5310
			'Attachment' => array(
5311
				'attachment' => array(
5312
					'This field cannot be left blank'
5313
				)
5314
			)
5315
		);
5316
		$this->assertEquals($expected, $model->validationErrors);
5317
		$this->assertEquals($expected['Attachment'], $model->Attachment->validationErrors);
5318
	}
5319
5320
/**
5321
 * testSaveAssociatedAtomic method
5322
 *
5323
 * @return void
5324
 */
5325
	public function testSaveAssociatedAtomic() {
5326
		$this->loadFixtures('Article', 'User');
5327
		$TestModel = new Article();
5328
5329
		$result = $TestModel->saveAssociated(array(
5330
			'Article' => array(
5331
				'title' => 'Post with Author',
5332
				'body' => 'This post will be saved with an author',
5333
				'user_id' => 2
5334
			),
5335
			'Comment' => array(
5336
				array('comment' => 'First new comment', 'user_id' => 2))
5337
		), array('atomic' => false));
5338
5339
		$this->assertSame($result, array('Article' => true, 'Comment' => array(true)));
5340
5341
		$result = $TestModel->saveAssociated(array(
5342
			'Article' => array('id' => 2),
5343
			'Comment' => array(
5344
				array(
5345
					'comment' => 'First new comment',
5346
					'published' => 'Y',
5347
					'user_id' => 1
5348
				),
5349
				array(
5350
					'comment' => 'Second new comment',
5351
					'published' => 'Y',
5352
					'user_id' => 2
5353
			))
5354
		), array('validate' => true, 'atomic' => false));
5355
		$this->assertSame($result, array('Article' => true, 'Comment' => array(true, true)));
5356
	}
5357
5358
/**
5359
 * testSaveManyAtomic method
5360
 *
5361
 * @return void
5362
 */
5363
	public function testSaveManyAtomic() {
5364
		$this->loadFixtures('Article', 'User');
5365
		$TestModel = new Article();
5366
5367
		$result = $TestModel->saveMany(array(
5368
			array(
5369
				'id' => '1',
5370
				'title' => 'Baleeted First Post',
5371
				'body' => 'Baleeted!',
5372
				'published' => 'N'
5373
			),
5374
			array(
5375
				'id' => '2',
5376
				'title' => 'Just update the title'
5377
			),
5378
			array(
5379
				'title' => 'Creating a fourth post',
5380
				'body' => 'Fourth post body',
5381
				'user_id' => 2
5382
			)
5383
		), array('atomic' => false));
5384
		$this->assertSame($result, array(true, true, true));
5385
5386
		$TestModel->validate = array('title' => 'notEmpty', 'author_id' => 'numeric');
5387
		$result = $TestModel->saveMany(array(
5388
			array(
5389
				'id' => '1',
5390
				'title' => 'Un-Baleeted First Post',
5391
				'body' => 'Not Baleeted!',
5392
				'published' => 'Y'
5393
			),
5394
			array(
5395
				'id' => '2',
5396
				'title' => '',
5397
				'body' => 'Trying to get away with an empty title'
5398
			)
5399
		), array('validate' => true, 'atomic' => false));
5400
5401
		$this->assertSame(array(true, false), $result);
5402
	}
5403
5404
/**
5405
 * testSaveAssociatedHasMany method
5406
 *
5407
 * @return void
5408
 */
5409
	public function testSaveAssociatedHasMany() {
5410
		$this->loadFixtures('Article', 'Comment');
5411
		$TestModel = new Article();
5412
		$TestModel->belongsTo = $TestModel->hasAndBelongsToMany = array();
5413
5414
		$result = $TestModel->saveAssociated(array(
5415
			'Article' => array('id' => 2),
5416
			'Comment' => array(
5417
				array('comment' => 'First new comment', 'published' => 'Y', 'user_id' => 1),
5418
				array('comment' => 'Second new comment', 'published' => 'Y', 'user_id' => 2)
5419
			)
5420
		));
5421
		$this->assertFalse(empty($result));
5422
5423
		$result = $TestModel->findById(2);
0 ignored issues
show
Documentation Bug introduced by
The method findById does not exist on object<Article>? Since you implemented __call, maybe consider adding a @method annotation.

If you implement __call and you know which methods are available, you can improve IDE auto-completion and static analysis by adding a @method annotation to the class.

This is often the case, when __call is implemented by a parent class and only the child class knows which methods exist:

class ParentClass {
    private $data = array();

    public function __call($method, array $args) {
        if (0 === strpos($method, 'get')) {
            return $this->data[strtolower(substr($method, 3))];
        }

        throw new \LogicException(sprintf('Unsupported method: %s', $method));
    }
}

/**
 * If this class knows which fields exist, you can specify the methods here:
 *
 * @method string getName()
 */
class SomeClass extends ParentClass { }
Loading history...
5424
		$expected = array(
5425
			'First Comment for Second Article',
5426
			'Second Comment for Second Article',
5427
			'First new comment',
5428
			'Second new comment'
5429
		);
5430
		$this->assertEquals($expected, Hash::extract($result['Comment'], '{n}.comment'));
5431
5432
		$result = $TestModel->saveAssociated(
5433
			array(
5434
				'Article' => array('id' => 2),
5435
				'Comment' => array(
5436
					array(
5437
						'comment' => 'Third new comment',
5438
						'published' => 'Y',
5439
						'user_id' => 1
5440
			))),
5441
			array('atomic' => false)
5442
		);
5443
		$this->assertFalse(empty($result));
5444
5445
		$result = $TestModel->findById(2);
0 ignored issues
show
Documentation Bug introduced by
The method findById does not exist on object<Article>? Since you implemented __call, maybe consider adding a @method annotation.

If you implement __call and you know which methods are available, you can improve IDE auto-completion and static analysis by adding a @method annotation to the class.

This is often the case, when __call is implemented by a parent class and only the child class knows which methods exist:

class ParentClass {
    private $data = array();

    public function __call($method, array $args) {
        if (0 === strpos($method, 'get')) {
            return $this->data[strtolower(substr($method, 3))];
        }

        throw new \LogicException(sprintf('Unsupported method: %s', $method));
    }
}

/**
 * If this class knows which fields exist, you can specify the methods here:
 *
 * @method string getName()
 */
class SomeClass extends ParentClass { }
Loading history...
5446
		$expected = array(
5447
			'First Comment for Second Article',
5448
			'Second Comment for Second Article',
5449
			'First new comment',
5450
			'Second new comment',
5451
			'Third new comment'
5452
		);
5453
		$this->assertEquals($expected, Hash::extract($result['Comment'], '{n}.comment'));
5454
5455
		$TestModel->beforeSaveReturn = false;
5456
		$result = $TestModel->saveAssociated(
5457
			array(
5458
				'Article' => array('id' => 2),
5459
				'Comment' => array(
5460
					array(
5461
						'comment' => 'Fourth new comment',
5462
						'published' => 'Y',
5463
						'user_id' => 1
5464
			))),
5465
			array('atomic' => false)
5466
		);
5467
		$this->assertEquals(array('Article' => false), $result);
5468
5469
		$result = $TestModel->findById(2);
0 ignored issues
show
Documentation Bug introduced by
The method findById does not exist on object<Article>? Since you implemented __call, maybe consider adding a @method annotation.

If you implement __call and you know which methods are available, you can improve IDE auto-completion and static analysis by adding a @method annotation to the class.

This is often the case, when __call is implemented by a parent class and only the child class knows which methods exist:

class ParentClass {
    private $data = array();

    public function __call($method, array $args) {
        if (0 === strpos($method, 'get')) {
            return $this->data[strtolower(substr($method, 3))];
        }

        throw new \LogicException(sprintf('Unsupported method: %s', $method));
    }
}

/**
 * If this class knows which fields exist, you can specify the methods here:
 *
 * @method string getName()
 */
class SomeClass extends ParentClass { }
Loading history...
5470
		$expected = array(
5471
			'First Comment for Second Article',
5472
			'Second Comment for Second Article',
5473
			'First new comment',
5474
			'Second new comment',
5475
			'Third new comment'
5476
		);
5477
		$this->assertEquals($expected, Hash::extract($result['Comment'], '{n}.comment'));
5478
	}
5479
5480
/**
5481
 * testSaveAssociatedHasManyEmpty method
5482
 *
5483
 * @return void
5484
 */
5485
	public function testSaveAssociatedHasManyEmpty() {
5486
		$this->loadFixtures('Article', 'Comment');
5487
		$TestModel = new Article();
5488
		$TestModel->belongsTo = $TestModel->hasAndBelongsToMany = array();
5489
		$TestModel->validate = $TestModel->Comment->validate = array('user_id' => array('notEmpty' => array('rule' => 'notEmpty', 'required' => true)));
5490
5491
		//empty hasMany data is ignored in save
5492
		$result = $TestModel->saveAssociated(array(
5493
			'Article' => array('title' => 'title', 'user_id' => 1),
5494
			'Comment' => array()
5495
		), array('validate' => true));
5496
		$this->assertTrue($result);
5497
5498
		$result = $TestModel->saveAssociated(array(
5499
			'Article' => array('title' => 'title', 'user_id' => 1),
5500
			'Comment' => array()
5501
		), array('validate' => true, 'atomic' => false));
5502
		$this->assertEquals(array('Article' => true), $result);
5503
5504
		//empty primary data is not ignored
5505
		$result = $TestModel->saveAssociated(array('Article' => array()), array('validate' => true));
5506
		$this->assertFalse($result);
5507
5508
		$result = $TestModel->saveAssociated(array('Article' => array()), array('validate' => true, 'atomic' => false));
5509
		$this->assertEquals(array('Article' => false), $result);
5510
	}
5511
5512
/**
5513
 * testSaveAssociatedHasManyValidation method
5514
 *
5515
 * @return void
5516
 */
5517 View Code Duplication
	public function testSaveAssociatedHasManyValidation() {
5518
		$this->loadFixtures('Article', 'Comment');
5519
		$TestModel = new Article();
5520
		$TestModel->belongsTo = $TestModel->hasAndBelongsToMany = array();
5521
		$TestModel->Comment->validate = array('comment' => 'notEmpty');
5522
5523
		$result = $TestModel->saveAssociated(array(
5524
			'Article' => array('id' => 2),
5525
			'Comment' => array(
5526
				array('comment' => '', 'published' => 'Y', 'user_id' => 1),
5527
			)
5528
		), array('validate' => true));
5529
		$this->assertFalse($result);
5530
5531
		$expected = array('Comment' => array(
5532
			array('comment' => array('This field cannot be left blank'))
5533
		));
5534
		$this->assertEquals($expected, $TestModel->validationErrors);
5535
		$expected = array(
5536
			array('comment' => array('This field cannot be left blank'))
5537
		);
5538
		$this->assertEquals($expected, $TestModel->Comment->validationErrors);
5539
5540
		$result = $TestModel->saveAssociated(array(
5541
			'Article' => array('id' => 2),
5542
			'Comment' => array(
5543
				array(
5544
					'comment' => '',
5545
					'published' => 'Y',
5546
					'user_id' => 1
5547
			))
5548
		), array('validate' => 'first'));
5549
		$this->assertFalse($result);
5550
	}
5551
5552
/**
5553
 * test saveMany with transactions and ensure there is no missing rollback.
5554
 *
5555
 * @return void
5556
 */
5557 View Code Duplication
	public function testSaveManyTransactionNoRollback() {
5558
		$this->loadFixtures('Post');
5559
5560
		$db = $this->getMock('DboSource', array('begin', 'connect', 'rollback', 'describe'));
5561
5562
		$db->expects($this->once())
5563
			->method('describe')
5564
			->will($this->returnValue(array()));
5565
		$db->expects($this->once())->method('rollback');
5566
5567
		$Post = new TestPost();
5568
		$Post->setDataSourceObject($db);
5569
5570
		$Post->validate = array(
5571
			'title' => array('rule' => array('notEmpty'))
5572
		);
5573
5574
		$data = array(
5575
			array('author_id' => 1, 'title' => 'New Fourth Post'),
5576
			array('author_id' => 1, 'title' => '')
5577
		);
5578
		$Post->saveMany($data, array('validate' => true));
5579
	}
5580
5581
/**
5582
 * test saveAssociated with transactions and ensure there is no missing rollback.
5583
 *
5584
 * @return void
5585
 */
5586 View Code Duplication
	public function testSaveAssociatedTransactionNoRollback() {
5587
		$testDb = ConnectionManager::getDataSource('test');
5588
5589
		$db = $this->getMock('DboSource', array('connect', 'rollback', 'describe', 'create', 'begin'));
5590
		$db->columns = $testDb->columns;
0 ignored issues
show
Bug introduced by
The property columns does not seem to exist in DataSource.

An attempt at access to an undefined property has been detected. This may either be a typographical error or the property has been renamed but there are still references to its old name.

If you really want to allow access to undefined properties, you can define magic methods to allow access. See the php core documentation on Overloading.

Loading history...
5591
5592
		$db->expects($this->once())->method('rollback');
5593
		$db->expects($this->any())->method('describe')
5594
			->will($this->returnValue(array(
5595
				'id' => array('type' => 'integer', 'length' => 11),
5596
				'title' => array('type' => 'string'),
5597
				'body' => array('type' => 'text'),
5598
				'published' => array('type' => 'string')
5599
			)));
5600
5601
		$Post = new TestPost();
5602
		$Post->setDataSourceObject($db);
5603
		$Post->Author->setDataSourceObject($db);
5604
5605
		$Post->Author->validate = array(
5606
			'user' => array('rule' => array('notEmpty'))
5607
		);
5608
5609
		$data = array(
5610
			'Post' => array(
5611
				'title' => 'New post',
5612
				'body' => 'Content',
5613
				'published' => 'Y'
5614
			),
5615
			'Author' => array(
5616
				'user' => '',
5617
				'password' => "sekret"
5618
			)
5619
		);
5620
		$Post->saveAssociated($data, array('validate' => true, 'atomic' => true));
5621
	}
5622
5623
/**
5624
 * test saveMany with nested saveMany call.
5625
 *
5626
 * @return void
5627
 */
5628 View Code Duplication
	public function testSaveManyNestedSaveMany() {
5629
		$this->loadFixtures('Sample');
5630
		$TransactionManyTestModel = new TransactionManyTestModel();
5631
5632
		$data = array(
5633
			array('apple_id' => 1, 'name' => 'sample5'),
5634
		);
5635
5636
		$this->assertTrue($TransactionManyTestModel->saveMany($data, array('atomic' => true)));
5637
	}
5638
5639
/**
5640
 * testSaveManyTransaction method
5641
 *
5642
 * @return void
5643
 */
5644
	public function testSaveManyTransaction() {
5645
		$this->loadFixtures('Post', 'Author', 'Comment', 'Attachment');
5646
		$TestModel = new Post();
5647
5648
		$TestModel->validate = array('title' => 'notEmpty');
5649
		$data = array(
5650
			array('author_id' => 1, 'title' => 'New Fourth Post'),
5651
			array('author_id' => 1, 'title' => 'New Fifth Post'),
5652
			array('author_id' => 1, 'title' => '')
5653
		);
5654
		$this->assertFalse($TestModel->saveMany($data));
5655
5656
		$result = $TestModel->find('all', array('recursive' => -1));
5657
		$expected = array(
5658
			array('Post' => array(
5659
				'id' => '1',
5660
				'author_id' => 1,
5661
				'title' => 'First Post',
5662
				'body' => 'First Post Body',
5663
				'published' => 'Y',
5664
				'created' => '2007-03-18 10:39:23',
5665
				'updated' => '2007-03-18 10:41:31'
5666
			)),
5667
			array('Post' => array(
5668
				'id' => '2',
5669
				'author_id' => 3,
5670
				'title' => 'Second Post',
5671
				'body' => 'Second Post Body',
5672
				'published' => 'Y',
5673
				'created' => '2007-03-18 10:41:23',
5674
				'updated' => '2007-03-18 10:43:31'
5675
			)),
5676
			array('Post' => array(
5677
				'id' => '3',
5678
				'author_id' => 1,
5679
				'title' => 'Third Post',
5680
				'body' => 'Third Post Body',
5681
				'published' => 'Y',
5682
				'created' => '2007-03-18 10:43:23',
5683
				'updated' => '2007-03-18 10:45:31'
5684
		)));
5685
5686
		if (count($result) != 3) {
5687
			// Database doesn't support transactions
5688
			$expected[] = array(
5689
				'Post' => array(
5690
					'id' => '4',
5691
					'author_id' => 1,
5692
					'title' => 'New Fourth Post',
5693
					'body' => null,
5694
					'published' => 'N'
5695
			));
5696
5697
			$expected[] = array(
5698
				'Post' => array(
5699
					'id' => '5',
5700
					'author_id' => 1,
5701
					'title' => 'New Fifth Post',
5702
					'body' => null,
5703
					'published' => 'N',
5704
			));
5705
5706
			$this->assertEquals(self::date(), $result[3]['Post']['created']);
5707
			$this->assertEquals(self::date(), $result[3]['Post']['updated']);
5708
			$this->assertEquals(self::date(), $result[4]['Post']['created']);
5709
			$this->assertEquals(self::date(), $result[4]['Post']['updated']);
5710
			unset($result[3]['Post']['created'], $result[3]['Post']['updated']);
5711
			unset($result[4]['Post']['created'], $result[4]['Post']['updated']);
5712
			$this->assertEquals($expected, $result);
5713
			// Skip the rest of the transactional tests
5714
			return;
5715
		}
5716
5717
		$this->assertEquals($expected, $result);
5718
5719
		$data = array(
5720
			array('author_id' => 1, 'title' => 'New Fourth Post'),
5721
			array('author_id' => 1, 'title' => ''),
5722
			array('author_id' => 1, 'title' => 'New Sixth Post')
5723
		);
5724
		$this->assertFalse($TestModel->saveMany($data));
5725
5726
		$result = $TestModel->find('all', array('recursive' => -1));
5727
		$expected = array(
5728
			array('Post' => array(
5729
				'id' => '1',
5730
				'author_id' => 1,
5731
				'title' => 'First Post',
5732
				'body' => 'First Post Body',
5733
				'published' => 'Y',
5734
				'created' => '2007-03-18 10:39:23',
5735
				'updated' => '2007-03-18 10:41:31'
5736
			)),
5737
			array('Post' => array(
5738
				'id' => '2',
5739
				'author_id' => 3,
5740
				'title' => 'Second Post',
5741
				'body' => 'Second Post Body',
5742
				'published' => 'Y',
5743
				'created' => '2007-03-18 10:41:23',
5744
				'updated' => '2007-03-18 10:43:31'
5745
			)),
5746
			array('Post' => array(
5747
				'id' => '3',
5748
				'author_id' => 1,
5749
				'title' => 'Third Post',
5750
				'body' => 'Third Post Body',
5751
				'published' => 'Y',
5752
				'created' => '2007-03-18 10:43:23',
5753
				'updated' => '2007-03-18 10:45:31'
5754
		)));
5755
5756
		if (count($result) != 3) {
5757
			// Database doesn't support transactions
5758
			$expected[] = array(
5759
				'Post' => array(
5760
					'id' => '4',
5761
					'author_id' => 1,
5762
					'title' => 'New Fourth Post',
5763
					'body' => 'Third Post Body',
5764
					'published' => 'N'
5765
			));
5766
5767
			$expected[] = array(
5768
				'Post' => array(
5769
					'id' => '5',
5770
					'author_id' => 1,
5771
					'title' => 'Third Post',
5772
					'body' => 'Third Post Body',
5773
					'published' => 'N'
5774
			));
5775
			$this->assertEquals(self::date(), $result[3]['Post']['created']);
5776
			$this->assertEquals(self::date(), $result[3]['Post']['updated']);
5777
			$this->assertEquals(self::date(), $result[4]['Post']['created']);
5778
			$this->assertEquals(self::date(), $result[4]['Post']['updated']);
5779
			unset($result[3]['Post']['created'], $result[3]['Post']['updated']);
5780
			unset($result[4]['Post']['created'], $result[4]['Post']['updated']);
5781
		}
5782
		$this->assertEquals($expected, $result);
5783
5784
		$TestModel->validate = array('title' => 'notEmpty');
5785
		$data = array(
5786
			array('author_id' => 1, 'title' => 'New Fourth Post'),
5787
			array('author_id' => 1, 'title' => 'New Fifth Post'),
5788
			array('author_id' => 1, 'title' => 'New Sixth Post')
5789
		);
5790
		$this->assertTrue($TestModel->saveMany($data));
5791
5792
		$result = $TestModel->find('all', array(
5793
			'recursive' => -1,
5794
			'fields' => array('author_id', 'title', 'body', 'published'),
5795
			'order' => array('Post.created' => 'ASC')
5796
		));
5797
5798
		$expected = array(
5799
			array('Post' => array(
5800
				'author_id' => 1,
5801
				'title' => 'First Post',
5802
				'body' => 'First Post Body',
5803
				'published' => 'Y'
5804
			)),
5805
			array('Post' => array(
5806
				'author_id' => 3,
5807
				'title' => 'Second Post',
5808
				'body' => 'Second Post Body',
5809
				'published' => 'Y'
5810
			)),
5811
			array('Post' => array(
5812
				'author_id' => 1,
5813
				'title' => 'Third Post',
5814
				'body' => 'Third Post Body',
5815
				'published' => 'Y'
5816
			)),
5817
			array('Post' => array(
5818
				'author_id' => 1,
5819
				'title' => 'New Fourth Post',
5820
				'body' => '',
5821
				'published' => 'N'
5822
			)),
5823
			array('Post' => array(
5824
				'author_id' => 1,
5825
				'title' => 'New Fifth Post',
5826
				'body' => '',
5827
				'published' => 'N'
5828
			)),
5829
			array('Post' => array(
5830
				'author_id' => 1,
5831
				'title' => 'New Sixth Post',
5832
				'body' => '',
5833
				'published' => 'N'
5834
		)));
5835
		$this->assertEquals($expected, $result);
5836
	}
5837
5838
/**
5839
 * testSaveManyValidation method
5840
 *
5841
 * @return void
5842
 */
5843
	public function testSaveManyValidation() {
5844
		$this->loadFixtures('Post', 'Author', 'Comment', 'Attachment');
5845
		$TestModel = new Post();
5846
5847
		$data = array(
5848
			array(
5849
				'id' => '1',
5850
				'title' => 'Baleeted First Post',
5851
				'body' => 'Baleeted!',
5852
				'published' => 'N'
5853
			),
5854
			array(
5855
				'id' => '2',
5856
				'title' => 'Just update the title'
5857
			),
5858
			array(
5859
				'title' => 'Creating a fourth post',
5860
				'body' => 'Fourth post body',
5861
				'author_id' => 2
5862
		));
5863
5864
		$this->assertTrue($TestModel->saveMany($data));
5865
5866
		$result = $TestModel->find('all', array('recursive' => -1, 'order' => 'Post.id ASC'));
5867
		$expected = array(
5868
			array(
5869
				'Post' => array(
5870
					'id' => '1',
5871
					'author_id' => '1',
5872
					'title' => 'Baleeted First Post',
5873
					'body' => 'Baleeted!',
5874
					'published' => 'N',
5875
					'created' => '2007-03-18 10:39:23'
5876
				)
5877
			),
5878
			array(
5879
				'Post' => array(
5880
					'id' => '2',
5881
					'author_id' => '3',
5882
					'title' => 'Just update the title',
5883
					'body' => 'Second Post Body',
5884
					'published' => 'Y',
5885
					'created' => '2007-03-18 10:41:23'
5886
				)
5887
			),
5888
			array(
5889
				'Post' => array(
5890
					'id' => '3',
5891
					'author_id' => '1',
5892
					'title' => 'Third Post',
5893
					'body' => 'Third Post Body',
5894
					'published' => 'Y',
5895
					'created' => '2007-03-18 10:43:23',
5896
					'updated' => '2007-03-18 10:45:31'
5897
			)),
5898
			array(
5899
				'Post' => array(
5900
					'id' => '4',
5901
					'author_id' => '2',
5902
					'title' => 'Creating a fourth post',
5903
					'body' => 'Fourth post body',
5904
					'published' => 'N'
5905
				)
5906
			)
5907
		);
5908
5909
		$this->assertEquals(self::date(), $result[0]['Post']['updated']);
5910
		$this->assertEquals(self::date(), $result[1]['Post']['updated']);
5911
		$this->assertEquals(self::date(), $result[3]['Post']['created']);
5912
		$this->assertEquals(self::date(), $result[3]['Post']['updated']);
5913
		unset($result[0]['Post']['updated'], $result[1]['Post']['updated']);
5914
		unset($result[3]['Post']['created'], $result[3]['Post']['updated']);
5915
		$this->assertEquals($expected, $result);
5916
5917
		$TestModel->validate = array('title' => 'notEmpty', 'author_id' => 'numeric');
5918
		$data = array(
5919
			array(
5920
				'id' => '1',
5921
				'title' => 'Un-Baleeted First Post',
5922
				'body' => 'Not Baleeted!',
5923
				'published' => 'Y'
5924
			),
5925
			array(
5926
				'id' => '2',
5927
				'title' => '',
5928
				'body' => 'Trying to get away with an empty title'
5929
		));
5930
		$result = $TestModel->saveMany($data);
5931
		$this->assertFalse($result);
5932
5933
		$result = $TestModel->find('all', array('recursive' => -1, 'order' => 'Post.id ASC'));
5934
		$errors = array(1 => array('title' => array('This field cannot be left blank')));
5935
		$transactionWorked = Set::matches('/Post[1][title=Baleeted First Post]', $result);
0 ignored issues
show
Bug introduced by
It seems like $result defined by $TestModel->find('all', ...der' => 'Post.id ASC')) on line 5933 can also be of type null; however, Set::matches() does only seem to accept array, maybe add an additional type check?

If a method or function can return multiple different values and unless you are sure that you only can receive a single value in this context, we recommend to add an additional type check:

/**
 * @return array|string
 */
function returnsDifferentValues($x) {
    if ($x) {
        return 'foo';
    }

    return array();
}

$x = returnsDifferentValues($y);
if (is_array($x)) {
    // $x is an array.
}

If this a common case that PHP Analyzer should handle natively, please let us know by opening an issue.

Loading history...
5936
		if (!$transactionWorked) {
5937
			$this->assertTrue(Set::matches('/Post[1][title=Un-Baleeted First Post]', $result));
0 ignored issues
show
Bug introduced by
It seems like $result defined by $TestModel->find('all', ...der' => 'Post.id ASC')) on line 5933 can also be of type null; however, Set::matches() does only seem to accept array, maybe add an additional type check?

If a method or function can return multiple different values and unless you are sure that you only can receive a single value in this context, we recommend to add an additional type check:

/**
 * @return array|string
 */
function returnsDifferentValues($x) {
    if ($x) {
        return 'foo';
    }

    return array();
}

$x = returnsDifferentValues($y);
if (is_array($x)) {
    // $x is an array.
}

If this a common case that PHP Analyzer should handle natively, please let us know by opening an issue.

Loading history...
5938
			$this->assertTrue(Set::matches('/Post[2][title=Just update the title]', $result));
0 ignored issues
show
Bug introduced by
It seems like $result defined by $TestModel->find('all', ...der' => 'Post.id ASC')) on line 5933 can also be of type null; however, Set::matches() does only seem to accept array, maybe add an additional type check?

If a method or function can return multiple different values and unless you are sure that you only can receive a single value in this context, we recommend to add an additional type check:

/**
 * @return array|string
 */
function returnsDifferentValues($x) {
    if ($x) {
        return 'foo';
    }

    return array();
}

$x = returnsDifferentValues($y);
if (is_array($x)) {
    // $x is an array.
}

If this a common case that PHP Analyzer should handle natively, please let us know by opening an issue.

Loading history...
5939
		}
5940
5941
		$this->assertEquals($errors, $TestModel->validationErrors);
5942
5943
		$TestModel->validate = array('title' => 'notEmpty', 'author_id' => 'numeric');
5944
		$data = array(
5945
			array(
5946
				'id' => '1',
5947
				'title' => 'Un-Baleeted First Post',
5948
				'body' => 'Not Baleeted!',
5949
				'published' => 'Y'
5950
			),
5951
			array(
5952
				'id' => '2',
5953
				'title' => '',
5954
				'body' => 'Trying to get away with an empty title'
5955
		));
5956
		$result = $TestModel->saveMany($data, array('validate' => true, 'atomic' => false));
5957
		$this->assertEquals(array(true, false), $result);
5958
5959
		$result = $TestModel->find('all', array(
5960
			'fields' => array('id', 'author_id', 'title', 'body', 'published'),
5961
			'recursive' => -1,
5962
			'order' => 'Post.id ASC'
5963
		));
5964
		$errors = array(1 => array('title' => array('This field cannot be left blank')));
5965
		$expected = array(
5966
			array(
5967
				'Post' => array(
5968
					'id' => '1',
5969
					'author_id' => '1',
5970
					'title' => 'Un-Baleeted First Post',
5971
					'body' => 'Not Baleeted!',
5972
					'published' => 'Y',
5973
			)),
5974
			array(
5975
				'Post' => array(
5976
					'id' => '2',
5977
					'author_id' => '3',
5978
					'title' => 'Just update the title',
5979
					'body' => 'Second Post Body',
5980
					'published' => 'Y',
5981
			)),
5982
			array(
5983
				'Post' => array(
5984
					'id' => '3',
5985
					'author_id' => '1',
5986
					'title' => 'Third Post',
5987
					'body' => 'Third Post Body',
5988
					'published' => 'Y',
5989
			)),
5990
			array(
5991
				'Post' => array(
5992
					'id' => '4',
5993
					'author_id' => '2',
5994
					'title' => 'Creating a fourth post',
5995
					'body' => 'Fourth post body',
5996
					'published' => 'N',
5997
		)));
5998
		$this->assertEquals($expected, $result);
5999
		$this->assertEquals($errors, $TestModel->validationErrors);
6000
6001
		$data = array(
6002
			array(
6003
				'id' => '1',
6004
				'title' => 'Re-Baleeted First Post',
6005
				'body' => 'Baleeted!',
6006
				'published' => 'N'
6007
			),
6008
			array(
6009
				'id' => '2',
6010
				'title' => '',
6011
				'body' => 'Trying to get away with an empty title'
6012
		));
6013
		$this->assertFalse($TestModel->saveMany($data, array('validate' => 'first')));
6014
6015
		$result = $TestModel->find('all', array(
6016
			'fields' => array('id', 'author_id', 'title', 'body', 'published'),
6017
			'recursive' => -1,
6018
			'order' => 'Post.id ASC'
6019
		));
6020
		$this->assertEquals($expected, $result);
6021
		$this->assertEquals($errors, $TestModel->validationErrors);
6022
	}
6023
6024
/**
6025
 * testValidateMany method
6026
 *
6027
 * @return void
6028
 */
6029
	public function testValidateMany() {
6030
		$TestModel = new Article();
6031
		$TestModel->validate = array('title' => 'notEmpty');
6032
		$data = array(
6033
				0 => array('title' => ''),
6034
				1 => array('title' => 'title 1'),
6035
				2 => array('title' => 'title 2'),
6036
		);
6037
		$result = $TestModel->validateMany($data);
6038
		$this->assertFalse($result);
6039
		$expected = array(
6040
			0 => array('title' => array('This field cannot be left blank')),
6041
		);
6042
		$this->assertEquals($expected, $TestModel->validationErrors);
6043
6044
		$data = array(
6045
				0 => array('title' => 'title 0'),
6046
				1 => array('title' => ''),
6047
				2 => array('title' => 'title 2'),
6048
		);
6049
		$result = $TestModel->validateMany($data);
6050
		$this->assertFalse($result);
6051
		$expected = array(
6052
			1 => array('title' => array('This field cannot be left blank')),
6053
		);
6054
		$this->assertEquals($expected, $TestModel->validationErrors);
6055
	}
6056
6057
/**
6058
 * testSaveAssociatedValidateFirst method
6059
 *
6060
 * @return void
6061
 */
6062 View Code Duplication
	public function testSaveAssociatedValidateFirst() {
6063
		$this->loadFixtures('Article', 'Comment', 'Attachment');
6064
		$model = new Article();
6065
		$model->deleteAll(true);
6066
6067
		$model->Comment->validate = array('comment' => 'notEmpty');
6068
		$result = $model->saveAssociated(array(
6069
			'Article' => array(
6070
				'title' => 'Post with Author',
6071
				'body' => 'This post will be saved author'
6072
			),
6073
			'Comment' => array(
6074
				array('comment' => 'First new comment'),
6075
				array('comment' => '')
6076
			)
6077
		), array('validate' => 'first'));
6078
6079
		$this->assertFalse($result);
6080
6081
		$result = $model->find('all');
6082
		$this->assertSame(array(), $result);
6083
		$expected = array('Comment' => array(
6084
			1 => array('comment' => array('This field cannot be left blank'))
6085
		));
6086
6087
		$this->assertEquals($expected['Comment'], $model->Comment->validationErrors);
6088
6089
		$this->assertSame($model->Comment->find('count'), 0);
6090
6091
		$result = $model->saveAssociated(
6092
			array(
6093
				'Article' => array(
6094
					'title' => 'Post with Author',
6095
					'body' => 'This post will be saved with an author',
6096
					'user_id' => 2
6097
				),
6098
				'Comment' => array(
6099
					array(
6100
						'comment' => 'Only new comment',
6101
						'user_id' => 2
6102
			))),
6103
			array('validate' => 'first')
6104
		);
6105
6106
		$this->assertTrue($result);
6107
6108
		$result = $model->Comment->find('all');
6109
		$this->assertSame(count($result), 1);
6110
		$result = Hash::extract($result, '{n}.Comment.article_id');
6111
		$this->assertEquals(4, $result[0]);
6112
6113
		$model->deleteAll(true);
6114
		$data = array(
6115
			'Article' => array(
6116
				'title' => 'Post with Author saveAlled from comment',
6117
				'body' => 'This post will be saved with an author',
6118
				'user_id' => 2
6119
			),
6120
			'Comment' => array(
6121
				'comment' => 'Only new comment', 'user_id' => 2
6122
		));
6123
6124
		$result = $model->Comment->saveAssociated($data, array('validate' => 'first'));
6125
		$this->assertFalse(empty($result));
6126
6127
		$result = $model->find('all');
6128
		$this->assertEquals(
6129
			'Post with Author saveAlled from comment',
6130
			$result[0]['Article']['title']
6131
		);
6132
		$this->assertEquals('Only new comment', $result[0]['Comment'][0]['comment']);
6133
	}
6134
6135
/**
6136
 * test saveMany()'s return is correct when using atomic = false and validate = first.
6137
 *
6138
 * @return void
6139
 */
6140
	public function testSaveManyValidateFirstAtomicFalse() {
6141
		$Something = new Something();
6142
		$invalidData = array(
6143
			array(
6144
				'title' => 'foo',
6145
				'body' => 'bar',
6146
				'published' => 'baz',
6147
			),
6148
			array(
6149
				'body' => 3,
6150
				'published' => 'sd',
6151
			),
6152
		);
6153
		$Something->create();
6154
		$Something->validate = array(
6155
			'title' => array(
6156
				'rule' => 'alphaNumeric',
6157
				'required' => true,
6158
			),
6159
			'body' => array(
6160
				'rule' => 'alphaNumeric',
6161
				'required' => true,
6162
				'allowEmpty' => true,
6163
			),
6164
		);
6165
		$result = $Something->saveMany($invalidData, array(
6166
			'atomic' => false,
6167
			'validate' => 'first',
6168
		));
6169
		$expected = array(true, false);
6170
		$this->assertEquals($expected, $result);
6171
6172
		$Something = new Something();
6173
		$validData = array(
6174
			array(
6175
				'title' => 'title value',
6176
				'body' => 'body value',
6177
				'published' => 'baz',
6178
			),
6179
			array(
6180
				'title' => 'valid',
6181
				'body' => 'this body',
6182
				'published' => 'sd',
6183
			),
6184
		);
6185
		$Something->create();
6186
		$result = $Something->saveMany($validData, array(
6187
			'atomic' => false,
6188
			'validate' => 'first',
6189
		));
6190
		$expected = array(true, true);
6191
		$this->assertEquals($expected, $result);
6192
	}
6193
6194
/**
6195
 * testValidateAssociated method
6196
 *
6197
 * @return void
6198
 */
6199
	public function testValidateAssociated() {
6200
		$this->loadFixtures('Attachment', 'Article', 'Comment');
6201
		$TestModel = new Comment();
6202
		$TestModel->Attachment->validate = array('attachment' => 'notEmpty');
6203
6204
		$data = array(
6205
			'Comment' => array(
6206
				'comment' => 'This is the comment'
6207
			),
6208
			'Attachment' => array(
6209
				'attachment' => ''
6210
			)
6211
		);
6212
6213
		$result = $TestModel->validateAssociated($data);
6214
		$this->assertFalse($result);
6215
6216
		$TestModel = new Article();
6217
		$TestModel->belongsTo = $TestModel->hasAndBelongsToMany = array();
6218
		$TestModel->Comment->validate = array('comment' => 'notEmpty');
6219
6220
		$data = array(
6221
			'Article' => array('id' => 2),
6222
			'Comment' => array(
6223
				array(
6224
					'id' => 1,
6225
					'comment' => '',
6226
					'published' => 'Y',
6227
					'user_id' => 1),
6228
				array(
6229
					'id' => 2,
6230
					'comment' =>
6231
					'comment',
6232
					'published' => 'Y',
6233
					'user_id' => 1
6234
		)));
6235
		$result = $TestModel->validateAssociated($data);
6236
		$this->assertFalse($result);
6237
6238
		$data = array(
6239
			'Article' => array('id' => 2),
6240
			'Comment' => array(
6241
				array(
6242
					'id' => 1,
6243
					'comment' => '',
6244
					'published' => 'Y',
6245
					'user_id' => 1
6246
				),
6247
				array(
6248
					'id' => 2,
6249
					'comment' => 'comment',
6250
					'published' => 'Y',
6251
					'user_id' => 1
6252
				),
6253
				array(
6254
					'id' => 3,
6255
					'comment' => '',
6256
					'published' => 'Y',
6257
					'user_id' => 1
6258
		)));
6259
		$result = $TestModel->validateAssociated($data, array(
6260
				'atomic' => false
6261
		));
6262
		$expected = array(
6263
			'Article' => true,
6264
			'Comment' => array(false, true, false)
6265
		);
6266
		$this->assertSame($expected, $result);
6267
6268
		$expected = array('Comment' => array(
6269
			0 => array('comment' => array('This field cannot be left blank')),
6270
			2 => array('comment' => array('This field cannot be left blank'))
6271
		));
6272
		$this->assertEquals($expected, $TestModel->validationErrors);
6273
6274
		$expected = array(
6275
			0 => array('comment' => array('This field cannot be left blank')),
6276
			2 => array('comment' => array('This field cannot be left blank'))
6277
		);
6278
		$this->assertEquals($expected, $TestModel->Comment->validationErrors);
6279
	}
6280
6281
/**
6282
 * test that saveMany behaves like plain save() when suplied empty data
6283
 *
6284
 * @link https://cakephp.lighthouseapp.com/projects/42648/tickets/277-test-saveall-with-validation-returns-incorrect-boolean-when-saving-empty-data
6285
 * @return void
6286
 */
6287 View Code Duplication
	public function testSaveManyEmptyData() {
6288
		$this->skipIf($this->db instanceof Sqlserver, 'This test is not compatible with SQL Server.');
6289
6290
		$this->loadFixtures('Article', 'ProductUpdateAll', 'Comment', 'Attachment');
6291
		$model = new Article();
6292
		$result = $model->saveMany(array(), array('validate' => true));
6293
		$this->assertFalse(empty($result));
6294
6295
		$model = new ProductUpdateAll();
6296
		$result = $model->saveMany(array());
6297
		$this->assertFalse($result);
6298
	}
6299
6300
/**
6301
 * test that saveAssociated behaves like plain save() when supplied empty data
6302
 *
6303
 * @link https://cakephp.lighthouseapp.com/projects/42648/tickets/277-test-saveall-with-validation-returns-incorrect-boolean-when-saving-empty-data
6304
 * @return void
6305
 */
6306 View Code Duplication
	public function testSaveAssociatedEmptyData() {
6307
		$this->skipIf($this->db instanceof Sqlserver, 'This test is not compatible with SQL Server.');
6308
6309
		$this->loadFixtures('Article', 'ProductUpdateAll', 'Comment', 'Attachment');
6310
		$model = new Article();
6311
		$result = $model->saveAssociated(array(), array('validate' => true));
6312
		$this->assertFalse(empty($result));
6313
6314
		$model = new ProductUpdateAll();
6315
		$result = $model->saveAssociated(array());
6316
		$this->assertFalse($result);
6317
	}
6318
6319
/**
6320
 * Test that saveAssociated will accept expression object values when saving.
6321
 *
6322
 * @return void
6323
 */
6324
	public function testSaveAssociatedExpressionObjects() {
6325
		$this->loadFixtures('Post', 'Author', 'Comment', 'Attachment', 'Article', 'User');
6326
		$TestModel = new Post();
6327
		$db = $TestModel->getDataSource();
6328
6329
		$TestModel->saveAssociated(array(
6330
			'Post' => array(
6331
				'title' => $db->expression("(SELECT 'Post with Author')"),
6332
				'body' => 'This post will be saved with an author'
6333
			),
6334
			'Author' => array(
6335
				'user' => 'bob',
6336
				'password' => '5f4dcc3b5aa765d61d8327deb882cf90'
6337
		)), array('atomic' => false));
6338
6339
		$result = $TestModel->find('first', array(
6340
			'order' => array('Post.id ' => 'DESC')
6341
		));
6342
		$this->assertEquals('Post with Author', $result['Post']['title']);
6343
	}
6344
6345
/**
6346
 * testUpdateWithCalculation method
6347
 *
6348
 * @return void
6349
 */
6350
	public function testUpdateWithCalculation() {
6351
		$this->loadFixtures('DataTest');
6352
		$model = new DataTest();
6353
		$model->deleteAll(true);
6354
		$result = $model->saveMany(array(
6355
			array('count' => 5, 'float' => 1.1),
6356
			array('count' => 3, 'float' => 1.2),
6357
			array('count' => 4, 'float' => 1.3),
6358
			array('count' => 1, 'float' => 2.0),
6359
		));
6360
		$this->assertFalse(empty($result));
6361
6362
		$result = Hash::extract($model->find('all', array('fields' => 'count')), '{n}.DataTest.count');
0 ignored issues
show
Bug introduced by
It seems like $model->find('all', array('fields' => 'count')) targeting Model::find() can also be of type null; however, Hash::extract() does only seem to accept array, maybe add an additional type check?

This check looks at variables that are passed out again to other methods.

If the outgoing method call has stricter type requirements than the method itself, an issue is raised.

An additional type check may prevent trouble.

Loading history...
6363
		$this->assertEquals(array(5, 3, 4, 1), $result);
6364
6365
		$this->assertTrue($model->updateAll(array('count' => 'count + 2')));
6366
		$result = Hash::extract($model->find('all', array('fields' => 'count')), '{n}.DataTest.count');
0 ignored issues
show
Bug introduced by
It seems like $model->find('all', array('fields' => 'count')) targeting Model::find() can also be of type null; however, Hash::extract() does only seem to accept array, maybe add an additional type check?

This check looks at variables that are passed out again to other methods.

If the outgoing method call has stricter type requirements than the method itself, an issue is raised.

An additional type check may prevent trouble.

Loading history...
6367
		$this->assertEquals(array(7, 5, 6, 3), $result);
6368
6369
		$this->assertTrue($model->updateAll(array('DataTest.count' => 'DataTest.count - 1')));
6370
		$result = Hash::extract($model->find('all', array('fields' => 'count')), '{n}.DataTest.count');
0 ignored issues
show
Bug introduced by
It seems like $model->find('all', array('fields' => 'count')) targeting Model::find() can also be of type null; however, Hash::extract() does only seem to accept array, maybe add an additional type check?

This check looks at variables that are passed out again to other methods.

If the outgoing method call has stricter type requirements than the method itself, an issue is raised.

An additional type check may prevent trouble.

Loading history...
6371
		$this->assertEquals(array(6, 4, 5, 2), $result);
6372
	}
6373
6374
	public function testToggleBoolFields() {
6375
		$this->loadFixtures('CounterCacheUser', 'CounterCachePost');
6376
		$Post = new CounterCachePost();
6377
		$Post->unbindModel(array('belongsTo' => array('User')), true);
6378
6379
		$true = array('Post' => array('published' => true, 'id' => 2));
6380
		$false = array('Post' => array('published' => false, 'id' => 2));
6381
		$fields = array('Post.published', 'Post.id');
6382
		$updateConditions = array('Post.id' => 2);
6383
6384
		// check its true
6385
		$result = $Post->find('first', array('conditions' => $updateConditions, 'fields' => $fields));
6386
		$this->assertEquals($true, $result);
6387
6388
		// Testing without the alias
6389
		$this->assertTrue($Post->updateAll(array('published' => 'NOT published'), $updateConditions));
6390
		$result = $Post->find('first', array('conditions' => $updateConditions, 'fields' => $fields));
6391
		$this->assertEquals($false, $result);
6392
6393
		$this->assertTrue($Post->updateAll(array('published' => 'NOT published'), $updateConditions));
6394
		$result = $Post->find('first', array('conditions' => $updateConditions, 'fields' => $fields));
6395
		$this->assertEquals($true, $result);
6396
6397
		$db = ConnectionManager::getDataSource('test');
6398
		$alias = $db->name('Post.published');
6399
6400
		// Testing with the alias
6401
		$this->assertTrue($Post->updateAll(array('Post.published' => "NOT $alias"), $updateConditions));
6402
		$result = $Post->find('first', array('conditions' => $updateConditions, 'fields' => $fields));
6403
		$this->assertEquals($false, $result);
6404
6405
		$this->assertTrue($Post->updateAll(array('Post.published' => "NOT $alias"), $updateConditions));
6406
		$result = $Post->find('first', array('conditions' => $updateConditions, 'fields' => $fields));
6407
		$this->assertEquals($true, $result);
6408
	}
6409
6410
/**
6411
 * TestFindAllWithoutForeignKey
6412
 *
6413
 * @return void
6414
 */
6415
	public function testFindAllForeignKey() {
6416
		$this->loadFixtures('ProductUpdateAll', 'GroupUpdateAll');
6417
		$ProductUpdateAll = new ProductUpdateAll();
6418
6419
		$conditions = array('Group.name' => 'group one');
6420
6421
		$ProductUpdateAll->bindModel(array(
6422
			'belongsTo' => array(
6423
				'Group' => array('className' => 'GroupUpdateAll')
6424
			)
6425
		));
6426
6427
		$ProductUpdateAll->belongsTo = array(
6428
			'Group' => array('className' => 'GroupUpdateAll', 'foreignKey' => 'group_id')
6429
		);
6430
6431
		$results = $ProductUpdateAll->find('all', compact('conditions'));
6432
		$this->assertTrue(!empty($results));
6433
6434
		$ProductUpdateAll->bindModel(array('belongsTo' => array('Group')));
6435
		$ProductUpdateAll->belongsTo = array(
6436
			'Group' => array(
6437
				'className' => 'GroupUpdateAll',
6438
				'foreignKey' => false,
6439
				'conditions' => 'ProductUpdateAll.groupcode = Group.code'
6440
			));
6441
6442
		$resultsFkFalse = $ProductUpdateAll->find('all', compact('conditions'));
6443
		$this->assertTrue(!empty($resultsFkFalse));
6444
		$expected = array(
6445
			'0' => array(
6446
				'ProductUpdateAll' => array(
6447
					'id' => 1,
6448
					'name'	=> 'product one',
6449
					'groupcode' => 120,
6450
					'group_id' => 1),
6451
				'Group' => array(
6452
					'id' => 1,
6453
					'name' => 'group one',
6454
					'code' => 120)
6455
				),
6456
			'1' => array(
6457
				'ProductUpdateAll' => array(
6458
					'id' => 2,
6459
					'name'	=> 'product two',
6460
					'groupcode'	=> 120,
6461
					'group_id'	=> 1),
6462
				'Group' => array(
6463
					'id' => 1,
6464
					'name' => 'group one',
6465
					'code' => 120)
6466
				)
6467
6468
			);
6469
		$this->assertEquals($expected, $results);
6470
		$this->assertEquals($expected, $resultsFkFalse);
6471
	}
6472
6473
/**
6474
 * test updateAll with empty values.
6475
 *
6476
 * @return void
6477
 */
6478
	public function testUpdateAllEmptyValues() {
6479
		$this->skipIf($this->db instanceof Sqlserver || $this->db instanceof Postgres, 'This test is not compatible with Postgres or SQL Server.');
6480
6481
		$this->loadFixtures('Author', 'Post');
6482
		$model = new Author();
6483
		$result = $model->updateAll(array('user' => '""'));
6484
		$this->assertTrue($result);
6485
	}
6486
6487
/**
6488
 * testUpdateAllWithJoins
6489
 *
6490
 * @return void
6491
 */
6492
	public function testUpdateAllWithJoins() {
6493
		$this->skipIf(!$this->db instanceof Mysql, 'Currently, there is no way of doing joins in an update statement in postgresql or sqlite');
6494
6495
		$this->loadFixtures('ProductUpdateAll', 'GroupUpdateAll');
6496
		$ProductUpdateAll = new ProductUpdateAll();
6497
6498
		$conditions = array('Group.name' => 'group one');
6499
6500
		$ProductUpdateAll->bindModel(array('belongsTo' => array(
6501
			'Group' => array('className' => 'GroupUpdateAll')))
6502
		);
6503
6504
		$ProductUpdateAll->updateAll(array('name' => "'new product'"), $conditions);
6505
		$results = $ProductUpdateAll->find('all', array(
6506
			'conditions' => array('ProductUpdateAll.name' => 'new product')
6507
		));
6508
		$expected = array(
6509
			'0' => array(
6510
				'ProductUpdateAll' => array(
6511
					'id' => 1,
6512
					'name' => 'new product',
6513
					'groupcode'	=> 120,
6514
					'group_id' => 1),
6515
				'Group' => array(
6516
					'id' => 1,
6517
					'name' => 'group one',
6518
					'code' => 120)
6519
				),
6520
			'1' => array(
6521
				'ProductUpdateAll' => array(
6522
					'id' => 2,
6523
					'name' => 'new product',
6524
					'groupcode' => 120,
6525
					'group_id' => 1),
6526
				'Group' => array(
6527
					'id' => 1,
6528
					'name' => 'group one',
6529
					'code' => 120)));
6530
6531
		$this->assertEquals($expected, $results);
6532
	}
6533
6534
/**
6535
 * testUpdateAllWithoutForeignKey
6536
 *
6537
 * @return void
6538
 */
6539
	public function testUpdateAllWithoutForeignKey() {
6540
		$this->skipIf(!$this->db instanceof Mysql, 'Currently, there is no way of doing joins in an update statement in postgresql');
6541
6542
		$this->loadFixtures('ProductUpdateAll', 'GroupUpdateAll');
6543
		$ProductUpdateAll = new ProductUpdateAll();
6544
6545
		$conditions = array('Group.name' => 'group one');
6546
6547
		$ProductUpdateAll->bindModel(array('belongsTo' => array(
6548
			'Group' => array('className' => 'GroupUpdateAll')
6549
		)));
6550
6551
		$ProductUpdateAll->belongsTo = array(
6552
			'Group' => array(
6553
				'className' => 'GroupUpdateAll',
6554
				'foreignKey' => false,
6555
				'conditions' => 'ProductUpdateAll.groupcode = Group.code'
6556
			)
6557
		);
6558
6559
		$ProductUpdateAll->updateAll(array('name' => "'new product'"), $conditions);
6560
		$resultsFkFalse = $ProductUpdateAll->find('all', array('conditions' => array('ProductUpdateAll.name' => 'new product')));
6561
		$expected = array(
6562
			'0' => array(
6563
				'ProductUpdateAll' => array(
6564
					'id' => 1,
6565
					'name' => 'new product',
6566
					'groupcode'	=> 120,
6567
					'group_id' => 1),
6568
				'Group' => array(
6569
					'id' => 1,
6570
					'name' => 'group one',
6571
					'code' => 120)
6572
				),
6573
			'1' => array(
6574
				'ProductUpdateAll' => array(
6575
					'id' => 2,
6576
					'name' => 'new product',
6577
					'groupcode' => 120,
6578
					'group_id' => 1),
6579
				'Group' => array(
6580
					'id' => 1,
6581
					'name' => 'group one',
6582
					'code' => 120)));
6583
		$this->assertEquals($expected, $resultsFkFalse);
6584
	}
6585
6586
/**
6587
 * test writing floats in german locale.
6588
 *
6589
 * @return void
6590
 */
6591
	public function testWriteFloatAsGerman() {
6592
		$restore = setlocale(LC_NUMERIC, 0);
6593
6594
		$this->skipIf(setlocale(LC_NUMERIC, 'de_DE') === false, "The German locale isn't available.");
6595
6596
		$model = new DataTest();
6597
		$result = $model->save(array(
6598
			'count' => 1,
6599
			'float' => 3.14593
6600
		));
6601
		$this->assertTrue((bool)$result);
6602
		setlocale(LC_NUMERIC, $restore);
6603
	}
6604
6605
/**
6606
 * Test returned array contains primary key when save creates a new record
6607
 *
6608
 * @return void
6609
 */
6610
	public function testPkInReturnArrayForCreate() {
6611
		$this->loadFixtures('Article');
6612
		$TestModel = new Article();
6613
6614
		$data = array('Article' => array(
6615
			'user_id' => '1',
6616
			'title' => 'Fourth Article',
6617
			'body' => 'Fourth Article Body',
6618
			'published' => 'Y'
6619
		));
6620
		$result = $TestModel->save($data);
6621
		$this->assertSame($result['Article']['id'], $TestModel->id);
6622
	}
6623
6624
/**
6625
 * testSaveAllFieldListValidateBelongsTo
6626
 *
6627
 * @return void
6628
 */
6629
	public function testSaveAllFieldListValidateBelongsTo() {
6630
		$this->loadFixtures('Post', 'Author', 'Comment', 'Attachment');
6631
		$TestModel = new Post();
6632
6633
		$result = $TestModel->find('all');
6634
		$this->assertEquals(3, count($result));
6635
		$this->assertFalse(isset($result[3]));
6636
6637
		// test belongsTo
6638
		$fieldList = array(
6639
			'Post' => array('title'),
6640
			'Author' => array('user')
6641
		);
6642
		$data = array(
6643
			'Post' => array(
6644
				'title' => 'Post without body',
6645
				'body' => 'This will not be saved',
6646
			),
6647
			'Author' => array(
6648
				'user' => 'bob',
6649
				'test' => 'This will not be saved',
6650
6651
		));
6652
		$TestModel->saveAll($data, array('fieldList' => $fieldList));
6653
6654
		$result = $TestModel->find('all', array(
6655
			'order' => 'Post.id ASC',
6656
		));
6657
		$expected = array(
6658
			'Post' => array(
6659
				'id' => '4',
6660
				'author_id' => '5',
6661
				'title' => 'Post without body',
6662
				'body' => null,
6663
				'published' => 'N',
6664
				'created' => self::date(),
6665
				'updated' => self::date(),
6666
			),
6667
			'Author' => array(
6668
				'id' => '5',
6669
				'user' => 'bob',
6670
				'password' => null,
6671
				'created' => self::date(),
6672
				'updated' => self::date(),
6673
				'test' => 'working',
6674
			),
6675
		);
6676
		$this->assertEquals($expected, $result[3]);
6677
		$this->assertEquals(4, count($result));
6678
		$this->assertEquals('', $result[3]['Post']['body']);
6679
		$this->assertEquals('working', $result[3]['Author']['test']);
6680
6681
		$fieldList = array(
6682
			'Post' => array('title')
6683
		);
6684
		$data = array(
6685
			'Post' => array(
6686
				'title' => 'Post without body 2',
6687
				'body' => 'This will not be saved'
6688
			),
6689
			'Author' => array(
6690
				'user' => 'jack'
6691
			)
6692
		);
6693
		$TestModel->saveAll($data, array('fieldList' => $fieldList));
6694
		$result = $TestModel->find('all', array(
6695
			'order' => 'Post.id ASC',
6696
		));
6697
		$this->assertNull($result[4]['Post']['body']);
6698
6699
		$fieldList = array(
6700
			'Author' => array('password')
6701
		);
6702
		$data = array(
6703
			'Post' => array(
6704
				'id' => '5',
6705
				'title' => 'Post title',
6706
				'body' => 'Post body'
6707
			),
6708
			'Author' => array(
6709
				'id' => '6',
6710
				'user' => 'will not change',
6711
				'password' => 'foobar'
6712
			)
6713
		);
6714
		$result = $TestModel->saveAll($data, array('fieldList' => $fieldList));
6715
		$this->assertTrue($result);
6716
6717
		$result = $TestModel->find('all', array(
6718
			'order' => 'Post.id ASC',
6719
		));
6720
		$expected = array(
6721
			'Post' => array(
6722
				'id' => '5',
6723
				'author_id' => '6',
6724
				'title' => 'Post title',
6725
				'body' => 'Post body',
6726
				'published' => 'N',
6727
				'created' => self::date(),
6728
				'updated' => self::date()
6729
			),
6730
			'Author' => array(
6731
				'id' => '6',
6732
				'user' => 'jack',
6733
				'password' => 'foobar',
6734
				'created' => self::date(),
6735
				'updated' => self::date(),
6736
				'test' => 'working'
6737
			),
6738
		);
6739
		$this->assertEquals($expected, $result[4]);
6740
6741
		// test multirecord
6742
		$this->db->truncate($TestModel);
6743
6744
		$fieldList = array('title', 'author_id');
6745
		$TestModel->saveAll(array(
6746
			array(
6747
				'title' => 'Multi-record post 1',
6748
				'body' => 'First multi-record post',
6749
				'author_id' => 2
6750
			),
6751
			array(
6752
				'title' => 'Multi-record post 2',
6753
				'body' => 'Second multi-record post',
6754
				'author_id' => 2
6755
		)), array('fieldList' => $fieldList));
6756
6757
		$result = $TestModel->find('all', array(
6758
			'recursive' => -1,
6759
			'order' => 'Post.id ASC'
6760
		));
6761
		$expected = array(
6762
			array(
6763
				'Post' => array(
6764
					'id' => '1',
6765
					'author_id' => '2',
6766
					'title' => 'Multi-record post 1',
6767
					'body' => '',
6768
					'published' => 'N',
6769
					'created' => self::date(),
6770
					'updated' => self::date()
6771
				)
6772
			),
6773
			array(
6774
				'Post' => array(
6775
					'id' => '2',
6776
					'author_id' => '2',
6777
					'title' => 'Multi-record post 2',
6778
					'body' => '',
6779
					'published' => 'N',
6780
					'created' => self::date(),
6781
					'updated' => self::date()
6782
				)
6783
			)
6784
		);
6785
		$this->assertEquals($expected, $result);
6786
	}
6787
6788
/**
6789
 * testSaveAllFieldListHasMany method
6790
 *
6791
 * @return void
6792
 */
6793
	public function testSaveAllFieldListHasMany() {
6794
		$this->loadFixtures('Article', 'Comment');
6795
		$TestModel = new Article();
6796
		$TestModel->belongsTo = $TestModel->hasAndBelongsToMany = array();
6797
6798
		$this->db->truncate($TestModel);
6799
		$this->db->truncate(new Comment());
6800
6801
		$data = array(
6802
			'Article' => array('title' => 'I will not save'),
6803
			'Comment' => array(
6804
				array('comment' => 'First new comment', 'published' => 'Y', 'user_id' => 1),
6805
				array('comment' => 'Second new comment', 'published' => 'Y', 'user_id' => 2)
6806
			)
6807
		);
6808
6809
		$fieldList = array(
6810
			'Article' => array('id'),
6811
			'Comment' => array('article_id', 'user_id')
6812
		);
6813
		$TestModel->saveAll($data, array('fieldList' => $fieldList));
6814
6815
		$result = $TestModel->find('all');
6816
		$this->assertEquals('', $result[0]['Article']['title']);
6817
		$this->assertEquals('', $result[0]['Comment'][0]['comment']);
6818
		$this->assertEquals('', $result[0]['Comment'][1]['comment']);
6819
6820
		$fieldList = array(
6821
			'Article' => array('id'),
6822
			'Comment' => array('user_id')
6823
		);
6824
		$TestModel->saveAll($data, array('fieldList' => $fieldList));
6825
		$result = $TestModel->find('all');
6826
6827
		$this->assertEquals('', $result[1]['Article']['title']);
6828
		$this->assertEquals(2, count($result[1]['Comment']));
6829
6830
		$TestModel->whitelist = array('id');
6831
		$TestModel->Comment->whitelist = array('user_id');
6832
		$TestModel->saveAll($data);
6833
		$result = $TestModel->find('all');
6834
6835
		$this->assertEquals('', $result[2]['Article']['title']);
6836
		$this->assertEquals(2, count($result[2]['Comment']));
6837
	}
6838
6839
/**
6840
 * testSaveAllFieldListHasOne method
6841
 *
6842
 * @return void
6843
 */
6844
	public function testSaveAllFieldListHasOne() {
6845
		$this->loadFixtures('Attachment', 'Comment', 'Article', 'User');
6846
		$TestModel = new Comment();
6847
6848
		$TestModel->validate = array('comment' => 'notEmpty');
6849
		$TestModel->Attachment->validate = array('attachment' => 'notEmpty');
6850
6851
		$record = array(
6852
			'Comment' => array(
6853
				'user_id' => 1,
6854
				'article_id' => 1,
6855
				'comment' => '',
6856
			),
6857
			'Attachment' => array(
6858
				'attachment' => ''
6859
			)
6860
		);
6861
		$result = $TestModel->saveAll($record, array('validate' => 'only'));
6862
		$this->assertFalse($result);
6863
6864
		$fieldList = array(
6865
			'Comment' => array('id', 'article_id', 'user_id'),
6866
			'Attachment' => array('comment_id')
6867
		);
6868
		$result = $TestModel->saveAll($record, array(
6869
			'fieldList' => $fieldList, 'validate' => 'only'
6870
		));
6871
		$this->assertTrue($result);
6872
		$this->assertEmpty($TestModel->validationErrors);
6873
	}
6874
6875
/**
6876
 * testSaveAllFieldListHasOneAddFkToWhitelist method
6877
 *
6878
 * @return void
6879
 */
6880
	public function testSaveAllFieldListHasOneAddFkToWhitelist() {
6881
		$this->loadFixtures('ArticleFeatured', 'Featured');
6882
		$Article = new ArticleFeatured();
6883
		$Article->belongsTo = $Article->hasMany = array();
6884
		$Article->Featured->validate = array('end_date' => 'notEmpty');
6885
6886
		$record = array(
6887
			'ArticleFeatured' => array(
6888
				'user_id' => 1,
6889
				'title' => 'First Article',
6890
				'body' => '',
6891
				'published' => 'Y'
6892
			),
6893
			'Featured' => array(
6894
				'category_id' => 1,
6895
				'end_date' => ''
6896
			)
6897
		);
6898
		$result = $Article->saveAll($record, array('validate' => 'only'));
6899
		$this->assertFalse($result);
6900
		$expected = array(
6901
			'body' => array(
6902
				'This field cannot be left blank'
6903
			),
6904
			'Featured' => array(
6905
				'end_date' => array(
6906
					'This field cannot be left blank'
6907
				)
6908
			)
6909
		);
6910
		$this->assertEquals($expected, $Article->validationErrors);
6911
6912
		$fieldList = array(
6913
			'ArticleFeatured' => array('user_id', 'title'),
6914
			'Featured' => array('category_id')
6915
		);
6916
6917
		$result = $Article->saveAll($record, array(
6918
			'fieldList' => $fieldList, 'validate' => 'first'
6919
		));
6920
		$this->assertTrue($result);
6921
		$this->assertEmpty($Article->validationErrors);
6922
6923
		$Article->recursive = 0;
6924
		$result = $Article->find('first', array('order' => array('ArticleFeatured.created' => 'DESC')));
6925
		$this->assertSame($result['ArticleFeatured']['id'], $result['Featured']['article_featured_id']);
6926
	}
6927
6928
/**
6929
 * testSaveAllDeepFieldListValidateBelongsTo
6930
 *
6931
 * @return void
6932
 */
6933
	public function testSaveAllDeepFieldListValidateBelongsTo() {
6934
		$this->loadFixtures('Post', 'Author', 'Comment', 'Attachment', 'Article', 'User');
6935
		$TestModel = new Post();
6936
		$TestModel->Author->bindModel(array('hasMany' => array('Comment' => array('foreignKey' => 'user_id'))), false);
6937
		$TestModel->recursive = 2;
6938
6939
		$result = $TestModel->find('all');
6940
		$this->assertEquals(3, count($result));
6941
		$this->assertFalse(isset($result[3]));
6942
6943
		// test belongsTo
6944
		$fieldList = array(
6945
			'Post' => array('title', 'author_id'),
6946
			'Author' => array('user'),
6947
			'Comment' => array('comment')
6948
		);
6949
		$TestModel->saveAll(array(
6950
			'Post' => array(
6951
				'title' => 'Post without body',
6952
				'body' => 'This will not be saved',
6953
			),
6954
			'Author' => array(
6955
				'user' => 'bob',
6956
				'test' => 'This will not be saved',
6957
				'Comment' => array(
6958
					array('id' => 5, 'comment' => 'I am still published', 'published' => 'N'))
6959
6960
		)), array('fieldList' => $fieldList, 'deep' => true));
6961
6962
		$result = $TestModel->Author->Comment->find('first', array(
6963
			'conditions' => array('Comment.id' => 5),
6964
			'fields' => array('comment', 'published')
6965
		));
6966
		$expected = array(
6967
			'Comment' => array(
6968
				'comment' => 'I am still published',
6969
				'published' => 'Y'
6970
			)
6971
		);
6972
		$this->assertEquals($expected, $result);
6973
	}
6974
6975
/**
6976
 * testSaveAllDeepFieldListHasMany method
6977
 *
6978
 * @return void
6979
 */
6980
	public function testSaveAllDeepFieldListHasMany() {
6981
		$this->loadFixtures('Article', 'Comment', 'User');
6982
		$TestModel = new Article();
6983
		$TestModel->belongsTo = $TestModel->hasAndBelongsToMany = array();
6984
6985
		$this->db->truncate($TestModel);
6986
		$this->db->truncate(new Comment());
6987
6988
		$fieldList = array(
6989
			'Article' => array('id'),
6990
			'Comment' => array('article_id', 'user_id'),
6991
			'User' => array('user')
6992
		);
6993
6994
		$result = $TestModel->saveAll(array(
6995
			'Article' => array('id' => 2, 'title' => 'I will not save'),
6996
			'Comment' => array(
6997
				array('comment' => 'First new comment', 'published' => 'Y', 'user_id' => 1),
6998
				array(
6999
					'comment' => 'Second new comment', 'published' => 'Y', 'user_id' => 2,
7000
					'User' => array('user' => 'nopassword', 'password' => 'not saved')
7001
				)
7002
			)
7003
		), array('fieldList' => $fieldList, 'deep' => true));
7004
7005
		$result = $TestModel->Comment->User->find('first', array(
7006
			'conditions' => array('User.user' => 'nopassword'),
7007
			'fields' => array('user', 'password')
7008
		));
7009
		$expected = array(
7010
			'User' => array(
7011
				'user' => 'nopassword',
7012
				'password' => ''
7013
			)
7014
		);
7015
		$this->assertEquals($expected, $result);
7016
	}
7017
7018
/**
7019
 * testSaveAllDeepHasManyBelongsTo method
7020
 *
7021
 * @return void
7022
 */
7023
	public function testSaveAllDeepHasManyBelongsTo() {
7024
		$this->loadFixtures('Article', 'Comment', 'User');
7025
		$TestModel = new Article();
7026
		$TestModel->belongsTo = $TestModel->hasAndBelongsToMany = array();
7027
7028
		$this->db->truncate($TestModel);
7029
		$this->db->truncate(new Comment());
7030
7031
		$result = $TestModel->saveAll(array(
7032
			'Article' => array('id' => 2, 'title' => 'The title'),
7033
			'Comment' => array(
7034
				array('comment' => 'First new comment', 'published' => 'Y', 'user_id' => 1),
7035
				array(
7036
					'comment' => 'belongsto', 'published' => 'Y',
7037
					'User' => array('user' => 'findme', 'password' => 'somepass')
7038
				)
7039
			)
7040
		), array('deep' => true));
7041
7042
		$result = $TestModel->Comment->User->find('first', array(
7043
			'conditions' => array('User.user' => 'findme'),
7044
			'fields' => array('id', 'user', 'password')
7045
		));
7046
		$expected = array(
7047
			'User' => array(
7048
				'id' => 5,
7049
				'user' => 'findme',
7050
				'password' => 'somepass',
7051
			)
7052
		);
7053
		$this->assertEquals($expected, $result);
7054
7055
		$result = $TestModel->Comment->find('first', array(
7056
			'conditions' => array('Comment.user_id' => 5),
7057
			'fields' => array('id', 'comment', 'published', 'user_id')
7058
		));
7059
		$expected = array(
7060
			'Comment' => array(
7061
				'id' => 2,
7062
				'comment' => 'belongsto',
7063
				'published' => 'Y',
7064
				'user_id' => 5
7065
			)
7066
		);
7067
		$this->assertEquals($expected, $result);
7068
	}
7069
7070
/**
7071
 * testSaveAllDeepHasManyhasMany method
7072
 *
7073
 * @return void
7074
 */
7075
	public function testSaveAllDeepHasManyHasMany() {
7076
		$this->loadFixtures('Article', 'Comment', 'User', 'Attachment');
7077
		$TestModel = new Article();
7078
		$TestModel->belongsTo = $TestModel->hasAndBelongsToMany = $TestModel->Comment->belongsTo = array();
7079
		$TestModel->Comment->unbindModel(array('hasOne' => array('Attachment')), false);
7080
		$TestModel->Comment->bindModel(array('hasMany' => array('Attachment')), false);
7081
7082
		$this->db->truncate($TestModel);
7083
		$this->db->truncate(new Comment());
7084
		$this->db->truncate(new Attachment());
7085
7086
		$result = $TestModel->saveAll(array(
7087
			'Article' => array('id' => 2, 'title' => 'The title'),
7088
			'Comment' => array(
7089
				array('comment' => 'First new comment', 'published' => 'Y', 'user_id' => 1),
7090
				array(
7091
					'comment' => 'hasmany', 'published' => 'Y', 'user_id' => 5,
7092
					'Attachment' => array(
7093
						array('attachment' => 'first deep attachment'),
7094
						array('attachment' => 'second deep attachment'),
7095
					)
7096
				)
7097
			)
7098
		), array('deep' => true));
7099
7100
		$result = $TestModel->Comment->find('first', array(
7101
			'conditions' => array('Comment.comment' => 'hasmany'),
7102
			'fields' => array('id', 'comment', 'published', 'user_id'),
7103
			'recursive' => -1
7104
		));
7105
		$expected = array(
7106
			'Comment' => array(
7107
				'id' => 2,
7108
				'comment' => 'hasmany',
7109
				'published' => 'Y',
7110
				'user_id' => 5
7111
			)
7112
		);
7113
		$this->assertEquals($expected, $result);
7114
7115
		$result = $TestModel->Comment->Attachment->find('all', array(
7116
			'fields' => array('attachment', 'comment_id'),
7117
			'order' => array('Attachment.id' => 'ASC')
7118
		));
7119
		$expected = array(
7120
			array('Attachment' => array('attachment' => 'first deep attachment', 'comment_id' => 2)),
7121
			array('Attachment' => array('attachment' => 'second deep attachment', 'comment_id' => 2)),
7122
		);
7123
		$this->assertEquals($expected, $result);
7124
	}
7125
7126
/**
7127
 * testSaveAllDeepOrderHasManyHasMany method
7128
 *
7129
 * @return void
7130
 */
7131
	public function testSaveAllDeepOrderHasManyHasMany() {
7132
		$this->loadFixtures('Article', 'Comment', 'User', 'Attachment');
7133
		$TestModel = new Article();
7134
		$TestModel->belongsTo = $TestModel->hasAndBelongsToMany = $TestModel->Comment->belongsTo = array();
7135
		$TestModel->Comment->unbindModel(array('hasOne' => array('Attachment')), false);
7136
		$TestModel->Comment->bindModel(array('hasMany' => array('Attachment')), false);
7137
7138
		$this->db->truncate($TestModel);
7139
		$this->db->truncate(new Comment());
7140
		$this->db->truncate(new Attachment());
7141
7142
		$result = $TestModel->saveAll(array(
7143
			'Article' => array('id' => 2, 'title' => 'Comment has its data after Attachment'),
7144
			'Comment' => array(
7145
				array(
7146
					'Attachment' => array(
7147
						array('attachment' => 'attachment should be created with comment_id'),
7148
						array('attachment' => 'comment should be created with article_id'),
7149
					),
7150
					'comment' => 'after associated data',
7151
					'user_id' => 1
7152
				)
7153
			)
7154
		), array('deep' => true));
7155
		$result = $TestModel->Comment->find('first', array(
7156
			'conditions' => array('Comment.article_id' => 2),
7157
		));
7158
7159
		$this->assertEquals(2, $result['Comment']['article_id']);
7160
		$this->assertEquals(2, count($result['Attachment']));
7161
	}
7162
7163
/**
7164
 * testSaveAllDeepEmptyHasManyHasMany method
7165
 *
7166
 * @return void
7167
 */
7168
	public function testSaveAllDeepEmptyHasManyHasMany() {
7169
		$this->skipIf(!$this->db instanceof Mysql, 'This test is only compatible with Mysql.');
7170
7171
		$this->loadFixtures('Article', 'Comment', 'User', 'Attachment');
7172
		$TestModel = new Article();
7173
		$TestModel->belongsTo = $TestModel->hasAndBelongsToMany = $TestModel->Comment->belongsTo = array();
7174
		$TestModel->Comment->unbindModel(array('hasOne' => array('Attachment')), false);
7175
		$TestModel->Comment->bindModel(array('hasMany' => array('Attachment')), false);
7176
7177
		$this->db->truncate($TestModel);
7178
		$this->db->truncate(new Comment());
7179
		$this->db->truncate(new Attachment());
7180
7181
		$result = $TestModel->saveAll(array(
7182
			'Article' => array('id' => 3, 'user_id' => 1, 'title' => 'Comment has no data'),
7183
			'Comment' => array(
7184
				array(
7185
					'user_id' => 1,
7186
					'Attachment' => array(
7187
						array('attachment' => 'attachment should be created with comment_id'),
7188
						array('attachment' => 'comment should be created with article_id'),
7189
					),
7190
				)
7191
			)
7192
		), array('deep' => true));
7193
		$result = $TestModel->Comment->find('first', array(
7194
			'conditions' => array('Comment.article_id' => 3),
7195
		));
7196
7197
		$this->assertEquals(3, $result['Comment']['article_id']);
7198
		$this->assertEquals(2, count($result['Attachment']));
7199
	}
7200
7201
/**
7202
 * testUpdateAllBoolean
7203
 *
7204
 * @return void
7205
 */
7206
	public function testUpdateAllBoolean() {
7207
		$this->loadFixtures('Item', 'Syfile', 'Portfolio', 'Image', 'ItemsPortfolio');
7208
		$TestModel = new Item();
7209
		$result = $TestModel->updateAll(array('published' => true));
7210
		$this->assertTrue($result);
7211
7212
		$result = $TestModel->find('first', array('fields' => array('id', 'published')));
7213
		$this->assertEquals(true, $result['Item']['published']);
7214
	}
7215
7216
/**
7217
 * testUpdateAllBooleanConditions
7218
 *
7219
 * @return void
7220
 */
7221 View Code Duplication
	public function testUpdateAllBooleanConditions() {
7222
		$this->loadFixtures('Item', 'Syfile', 'Portfolio', 'Image', 'ItemsPortfolio');
7223
		$TestModel = new Item();
7224
7225
		$result = $TestModel->updateAll(array('published' => true), array('Item.id' => 1));
7226
		$this->assertTrue($result);
7227
		$result = $TestModel->find('first', array(
7228
			'fields' => array('id', 'published'),
7229
			'conditions' => array('Item.id' => 1)));
7230
		$this->assertEquals(true, $result['Item']['published']);
7231
	}
7232
7233
/**
7234
 * testUpdateBoolean
7235
 *
7236
 * @return void
7237
 */
7238 View Code Duplication
	public function testUpdateBoolean() {
7239
		$this->loadFixtures('Item', 'Syfile', 'Portfolio', 'Image', 'ItemsPortfolio');
7240
		$TestModel = new Item();
7241
7242
		$result = $TestModel->save(array('published' => true, 'id' => 1));
7243
		$this->assertTrue((bool)$result);
7244
		$result = $TestModel->find('first', array(
7245
			'fields' => array('id', 'published'),
7246
			'conditions' => array('Item.id' => 1)));
7247
		$this->assertEquals(true, $result['Item']['published']);
7248
	}
7249
7250
/**
7251
 * Test the clear() method.
7252
 *
7253
 * @return void
7254
 */
7255
	public function testClear() {
7256
		$this->loadFixtures('Bid');
7257
		$model = ClassRegistry::init('Bid');
7258
		$model->set(array('name' => 'Testing', 'message_id' => 3));
7259
		$this->assertTrue(isset($model->data['Bid']['name']));
7260
		$this->assertTrue($model->clear());
7261
		$this->assertFalse(isset($model->data['Bid']['name']));
7262
		$this->assertFalse(isset($model->data['Bid']['message_id']));
7263
	}
7264
}
7265