Passed
Pull Request — master (#12)
by Dorian
04:12
created

TDBMServiceTest::testFindObjectDuplicateRow()   A

Complexity

Conditions 1
Paths 1

Size

Total Lines 4
Code Lines 2

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
dl 0
loc 4
rs 10
c 0
b 0
f 0
cc 1
eloc 2
nc 1
nop 0
1
<?php
2
3
/*
4
 Copyright (C) 2006-2014 David Négrier - THE CODING MACHINE
5
6
This program is free software; you can redistribute it and/or modify
7
it under the terms of the GNU General Public License as published by
8
the Free Software Foundation; either version 2 of the License, or
9
(at your option) any later version.
10
11
This program is distributed in the hope that it will be useful,
12
but WITHOUT ANY WARRANTY; without even the implied warranty of
13
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
14
GNU General Public License for more details.
15
16
You should have received a copy of the GNU General Public License
17
along with this program; if not, write to the Free Software
18
Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
19
*/
20
21
namespace TheCodingMachine\TDBM;
22
23
use TheCodingMachine\TDBM\Utils\DefaultNamingStrategy;
24
use Psr\Log\LogLevel;
25
use Wa72\SimpleLogger\ArrayLogger;
26
27
class TDBMServiceTest extends TDBMAbstractServiceTest
28
{
29
    public function testGetLinkBetweenInheritedTables()
30
    {
31
        $this->assertEquals(['users', 'contact', 'person'], $this->tdbmService->_getLinkBetweenInheritedTables(['contact', 'users']));
32
        $this->assertEquals(['users', 'contact', 'person'], $this->tdbmService->_getLinkBetweenInheritedTables(['users', 'contact']));
33
        $this->assertEquals(['contact', 'person'], $this->tdbmService->_getLinkBetweenInheritedTables(['person', 'contact']));
34
        $this->assertEquals(['users', 'contact', 'person'], $this->tdbmService->_getLinkBetweenInheritedTables(['users']));
35
        $this->assertEquals(['person'], $this->tdbmService->_getLinkBetweenInheritedTables(['person']));
36
    }
37
38
    public function testGetRelatedTablesByInheritance()
39
    {
40
        $contactRelatedTables = $this->tdbmService->_getRelatedTablesByInheritance('contact');
41
        $this->assertCount(3, $contactRelatedTables);
42
        $this->assertContains('users', $contactRelatedTables);
43
        $this->assertContains('contact', $contactRelatedTables);
44
        $this->assertContains('person', $contactRelatedTables);
45
        $this->assertEquals(['person', 'contact', 'users'], $this->tdbmService->_getRelatedTablesByInheritance('users'));
46
        $this->assertEquals(['person', 'contact', 'users'], $this->tdbmService->_getRelatedTablesByInheritance('person'));
47
    }
48
49
    /**
50
     * @expectedException \TheCodingMachine\TDBM\TDBMException
51
     *
52
     * @throws TDBMException
53
     */
54
    public function testGetPrimaryKeysFromIndexedPrimaryKeysException()
55
    {
56
        $this->tdbmService->_getPrimaryKeysFromIndexedPrimaryKeys('users', [5, 4]);
57
    }
58
59
    /**
60
     * @expectedException \TheCodingMachine\TDBM\TDBMException
61
     *
62
     * @throws TDBMException
63
     */
64
    public function testGetLinkBetweenInheritedTablesExceptions()
65
    {
66
        $this->tdbmService->_getLinkBetweenInheritedTables(['contact', 'country']);
67
    }
68
69
    public function testHashPrimaryKey()
70
    {
71
        $reflection = new \ReflectionClass(get_class($this->tdbmService));
72
        $method = $reflection->getMethod('getObjectHash');
73
        $method->setAccessible(true);
74
75
        $result = $method->invokeArgs($this->tdbmService, [
76
            ['id' => 42],
77
        ]);
78
        $this->assertEquals(42, $result);
79
80
        // Check that multiple primary keys are insensitive to column order
81
        $result1 = $method->invokeArgs($this->tdbmService, [
82
            ['id1' => 42, 'id2' => 24],
83
        ]);
84
        $result2 = $method->invokeArgs($this->tdbmService, [
85
            ['id2' => 24, 'id1' => 42],
86
        ]);
87
        $this->assertEquals($result1, $result2);
88
    }
89
90
    public function testInsertAndUpdateAndDelete()
91
    {
92
        $object = new TDBMObject('users');
93
        $object->setProperty('login', 'john.doe');
94
        $object->setProperty('country_id', 3);
95
        $object->setProperty('name', 'John Doe', 'person');
96
        $object->setProperty('email', '[email protected]', 'contact');
97
98
        $this->tdbmService->save($object);
99
100
        $this->assertNotEmpty($object->getProperty('id', 'person'));
101
        $this->assertNotEmpty($object->getProperty('id', 'users'));
102
        $this->assertEquals($object->getProperty('id', 'person'), $object->getProperty('id', 'users'));
103
104
        $object->setProperty('country_id', 2, 'users');
105
106
        $this->tdbmService->save($object);
107
108
        $this->tdbmService->delete($object);
109
    }
110
111
    public function testInsertMultipleDataAtOnceInInheritance()
112
    {
113
        $object = new TDBMObject();
114
        $object->setProperty('login', 'jane.doe', 'users');
115
        $object->setProperty('name', 'Jane Doe', 'person');
116
        $object->setProperty('country_id', 1, 'users');
117
        $object->setProperty('email', '[email protected]', 'contact');
118
119
        $this->tdbmService->save($object);
120
121
        $this->assertNotEmpty($object->getProperty('id', 'person'));
122
        $this->assertNotEmpty($object->getProperty('id', 'users'));
123
        $this->assertEquals($object->getProperty('id', 'person'), $object->getProperty('id', 'users'));
124
    }
125
126
    public function testCompleteSave()
127
    {
128
        $beans = $this->tdbmService->findObjects('users', 'users.login = :login', ['login' => 'jane.doe'], null, [], null, TDBMObject::class);
129
        $jane = $beans[0];
130
        $jane->setProperty('country_id', 2, 'users');
131
132
        $this->tdbmService->completeSave();
133
    }
134
135
    public function testCompleteSave2()
136
    {
137
        $beans = $this->tdbmService->findObjects('users', 'users.login = :login', ['login' => 'jane.doe'], null, [], null, TDBMObject::class);
138
        $jane = $beans[0];
139
140
        $this->assertEquals(2, $jane->getProperty('country_id', 'users'));
141
    }
142
143 View Code Duplication
    public function testUpdatePrimaryKey()
0 ignored issues
show
Duplication introduced by
This method 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...
144
    {
145
        $object = new TDBMObject('rights');
146
        $object->setProperty('label', 'CAN_EDIT_BOUK');
147
148
        $this->tdbmService->save($object);
149
150
        $object->setProperty('label', 'CAN_EDIT_BOOK');
151
152
        $this->tdbmService->save($object);
153
    }
154
155
    /**
156
     * @expectedException \TheCodingMachine\TDBM\TDBMInvalidOperationException
157
     *
158
     * @throws TDBMInvalidOperationException
159
     */
160
    public function testCannotDeleteDetachedObjects()
161
    {
162
        $object = new TDBMObject('rights');
163
        $object->setProperty('label', 'CAN_DELETE');
164
165
        $this->tdbmService->delete($object);
166
    }
167
168
    public function testDeleteNewObject()
169
    {
170
        $object = new TDBMObject('rights');
171
        $object->setProperty('label', 'CAN_DELETE');
172
173
        $this->tdbmService->attach($object);
174
175
        $this->tdbmService->delete($object);
176
177
        $exceptionRaised = false;
178
        try {
179
            $this->tdbmService->save($object);
180
        } catch (TDBMInvalidOperationException $e) {
181
            $exceptionRaised = true;
182
        }
183
        $this->assertTrue($exceptionRaised);
184
    }
185
186 View Code Duplication
    public function testDeleteLoadedObject()
0 ignored issues
show
Duplication introduced by
This method 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...
187
    {
188
        $object = new TDBMObject('rights');
189
        $object->setProperty('label', 'CAN_DELETE');
190
191
        $this->tdbmService->save($object);
192
193
        $object->setProperty('label', 'CAN_DELETE2');
194
195
        $this->tdbmService->delete($object);
196
197
        // Try to delete a deleted object (this should do nothing)
198
        $this->tdbmService->delete($object);
199
    }
200
201
    public function testFindObjects()
202
    {
203
        /*$magicQuery = new MagicQuery($this->tdbmService->getConnection());
0 ignored issues
show
Unused Code Comprehensibility introduced by
60% of this comment could be valid code. Did you maybe forget this after debugging?

Sometimes obsolete code just ends up commented out instead of removed. In this case it is better to remove the code once you have checked you do not need it.

The code might also have been commented out for debugging purposes. In this case it is vital that someone uncomments it again or your project may behave in very unexpected ways in production.

This check looks for comments that seem to be mostly valid code and reports them.

Loading history...
204
        $result = $magicQuery->parse("SELECT DISTINCT users.id, users.login FROM users");
205
        var_dump($result);*/
206
207
        $beans = $this->tdbmService->findObjects('contact', null, [], 'contact.id ASC', [], null, TDBMObject::class);
208
        $beans2 = $this->tdbmService->findObjects('contact', 'contact.id = :id', ['id' => 1], null, [], null, TDBMObject::class);
209
210
        foreach ($beans as $bean) {
211
            $bean1 = $bean;
212
            break;
213
        }
214
215
        foreach ($beans2 as $bean) {
216
            $bean2 = $bean;
217
            break;
218
        }
219
220
        $this->assertTrue($bean1 === $bean2);
0 ignored issues
show
Bug introduced by
The variable $bean1 does not seem to be defined for all execution paths leading up to this point.

If you define a variable conditionally, it can happen that it is not defined for all execution paths.

Let’s take a look at an example:

function myFunction($a) {
    switch ($a) {
        case 'foo':
            $x = 1;
            break;

        case 'bar':
            $x = 2;
            break;
    }

    // $x is potentially undefined here.
    echo $x;
}

In the above example, the variable $x is defined if you pass “foo” or “bar” as argument for $a. However, since the switch statement has no default case statement, if you pass any other value, the variable $x would be undefined.

Available Fixes

  1. Check for existence of the variable explicitly:

    function myFunction($a) {
        switch ($a) {
            case 'foo':
                $x = 1;
                break;
    
            case 'bar':
                $x = 2;
                break;
        }
    
        if (isset($x)) { // Make sure it's always set.
            echo $x;
        }
    }
    
  2. Define a default value for the variable:

    function myFunction($a) {
        $x = ''; // Set a default which gets overridden for certain paths.
        switch ($a) {
            case 'foo':
                $x = 1;
                break;
    
            case 'bar':
                $x = 2;
                break;
        }
    
        echo $x;
    }
    
  3. Add a value for the missing path:

    function myFunction($a) {
        switch ($a) {
            case 'foo':
                $x = 1;
                break;
    
            case 'bar':
                $x = 2;
                break;
    
            // We add support for the missing case.
            default:
                $x = '';
                break;
        }
    
        echo $x;
    }
    
Loading history...
Bug introduced by
The variable $bean2 does not seem to be defined for all execution paths leading up to this point.

If you define a variable conditionally, it can happen that it is not defined for all execution paths.

Let’s take a look at an example:

function myFunction($a) {
    switch ($a) {
        case 'foo':
            $x = 1;
            break;

        case 'bar':
            $x = 2;
            break;
    }

    // $x is potentially undefined here.
    echo $x;
}

In the above example, the variable $x is defined if you pass “foo” or “bar” as argument for $a. However, since the switch statement has no default case statement, if you pass any other value, the variable $x would be undefined.

Available Fixes

  1. Check for existence of the variable explicitly:

    function myFunction($a) {
        switch ($a) {
            case 'foo':
                $x = 1;
                break;
    
            case 'bar':
                $x = 2;
                break;
        }
    
        if (isset($x)) { // Make sure it's always set.
            echo $x;
        }
    }
    
  2. Define a default value for the variable:

    function myFunction($a) {
        $x = ''; // Set a default which gets overridden for certain paths.
        switch ($a) {
            case 'foo':
                $x = 1;
                break;
    
            case 'bar':
                $x = 2;
                break;
        }
    
        echo $x;
    }
    
  3. Add a value for the missing path:

    function myFunction($a) {
        switch ($a) {
            case 'foo':
                $x = 1;
                break;
    
            case 'bar':
                $x = 2;
                break;
    
            // We add support for the missing case.
            default:
                $x = '';
                break;
        }
    
        echo $x;
    }
    
Loading history...
221
        $this->assertEquals(5, $beans->count());
222
        $this->assertEquals(1, $beans2->count());
223
224
        //$this->assertTrue($beans[0] === $beans2[0]);
0 ignored issues
show
Unused Code Comprehensibility introduced by
77% of this comment could be valid code. Did you maybe forget this after debugging?

Sometimes obsolete code just ends up commented out instead of removed. In this case it is better to remove the code once you have checked you do not need it.

The code might also have been commented out for debugging purposes. In this case it is vital that someone uncomments it again or your project may behave in very unexpected ways in production.

This check looks for comments that seem to be mostly valid code and reports them.

Loading history...
225
        //var_dump($beans);
226
    }
227
228
    public function testRawSqlFilterCountriesByUserCount()
229
    {
230
        $sql = <<<SQL
231
SELECT country.*, GROUP_CONCAT(users.id) AS ids
232
FROM country
233
JOIN users ON country.id= users.country_id
234
GROUP BY country.id
235
HAVING COUNT(users.id) > 1;
236
SQL;
237
        /** @var Test\Dao\Bean\CountryBean[]|\Porpaginas\Result $beans */
238
        $beans = $this->tdbmService->findObjectsFromRawSql('country', $sql, [], null, Test\Dao\Bean\CountryBean::class);
239
240
        $count = 0;
241
        foreach ($beans as $country) {
242
            $this->assertGreaterThan(1, count($country->getUsers()));
243
            $count++;
244
        }
245
        $this->assertEquals($count, $beans->count());
246
    }
247
248
    public function testRawSqlOrderCountriesByUserCount()
249
    {
250
        $sql = <<<SQL
251
SELECT country.*, GROUP_CONCAT(users.id) AS ids
252
FROM country
253
JOIN users ON country.id= users.country_id
254
GROUP BY country.id
255
ORDER BY COUNT(users.id);
256
SQL;
257
258
        /** @var Test\Dao\Bean\CountryBean[]|\Porpaginas\Result $beans */
259
        $beans = $this->tdbmService->findObjectsFromRawSql('country', $sql, [], null, Test\Dao\Bean\CountryBean::class);
260
261
        $count = 0;
262
        foreach ($beans as $country) {
263
            $count++;
264
        }
265
        $this->assertEquals($count, $beans->count());
266
267
        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...
268
            $this->assertLessThanOrEqual(count($beans[$i]->getUsers()), count($beans[$i - 1]->getUsers()));
269
        }
270
    }
271
272
    public function testRawSqlOrderUsersByCustomRoleOrder()
273
    {
274
        $sql = <<<SQL
275
SELECT `person`.*, `contact`.*, `users`.*
276
FROM `contact`
277
JOIN `users` ON `users`.`id` = `contact`.`id`
278
JOIN `person` ON `person`.`id` = `users`.`id`
279
JOIN `users_roles` ON users.id = users_roles.user_id
280
JOIN `roles` ON roles.id = users_roles.role_id
281
GROUP BY users.id
282
ORDER BY MAX(IF(roles.name = 'Admins', 3, IF(roles.name = 'Writers', 2, IF(roles.name = 'Singers', 1, 0)))) DESC
283
SQL;
284
285
        /** @var Test\Dao\Bean\UserBean[]|\Porpaginas\Result $beans */
286
        $beans = $this->tdbmService->findObjectsFromRawSql('contact', $sql, [], null, Test\Dao\Bean\UserBean::class);
287
288
        function getCustomOrder(Test\Dao\Bean\UserBean $contact)
289
        {
290
            $max = 0;
291
            foreach ($contact->getRoles() as $role) {
292
                $max = max($max, [
293
                    'Admins' => 3,
294
                    'Writers' => 2,
295
                    'Singers' => 1,
296
                ][$role->getName()]);
297
            }
298
            return $max;
299
        }
300
301
        $this->assertCount(4, $beans);
302
303
        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...
304
            $this->assertGreaterThanOrEqual(getCustomOrder($beans[$i]), getCustomOrder($beans[$i - 1]), 'Beans order does not comply with expected result.');
305
        }
306
    }
