Issues (291)

tests/TDBMServiceTest.php (2 issues)

1
<?php
2
3
declare(strict_types=1);
4
5
/*
6
 Copyright (C) 2006-2014 David Négrier - THE CODING MACHINE
7
8
This program is free software; you can redistribute it and/or modify
9
it under the terms of the GNU General Public License as published by
10
the Free Software Foundation; either version 2 of the License, or
11
(at your option) any later version.
12
13
This program is distributed in the hope that it will be useful,
14
but WITHOUT ANY WARRANTY; without even the implied warranty of
15
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
16
GNU General Public License for more details.
17
18
You should have received a copy of the GNU General Public License
19
along with this program; if not, write to the Free Software
20
Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
21
*/
22
23
namespace TheCodingMachine\TDBM;
24
25
use Psr\Log\LogLevel;
26
use Psr\Log\NullLogger;
27
use TheCodingMachine\TDBM\Test\Dao\Bean\ContactBean;
28
use TheCodingMachine\TDBM\Test\ResultIterator\ContactResultIterator;
29
use TheCodingMachine\TDBM\Test\ResultIterator\CountryResultIterator;
30
use TheCodingMachine\TDBM\Test\ResultIterator\PersonResultIterator;
31
use TheCodingMachine\TDBM\Test\ResultIterator\RoleResultIterator;
32
use TheCodingMachine\TDBM\Test\ResultIterator\UserResultIterator;
33
use Wa72\SimpleLogger\ArrayLogger;
34
35
class TDBMServiceTest extends TDBMAbstractServiceTest
36
{
37
    public function testGetLinkBetweenInheritedTables(): void
38
    {
39
        $this->assertEquals(['users', 'contact', 'person'], $this->tdbmService->_getLinkBetweenInheritedTables(['contact', 'users']));
40
        $this->assertEquals(['users', 'contact', 'person'], $this->tdbmService->_getLinkBetweenInheritedTables(['users', 'contact']));
41
        $this->assertEquals(['contact', 'person'], $this->tdbmService->_getLinkBetweenInheritedTables(['person', 'contact']));
42
        $this->assertEquals(['users', 'contact', 'person'], $this->tdbmService->_getLinkBetweenInheritedTables(['users']));
43
        $this->assertEquals(['person'], $this->tdbmService->_getLinkBetweenInheritedTables(['person']));
44
    }
45
46
    public function testGetRelatedTablesByInheritance(): void
47
    {
48
        $contactRelatedTables = $this->tdbmService->_getRelatedTablesByInheritance('contact');
49
        $this->assertCount(3, $contactRelatedTables);
50
        $this->assertContains('users', $contactRelatedTables);
51
        $this->assertContains('contact', $contactRelatedTables);
52
        $this->assertContains('person', $contactRelatedTables);
53
        $this->assertEquals(['person', 'contact', 'users'], $this->tdbmService->_getRelatedTablesByInheritance('users'));
54
        $this->assertEquals(['person', 'contact', 'users'], $this->tdbmService->_getRelatedTablesByInheritance('person'));
55
    }
56
57
    /**
58
     *
59
     * @throws TDBMException
60
     */
61
    public function testGetPrimaryKeysFromIndexedPrimaryKeysException(): void
62
    {
63
        $this->expectException('TheCodingMachine\TDBM\TDBMException');
64
        $this->tdbmService->_getPrimaryKeysFromIndexedPrimaryKeys('users', [5, 4]);
65
    }
66
67
    /**
68
     *
69
     * @throws TDBMException
70
     */
71
    public function testGetLinkBetweenInheritedTablesExceptions(): void
72
    {
73
        $this->expectException('TheCodingMachine\TDBM\TDBMException');
74
        $this->tdbmService->_getLinkBetweenInheritedTables(['contact', 'country']);
75
    }
76
77
    public function testHashPrimaryKey(): void
78
    {
79
        $reflection = new \ReflectionClass(get_class($this->tdbmService));
80
        $method = $reflection->getMethod('getObjectHash');
81
        $method->setAccessible(true);
82
83
        $result = $method->invokeArgs($this->tdbmService, [
84
            ['id' => 42],
85
        ]);
86
        $this->assertEquals(42, $result);
87
88
        // Check that multiple primary keys are insensitive to column order
89
        $result1 = $method->invokeArgs($this->tdbmService, [
90
            ['id1' => 42, 'id2' => 24],
91
        ]);
92
        $result2 = $method->invokeArgs($this->tdbmService, [
93
            ['id2' => 24, 'id1' => 42],
94
        ]);
95
        $this->assertEquals($result1, $result2);
96
    }
97
98
    public function testInsertAndUpdateAndDelete(): void
99
    {
100
        $object = new TDBMObject('users');
101
        $object->setProperty('login', 'john.doe');
102
        $object->setProperty('country_id', 3);
103
        $object->setProperty('name', 'John Doe', 'person');
104
        $object->setProperty('email', '[email protected]', 'contact');
105
106
        $this->tdbmService->save($object);
107
108
        $this->assertNotEmpty($object->getProperty('id', 'person'));
109
        $this->assertNotEmpty($object->getProperty('id', 'users'));
110
        $this->assertEquals($object->getProperty('id', 'person'), $object->getProperty('id', 'users'));
111
112
        $object->setProperty('country_id', 2, 'users');
113
114
        $this->tdbmService->save($object);
115
116
        $this->tdbmService->delete($object);
117
    }
118
119
    public function testInsertMultipleDataAtOnceInInheritance(): void
120
    {
121
        $object = new TDBMObject();
122
        $object->setProperty('login', 'jane.doe', 'users');
123
        $object->setProperty('name', 'Jane Doe', 'person');
124
        $object->setProperty('country_id', 1, 'users');
125
        $object->setProperty('email', '[email protected]', 'contact');
126
127
        $this->tdbmService->save($object);
128
129
        $this->assertNotEmpty($object->getProperty('id', 'person'));
130
        $this->assertNotEmpty($object->getProperty('id', 'users'));
131
        $this->assertEquals($object->getProperty('id', 'person'), $object->getProperty('id', 'users'));
132
    }
133
134
    public function testCompleteSave(): void
135
    {
136
        $beans = $this->tdbmService->findObjects('users', 'users.login = :login', ['login' => 'jane.doe'], null, [], null, TDBMObject::class, ResultIterator::class);
137
        $jane = $beans[0];
138
        $jane->setProperty('country_id', 2, 'users');
139
140
        $this->tdbmService->completeSave();
141
        $this->assertNotNull($jane->getProperty('id', 'users'));
142
    }
143
144
    public function testCompleteSave2(): void
145
    {
146
        $beans = $this->tdbmService->findObjects('users', 'users.login = :login', ['login' => 'jane.doe'], null, [], null, TDBMObject::class, ResultIterator::class);
147
        $jane = $beans[0];
148
149
        $this->assertEquals(2, $jane->getProperty('country_id', 'users'));
150
    }
151
152
    public function testUpdatePrimaryKey(): void
153
    {
154
        $object = new TDBMObject('rights');
155
        $object->setProperty('label', 'CAN_EDIT_BOUK');
156
157
        $this->tdbmService->save($object);
158
159
        $object->setProperty('label', 'CAN_EDIT_BOOK');
160
161
        $this->tdbmService->save($object);
162
163
        $this->assertSame('CAN_EDIT_BOOK', $object->getProperty('label'));
164
    }
165
166
    /**
167
     *
168
     * @throws TDBMInvalidOperationException
169
     */
170
    public function testCannotDeleteDetachedObjects(): void
171
    {
172
        $this->expectException('TheCodingMachine\TDBM\TDBMInvalidOperationException');
173
        $object = new TDBMObject('rights');
174
        $object->setProperty('label', 'CAN_DELETE');
175
176
        $this->tdbmService->delete($object);
177
    }
178
179
    public function testDeleteNewObject(): void
180
    {
181
        $object = new TDBMObject('rights');
182
        $object->setProperty('label', 'CAN_DELETE');
183
184
        $this->tdbmService->attach($object);
185
186
        $this->tdbmService->delete($object);
187
188
        $exceptionRaised = false;
189
        try {
190
            $this->tdbmService->save($object);
191
        } catch (TDBMInvalidOperationException $e) {
192
            $exceptionRaised = true;
193
        }
194
        $this->assertTrue($exceptionRaised);
195
    }
196
197
    public function testDeleteLoadedObject(): void
198
    {
199
        $object = new TDBMObject('rights');
200
        $object->setProperty('label', 'CAN_DELETE');
201
202
        $this->tdbmService->save($object);
203
204
        $object->setProperty('label', 'CAN_DELETE2');
205
206
        $this->tdbmService->delete($object);
207
208
        // Try to delete a deleted object (this should do nothing)
209
        $this->tdbmService->delete($object);
210
        $this->assertSame(TDBMObjectStateEnum::STATE_DELETED, $object->_getStatus());
211
    }
212
213
    public function testFindObjects(): void
214
    {
215
        /*$magicQuery = new MagicQuery($this->tdbmService->getConnection());
216
        $result = $magicQuery->parse("SELECT DISTINCT users.id, users.login FROM users");
217
        var_dump($result);*/
218
219
        $beans = $this->tdbmService->findObjects('contact', null, [], 'contact.id ASC', [], null, TDBMObject::class, ContactResultIterator::class);
220
        $beans2 = $this->tdbmService->findObjects('contact', 'contact.id = :id', ['id' => 1], null, [], null, TDBMObject::class, ContactResultIterator::class);
221
222
        foreach ($beans as $bean) {
223
            $bean1 = $bean;
224
            break;
225
        }
226
227
        foreach ($beans2 as $bean) {
228
            $bean2 = $bean;
229
            break;
230
        }
231
232
        $this->assertTrue($bean1 === $bean2);
0 ignored issues
show
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...
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...
233
        $this->assertEquals(5, $beans->count());
234
        $this->assertEquals(1, $beans2->count());
235
236
        //$this->assertTrue($beans[0] === $beans2[0]);
237
        //var_dump($beans);
238
    }
239
240
    public function testRawSqlFilterCountriesByUserCount(): void
241
    {
242
        $this->onlyMySql();
243
244
        $sql = <<<SQL
245
SELECT country.*, GROUP_CONCAT(users.id) AS ids
246
FROM country
247
JOIN users ON country.id= users.country_id
248
GROUP BY country.id
249
HAVING COUNT(users.id) > 1;
250
SQL;
251
        /** @var Test\Dao\Bean\CountryBean[]|ResultInterface $beans */
252
        $beans = $this->tdbmService->findObjectsFromRawSql('country', $sql, [], null, Test\Dao\Bean\CountryBean::class, null, CountryResultIterator::class);
253
254
        $count = 0;
255
        foreach ($beans as $country) {
256
            $this->assertGreaterThan(1, count($country->getUsers()));
257
            $count++;
258
        }
259
        $this->assertEquals($count, $beans->count());
260
    }
261
262
    public function testRawSqlOrderCountriesByUserCount(): void
263
    {
264
        $this->onlyMySql();
265
266
        $sql = <<<SQL
267
SELECT country.*, GROUP_CONCAT(users.id) AS ids
268
FROM country
269
JOIN users ON country.id= users.country_id
270
GROUP BY country.id
271
ORDER BY COUNT(users.id);
272
SQL;
273
274
        /** @var Test\Dao\Bean\CountryBean[]|ResultInterface $beans */
275
        $beans = $this->tdbmService->findObjectsFromRawSql('country', $sql, [], null, Test\Dao\Bean\CountryBean::class, null, CountryResultIterator::class);
276
277
        $count = 0;
278
        foreach ($beans as $country) {
279
            $count++;
280
        }
281
        $this->assertEquals($count, $beans->count());
282
283
        for ($i = 1; $i < count($beans); $i++) {
284
            $this->assertLessThanOrEqual(count($beans[$i]->getUsers()), count($beans[$i - 1]->getUsers()));
285
        }
286
    }
287
288
    public function testRawSqlOrderUsersByCustomRoleOrder(): void
289
    {
290
        $this->onlyMySql();
291
292
        $sql = <<<SQL
293
SELECT `person`.*, `contact`.*, `users`.*
294
FROM `contact`
295
JOIN `users` ON `users`.`id` = `contact`.`id`
296
JOIN `person` ON `person`.`id` = `users`.`id`
297
JOIN `users_roles` ON users.id = users_roles.user_id
298
JOIN `roles` ON roles.id = users_roles.role_id
299
GROUP BY users.id
300
ORDER BY MAX(IF(roles.name = 'Admins', 3, IF(roles.name = 'Writers', 2, IF(roles.name = 'Singers', 1, 0)))) DESC
301
SQL;
302
303
        /** @var Test\Dao\Bean\UserBean[]|ResultInterface $beans */
304
        $beans = $this->tdbmService->findObjectsFromRawSql('contact', $sql, [], null, Test\Dao\Bean\UserBean::class, null, UserResultIterator::class);
305
306
        function getCustomOrder(Test\Dao\Bean\UserBean $contact)
307
        {
308
            $max = 0;
309
            foreach ($contact->getRoles() as $role) {
310
                $max = max($max, [
311
                    'Admins' => 3,
312
                    'Writers' => 2,
313
                    'Singers' => 1,
314
                ][$role->getName()]);
315
            }
316
            return $max;
317
        }
318
319
        $this->assertCount(4, $beans);
320
321
        for ($i = 1; $i < count($beans); $i++) {
322
            $this->assertGreaterThanOrEqual(getCustomOrder($beans[$i]), getCustomOrder($beans[$i - 1]), 'Beans order does not comply with expected result.');
323
        }
324
    }
325
326
    public function testArrayAccess(): void
327
    {
328
        $beans = $this->tdbmService->findObjects('contact', null, [], 'contact.id ASC', [], null, TDBMObject::class, ResultIterator::class);
329
330
        $this->assertTrue(isset($beans[0]));
331
        $this->assertFalse(isset($beans[42]));
332
        $this->assertEquals(1, $beans[0]->getProperty('id', 'person'));
333
334
        $result1 = [];
335
        foreach ($beans as $bean) {
336
            $result1[] = $bean;
337
        }
338
339
        $result2 = [];
340
        foreach ($beans as $bean) {
341
            $result2[] = $bean;
342
        }
343
344
        $this->assertEquals($result1, $result2);
345
        $this->assertTrue($result1[0] === $result2[0]);
346
    }
347
348
    /**
349
     *
350
     * @throws TDBMInvalidOffsetException
351
     */
352
    public function testArrayAccessException(): void
353
    {
354
        $this->expectException('TheCodingMachine\TDBM\TDBMInvalidOffsetException');
355
        $beans = $this->tdbmService->findObjects('contact', null, [], 'contact.id ASC', [], null, TDBMObject::class, ContactResultIterator::class);
356
357
        $beans[-1];
358
    }
359
360
    /**
361
     *
362
     * @throws TDBMInvalidOffsetException
363
     */
364
    public function testArrayAccessException2(): void
365
    {
366
        $this->expectException('TheCodingMachine\TDBM\TDBMInvalidOffsetException');
367
        $beans = $this->tdbmService->findObjects('contact', null, [], 'contact.id ASC', [], null, TDBMObject::class, ContactResultIterator::class);
368
369
        $beans['foo'];
370
    }
371
372
    /**
373
     *
374
     * @throws TDBMException
375
     */
376
    public function testBeanGetException(): void
377
    {
378
        $this->expectException('TheCodingMachine\TDBM\TDBMException');
379
        $beans = $this->tdbmService->findObjects('contact', null, [], 'contact.id ASC', [], null, TDBMObject::class, ResultIterator::class);
380
        $bean = $beans[0];
381
382
        // we don't specify the table on inheritance table => exception.
383
        $bean->getProperty('id');
384
    }
385
386
    /**
387
     *
388
     * @throws TDBMException
389
     */
390
    public function testBeanSetException(): void
391
    {
392
        $this->expectException('TheCodingMachine\TDBM\TDBMException');
393
        $beans = $this->tdbmService->findObjects('contact', null, [], 'contact.id ASC', [], null, TDBMObject::class, ResultIterator::class);
394
        $bean = $beans[0];
395
396
        // we don't specify the table on inheritance table => exception.
397
        $bean->setProperty('name', 'foo');
398
    }
399
400
    public function testTake(): void
401
    {
402
        $beans = $this->tdbmService->findObjects('contact', null, [], 'contact.id ASC', [], null, TDBMObject::class, ResultIterator::class);
403
404
        $page = $beans->take(0, 2);
405
406
        $this->assertEquals(2, $page->count());
407
408
        $results = [];
409
        foreach ($page as $result) {
410
            $results[] = $result;
411
        }
412
        $this->assertCount(2, $results);
413
414
        $this->assertEquals(5, $page->totalCount());
415
416
        $page = $beans->take(1, 1);
417
418
        $this->assertEquals(1, $page->count());
419
420
        $resultArray = $page->toArray();
421
        $this->assertCount(1, $resultArray);
422
        $this->assertTrue($resultArray[0] === $page[0]);
423
        // Test page isset
424
        $this->assertTrue(isset($page[0]));
425
    }
426
427
    public function testTakeInCursorMode(): void
428
    {
429
        $beans = $this->tdbmService->findObjects('contact', null, [], 'contact.id ASC', [], TDBMService::MODE_CURSOR, TDBMObject::class, ContactResultIterator::class);
430
431
        $page = $beans->take(0, 2);
432
433
        $this->assertEquals(2, $page->count());
434
        $this->assertEquals(0, $page->getCurrentOffset());
435
        $this->assertEquals(2, $page->getCurrentLimit());
436
        $this->assertEquals(1, $page->getCurrentPage());
437
438
        $results = [];
439
        foreach ($page as $result) {
440
            $results[] = $result;
441
        }
442
        $this->assertCount(2, $results);
443
444
        $this->assertEquals(5, $page->totalCount());
445
446
        $page = $beans->take(1, 1);
447
        $this->assertEquals(1, $page->getCurrentOffset());
448
        $this->assertEquals(1, $page->getCurrentLimit());
449
        $this->assertEquals(2, $page->getCurrentPage());
450
451
        $this->assertEquals(1, $page->count());
452
    }
453
454
    public function testMap(): void
455
    {
456
        $beans = $this->tdbmService->findObjects('person', null, [], 'person.id ASC', [], null, TDBMObject::class, ResultIterator::class);
457
458
        $results = $beans->map(function ($item) {
459
            return $item->getProperty('id', 'person');
460
        })->toArray();
461
462
        $this->assertEquals([1, 2, 3, 4, 6], $results);
463
464
        // Same test with page
465
        $page = $beans->take(0, 2);
466
467
        $results = $page->map(function ($item) {
468
            return $item->getProperty('id', 'person');
469
        })->toArray();
470
471
        $this->assertEquals([1, 2], $results);
472
    }
473
474
    /**
475
     *
476
     * @throws TDBMException
477
     */
478
    public function testUnsetException(): void
479
    {
480
        $this->expectException('TheCodingMachine\TDBM\TDBMException');
481
        $beans = $this->tdbmService->findObjects('contact', null, [], 'contact.id ASC', [], null, TDBMObject::class, ContactResultIterator::class);
482
483
        unset($beans[0]);
484
    }
485
486
    /**
487
     *
488
     * @throws TDBMException
489
     */
490
    public function testSetException(): void
491
    {
492
        $this->expectException('TheCodingMachine\TDBM\TDBMException');
493
        $beans = $this->tdbmService->findObjects('contact', null, [], 'contact.id ASC', [], null, TDBMObject::class, ContactResultIterator::class);
494
495
        $beans[0] = 'foo';
496
    }
497
498
    /**
499
     *
500
     * @throws TDBMException
501
     */
502
    public function testPageUnsetException(): void
503
    {
504
        $this->expectException('TheCodingMachine\TDBM\TDBMException');
505
        $beans = $this->tdbmService->findObjects('contact', null, [], 'contact.id ASC', [], null, TDBMObject::class, ContactResultIterator::class);
506
        $page = $beans->take(0, 1);
507
        unset($page[0]);
508
    }
509
510
    /**
511
     *
512
     * @throws TDBMException
513
     */
514
    public function testPageSetException(): void
515
    {
516
        $this->expectException('TheCodingMachine\TDBM\TDBMException');
517
        $beans = $this->tdbmService->findObjects('contact', null, [], 'contact.id ASC', [], null, TDBMObject::class, ContactResultIterator::class);
518
        $page = $beans->take(0, 1);
519
        $page[0] = 'foo';
520
    }
521
522
    public function testToArray(): void
523
    {
524
        $beans = $this->tdbmService->findObjects('contact', 'contact.id = :id', ['id' => 1], null, [], null, TDBMObject::class, ResultIterator::class);
525
526
        $beanArray = $beans->toArray();
527
528
        $this->assertCount(1, $beanArray);
529
        $this->assertEquals(1, $beanArray[0]->getProperty('id', 'contact'));
530
    }
531
532
    public function testCursorMode(): void
533
    {
534
        $beans = $this->tdbmService->findObjects('contact', 'contact.id = :id', ['id' => 1], null, [], TDBMService::MODE_CURSOR, TDBMObject::class, ContactResultIterator::class);
535
536
        $this->assertInstanceOf('\\TheCodingMachine\\TDBM\\ResultIterator', $beans);
537
538
        $result = [];
539
        foreach ($beans as $bean) {
540
            $result[] = $bean;
541
        }
542
543
        $this->assertCount(1, $result);
544
545
        // In cursor mode, access by array causes an exception.
546
        $exceptionTriggered = false;
547
        try {
548
            $beans[0];
549
        } catch (TDBMInvalidOperationException $e) {
550
            $exceptionTriggered = true;
551
        }
552
        $this->assertTrue($exceptionTriggered);
553
554
        $exceptionTriggered = false;
555
        try {
556
            isset($beans[0]);
557
        } catch (TDBMInvalidOperationException $e) {
558
            $exceptionTriggered = true;
559
        }
560
        $this->assertTrue($exceptionTriggered);
561
    }
562
563
    public function testSetFetchMode(): void
564
    {
565
        $this->tdbmService->setFetchMode(TDBMService::MODE_CURSOR);
566
        $beans = $this->tdbmService->findObjects('contact', 'contact.id = :id', ['id' => 1], null, [], null, TDBMObject::class, ContactResultIterator::class);
567
568
        $this->assertInstanceOf('\\TheCodingMachine\\TDBM\\ResultIterator', $beans);
569
570
        // In cursor mode, access by array causes an exception.
571
        $exceptionTriggered = false;
572
        try {
573
            $beans[0];
574
        } catch (TDBMInvalidOperationException $e) {
575
            $exceptionTriggered = true;
576
        }
577
        $this->assertTrue($exceptionTriggered);
578
    }
579
580
    /**
581
     *
582
     * @throws TDBMException
583
     */
584
    public function testInvalidSetFetchMode(): void
585
    {
586
        $this->expectException('TheCodingMachine\TDBM\TDBMException');
587
        $this->tdbmService->setFetchMode(99);
588
    }
589
590
    /**
591
     *
592
     * @throws TDBMException
593
     */
594
    public function testCursorModeException(): void
595
    {
596
        $this->expectException('TheCodingMachine\TDBM\TDBMException');
597
        $beans = $this->tdbmService->findObjects('contact', 'contact.id = :id', ['id' => 1], null, [], 99, ContactBean::class, ContactResultIterator::class);
598
    }
599
600
    /**
601
     *
602
     * @throws TDBMException
603
     */
604
    public function testTableNameException(): void
605
    {
606
        $this->expectException('TheCodingMachine\TDBM\TDBMException');
607
        $beans = $this->tdbmService->findObjects('foo bar', null, [], null, [], null, AbstractTDBMObject::class, ResultIterator::class);
608
    }
609
610
    public function testLinkedTableFetch(): void
611
    {
612
        $beans = $this->tdbmService->findObjects('contact', 'contact.id = :id', ['id' => 1], null, ['country'], null, TDBMObject::class, ContactResultIterator::class);
613
        $this->assertInstanceOf(ResultIterator::class, $beans);
614
    }
615
616
    public function testFindObject(): void
617
    {
618
        $bean = $this->tdbmService->findObject('contact', 'contact.id = :id', ['id' => -42], [], TDBMObject::class, ContactResultIterator::class);
619
        $this->assertNull($bean);
620
    }
621
622
    /**
623
     *
624
     * @throws NoBeanFoundException
625
     */
626
    public function testFindObjectOrFail(): void
627
    {
628
        $this->expectException('TheCodingMachine\TDBM\NoBeanFoundException');
629
        $bean = $this->tdbmService->findObjectOrFail('contact', 'contact.id = :id', ['id' => -42], [], TDBMObject::class, ContactResultIterator::class);
630
    }
631
632
    /**
633
     * @throws NoBeanFoundException
634
     */
635
    public function testFindObjectByPkException(): void
636
    {
637
        $this->expectException(NoBeanFoundException::class);
638
        $this->expectExceptionMessage("No result found for query on table 'contact' for 'id' = -42");
639
        $bean = $this->tdbmService->findObjectByPk('contact', ['id' => -42], [], false, TDBMObject::class, ContactResultIterator::class);
640
    }
641
642
    /**
643
     * @throws DuplicateRowException
644
     */
645
    public function testFindObjectDuplicateRow(): void
646
    {
647
        $this->expectException(DuplicateRowException::class);
648
649
        $bean = $this->tdbmService->findObject('contact', null, [], [], TDBMObject::class, ContactResultIterator::class);
650
    }
651
652
    public function testFindObjectsByBean(): void
653
    {
654
        $countryBean = $this->tdbmService->findObject('country', 'id = :id', ['id' => 1], [], TDBMObject::class, ResultIterator::class);
655
656
        $users = $this->tdbmService->findObjects('users', $countryBean, [], null, [], null, TDBMObject::class, ResultIterator::class);
657
        $this->assertCount(1, $users);
658
        $this->assertEquals('jean.dupont', $users[0]->getProperty('login', 'users'));
659
    }
660
661
    /**
662
     *
663
     * @throws TDBMException
664
     * @throws TDBMInvalidOperationException
665
     */
666
    public function testBeanWithoutStatus(): void
667
    {
668
        $this->expectException('TheCodingMachine\TDBM\TDBMException');
669
        $reflectionClass = new \ReflectionClass(TDBMObject::class);
670
        $object = $reflectionClass->newInstanceWithoutConstructor();
671
        $object->_getStatus();
672
    }
673
674
    public function testFindObjectsFromSql(): void
675
    {
676
        $roles = $this->tdbmService->findObjectsFromSql(
677
            'roles',
678
            'roles JOIN roles_rights ON roles.id = roles_rights.role_id JOIN rights ON rights.label = roles_rights.right_label',
679
            'rights.label = :right',
680
            array('right' => 'CAN_SING'),
681
            'roles.name DESC',
682
            null,
683
            null,
684
            RoleResultIterator::class
685
        );
686
        $this->assertCount(2, $roles);
687
        $this->assertInstanceOf(AbstractTDBMObject::class, $roles[0]);
688
    }
689
690
    /**
691
     *
692
     * @throws TDBMException
693
     */
694
    public function testFindObjectsFromSqlBadTableName(): void
695
    {
696
        $this->expectException(TDBMException::class);
697
        $this->tdbmService->findObjectsFromSql(
698
            '#{azerty',
699
            'roles JOIN roles_rights ON roles.id = roles_rights.role_id JOIN rights ON rights.label = roles_rights.right_label',
700
            'rights.label = :right',
701
            array('right' => 'CAN_SING'),
702
            'name DESC',
703
            null,
704
            null,
705
            ResultIterator::class
706
        );
707
    }
708
709
    /**
710
     *
711
     * @throws TDBMException
712
     */
713
    public function testFindObjectsFromSqlGroupBy(): void
714
    {
715
        $this->expectException(TDBMException::class);
716
        $roles = $this->tdbmService->findObjectsFromSql(
717
            'roles',
718
            'roles JOIN roles_rights ON roles.id = roles_rights.role_id JOIN rights ON rights.label = roles_rights.right_label',
719
            'rights.label = :right GROUP BY roles.name',
720
            array('right' => 'CAN_SING'),
721
            'name DESC',
722
            null,
723
            null,
724
            RoleResultIterator::class
725
        );
726
        $role = $roles[0];
727
    }
728
729
    /**
730
     *
731
     * @throws TDBMException
732
     */
733
    public function testFindObjectsFromRawSqlBadTableName(): void
734
    {
735
        $this->expectException(TDBMException::class);
736
        $this->tdbmService->findObjectsFromRawSql(
737
            '#{azerty',
738
            'roles JOIN roles_rights ON roles.id = roles_rights.role_id JOIN rights ON rights.label = roles_rights.right_label WHERE rights.label = :right',
739
            array('right' => 'CAN_SING'),
740
            null,
741
            TDBMObject::class,
742
            null,
743
            ResultIterator::class
744
        );
745
    }
746
747
    public function testFindObjectFromSql(): void
748
    {
749
        $role = $this->tdbmService->findObjectFromSql(
750
            'roles',
751
            'roles JOIN roles_rights ON roles.id = roles_rights.role_id JOIN rights ON rights.label = roles_rights.right_label',
752
            'rights.label = :right AND name = :name',
753
            array('right' => 'CAN_SING', 'name' => 'Singers'),
754
            null,
755
            RoleResultIterator::class
756
        );
757
        $this->assertInstanceOf(AbstractTDBMObject::class, $role);
758
    }
759
760
    /**
761
     * @throws DuplicateRowException
762
     */
763
    public function testFindObjectFromSqlException(): void
764
    {
765
        $this->expectException(DuplicateRowException::class);
766
        $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\'".');
767
        $this->tdbmService->findObjectFromSql(
768
            'roles',
769
            'roles JOIN roles_rights ON roles.id = roles_rights.role_id JOIN rights ON rights.label = roles_rights.right_label',
770
            'rights.label = :right',
771
            array('right' => 'CAN_SING'),
772
            null,
773
            RoleResultIterator::class
774
        );
775
    }
