Passed
Pull Request — master (#176)
by
unknown
04:32
created

TDBMServiceTest   F

Complexity

Total Complexity 73

Size/Duplication

Total Lines 815
Duplicated Lines 0 %

Importance

Changes 7
Bugs 0 Features 2
Metric Value
wmc 73
eloc 370
c 7
b 0
f 2
dl 0
loc 815
rs 2.56

58 Methods

Rating   Name   Duplication   Size   Complexity  
A testGetLinkBetweenInheritedTablesExceptions() 0 4 1
A testFindObjectsFromSqlHierarchyUp() 0 13 1
A testFindObjectsCountWithOneToManyLink() 0 5 1
A testBuildFilterFromFilterBagIterator() 0 7 1
A testFindObjectFromSql() 0 9 1
A testGetLinkBetweenInheritedTables() 0 7 1
A testFindObjectsFromSqlBadTableName() 0 9 1
A testFindObjects() 0 22 3
A testLinkedTableFetch() 0 4 1
A testInvalidSetFetchMode() 0 4 1
A testMap() 0 18 1
A testArrayAccess() 0 20 3
A testFindObjectsFromRawSqlBadTableName() 0 7 1
A testFindObjectsByBean() 0 7 1
A testCompleteSave2() 0 6 1
A testFindObjectOrFail() 0 4 1
A testInsertAndUpdateAndDelete() 0 19 1
A testUpdatePrimaryKey() 0 12 1
A testDeleteNewObject() 0 16 2
A testArrayAccessException2() 0 6 1
A testFindObject() 0 4 1
A testTableNameException() 0 4 1
A testGetPrimaryKeysFromIndexedPrimaryKeysException() 0 4 1
A testArrayAccessException() 0 6 1
A testCursorMode() 0 29 4
A testFindObjectDuplicateRow() 0 5 1
A testBeanGetException() 0 8 1
A testFindObjectsMethodWithoutResultIteratorClass() 0 7 1
A testTakeInCursorMode() 0 25 2
A testFindObjectsFromSqlHierarchyDown() 0 13 1
A testFindObjectFromSqlException() 0 9 1
A testSetException() 0 6 1
A testTake() 0 25 2
A testBeanWithoutStatus() 0 6 1
A testCompleteSave() 0 8 1
A testFindObjectsFromSqlCountWithOneToManyLink() 0 5 1
A testSetFetchMode() 0 15 2
A testRawSqlFilterCountriesByUserCount() 0 20 2
A testGetRelatedTablesByInheritance() 0 9 1
A testBeanSetException() 0 8 1
A testFindObjectsFromRawSqlMethodWithoutResultIteratorClass() 0 7 1
A testFindObjectsFromSqlGroupBy() 0 11 1
A testCannotDeleteDetachedObjects() 0 7 1
A testUnsetException() 0 6 1
A testToArray() 0 8 1
A testInsertMultipleDataAtOnceInInheritance() 0 13 1
A testDeleteLoadedObject() 0 14 1
A testCursorModeException() 0 4 1
A testFindObjectsFromSql() 0 11 1
A getCustomOrder() 0 11 2
A testRawSqlOrderUsersByCustomRoleOrder() 0 35 3
A testPageUnsetException() 0 6 1
A testFindObjectByPkException() 0 5 1
A testFindObjectsFromSqlMethodWithoutResultIteratorClass() 0 7 1
A testRawSqlOrderCountriesByUserCount() 0 23 3
A testLogger() 0 10 1
A testHashPrimaryKey() 0 19 1
A testPageSetException() 0 6 1

How to fix   Complexity   

Complex Class

Complex classes like TDBMServiceTest often do a lot of different things. To break such a class down, we need to identify a cohesive component within that class. A common approach to find such a component is to look for fields/methods that share the same prefixes, or suffixes.

Once you have determined the fields that belong together, you can apply the Extract Class refactoring. If the component makes sense as a sub-class, Extract Subclass is also a candidate, and is often faster.

While breaking up the class, it is a good idea to analyze how other classes use TDBMServiceTest, and based on these observations, apply Extract Interface, too.

1
<?php
2
declare(strict_types=1);
3
4
/*
5
 Copyright (C) 2006-2014 David Négrier - THE CODING MACHINE
6
7
This program is free software; you can redistribute it and/or modify
8
it under the terms of the GNU General Public License as published by
9
the Free Software Foundation; either version 2 of the License, or
10
(at your option) any later version.
11
12
This program is distributed in the hope that it will be useful,
13
but WITHOUT ANY WARRANTY; without even the implied warranty of
14
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
15
GNU General Public License for more details.
16
17
You should have received a copy of the GNU General Public License
18
along with this program; if not, write to the Free Software
19
Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
20
*/
21
22
namespace TheCodingMachine\TDBM;
23
24
use Psr\Log\LogLevel;
25
use Psr\Log\NullLogger;
26
use Wa72\SimpleLogger\ArrayLogger;
27
28
class TDBMServiceTest extends TDBMAbstractServiceTest
29
{
30
    public function testGetLinkBetweenInheritedTables(): void
31
    {
32
        $this->assertEquals(['users', 'contact', 'person'], $this->tdbmService->_getLinkBetweenInheritedTables(['contact', 'users']));
33
        $this->assertEquals(['users', 'contact', 'person'], $this->tdbmService->_getLinkBetweenInheritedTables(['users', 'contact']));
34
        $this->assertEquals(['contact', 'person'], $this->tdbmService->_getLinkBetweenInheritedTables(['person', 'contact']));
35
        $this->assertEquals(['users', 'contact', 'person'], $this->tdbmService->_getLinkBetweenInheritedTables(['users']));
36
        $this->assertEquals(['person'], $this->tdbmService->_getLinkBetweenInheritedTables(['person']));
37
    }
38
39
    public function testGetRelatedTablesByInheritance(): void
40
    {
41
        $contactRelatedTables = $this->tdbmService->_getRelatedTablesByInheritance('contact');
42
        $this->assertCount(3, $contactRelatedTables);
43
        $this->assertContains('users', $contactRelatedTables);
44
        $this->assertContains('contact', $contactRelatedTables);
45
        $this->assertContains('person', $contactRelatedTables);
46
        $this->assertEquals(['person', 'contact', 'users'], $this->tdbmService->_getRelatedTablesByInheritance('users'));
47
        $this->assertEquals(['person', 'contact', 'users'], $this->tdbmService->_getRelatedTablesByInheritance('person'));
48
    }
49
50
    /**
51
     *
52
     * @throws TDBMException
53
     */
54
    public function testGetPrimaryKeysFromIndexedPrimaryKeysException(): void
55
    {
56
        $this->expectException('TheCodingMachine\TDBM\TDBMException');
57
        $this->tdbmService->_getPrimaryKeysFromIndexedPrimaryKeys('users', [5, 4]);
58
    }
59
60
    /**
61
     *
62
     * @throws TDBMException
63
     */
64
    public function testGetLinkBetweenInheritedTablesExceptions(): void
65
    {
66
        $this->expectException('TheCodingMachine\TDBM\TDBMException');
67
        $this->tdbmService->_getLinkBetweenInheritedTables(['contact', 'country']);
68
    }
69
70
    public function testHashPrimaryKey(): void
71
    {
72
        $reflection = new \ReflectionClass(get_class($this->tdbmService));
73
        $method = $reflection->getMethod('getObjectHash');
74
        $method->setAccessible(true);
75
76
        $result = $method->invokeArgs($this->tdbmService, [
77
            ['id' => 42],
78
        ]);
79
        $this->assertEquals(42, $result);
80
81
        // Check that multiple primary keys are insensitive to column order
82
        $result1 = $method->invokeArgs($this->tdbmService, [
83
            ['id1' => 42, 'id2' => 24],
84
        ]);
85
        $result2 = $method->invokeArgs($this->tdbmService, [
86
            ['id2' => 24, 'id1' => 42],
87
        ]);
88
        $this->assertEquals($result1, $result2);
89
    }
90
91
    public function testInsertAndUpdateAndDelete(): void
92
    {
93
        $object = new TDBMObject('users');
94
        $object->setProperty('login', 'john.doe');
95
        $object->setProperty('country_id', 3);
96
        $object->setProperty('name', 'John Doe', 'person');
97
        $object->setProperty('email', '[email protected]', 'contact');
98
99
        $this->tdbmService->save($object);
100
101
        $this->assertNotEmpty($object->getProperty('id', 'person'));
102
        $this->assertNotEmpty($object->getProperty('id', 'users'));
103
        $this->assertEquals($object->getProperty('id', 'person'), $object->getProperty('id', 'users'));
104
105
        $object->setProperty('country_id', 2, 'users');
106
107
        $this->tdbmService->save($object);
108
109
        $this->tdbmService->delete($object);
110
    }
111
112
    public function testInsertMultipleDataAtOnceInInheritance(): void
113
    {
114
        $object = new TDBMObject();
115
        $object->setProperty('login', 'jane.doe', 'users');
116
        $object->setProperty('name', 'Jane Doe', 'person');
117
        $object->setProperty('country_id', 1, 'users');
118
        $object->setProperty('email', '[email protected]', 'contact');
119
120
        $this->tdbmService->save($object);
121
122
        $this->assertNotEmpty($object->getProperty('id', 'person'));
123
        $this->assertNotEmpty($object->getProperty('id', 'users'));
124
        $this->assertEquals($object->getProperty('id', 'person'), $object->getProperty('id', 'users'));
125
    }
126
127
    public function testCompleteSave(): void
128
    {
129
        $beans = $this->tdbmService->findObjects('users', 'users.login = :login', ['login' => 'jane.doe'], null, [], null, TDBMObject::class);
130
        $jane = $beans[0];
131
        $jane->setProperty('country_id', 2, 'users');
132
133
        $this->tdbmService->completeSave();
134
        $this->assertNotNull($jane->getProperty('id', 'users'));
135
    }
136
137
    public function testCompleteSave2(): void
138
    {
139
        $beans = $this->tdbmService->findObjects('users', 'users.login = :login', ['login' => 'jane.doe'], null, [], null, TDBMObject::class);
140
        $jane = $beans[0];
141
142
        $this->assertEquals(2, $jane->getProperty('country_id', 'users'));
143
    }
144
145
    public function testUpdatePrimaryKey(): void
146
    {
147
        $object = new TDBMObject('rights');
148
        $object->setProperty('label', 'CAN_EDIT_BOUK');
149
150
        $this->tdbmService->save($object);
151
152
        $object->setProperty('label', 'CAN_EDIT_BOOK');
153
154
        $this->tdbmService->save($object);
155
156
        $this->assertSame('CAN_EDIT_BOOK', $object->getProperty('label'));
157
    }
158
159
    /**
160
     *
161
     * @throws TDBMInvalidOperationException
162
     */
163
    public function testCannotDeleteDetachedObjects(): void
164
    {
165
        $this->expectException('TheCodingMachine\TDBM\TDBMInvalidOperationException');
166
        $object = new TDBMObject('rights');
167
        $object->setProperty('label', 'CAN_DELETE');
168
169
        $this->tdbmService->delete($object);
170
    }
171
172
    public function testDeleteNewObject(): void
173
    {
174
        $object = new TDBMObject('rights');
175
        $object->setProperty('label', 'CAN_DELETE');
176
177
        $this->tdbmService->attach($object);
178
179
        $this->tdbmService->delete($object);
180
181
        $exceptionRaised = false;
182
        try {
183
            $this->tdbmService->save($object);
184
        } catch (TDBMInvalidOperationException $e) {
185
            $exceptionRaised = true;
186
        }
187
        $this->assertTrue($exceptionRaised);
188
    }
189
190
    public function testDeleteLoadedObject(): void
191
    {
192
        $object = new TDBMObject('rights');
193
        $object->setProperty('label', 'CAN_DELETE');
194
195
        $this->tdbmService->save($object);
196
197
        $object->setProperty('label', 'CAN_DELETE2');
198
199
        $this->tdbmService->delete($object);
200
201
        // Try to delete a deleted object (this should do nothing)
202
        $this->tdbmService->delete($object);
203
        $this->assertSame(TDBMObjectStateEnum::STATE_DELETED, $object->_getStatus());
204
    }
205
206
    public function testFindObjects(): void
207
    {
208
        /*$magicQuery = new MagicQuery($this->tdbmService->getConnection());
209
        $result = $magicQuery->parse("SELECT DISTINCT users.id, users.login FROM users");
210
        var_dump($result);*/
211
212
        $beans = $this->tdbmService->findObjects('contact', null, [], 'contact.id ASC', [], null, TDBMObject::class);
213
        $beans2 = $this->tdbmService->findObjects('contact', 'contact.id = :id', ['id' => 1], null, [], null, TDBMObject::class);
214
215
        foreach ($beans as $bean) {
216
            $bean1 = $bean;
217
            break;
218
        }
219
220
        foreach ($beans2 as $bean) {
221
            $bean2 = $bean;
222
            break;
223
        }
224
225
        $this->assertTrue($bean1 === $bean2);
0 ignored issues
show
Comprehensibility Best Practice introduced by
The variable $bean1 does not seem to be defined for all execution paths leading up to this point.
Loading history...
Comprehensibility Best Practice introduced by
The variable $bean2 does not seem to be defined for all execution paths leading up to this point.
Loading history...
226
        $this->assertEquals(5, $beans->count());
227
        $this->assertEquals(1, $beans2->count());
228
229
        //$this->assertTrue($beans[0] === $beans2[0]);
230
        //var_dump($beans);
231
    }
232
233
    public function testRawSqlFilterCountriesByUserCount(): void
234
    {
235
        $this->onlyMySql();
236
237
        $sql = <<<SQL
238
SELECT country.*, GROUP_CONCAT(users.id) AS ids
239
FROM country
240
JOIN users ON country.id= users.country_id
241
GROUP BY country.id
242
HAVING COUNT(users.id) > 1;
243
SQL;
244
        /** @var Test\Dao\Bean\CountryBean[]|\Porpaginas\Result $beans */
245
        $beans = $this->tdbmService->findObjectsFromRawSql('country', $sql, [], null, Test\Dao\Bean\CountryBean::class);
0 ignored issues
show
Bug introduced by
The type TheCodingMachine\TDBM\Test\Dao\Bean\CountryBean was not found. Maybe you did not declare it correctly or list all dependencies?

The issue could also be caused by a filter entry in the build configuration. If the path has been excluded in your configuration, e.g. excluded_paths: ["lib/*"], you can move it to the dependency path list as follows:

filter:
    dependency_paths: ["lib/*"]

For further information see https://scrutinizer-ci.com/docs/tools/php/php-scrutinizer/#list-dependency-paths

Loading history...
246
247
        $count = 0;
248
        foreach ($beans as $country) {
249
            $this->assertGreaterThan(1, count($country->getUsers()));
250
            $count++;
251
        }
252
        $this->assertEquals($count, $beans->count());
253
    }
254
255
    public function testRawSqlOrderCountriesByUserCount(): void
256
    {
257
        $this->onlyMySql();
258
259
        $sql = <<<SQL
260
SELECT country.*, GROUP_CONCAT(users.id) AS ids
261
FROM country
262
JOIN users ON country.id= users.country_id
263
GROUP BY country.id
264
ORDER BY COUNT(users.id);
265
SQL;
266
267
        /** @var Test\Dao\Bean\CountryBean[]|\Porpaginas\Result $beans */
268
        $beans = $this->tdbmService->findObjectsFromRawSql('country', $sql, [], null, Test\Dao\Bean\CountryBean::class);
269
270
        $count = 0;
271
        foreach ($beans as $country) {
272
            $count++;
273
        }
274
        $this->assertEquals($count, $beans->count());
275
276
        for ($i = 1; $i < count($beans); $i++) {
0 ignored issues
show
Performance Best Practice introduced by
It seems like you are calling the size function count() as part of the test condition. You might want to compute the size beforehand, and not on each iteration.

If the size of the collection does not change during the iteration, it is generally a good practice to compute it beforehand, and not on each iteration:

for ($i=0; $i<count($array); $i++) { // calls count() on each iteration
}

// Better
for ($i=0, $c=count($array); $i<$c; $i++) { // calls count() just once
}
Loading history...
277
            $this->assertLessThanOrEqual(count($beans[$i]->getUsers()), count($beans[$i - 1]->getUsers()));
278
        }
279
    }
280
281
    public function testRawSqlOrderUsersByCustomRoleOrder(): void
282
    {
283
        $this->onlyMySql();
284
285
        $sql = <<<SQL
286
SELECT `person`.*, `contact`.*, `users`.*
287
FROM `contact`
288
JOIN `users` ON `users`.`id` = `contact`.`id`
289
JOIN `person` ON `person`.`id` = `users`.`id`
290
JOIN `users_roles` ON users.id = users_roles.user_id
291
JOIN `roles` ON roles.id = users_roles.role_id
292
GROUP BY users.id
293
ORDER BY MAX(IF(roles.name = 'Admins', 3, IF(roles.name = 'Writers', 2, IF(roles.name = 'Singers', 1, 0)))) DESC
294
SQL;
295
296
        /** @var Test\Dao\Bean\UserBean[]|\Porpaginas\Result $beans */
297
        $beans = $this->tdbmService->findObjectsFromRawSql('contact', $sql, [], null, Test\Dao\Bean\UserBean::class);
0 ignored issues
show
Bug introduced by
The type TheCodingMachine\TDBM\Test\Dao\Bean\UserBean was not found. Maybe you did not declare it correctly or list all dependencies?

The issue could also be caused by a filter entry in the build configuration. If the path has been excluded in your configuration, e.g. excluded_paths: ["lib/*"], you can move it to the dependency path list as follows:

filter:
    dependency_paths: ["lib/*"]

For further information see https://scrutinizer-ci.com/docs/tools/php/php-scrutinizer/#list-dependency-paths

Loading history...
298
299
        function getCustomOrder(Test\Dao\Bean\UserBean $contact)
300
        {
301
            $max = 0;
302
            foreach ($contact->getRoles() as $role) {
303
                $max = max($max, [
304
                    'Admins' => 3,
305
                    'Writers' => 2,
306
                    'Singers' => 1,
307
                ][$role->getName()]);
308
            }
309
            return $max;
310
        }
311
312
        $this->assertCount(4, $beans);
313
314
        for ($i = 1; $i < count($beans); $i++) {
0 ignored issues
show
Performance Best Practice introduced by
It seems like you are calling the size function count() as part of the test condition. You might want to compute the size beforehand, and not on each iteration.

If the size of the collection does not change during the iteration, it is generally a good practice to compute it beforehand, and not on each iteration:

for ($i=0; $i<count($array); $i++) { // calls count() on each iteration
}

// Better
for ($i=0, $c=count($array); $i<$c; $i++) { // calls count() just once
}
Loading history...
315
            $this->assertGreaterThanOrEqual(getCustomOrder($beans[$i]), getCustomOrder($beans[$i - 1]), 'Beans order does not comply with expected result.');
316
        }
317
    }
318
319
    public function testArrayAccess(): void
320
    {
321
        $beans = $this->tdbmService->findObjects('contact', null, [], 'contact.id ASC', [], null, TDBMObject::class);
322
323
        $this->assertTrue(isset($beans[0]));
324
        $this->assertFalse(isset($beans[42]));
325
        $this->assertEquals(1, $beans[0]->getProperty('id', 'person'));
326
327
        $result1 = [];
328
        foreach ($beans as $bean) {
329
            $result1[] = $bean;
330
        }
331
332
        $result2 = [];
333
        foreach ($beans as $bean) {
334
            $result2[] = $bean;
335
        }
336
337
        $this->assertEquals($result1, $result2);
338
        $this->assertTrue($result1[0] === $result2[0]);
339
    }
340
341
    /**
342
     *
343
     * @throws TDBMInvalidOffsetException
344
     */
345
    public function testArrayAccessException(): void
346
    {
347
        $this->expectException('TheCodingMachine\TDBM\TDBMInvalidOffsetException');
348
        $beans = $this->tdbmService->findObjects('contact', null, [], 'contact.id ASC', [], null, TDBMObject::class);
349
350
        $beans[-1];
351
    }
352
353
    /**
354
     *
355
     * @throws TDBMInvalidOffsetException
356
     */
357
    public function testArrayAccessException2(): void
358
    {
359
        $this->expectException('TheCodingMachine\TDBM\TDBMInvalidOffsetException');
360
        $beans = $this->tdbmService->findObjects('contact', null, [], 'contact.id ASC', [], null, TDBMObject::class);
361
362
        $beans['foo'];
363
    }
364
365
    /**
366
     *
367
     * @throws TDBMException
368
     */
369
    public function testBeanGetException(): void
370
    {
371
        $this->expectException('TheCodingMachine\TDBM\TDBMException');
372
        $beans = $this->tdbmService->findObjects('contact', null, [], 'contact.id ASC', [], null, TDBMObject::class);
373
        $bean = $beans[0];
374
375
        // we don't specify the table on inheritance table => exception.
376
        $bean->getProperty('id');
377
    }
378
379
    /**
380
     *
381
     * @throws TDBMException
382
     */
383
    public function testBeanSetException(): void
384
    {
385
        $this->expectException('TheCodingMachine\TDBM\TDBMException');
386
        $beans = $this->tdbmService->findObjects('contact', null, [], 'contact.id ASC', [], null, TDBMObject::class);
387
        $bean = $beans[0];
388
389
        // we don't specify the table on inheritance table => exception.
390
        $bean->setProperty('name', 'foo');
391
    }
392
393
    public function testTake(): void
394
    {
395
        $beans = $this->tdbmService->findObjects('contact', null, [], 'contact.id ASC', [], null, TDBMObject::class);
396
397
        $page = $beans->take(0, 2);
398
399
        $this->assertEquals(2, $page->count());
400
401
        $results = [];
402
        foreach ($page as $result) {
403
            $results[] = $result;
404
        }
405
        $this->assertCount(2, $results);
406
407
        $this->assertEquals(5, $page->totalCount());
408
409
        $page = $beans->take(1, 1);
410
411
        $this->assertEquals(1, $page->count());
412
413
        $resultArray = $page->toArray();
414
        $this->assertCount(1, $resultArray);
415
        $this->assertTrue($resultArray[0] === $page[0]);
416
        // Test page isset
417
        $this->assertTrue(isset($page[0]));
418
    }
419
420
    public function testTakeInCursorMode(): void
421
    {
422
        $beans = $this->tdbmService->findObjects('contact', null, [], 'contact.id ASC', [], TDBMService::MODE_CURSOR, TDBMObject::class);
423
424
        $page = $beans->take(0, 2);
425
426
        $this->assertEquals(2, $page->count());
427
        $this->assertEquals(0, $page->getCurrentOffset());
428
        $this->assertEquals(2, $page->getCurrentLimit());
429
        $this->assertEquals(1, $page->getCurrentPage());
430
431
        $results = [];
432
        foreach ($page as $result) {
433
            $results[] = $result;
434
        }
435
        $this->assertCount(2, $results);
436
437
        $this->assertEquals(5, $page->totalCount());
438
439
        $page = $beans->take(1, 1);
440
        $this->assertEquals(1, $page->getCurrentOffset());
441
        $this->assertEquals(1, $page->getCurrentLimit());
442
        $this->assertEquals(2, $page->getCurrentPage());
443
444
        $this->assertEquals(1, $page->count());
445
    }
446
447
    public function testMap(): void
448
    {
449
        $beans = $this->tdbmService->findObjects('person', null, [], 'person.id ASC', [], null, TDBMObject::class);
450
451
        $results = $beans->map(function ($item) {
452
            return $item->getProperty('id', 'person');
453
        })->toArray();
454
455
        $this->assertEquals([1, 2, 3, 4, 6], $results);
456
457
        // Same test with page
458
        $page = $beans->take(0, 2);
459
460
        $results = $page->map(function ($item) {
461
            return $item->getProperty('id', 'person');
462
        })->toArray();
463
464
        $this->assertEquals([1, 2], $results);
465
    }
466
467
    /**
468
     *
469
     * @throws TDBMException
470
     */
471
    public function testUnsetException(): void
472
    {
473
        $this->expectException('TheCodingMachine\TDBM\TDBMException');
474
        $beans = $this->tdbmService->findObjects('contact', null, [], 'contact.id ASC', [], null, TDBMObject::class);
475
476
        unset($beans[0]);
477
    }
478
479
    /**
480
     *
481
     * @throws TDBMException
482
     */
483
    public function testSetException(): void
484
    {
485
        $this->expectException('TheCodingMachine\TDBM\TDBMException');
486
        $beans = $this->tdbmService->findObjects('contact', null, [], 'contact.id ASC', [], null, TDBMObject::class);
487
488
        $beans[0] = 'foo';
489
    }
490
491
    /**
492
     *
493
     * @throws TDBMException
494
     */
495
    public function testPageUnsetException(): void
496
    {
497
        $this->expectException('TheCodingMachine\TDBM\TDBMException');
498
        $beans = $this->tdbmService->findObjects('contact', null, [], 'contact.id ASC', [], null, TDBMObject::class);
499
        $page = $beans->take(0, 1);
500
        unset($page[0]);
501
    }
502
503
    /**
504
     *
505
     * @throws TDBMException
506
     */
507
    public function testPageSetException(): void
508
    {
509
        $this->expectException('TheCodingMachine\TDBM\TDBMException');
510
        $beans = $this->tdbmService->findObjects('contact', null, [], 'contact.id ASC', [], null, TDBMObject::class);
511
        $page = $beans->take(0, 1);
512
        $page[0] = 'foo';
513
    }
514
515
    public function testToArray(): void
516
    {
517
        $beans = $this->tdbmService->findObjects('contact', 'contact.id = :id', ['id' => 1], null, [], null, TDBMObject::class);
518
519
        $beanArray = $beans->toArray();
520
521
        $this->assertCount(1, $beanArray);
522
        $this->assertEquals(1, $beanArray[0]->getProperty('id', 'contact'));
523
    }
524
525
    public function testCursorMode(): void
526
    {
527
        $beans = $this->tdbmService->findObjects('contact', 'contact.id = :id', ['id' => 1], null, [], TDBMService::MODE_CURSOR, TDBMObject::class);
528
529
        $this->assertInstanceOf('\\TheCodingMachine\\TDBM\\ResultIterator', $beans);
530
531
        $result = [];
532
        foreach ($beans as $bean) {
533
            $result[] = $bean;
534
        }
535
536
        $this->assertCount(1, $result);
537
538
        // In cursor mode, access by array causes an exception.
539
        $exceptionTriggered = false;
540
        try {
541
            $beans[0];
542
        } catch (TDBMInvalidOperationException $e) {
543
            $exceptionTriggered = true;
544
        }
545
        $this->assertTrue($exceptionTriggered);
546
547
        $exceptionTriggered = false;
548
        try {
549
            isset($beans[0]);
550
        } catch (TDBMInvalidOperationException $e) {
551
            $exceptionTriggered = true;
552
        }
553
        $this->assertTrue($exceptionTriggered);
554
    }
555
556
    public function testSetFetchMode(): void
557
    {
558
        $this->tdbmService->setFetchMode(TDBMService::MODE_CURSOR);
559
        $beans = $this->tdbmService->findObjects('contact', 'contact.id = :id', ['id' => 1], null, [], null, TDBMObject::class);
560
561
        $this->assertInstanceOf('\\TheCodingMachine\\TDBM\\ResultIterator', $beans);
562
563
        // In cursor mode, access by array causes an exception.
564
        $exceptionTriggered = false;
565
        try {
566
            $beans[0];
567
        } catch (TDBMInvalidOperationException $e) {
568
            $exceptionTriggered = true;
569
        }
570
        $this->assertTrue($exceptionTriggered);
571
    }
572
573
    /**
574
     *
575
     * @throws TDBMException
576
     */
577
    public function testInvalidSetFetchMode(): void
578
    {
579
        $this->expectException('TheCodingMachine\TDBM\TDBMException');
580
        $this->tdbmService->setFetchMode(99);
581
    }
582
583
    /**
584
     *
585
     * @throws TDBMException
586
     */
587
    public function testCursorModeException(): void
588
    {
589
        $this->expectException('TheCodingMachine\TDBM\TDBMException');
590
        $beans = $this->tdbmService->findObjects('contact', 'contact.id = :id', ['id' => 1], null, [], 99);
0 ignored issues
show
Unused Code introduced by
The assignment to $beans is dead and can be removed.
Loading history...
591
    }
592
593
    /**
594
     *
595
     * @throws TDBMException
596
     */
597
    public function testTableNameException(): void
598
    {
599
        $this->expectException('TheCodingMachine\TDBM\TDBMException');
600
        $beans = $this->tdbmService->findObjects('foo bar');
0 ignored issues
show
Unused Code introduced by
The assignment to $beans is dead and can be removed.
Loading history...
601
    }
602
603
    public function testLinkedTableFetch(): void
604
    {
605
        $beans = $this->tdbmService->findObjects('contact', 'contact.id = :id', ['id' => 1], null, ['country'], null, TDBMObject::class);
606
        $this->assertInstanceOf(ResultIterator::class, $beans);
607
    }
608
609
    public function testFindObject(): void
610
    {
611
        $bean = $this->tdbmService->findObject('contact', 'contact.id = :id', ['id' => -42], [], TDBMObject::class);
612
        $this->assertNull($bean);
613
    }
614
615
    /**
616
     *
617
     * @throws NoBeanFoundException
618
     */
619
    public function testFindObjectOrFail(): void
620
    {
621
        $this->expectException('TheCodingMachine\TDBM\NoBeanFoundException');
622
        $bean = $this->tdbmService->findObjectOrFail('contact', 'contact.id = :id', ['id' => -42], [], TDBMObject::class);
0 ignored issues
show
Unused Code introduced by
The assignment to $bean is dead and can be removed.
Loading history...
623
    }
624
625
    /**
626
     * @throws NoBeanFoundException
627
     */
628
    public function testFindObjectByPkException(): void
629
    {
630
        $this->expectException(NoBeanFoundException::class);
631
        $this->expectExceptionMessage("No result found for query on table 'contact' for 'id' = -42");
632
        $bean = $this->tdbmService->findObjectByPk('contact', ['id' => -42], [], false, TDBMObject::class);
0 ignored issues
show
Unused Code introduced by
The assignment to $bean is dead and can be removed.
Loading history...
633
    }
634
635
    /**
636
     * @throws DuplicateRowException
637
     */
638
    public function testFindObjectDuplicateRow(): void
639
    {
640
        $this->expectException(DuplicateRowException::class);
641
642
        $bean = $this->tdbmService->findObject('contact');
0 ignored issues
show
Unused Code introduced by
The assignment to $bean is dead and can be removed.
Loading history...
643
    }
644
645
    public function testFindObjectsByBean(): void
646
    {
647
        $countryBean = $this->tdbmService->findObject('country', 'id = :id', ['id' => 1], [], TDBMObject::class);
648
649
        $users = $this->tdbmService->findObjects('users', $countryBean, [], null, [], null, TDBMObject::class);
0 ignored issues
show
Bug introduced by
It seems like $countryBean can also be of type TheCodingMachine\TDBM\AbstractTDBMObject; however, parameter $filter of TheCodingMachine\TDBM\TDBMService::findObjects() does only seem to accept array|null|string, maybe add an additional type check? ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-type  annotation

649
        $users = $this->tdbmService->findObjects('users', /** @scrutinizer ignore-type */ $countryBean, [], null, [], null, TDBMObject::class);
Loading history...
650
        $this->assertCount(1, $users);
651
        $this->assertEquals('jean.dupont', $users[0]->getProperty('login', 'users'));
652
    }
653
654
    /**
655
     *
656
     * @throws TDBMException
657
     * @throws TDBMInvalidOperationException
658
     */
659
    public function testBeanWithoutStatus(): void
660
    {
661
        $this->expectException('TheCodingMachine\TDBM\TDBMException');
662
        $reflectionClass = new \ReflectionClass(TDBMObject::class);
663
        $object = $reflectionClass->newInstanceWithoutConstructor();
664
        $object->_getStatus();
665
    }
666
667
    public function testFindObjectsFromSql(): void
668
    {
669
        $roles = $this->tdbmService->findObjectsFromSql(
670
            'roles',
671
            'roles JOIN roles_rights ON roles.id = roles_rights.role_id JOIN rights ON rights.label = roles_rights.right_label',
672
            'rights.label = :right',
673
            array('right' => 'CAN_SING'),
674
            'roles.name DESC'
675
        );
676
        $this->assertCount(2, $roles);
677
        $this->assertInstanceOf(AbstractTDBMObject::class, $roles[0]);
678
    }
679
680
    /**
681
     *
682
     * @throws TDBMException
683
     */
684
    public function testFindObjectsFromSqlBadTableName(): void
685
    {
686
        $this->expectException(TDBMException::class);
687
        $this->tdbmService->findObjectsFromSql(
688
            '#{azerty',
689
            'roles JOIN roles_rights ON roles.id = roles_rights.role_id JOIN rights ON rights.label = roles_rights.right_label',
690
            'rights.label = :right',
691
            array('right' => 'CAN_SING'),
692
            'name DESC'
693
        );
694
    }
695
696
    /**
697
     *
698
     * @throws TDBMException
699
     */
700
    public function testFindObjectsFromSqlGroupBy(): void
701
    {
702
        $this->expectException(TDBMException::class);
703
        $roles = $this->tdbmService->findObjectsFromSql(
704
            'roles',
705
            'roles JOIN roles_rights ON roles.id = roles_rights.role_id JOIN rights ON rights.label = roles_rights.right_label',
706
            'rights.label = :right GROUP BY roles.name',
707
            array('right' => 'CAN_SING'),
708
            'name DESC'
709
        );
710
        $role = $roles[0];
0 ignored issues
show
Unused Code introduced by
The assignment to $role is dead and can be removed.
Loading history...
711
    }
712
713
    /**
714
     *
715
     * @throws TDBMException
716
     */
717
    public function testFindObjectsFromRawSqlBadTableName(): void
718
    {
719
        $this->expectException(TDBMException::class);
720
        $this->tdbmService->findObjectsFromRawSql(
721
            '#{azerty',
722
            'roles JOIN roles_rights ON roles.id = roles_rights.role_id JOIN rights ON rights.label = roles_rights.right_label WHERE rights.label = :right',
723
            array('right' => 'CAN_SING')
724
        );
725
    }
726
727
    public function testFindObjectFromSql(): void
728
    {
729
        $role = $this->tdbmService->findObjectFromSql(
730
            'roles',
731
            'roles JOIN roles_rights ON roles.id = roles_rights.role_id JOIN rights ON rights.label = roles_rights.right_label',
732
            'rights.label = :right AND name = :name',
733
            array('right' => 'CAN_SING', 'name' => 'Singers')
734
        );
735
        $this->assertInstanceOf(AbstractTDBMObject::class, $role);
736
    }
737
738
    /**
739
     * @throws DuplicateRowException
740
     */
741
    public function testFindObjectFromSqlException(): void
742
    {
743
        $this->expectException(DuplicateRowException::class);
744
        $this->expectExceptionMessage('Error while querying an object in table \'roles\': More than 1 row have been returned, but we should have received at most one for filter "rights.label = \'CAN_SING\'".');
745
        $this->tdbmService->findObjectFromSql(
746
            'roles',
747
            'roles JOIN roles_rights ON roles.id = roles_rights.role_id JOIN rights ON rights.label = roles_rights.right_label',
748
            'rights.label = :right',
749
            array('right' => 'CAN_SING')
750
        );
751
    }
752
753
    public function testFindObjectsFromSqlHierarchyDown(): void
754
    {
755
        $users = $this->tdbmService->findObjectsFromSql(
756
            'person',
757
            'person',
758
            'name LIKE :name OR name LIKE :name2',
759
            array('name' => 'Robert Marley', 'name2' => 'Bill Shakespeare'),
760
            null,
761
            null,
762
            TDBMObject::class
763
        );
764
        $this->assertCount(2, $users);
765
        $this->assertSame('robert.marley', $users[0]->getProperty('login', 'users'));
766
    }
767
768
    public function testFindObjectsFromSqlHierarchyUp(): void
769
    {
770
        $users = $this->tdbmService->findObjectsFromSql(
771
            'users',
772
            'users',
773
            'login LIKE :login OR login LIKE :login2',
774
            array('login' => 'robert.marley', 'login2' => 'bill.shakespeare'),
775
            'users.login DESC',
776
            null,
777
            TDBMObject::class
778
        );
779
        $this->assertCount(2, $users);
780
        $this->assertSame('Robert Marley', $users[0]->getProperty('name', 'person'));
781
    }
782
783
    public function testLogger(): void
784
    {
785
        $arrayLogger = new ArrayLogger();
786
        $tdbmService = new TDBMService(new Configuration('TheCodingMachine\\TDBM\\Test\\Dao\\Bean', 'TheCodingMachine\\TDBM\\Test\\Dao', self::getConnection(), $this->getNamingStrategy(), null, null, $arrayLogger));
787
788
        $tdbmService->setLogLevel(LogLevel::DEBUG);
789
        $beans = $tdbmService->findObjects('contact', null, [], 'contact.id ASC', [], null, TDBMObject::class);
790
        $beans->first();
791
792
        $this->assertNotEmpty($arrayLogger->get());
793
    }
794
795
    public function testFindObjectsCountWithOneToManyLink(): void
796
    {
797
        $countries = $this->tdbmService->findObjects('country', "users.status = 'on' OR users.status = 'off'");
798
799
        $this->assertEquals(3, $countries->count());
800
    }
801
802
    public function testFindObjectsFromSqlCountWithOneToManyLink(): void
803
    {
804
        $countries = $this->tdbmService->findObjectsFromSql('country', 'country LEFT JOIN users ON country.id = users.country_id', "users.status = 'on' OR users.status = 'off'");
805
806
        $this->assertEquals(3, $countries->count());
807
    }
808
809
    public function testBuildFilterFromFilterBagIterator(): void
810
    {
811
        $tdbmService = new TDBMService(new Configuration('TheCodingMachine\\TDBM\\Test\\Dao\\Bean', 'TheCodingMachine\\TDBM\\Test\\Dao', self::getConnection(), $this->getNamingStrategy(), null, null, new NullLogger()));
812
813
        [$sql, $parameters, $counter] = $tdbmService->buildFilterFromFilterBag(new \ArrayIterator(['id' => 1]), self::getConnection()->getDatabasePlatform());
814
        $this->assertRegExp('/\(.id. = :tdbmparam1\)/', $sql);
815
        $this->assertEquals($parameters['tdbmparam1'], 1);
816
    }
817
818
    public function testFindObjectsMethodWithoutResultIteratorClass(): void
819
    {
820
        $this->expectException(TDBMInvalidArgumentException::class);
821
        $this->expectExceptionMessageRegExp('/^\$resultIteratorClass should be a `' . preg_quote(ResultIterator::class, '/') . '`. `(.*)` provided\.$/');
822
        $tdbmService = new TDBMService(new Configuration('TheCodingMachine\\TDBM\\Test\\Dao\\Bean', 'TheCodingMachine\\TDBM\\Test\\Dao', self::getConnection(), $this->getNamingStrategy(), null, null, new NullLogger()));
823
824
        $tdbmService->findObjects('', null, [], null, [], null, null, self::class);
825
    }
826
827
    public function testFindObjectsFromSqlMethodWithoutResultIteratorClass(): void
828
    {
829
        $this->expectException(TDBMInvalidArgumentException::class);
830
        $this->expectExceptionMessageRegExp('/^\$resultIteratorClass should be a `' . preg_quote(ResultIterator::class, '/') . '`. `(.*)` provided\.$/');
831
        $tdbmService = new TDBMService(new Configuration('TheCodingMachine\\TDBM\\Test\\Dao\\Bean', 'TheCodingMachine\\TDBM\\Test\\Dao', self::getConnection(), $this->getNamingStrategy(), null, null, new NullLogger()));
832
833
        $tdbmService->findObjectsFromSql('', '', null, [], null, null, null, self::class);
834
    }
835
836
    public function testFindObjectsFromRawSqlMethodWithoutResultIteratorClass(): void
837
    {
838
        $this->expectException(TDBMInvalidArgumentException::class);
839
        $this->expectExceptionMessageRegExp('/^\$resultIteratorClass should be a `' . preg_quote(ResultIterator::class, '/') . '`. `(.*)` provided\.$/');
840
        $tdbmService = new TDBMService(new Configuration('TheCodingMachine\\TDBM\\Test\\Dao\\Bean', 'TheCodingMachine\\TDBM\\Test\\Dao', self::getConnection(), $this->getNamingStrategy(), null, null, new NullLogger()));
841
842
        $tdbmService->findObjectsFromRawSql('', '', [], null, null, null, self::class);
843
    }
844
}
845