307
308
    public function testArrayAccess()
309
    {
310
        $beans = $this->tdbmService->findObjects('contact', null, [], 'contact.id ASC', [], null, TDBMObject::class);
311
312
        $this->assertTrue(isset($beans[0]));
313
        $this->assertFalse(isset($beans[42]));
314
        $this->assertEquals(1, $beans[0]->getProperty('id', 'person'));
315
316
        $result1 = [];
317
        foreach ($beans as $bean) {
318
            $result1[] = $bean;
319
        }
320
321
        $result2 = [];
322
        foreach ($beans as $bean) {
323
            $result2[] = $bean;
324
        }
325
326
        $this->assertEquals($result1, $result2);
327
        $this->assertTrue($result1[0] === $result2[0]);
328
    }
329
330
    /**
331
     * @expectedException \TheCodingMachine\TDBM\TDBMInvalidOffsetException
332
     *
333
     * @throws TDBMInvalidOffsetException
334
     */
335
    public function testArrayAccessException()
336
    {
337
        $beans = $this->tdbmService->findObjects('contact', null, [], 'contact.id ASC', [], null, TDBMObject::class);
338
339
        $beans[-1];
340
    }
341
342
    /**
343
     * @expectedException \TheCodingMachine\TDBM\TDBMInvalidOffsetException
344
     *
345
     * @throws TDBMInvalidOffsetException
346
     */