776
777
    public function testFindObjectsFromSqlHierarchyDown(): void
778
    {
779
        $users = $this->tdbmService->findObjectsFromSql(
780
            'person',
781
            'person',
782
            'name LIKE :name OR name LIKE :name2',
783
            array('name' => 'Robert Marley', 'name2' => 'Bill Shakespeare'),
784
            null,
785
            null,
786
            TDBMObject::class,
787
            PersonResultIterator::class
788
        );
789
        $this->assertCount(2, $users);
790
        $this->assertSame('robert.marley', $users[0]->getProperty('login', 'users'));
791
    }
792
793
    public function testFindObjectsFromSqlHierarchyUp(): void
794
    {
795
        $users = $this->tdbmService->findObjectsFromSql(
796
            'users',
797
            'users',
798
            'login LIKE :login OR login LIKE :login2',
799
            array('login' => 'robert.marley', 'login2' => 'bill.shakespeare'),
800
            'users.login DESC',
801
            null,
802
            TDBMObject::class,
803
            UserResultIterator::class
804
        );
805
        $this->assertCount(2, $users);
806
        $this->assertSame('Robert Marley', $users[0]->getProperty('name', 'person'));
807
    }
808
809
    public function testLogger(): void
810
    {
811
        $arrayLogger = new ArrayLogger();
812
        $tdbmService = new TDBMService(new Configuration('TheCodingMachine\\TDBM\\Test\\Dao\\Bean', 'TheCodingMachine\\TDBM\\Test\\Dao', self::getConnection(), $this->getNamingStrategy(), null, null, $arrayLogger));
813
814
        $tdbmService->setLogLevel(LogLevel::DEBUG);
815
        $beans = $tdbmService->findObjects('contact', null, [], 'contact.id ASC', [], null, TDBMObject::class, ContactResultIterator::class);
816
        $beans->first();
817
818
        $this->assertNotEmpty($arrayLogger->get());
819
    }