347
    public function testArrayAccessException2()
348
    {
349
        $beans = $this->tdbmService->findObjects('contact', null, [], 'contact.id ASC', [], null, TDBMObject::class);
350
351
        $beans['foo'];
352
    }
353
354
    /**
355
     * @expectedException \TheCodingMachine\TDBM\TDBMException
356
     *
357
     * @throws TDBMException
358
     */
359 View Code Duplication
    public function testBeanGetException()
0 ignored issues
show
Duplication introduced by
This method 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...
360
    {
361
        $beans = $this->tdbmService->findObjects('contact', null, [], 'contact.id ASC', [], null, TDBMObject::class);
362
        $bean = $beans[0];
363
364
        // we don't specify the table on inheritance table => exception.
365
        $bean->getProperty('id');
366
    }
367
368
    /**
369
     * @expectedException \TheCodingMachine\TDBM\TDBMException
370
     *
371
     * @throws TDBMException
372
     */
373 View Code Duplication
    public function testBeanSetException()
0 ignored issues
show
Duplication introduced by
This method 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...
374
    {
375
        $beans = $this->tdbmService->findObjects('contact', null, [], 'contact.id ASC', [], null, TDBMObject::class);
376
        $bean = $beans[0];
377
378
        // we don't specify the table on inheritance table => exception.
379
        $bean->setProperty('name', 'foo');
380
    }
381
382
    public function testTake()
383
    {
384
        $beans = $this->tdbmService->findObjects('contact', null, [], 'contact.id ASC', [], null, TDBMObject::class);
385
386
        $page = $beans->take(0, 2);
387
388
        $this->assertEquals(2, $page->count());
389
390
        $results = [];
391
        foreach ($page as $result) {
392
            $results[] = $result;
393
        }
394
        $this->assertCount(2, $results);
395
396
        $this->assertEquals(5, $page->totalCount());
397
398
        $page = $beans->take(1, 1);
399
400
        $this->assertEquals(1, $page->count());
401
402
        $resultArray = $page->toArray();
403
        $this->assertCount(1, $resultArray);
404
        $this->assertTrue($resultArray[0] === $page[0]);
405
        // Test page isset
406
        $this->assertTrue(isset($page[0]));
407
    }
408
409
    public function testTakeInCursorMode()
410
    {
411
        $beans = $this->tdbmService->findObjects('contact', null, [], 'contact.id ASC', [], TDBMService::MODE_CURSOR, TDBMObject::class);
412
413
        $page = $beans->take(0, 2);
414
415
        $this->assertEquals(2, $page->count());
416
        $this->assertEquals(0, $page->getCurrentOffset());
417
        $this->assertEquals(2, $page->getCurrentLimit());
418
        $this->assertEquals(1, $page->getCurrentPage());
419
420
        $results = [];
421
        foreach ($page as $result) {
422
            $results[] = $result;
423
        }
424
        $this->assertCount(2, $results);
425
426
        $this->assertEquals(5, $page->totalCount());
427
428
        $page = $beans->take(1, 1);
429
        $this->assertEquals(1, $page->getCurrentOffset());
430
        $this->assertEquals(1, $page->getCurrentLimit());
431
        $this->assertEquals(2, $page->getCurrentPage());
432
433
        $this->assertEquals(1, $page->count());
434
    }
435
436
    public function testMap()