820
821
    public function testFindObjectsCountWithOneToManyLink(): void
822
    {
823
        $countries = $this->tdbmService->findObjects('country', "users.status = 'on' OR users.status = 'off'", [], null, [], null, null, CountryResultIterator::class);
824
825
        $this->assertEquals(3, $countries->count());
826
    }
827
828
    public function testFindObjectsFromSqlCountWithOneToManyLink(): void
829
    {
830
        $countries = $this->tdbmService->findObjectsFromSql('country', 'country LEFT JOIN users ON country.id = users.country_id', "users.status = 'on' OR users.status = 'off'", [], null, null, null, CountryResultIterator::class);
831
832
        $this->assertEquals(3, $countries->count());
833
    }
834
835
    public function testBuildFilterFromFilterBagIterator(): void
836
    {
837
        $tdbmService = new TDBMService(new Configuration('TheCodingMachine\\TDBM\\Test\\Dao\\Bean', 'TheCodingMachine\\TDBM\\Test\\Dao', self::getConnection(), $this->getNamingStrategy(), null, null, new NullLogger()));
838
839
        [$sql, $parameters, $counter] = $tdbmService->buildFilterFromFilterBag(new \ArrayIterator(['id' => 1]), self::getConnection()->getDatabasePlatform());
840
        $this->assertMatchesRegularExpression('/\(.id. = :tdbmparam1\)/', $sql);
841
        $this->assertEquals($parameters['tdbmparam1'], 1);
842
    }