437
    {
438
        $beans = $this->tdbmService->findObjects('person', null, [], 'person.id ASC', [], null, TDBMObject::class);
439
440
        $results = $beans->map(function ($item) {
441
            return $item->getProperty('id', 'person');
442
        })->toArray();
443
444
        $this->assertEquals([1, 2, 3, 4, 6], $results);
445
446
        // Same test with page
447
        $page = $beans->take(0, 2);
448
449
        $results = $page->map(function ($item) {
450
            return $item->getProperty('id', 'person');
451
        })->toArray();
452
453
        $this->assertEquals([1, 2], $results);
454
    }
455
456
    /**
457
     * @expectedException \TheCodingMachine\TDBM\TDBMException
458
     *
459
     * @throws TDBMException
460
     */
461
    public function testUnsetException()
462
    {
463
        $beans = $this->tdbmService->findObjects('contact', null, [], 'contact.id ASC', [], null, TDBMObject::class);
464
465
        unset($beans[0]);
466
    }
467
468
    /**
469
     * @expectedException \TheCodingMachine\TDBM\TDBMException
470
     *
471
     * @throws TDBMException
472
     */
473
    public function testSetException()
474
    {
475
        $beans = $this->tdbmService->findObjects('contact', null, [], 'contact.id ASC', [], null, TDBMObject::class);
476
477
        $beans[0] = 'foo';
478
    }
479
480
    /**
481
     * @expectedException \TheCodingMachine\TDBM\TDBMException
482
     *
483
     * @throws TDBMException
484
     */
485
    public function testPageUnsetException()
486
    {
487
        $beans = $this->tdbmService->findObjects('contact', null, [], 'contact.id ASC', [], null, TDBMObject::class);
488
        $page = $beans->take(0, 1);
489
        unset($page[0]);
490
    }
491
492
    /**
493
     * @expectedException \TheCodingMachine\TDBM\TDBMException
494
     *
495
     * @throws TDBMException
496
     */
497
    public function testPageSetException()
498
    {
499
        $beans = $this->tdbmService->findObjects('contact', null, [], 'contact.id ASC', [], null, TDBMObject::class);
500
        $page = $beans->take(0, 1);
501
        $page[0] = 'foo';
502
    }
503
504 View Code Duplication
    public function testToArray()
0 ignored issues
show
Duplication introduced by
This method 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...
505
    {
506
        $beans = $this->tdbmService->findObjects('contact', 'contact.id = :id', ['id' => 1], null, [], null, TDBMObject::class);
507
508
        $beanArray = $beans->toArray();
509
510
        $this->assertCount(1, $beanArray);
511
        $this->assertEquals(1, $beanArray[0]->getProperty('id', 'contact'));
512
    }
513
514
    public function testCursorMode()
515
    {
516
        $beans = $this->tdbmService->findObjects('contact', 'contact.id = :id', ['id' => 1], null, [], TDBMService::MODE_CURSOR, TDBMObject::class);
517
518
        $this->assertInstanceOf('\\TheCodingMachine\\TDBM\\ResultIterator', $beans);
519
520
        $result = [];
521
        foreach ($beans as $bean) {
522
            $result[] = $bean;
523
        }
524
525
        $this->assertCount(1, $result);
526
527
        // In cursor mode, access by array causes an exception.
528
        $exceptionTriggered = false;
529
        try {
530
            $beans[0];
531
        } catch (TDBMInvalidOperationException $e) {
532
            $exceptionTriggered = true;
533
        }
534
        $this->assertTrue($exceptionTriggered);
535
536
        $exceptionTriggered = false;
537
        try {
538
            isset($beans[0]);
539
        } catch (TDBMInvalidOperationException $e) {
0 ignored issues
show
Unused Code introduced by
catch (\TheCodingMachine...tionTriggered = true; } does not seem to be reachable.

This check looks for unreachable code. It uses sophisticated control flow analysis techniques to find statements which will never be executed.

Unreachable code is most often the result of return, die or exit statements that have been added for debug purposes.

function fx() {
    try {
        doSomething();
        return true;
    }
    catch (\Exception $e) {
        return false;
    }

    return false;
}

In the above example, the last return false will never be executed, because a return statement has already been met in every possible execution path.

Loading history...
540
            $exceptionTriggered = true;
541
        }
542
        $this->assertTrue($exceptionTriggered);
543
    }
544
545
    public function testSetFetchMode()
546
    {
547
        $this->tdbmService->setFetchMode(TDBMService::MODE_CURSOR);
548
        $beans = $this->tdbmService->findObjects('contact', 'contact.id = :id', ['id' => 1], null, [], null, TDBMObject::class);
549
550
        $this->assertInstanceOf('\\TheCodingMachine\\TDBM\\ResultIterator', $beans);
551
552
        // In cursor mode, access by array causes an exception.
553
        $exceptionTriggered = false;
554
        try {
555
            $beans[0];
556
        } catch (TDBMInvalidOperationException $e) {
557
            $exceptionTriggered = true;
558
        }
559
        $this->assertTrue($exceptionTriggered);
560
    }
561
562
    /**
563
     * @expectedException \TheCodingMachine\TDBM\TDBMException
564
     *
565
     * @throws TDBMException
566
     */
567
    public function testInvalidSetFetchMode()
568
    {
569
        $this->tdbmService->setFetchMode('foo');
570
    }
571
572
    /**
573
     * @expectedException \TheCodingMachine\TDBM\TDBMException
574
     *
575
     * @throws TDBMException
576
     */
577
    public function testCursorModeException()