843
844
    public function testFindObjectsMethodWithoutResultIteratorClass(): void
845
    {
846
        $this->expectException(TDBMInvalidArgumentException::class);
847
        $this->expectExceptionMessageMatches('/^\$resultIteratorClass should be a `' . preg_quote(ResultIterator::class, '/') . '`. `(.*)` provided\.$/');
848
        $tdbmService = new TDBMService(new Configuration('TheCodingMachine\\TDBM\\Test\\Dao\\Bean', 'TheCodingMachine\\TDBM\\Test\\Dao', self::getConnection(), $this->getNamingStrategy(), null, null, new NullLogger()));
849
850
        $tdbmService->findObjects('', null, [], null, [], null, null, self::class);
851
    }
852
853
    public function testFindObjectsFromSqlMethodWithoutResultIteratorClass(): void
854
    {
855
        $this->expectException(TDBMInvalidArgumentException::class);
856
        $this->expectExceptionMessageMatches('/^\$resultIteratorClass should be a `' . preg_quote(ResultIterator::class, '/') . '`. `(.*)` provided\.$/');
857
        $tdbmService = new TDBMService(new Configuration('TheCodingMachine\\TDBM\\Test\\Dao\\Bean', 'TheCodingMachine\\TDBM\\Test\\Dao', self::getConnection(), $this->getNamingStrategy(), null, null, new NullLogger()));
858
859
        $tdbmService->findObjectsFromSql('', '', null, [], null, null, null, self::class);
860
    }
861
862
    public function testFindObjectsFromRawSqlMethodWithoutResultIteratorClass(): void
863
    {
864
        $this->expectException(TDBMInvalidArgumentException::class);
865
        $this->expectExceptionMessageMatches('/^\$resultIteratorClass should be a `' . preg_quote(ResultIterator::class, '/') . '`. `(.*)` provided\.$/');
866
        $tdbmService = new TDBMService(new Configuration('TheCodingMachine\\TDBM\\Test\\Dao\\Bean', 'TheCodingMachine\\TDBM\\Test\\Dao', self::getConnection(), $this->getNamingStrategy(), null, null, new NullLogger()));
867
868
        $tdbmService->findObjectsFromRawSql('', '', [], null, null, null, self::class);
869
    }
870
}
871