578
    {
579
        $beans = $this->tdbmService->findObjects('contact', 'contact.id = :id', ['id' => 1], null, [], 'foobaz');
0 ignored issues
show
Unused Code introduced by
$beans is not used, you could remove the assignment.

This check looks for variable assignements that are either overwritten by other assignments or where the variable is not used subsequently.

$myVar = 'Value';
$higher = false;

if (rand(1, 6) > 3) {
    $higher = true;
} else {
    $higher = false;
}

Both the $myVar assignment in line 1 and the $higher assignment in line 2 are dead. The first because $myVar is never used and the second because $higher is always overwritten for every possible time line.

Loading history...
580
    }
581
582
    /**
583
     * @expectedException \TheCodingMachine\TDBM\TDBMException
584
     *
585
     * @throws TDBMException
586
     */
587
    public function testTableNameException()
588
    {
589
        $beans = $this->tdbmService->findObjects('foo bar');
0 ignored issues
show
Unused Code introduced by
$beans is not used, you could remove the assignment.

This check looks for variable assignements that are either overwritten by other assignments or where the variable is not used subsequently.

$myVar = 'Value';
$higher = false;

if (rand(1, 6) > 3) {
    $higher = true;
} else {
    $higher = false;
}

Both the $myVar assignment in line 1 and the $higher assignment in line 2 are dead. The first because $myVar is never used and the second because $higher is always overwritten for every possible time line.

Loading history...
590
    }
591
592
    public function testLinkedTableFetch()
593
    {
594
        $beans = $this->tdbmService->findObjects('contact', 'contact.id = :id', ['id' => 1], null, ['country'], null, TDBMObject::class);
0 ignored issues
show
Unused Code introduced by
$beans is not used, you could remove the assignment.

This check looks for variable assignements that are either overwritten by other assignments or where the variable is not used subsequently.

$myVar = 'Value';
$higher = false;

if (rand(1, 6) > 3) {
    $higher = true;
} else {
    $higher = false;
}

Both the $myVar assignment in line 1 and the $higher assignment in line 2 are dead. The first because $myVar is never used and the second because $higher is always overwritten for every possible time line.

Loading history...
595
    }
596
597
    public function testFindObject()
598
    {
599
        $bean = $this->tdbmService->findObject('contact', 'contact.id = :id', ['id' => -42], [], TDBMObject::class);
600
        $this->assertNull($bean);
601
    }
602
603
    /**
604
     * @expectedException \TheCodingMachine\TDBM\NoBeanFoundException
605
     *
606
     * @throws NoBeanFoundException
607
     */
608
    public function testFindObjectOrFail()
609
    {
610
        $bean = $this->tdbmService->findObjectOrFail('contact', 'contact.id = :id', ['id' => -42], [], TDBMObject::class);
0 ignored issues
show
Unused Code introduced by
$bean is not used, you could remove the assignment.

This check looks for variable assignements that are either overwritten by other assignments or where the variable is not used subsequently.

$myVar = 'Value';
$higher = false;

if (rand(1, 6) > 3) {
    $higher = true;
} else {
    $higher = false;
}

Both the $myVar assignment in line 1 and the $higher assignment in line 2 are dead. The first because $myVar is never used and the second because $higher is always overwritten for every possible time line.

Loading history...
611
    }
612
613
    /**
614
     * @expectedException \TheCodingMachine\TDBM\DuplicateRowException
615
     *
616
     * @throws DuplicateRowException
617
     */
618
    public function testFindObjectDuplicateRow()
619
    {
620
        $bean = $this->tdbmService->findObject('contact');
0 ignored issues
show
Unused Code introduced by
$bean is not used, you could remove the assignment.

This check looks for variable assignements that are either overwritten by other assignments or where the variable is not used subsequently.

$myVar = 'Value';
$higher = false;

if (rand(1, 6) > 3) {
    $higher = true;
} else {
    $higher = false;
}

Both the $myVar assignment in line 1 and the $higher assignment in line 2 are dead. The first because $myVar is never used and the second because $higher is always overwritten for every possible time line.

Loading history...
621
    }
622
623 View Code Duplication
    public function testFindObjectsByBean()
0 ignored issues
show
Duplication introduced by
This method 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...
624
    {
625
        $countryBean = $this->tdbmService->findObject('country', 'id = :id', ['id' => 1], [], TDBMObject::class);
626
627
        $users = $this->tdbmService->findObjects('users', $countryBean, [], null, [], null, TDBMObject::class);
0 ignored issues
show
Bug introduced by
It seems like $countryBean defined by $this->tdbmService->find...TDBM\TDBMObject::class) on line 625 can also be of type object<TheCodingMachine\TDBM\AbstractTDBMObject>; however, TheCodingMachine\TDBM\TDBMService::findObjects() does only seem to accept string|array|null, 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...
628
        $this->assertCount(1, $users);
629
        $this->assertEquals('jean.dupont', $users[0]->getProperty('login', 'users'));
630
    }
631
632
    /**
633
     * @expectedException \TheCodingMachine\TDBM\TDBMException
634
     *
635
     * @throws TDBMException
636
     * @throws TDBMInvalidOperationException
637
     */
638
    public function testBeanWithoutStatus()
639
    {
640
        $object = new TDBMObject('users');
641
        $object->setProperty('login', 'john.doe');
642
        $object->setProperty('country_id', 3);
643
        $object->setProperty('name', 'John Doe', 'person');
644
        $object->setProperty('email', '[email protected]', 'contact');
645
        $object->_setStatus(null);
646
        $this->tdbmService->save($object);
647
    }
648
649
    public function testFindObjectsFromSql()
650
    {
651
        $roles = $this->tdbmService->findObjectsFromSql('roles', 'roles JOIN roles_rights ON roles.id = roles_rights.role_id JOIN rights ON rights.label = roles_rights.right_label',
652
            'rights.label = :right', array('right' => 'CAN_SING'), 'name DESC');
653
        $this->assertCount(2, $roles);
654
        $this->assertInstanceOf(AbstractTDBMObject::class, $roles[0]);
655
    }
656
657
    /**
658
     * @expectedException \TheCodingMachine\TDBM\TDBMException
659
     *
660
     * @throws TDBMException
661
     */
662
    public function testFindObjectsFromSqlBadTableName()
663
    {
664
        $this->tdbmService->findObjectsFromSql('#{azerty', 'roles JOIN roles_rights ON roles.id = roles_rights.role_id JOIN rights ON rights.label = roles_rights.right_label',
665
            'rights.label = :right', array('right' => 'CAN_SING'), 'name DESC');
666
    }
667
668
    /**
669
     * @expectedException \TheCodingMachine\TDBM\TDBMException
670
     *
671
     * @throws TDBMException
672
     */
673
    public function testFindObjectsFromSqlGroupBy()
674
    {
675
        $roles = $this->tdbmService->findObjectsFromSql('roles', 'roles JOIN roles_rights ON roles.id = roles_rights.role_id JOIN rights ON rights.label = roles_rights.right_label',
676
            'rights.label = :right GROUP BY roles.name', array('right' => 'CAN_SING'), 'name DESC');
677
        $role = $roles[0];
0 ignored issues
show
Unused Code introduced by
$role is not used, you could remove the assignment.

This check looks for variable assignements that are either overwritten by other assignments or where the variable is not used subsequently.

$myVar = 'Value';
$higher = false;

if (rand(1, 6) > 3) {
    $higher = true;
} else {
    $higher = false;
}

Both the $myVar assignment in line 1 and the $higher assignment in line 2 are dead. The first because $myVar is never used and the second because $higher is always overwritten for every possible time line.

Loading history...
678
    }
679
680
    public function testFindObjectFromSql()
681
    {
682
        $role = $this->tdbmService->findObjectFromSql('roles', 'roles JOIN roles_rights ON roles.id = roles_rights.role_id JOIN rights ON rights.label = roles_rights.right_label',
683
            'rights.label = :right AND name = :name', array('right' => 'CAN_SING', 'name' => 'Singers'));
684
        $this->assertInstanceOf(AbstractTDBMObject::class, $role);
685
    }
686
687
    /**
688
     * @expectedException \TheCodingMachine\TDBM\DuplicateRowException
689
     *
690
     * @throws DuplicateRowException
691
     */
692
    public function testFindObjectFromSqlException()
693
    {
694
        $this->tdbmService->findObjectFromSql('roles', 'roles JOIN roles_rights ON roles.id = roles_rights.role_id JOIN rights ON rights.label = roles_rights.right_label',
695
            'rights.label = :right', array('right' => 'CAN_SING'));
696
    }
697
698 View Code Duplication
    public function testFindObjectsFromSqlHierarchyDown()
0 ignored issues
show
Duplication introduced by
This method 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...
699
    {
700
        $users = $this->tdbmService->findObjectsFromSql('person', 'person', 'name LIKE :name OR name LIKE :name2',
701
            array('name' => 'Robert Marley', 'name2' => 'Bill Shakespeare'), null, null, TDBMObject::class);
702
        $this->assertCount(2, $users);
703
        $this->assertSame('robert.marley', $users[0]->getProperty('login', 'users'));
704
    }
705
706 View Code Duplication
    public function testFindObjectsFromSqlHierarchyUp()
0 ignored issues
show
Duplication introduced by
This method 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...
707
    {
708
        $users = $this->tdbmService->findObjectsFromSql('users', 'users', 'login LIKE :login OR login LIKE :login2',
709
            array('login' => 'robert.marley', 'login2' => 'bill.shakespeare'), null, null, TDBMObject::class);
710
        $this->assertCount(2, $users);
711
        $this->assertSame('Robert Marley', $users[0]->getProperty('name', 'person'));
712
    }
713
714
    public function testLogger()
715
    {
716
        $arrayLogger = new ArrayLogger();
717
        $tdbmService = new TDBMService(new Configuration('TheCodingMachine\\TDBM\\Test\\Dao\\Bean', 'TheCodingMachine\\TDBM\\Test\\Dao', $this->dbConnection, $this->getNamingStrategy(), null, null, $arrayLogger));
718
719
        $tdbmService->setLogLevel(LogLevel::DEBUG);
720
        $beans = $tdbmService->findObjects('contact', null, [], 'contact.id ASC', [], null, TDBMObject::class);
721
        $beans->first();
722
723
        $this->assertNotEmpty($arrayLogger->get());
724
    }
725
726
    public function testFindObjectsCountWithOneToManyLink()
727
    {
728
        $countries = $this->tdbmService->findObjects('country', "users.status = 'on' OR users.status = 'off'");
729
730
        $this->assertEquals(3, $countries->count());
731
    }
732
733
    public function testFindObjectsFromSqlCountWithOneToManyLink()
734
    {
735
        $countries = $this->tdbmService->findObjectsFromSql('country', 'country LEFT JOIN users ON country.id = users.country_id', "users.status = 'on' OR users.status = 'off'");
736
737
        $this->assertEquals(3, $countries->count());
738
    }
739
740
    /*
0 ignored issues
show
Unused Code Comprehensibility introduced by
57% of this comment could be valid code. Did you maybe forget this after debugging?

Sometimes obsolete code just ends up commented out instead of removed. In this case it is better to remove the code once you have checked you do not need it.

The code might also have been commented out for debugging purposes. In this case it is vital that someone uncomments it again or your project may behave in very unexpected ways in production.

This check looks for comments that seem to be mostly valid code and reports them.

Loading history...
741
        public function testObjectAsFilter() {
742
            $dpt = $this->tdbmService->getObject('departements', 1);
743
            $dpt2 =  $this->tdbmService->getObject('departements', $dpt);
744
            $this->assertEquals($dpt, $dpt2);
745
        }
746
747
        public function testOneWayAndTheOpposite() {
748
            $this->tdbmService->getObjects('utilisateur_entite', new EqualFilter('entites', 'appellation', 'foo'));
749
            $this->tdbmService->getObjects('entites', new EqualFilter('utilisateur_entite', 'id_utilisateur', '1'));
750
        }
751
752
        public function testOneWayAndTheOpposite2() {
753
            $this->tdbmService->getObjects('utilisateur_entite', new EqualFilter('departements', 'id', '1'));
754
            $this->tdbmService->getObjects('departements', new EqualFilter('utilisateur_entite', 'id_utilisateur', '1'));
755
        }
756
757
        public function testOneWayAndTheOpposite3() {
758
            $this->tdbmService->getObjects('utilisateur_entite',
759
                    [
760
                    new EqualFilter('entites', 'appellation', 1),
761
                    ]
762
            );
763
            $this->tdbmService->getObjects('entites', [
764
                        new EqualFilter('departements', 'id', 1),
765
                        new EqualFilter('utilisateur_entite', 'id_utilisateur', '1'),
766
                    ]
767
            );
768
        }
769
770
        public function testOneWayAndTheOpposite4() {
771
            $this->tdbmService->getObjects('utilisateur_entite', null,
772
                    [
773
                    new OrderByColumn('entites', 'appellation', 'ASC'),
774
                    ]
775
            );
776
            $this->tdbmService->getObjects('entites', new EqualFilter('utilisateur_entite', 'id_utilisateur', '1'),
777
                    [
778
                    new OrderByColumn('departements', 'id', 'ASC')
779
                    ]
780
            );
781
        }
782
783
        public function testTDBMObjectArrayMultipleForeach() {
784
            $results = $this->tdbmService->getObjects('departements');
785
            $this->assertTrue(is_array($results));
786
            $count = 0;
787
            foreach ($results as $result) {
788
                $count++;
789
            }
790
            $this->assertEquals(95, $count);
791
792
            $count = 0;
793
            foreach ($results as $result) {
794
                $count++;
795
            }
796
            $this->assertEquals(95, $count);
797
798
        }
799
800
        public function testTDBMObjectsCursorMode() {
801
            $this->tdbmService->setFetchMode(TDBMService::MODE_CURSOR);
802
            $results = $this->tdbmService->getObjects('departements');
803
804
            $count = 0;
805
            foreach ($results as $result) {
806
                $count++;
807
            }
808
            $this->assertEquals(95, $count);
809
        }
810
811
        public function testTDBMObjectCursorMode() {
812
            $this->tdbmService->setFetchMode(TDBMService::MODE_CURSOR);
813
            $result = $this->tdbmService->getObject('departements', array(new EqualFilter('departements', 'id', 1)));
814
815
            $this->assertEquals("Ain", $result->nom);
816
        }
817
818
819
        public function testTDBMObjectArrayCount() {
820
            $results = $this->tdbmService->getObjects('departements');
821
            $this->assertEquals(95, count($results));
822
            $this->assertEquals(95, count($results));
823
824
        }
825
826
827
        public function testTDBMObjectArrayAccessByKey() {
828
            $results = $this->tdbmService->getObjects('departements');
829
830
            $this->assertEquals("Alpes Maritimes", $results[5]->nom);
831
        }
832
833
        public function testTDBMObjectArrayCountAfterForeach() {
834
            $results = $this->tdbmService->getObjects('departements');
835
            foreach ($results as $result) {
836
                // Do nothing
837
            }
838
            $this->assertEquals(95, count($results));
839
        }
840
841
        public function testStorage() {
842
            $results = $this->tdbmService->getObjects('departements');
843
844
            $result = $this->tdbmService->getObject('departements', 1);
845
846
            $this->assertTrue($results[0] === $result);
847
        }
848
849
        public function testCloneTDBMObject()
850
        {
851
            // Create a new object
852
            $object = $this->tdbmService->getNewObject('departements');
853
            $object->id_region = 22;
854
            $object->numero = '100';
855
            $object->nom = 'test';
856
            $object->nom_web = 'test';
857
            // Save the object
858
            $object->save();
859
860
            // Try to clone the object
861
            $cloneObject = clone $object;
862
            // Save the cloned object
863
            $cloneObject->save();
864
865
            $this->assertNotEquals($object->id, $cloneObject->id);
866
            $this->assertEquals($object->nom, $cloneObject->nom);
867
868
            $this->tdbmService->deleteObject($object);
869
            $this->tdbmService->deleteObject($cloneObject);
870
        }
871
    */
872
}
873