Passed
Push — master ( 7984fa...8e6f61 )
by David
06:21 queued 02:56
created

TDBMAbstractServiceTest::getCache()   A

Complexity

Conditions 2
Paths 2

Size

Total Lines 6
Code Lines 3

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
eloc 3
dl 0
loc 6
rs 10
c 0
b 0
f 0
cc 2
nc 2
nop 0
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 Doctrine\Common\Cache\ArrayCache;
25
use Doctrine\Common\EventManager;
26
use Doctrine\DBAL\Connection;
27
use Doctrine\DBAL\DriverManager;
28
use Doctrine\DBAL\Event\Listeners\OracleSessionInit;
29
use Doctrine\DBAL\Platforms\MySqlPlatform;
30
use Doctrine\DBAL\Platforms\OraclePlatform;
31
use PHPUnit\Framework\TestCase;
32
use TheCodingMachine\FluidSchema\FluidSchema;
33
use TheCodingMachine\TDBM\Utils\Annotation\AnnotationParser;
34
use TheCodingMachine\TDBM\Utils\DefaultNamingStrategy;
35
use TheCodingMachine\TDBM\Utils\PathFinder\PathFinder;
36
37
abstract class TDBMAbstractServiceTest extends TestCase
38
{
39
    /**
40
     * @var Connection
41
     */
42
    protected static $dbConnection;
43
44
    /**
45
     * @var TDBMService
46
     */
47
    protected $tdbmService;
48
49
    /**
50
     * @var DummyGeneratorListener
51
     */
52
    private $dummyGeneratorListener;
53
54
    /**
55
     * @var ConfigurationInterface
56
     */
57
    private $configuration;
58
59
    /**
60
     * @var ArrayCache
61
     */
62
    private $cache;
63
64
    public static function setUpBeforeClass()
65
    {
66
        self::resetConnection();
67
68
        $config = new \Doctrine\DBAL\Configuration();
69
70
        $dbDriver = $GLOBALS['db_driver'];
71
72
        if ($dbDriver === 'pdo_sqlite') {
73
            $dbConnection = self::getConnection();
74
            $dbConnection->exec('PRAGMA foreign_keys = ON;');
75
        } elseif ($dbDriver === 'oci8') {
76
            $connectionParams = array(
77
                'servicename' => 'XE',
78
                'user' => $GLOBALS['db_admin_username'],
79
                // Because of issues in DBAL, admin and normal user password have to be the same.
80
                'password' => $GLOBALS['db_password'],
81
                'host' => $GLOBALS['db_host'],
82
                'port' => $GLOBALS['db_port'],
83
                'driver' => $GLOBALS['db_driver'],
84
                'dbname' => $GLOBALS['db_admin_username'],
85
                'charset' => 'AL32UTF8',
86
            );
87
88
            $adminConn = DriverManager::getConnection($connectionParams, $config);
89
90
            // When dropAndCreateDatabase is run several times, Oracle can have some issues releasing the TDBM user.
91
            // Let's forcefully delete the connection!
92
            $adminConn->exec("select 'alter system kill session ''' || sid || ',' || serial# || ''';' from v\$session where username = '".strtoupper($GLOBALS['db_name'])."'");
93
94
            $adminConn->getSchemaManager()->dropAndCreateDatabase($GLOBALS['db_name']);
95
96
            $dbConnection = self::getConnection();
97
        } else {
98
            $connectionParams = array(
99
                'user' => $GLOBALS['db_username'],
100
                'password' => $GLOBALS['db_password'],
101
                'host' => $GLOBALS['db_host'],
102
                'port' => $GLOBALS['db_port'],
103
                'driver' => $dbDriver,
104
            );
105
106
            $adminConn = DriverManager::getConnection($connectionParams, $config);
107
108
            $adminConn->getSchemaManager()->dropAndCreateDatabase($GLOBALS['db_name']);
109
110
            $connectionParams['dbname'] = $GLOBALS['db_name'];
111
112
            $dbConnection = DriverManager::getConnection($connectionParams, $config);
113
        }
114
115
116
        self::initSchema($dbConnection);
117
    }
118
119
    private static function resetConnection(): void
120
    {
121
        if (self::$dbConnection !== null) {
122
            self::$dbConnection->close();
123
        }
124
        self::$dbConnection = null;
125
    }
126
127
    protected static function getConnection(): Connection
128
    {
129
        if (self::$dbConnection === null) {
130
            $config = new \Doctrine\DBAL\Configuration();
131
132
            $dbDriver = $GLOBALS['db_driver'];
133
134
            if ($dbDriver === 'pdo_sqlite') {
135
                $connectionParams = array(
136
                    'memory' => true,
137
                    'driver' => 'pdo_sqlite',
138
                );
139
                self::$dbConnection = DriverManager::getConnection($connectionParams, $config);
140
            } elseif ($dbDriver === 'oci8') {
141
                $evm = new EventManager();
142
                $evm->addEventSubscriber(new OracleSessionInit(array(
143
                    'NLS_TIME_FORMAT' => 'HH24:MI:SS',
144
                    'NLS_DATE_FORMAT' => 'YYYY-MM-DD HH24:MI:SS',
145
                    'NLS_TIMESTAMP_FORMAT' => 'YYYY-MM-DD HH24:MI:SS',
146
                )));
147
148
                $connectionParams = array(
149
                    'servicename' => 'XE',
150
                    'user' => $GLOBALS['db_username'],
151
                    'password' => $GLOBALS['db_password'],
152
                    'host' => $GLOBALS['db_host'],
153
                    'port' => $GLOBALS['db_port'],
154
                    'driver' => $GLOBALS['db_driver'],
155
                    'dbname' => $GLOBALS['db_name'],
156
                    'charset' => 'AL32UTF8',
157
                );
158
                self::$dbConnection = DriverManager::getConnection($connectionParams, $config, $evm);
159
                self::$dbConnection->setAutoCommit(true);
160
            } else {
161
                $connectionParams = array(
162
                    'user' => $GLOBALS['db_username'],
163
                    'password' => $GLOBALS['db_password'],
164
                    'host' => $GLOBALS['db_host'],
165
                    'port' => $GLOBALS['db_port'],
166
                    'driver' => $GLOBALS['db_driver'],
167
                    'dbname' => $GLOBALS['db_name'],
168
                );
169
                self::$dbConnection = DriverManager::getConnection($connectionParams, $config);
170
            }
171
        }
172
        return self::$dbConnection;
173
    }
174
175
    protected function onlyMySql()
176
    {
177
        if (!self::getConnection()->getDatabasePlatform() instanceof MySqlPlatform) {
178
            $this->markTestSkipped('MySQL specific test');
179
        }
180
    }
181
182
    protected function setUp()
183
    {
184
        $this->tdbmService = new TDBMService($this->getConfiguration());
185
    }
186
187
    protected function getDummyGeneratorListener() : DummyGeneratorListener
188
    {
189
        if ($this->dummyGeneratorListener === null) {
190
            $this->dummyGeneratorListener = new DummyGeneratorListener();
191
        }
192
        return $this->dummyGeneratorListener;
193
    }
194
195
    protected function getCache(): ArrayCache
196
    {
197
        if ($this->cache === null) {
198
            $this->cache = new ArrayCache();
199
        }
200
        return $this->cache;
201
    }
202
203
    protected function getConfiguration() : ConfigurationInterface
204
    {
205
        if ($this->configuration === null) {
206
            $this->configuration = new Configuration('TheCodingMachine\\TDBM\\Test\\Dao\\Bean', 'TheCodingMachine\\TDBM\\Test\\Dao', self::getConnection(), $this->getNamingStrategy(), $this->getCache(), null, null, [$this->getDummyGeneratorListener()]);
207
            $this->configuration->setPathFinder(new PathFinder(null, dirname(__DIR__, 4)));
208
        }
209
        return $this->configuration;
210
    }
211
212
    protected function getNamingStrategy()
213
    {
214
        $strategy = new DefaultNamingStrategy(AnnotationParser::buildWithDefaultAnnotations([]), self::getConnection()->getSchemaManager());
215
        $strategy->setBeanPrefix('');
216
        $strategy->setBeanSuffix('Bean');
217
        $strategy->setBaseBeanPrefix('');
218
        $strategy->setBaseBeanSuffix('BaseBean');
219
        $strategy->setDaoPrefix('');
220
        $strategy->setDaoSuffix('Dao');
221
        $strategy->setBaseDaoPrefix('');
222
        $strategy->setBaseDaoSuffix('BaseDao');
223
224
        return $strategy;
225
    }
226
227
    private static function initSchema(Connection $connection): void
228
    {
229
        $fromSchema = $connection->getSchemaManager()->createSchema();
230
        $toSchema = clone $fromSchema;
231
232
        $db = new FluidSchema($toSchema, new \TheCodingMachine\FluidSchema\DefaultNamingStrategy($connection->getDatabasePlatform()));
233
234
        $db->table('country')
235
            ->column('id')->integer()->primaryKey()->autoIncrement()->comment('@Autoincrement')
236
            ->column('label')->string(255)->unique();
237
238
        $db->table('person')
239
            ->column('id')->integer()->primaryKey()->autoIncrement()->comment('@Autoincrement')
240
            ->column('name')->string(255);
241
242
        if ($connection->getDatabasePlatform() instanceof OraclePlatform) {
243
            $toSchema->getTable($connection->quoteIdentifier('person'))
244
                ->addColumn(
245
                    $connection->quoteIdentifier('created_at'),
246
                    'datetime',
247
                    ['columnDefinition' => 'TIMESTAMP(0) DEFAULT SYSDATE NOT NULL']
248
                );
249
        } else {
250
            $toSchema->getTable('person')
251
                ->addColumn(
252
                    $connection->quoteIdentifier('created_at'),
253
                    'datetime',
254
                    ['columnDefinition' => 'timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP']
255
                );
256
        }
257
258
        $db->table('person')
259
            ->column('modified_at')->datetime()->null()
260
            ->column('order')->integer()->null();
261
262
263
        $db->table('contact')
264
            ->extends('person')
265
            ->column('email')->string(255)
266
            ->column('manager_id')->references('contact')->null();
267
268
        $db->table('users')
269
            ->extends('contact')
270
            ->column('login')->string(255)
271
            ->column('password')->string(255)->null()
272
            ->column('status')->string(10)->null()->default(null)
273
            ->column('country_id')->references('country');
274
275
        $db->table('rights')
276
            ->column('label')->string(255)->primaryKey()->comment('Non autoincrementable primary key');
277
278
        $db->table('roles')
279
            ->column('id')->integer()->primaryKey()->autoIncrement()->comment('@Autoincrement')
280
            ->column('name')->string(255)
281
            ->column('created_at')->date()->null()
282
            ->column('status')->boolean()->null()->default(1);
283
284
        $db->table('roles_rights')
285
            ->column('role_id')->references('roles')
286
            ->column('right_label')->references('rights')->then()
287
            ->primaryKey(['role_id', 'right_label']);
288
289
        $db->table('users_roles')
290
            ->column('id')->integer()->primaryKey()->autoIncrement()->comment('@Autoincrement')
291
            ->column('user_id')->references('users')
292
            ->column('role_id')->references('roles');
293
294
        $db->table('all_nullable')
295
            ->column('id')->integer()->primaryKey()->autoIncrement()->comment('@Autoincrement')
296
            ->column('label')->string(255)->null()
297
            ->column('country_id')->references('country')->null();
298
299
        $db->table('animal')
300
            ->column('id')->integer()->primaryKey()->autoIncrement()->comment('@Autoincrement')
301
            ->column('name')->string(45)->index()
302
            ->column('UPPERCASE_COLUMN')->string(45)->null()
303
            ->column('order')->integer()->null();
304
305
        $db->table('dog')
306
            ->extends('animal')
307
            ->column('race')->string(45)->null();
308
309
        $db->table('cat')
310
            ->extends('animal')
311
            ->column('cuteness_level')->integer()->null();
312
313
        $db->table('panda')
314
            ->extends('animal')
315
            ->column('weight')->float()->null();
316
317
        $db->table('boats')
318
            ->column('id')->integer()->primaryKey()->autoIncrement()->comment('@Autoincrement')
319
            ->column('name')->string(255)
320
            ->column('anchorage_country')->references('country')->notNull()->then()
321
            ->column('current_country')->references('country')->null()->then()
322
            ->column('length')->decimal(10, 2)->null()->then()
323
            ->unique(['anchorage_country', 'name']);
324
325
        $db->table('sailed_countries')
326
            ->column('boat_id')->references('boats')
327
            ->column('country_id')->references('country')
328
            ->then()->primaryKey(['boat_id', 'country_id']);
329
330
        $db->table('category')
331
            ->column('id')->integer()->primaryKey()->autoIncrement()->comment('@Autoincrement')
332
            ->column('label')->string(255)
333
            ->column('parent_id')->references('category')->null();
334
335
        $db->table('article')
336
            ->column('id')->string(36)->primaryKey()->comment('@UUID')
337
            ->column('content')->string(255)
338
            ->column('author_id')->references('users')->null();
339
340
        $db->table('article2')
341
            ->column('id')->string(36)->primaryKey()->comment('@UUID v4')
342
            ->column('content')->string(255);
343
344
        $db->table('files')
345
            ->column('id')->integer()->primaryKey()->autoIncrement()->comment('@Autoincrement')
346
            ->column('file')->blob()
347
            ->column('md5')->string()->null()->comment("@ProtectedGetter\n@ProtectedSetter")
348
            ->column('article_id')->references('article')->null()->comment("@ProtectedGetter\n@ProtectedSetter\n@ProtectedOneToMany");
349
350
        $toSchema->getTable('users')
351
            ->addUniqueIndex([$connection->quoteIdentifier('login')], 'users_login_idx')
352
            ->addIndex([$connection->quoteIdentifier('status'), $connection->quoteIdentifier('country_id')], 'users_status_country_idx');
353
354
        // We create the same index twice
355
        // except for Oracle that won't let us create twice the same index.
356
        if (!$connection->getDatabasePlatform() instanceof OraclePlatform) {
357
            $toSchema->getTable('users')
358
                ->addUniqueIndex([$connection->quoteIdentifier('login')], 'users_login_idx_2');
359
        }
360
361
        // A table with a foreign key that references a non primary key.
362
        $db->table('ref_no_prim_key')
363
            ->column('id')->integer()->primaryKey()->autoIncrement()->comment('@Autoincrement')
364
            ->column('from')->string(50)
365
            ->column('to')->string(50)->unique();
366
367
        $toSchema->getTable($connection->quoteIdentifier('ref_no_prim_key'))->addForeignKeyConstraint($connection->quoteIdentifier('ref_no_prim_key'), [$connection->quoteIdentifier('from')], [$connection->quoteIdentifier('to')]);
368
369
        // A table with multiple primary keys.
370
        $db->table('states')
371
            ->column('country_id')->references('country')
372
            ->column('code')->string(3)
373
            ->column('name')->string(50)->then()
374
            ->primaryKey(['country_id', 'code']);
375
376
        $sqlStmts = $toSchema->getMigrateFromSql($fromSchema, $connection->getDatabasePlatform());
377
378
        foreach ($sqlStmts as $sqlStmt) {
379
            $connection->exec($sqlStmt);
380
        }
381
382
        self::insert($connection, 'country', [
383
            'label' => 'France',
384
        ]);
385
        self::insert($connection, 'country', [
386
            'label' => 'UK',
387
        ]);
388
        self::insert($connection, 'country', [
389
            'label' => 'Jamaica',
390
        ]);
391
392
        self::insert($connection, 'person', [
393
            'name' => 'John Smith',
394
            'created_at' => '2015-10-24 11:57:13',
395
        ]);
396
        self::insert($connection, 'person', [
397
            'name' => 'Jean Dupont',
398
            'created_at' => '2015-10-24 11:57:13',
399
        ]);
400
        self::insert($connection, 'person', [
401
            'name' => 'Robert Marley',
402
            'created_at' => '2015-10-24 11:57:13',
403
        ]);
404
        self::insert($connection, 'person', [
405
            'name' => 'Bill Shakespeare',
406
            'created_at' => '2015-10-24 11:57:13',
407
        ]);
408
409
        self::insert($connection, 'contact', [
410
            'id' => 1,
411
            'email' => '[email protected]',
412
            'manager_id' => null,
413
        ]);
414
        self::insert($connection, 'contact', [
415
            'id' => 2,
416
            'email' => '[email protected]',
417
            'manager_id' => null,
418
        ]);
419
        self::insert($connection, 'contact', [
420
            'id' => 3,
421
            'email' => '[email protected]',
422
            'manager_id' => null,
423
        ]);
424
        self::insert($connection, 'contact', [
425
            'id' => 4,
426
            'email' => '[email protected]',
427
            'manager_id' => 1,
428
        ]);
429
430
        self::insert($connection, 'rights', [
431
            'label' => 'CAN_SING',
432
        ]);
433
        self::insert($connection, 'rights', [
434
            'label' => 'CAN_WRITE',
435
        ]);
436
437
        self::insert($connection, 'roles', [
438
            'name' => 'Admins',
439
            'created_at' => '2015-10-24'
440
        ]);
441
        self::insert($connection, 'roles', [
442
            'name' => 'Writers',
443
            'created_at' => '2015-10-24'
444
        ]);
445
        self::insert($connection, 'roles', [
446
            'name' => 'Singers',
447
            'created_at' => '2015-10-24'
448
        ]);
449
450
        self::insert($connection, 'roles_rights', [
451
            'role_id' => 1,
452
            'right_label' => 'CAN_SING'
453
        ]);
454
        self::insert($connection, 'roles_rights', [
455
            'role_id' => 3,
456
            'right_label' => 'CAN_SING'
457
        ]);
458
        self::insert($connection, 'roles_rights', [
459
            'role_id' => 1,
460
            'right_label' => 'CAN_WRITE'
461
        ]);
462
        self::insert($connection, 'roles_rights', [
463
            'role_id' => 2,
464
            'right_label' => 'CAN_WRITE'
465
        ]);
466
467
        self::insert($connection, 'users', [
468
            'id' => 1,
469
            'login' => 'john.smith',
470
            'password' => null,
471
            'status' => 'on',
472
            'country_id' => 2
473
        ]);
474
        self::insert($connection, 'users', [
475
            'id' => 2,
476
            'login' => 'jean.dupont',
477
            'password' => null,
478
            'status' => 'on',
479
            'country_id' => 1
480
        ]);
481
        self::insert($connection, 'users', [
482
            'id' => 3,
483
            'login' => 'robert.marley',
484
            'password' => null,
485
            'status' => 'off',
486
            'country_id' => 3
487
        ]);
488
        self::insert($connection, 'users', [
489
            'id' => 4,
490
            'login' => 'bill.shakespeare',
491
            'password' => null,
492
            'status' => 'off',
493
            'country_id' => 2
494
        ]);
495
496
        self::insert($connection, 'users_roles', [
497
            'user_id' => 1,
498
            'role_id' => 1,
499
        ]);
500
        self::insert($connection, 'users_roles', [
501
            'user_id' => 2,
502
            'role_id' => 1,
503
        ]);
504
        self::insert($connection, 'users_roles', [
505
            'user_id' => 3,
506
            'role_id' => 3,
507
        ]);
508
        self::insert($connection, 'users_roles', [
509
            'user_id' => 4,
510
            'role_id' => 2,
511
        ]);
512
        self::insert($connection, 'users_roles', [
513
            'user_id' => 3,
514
            'role_id' => 2,
515
        ]);
516
517
        self::insert($connection, 'ref_no_prim_key', [
518
            'from' => 'foo',
519
            'to' => 'foo',
520
        ]);
521
    }
522
523
    protected static function insert(Connection $connection, string $tableName, array $data): void
524
    {
525
        $quotedData = [];
526
        foreach ($data as $id => $value) {
527
            $quotedData[$connection->quoteIdentifier($id)] = $value;
528
        }
529
        $connection->insert($connection->quoteIdentifier($tableName), $quotedData);
530
    }
531
532
    protected static function delete(Connection $connection, string $tableName, array $data): void
533
    {
534
        $quotedData = [];
535
        foreach ($data as $id => $value) {
536
            $quotedData[$connection->quoteIdentifier($id)] = $value;
537
        }
538
        $connection->delete($connection->quoteIdentifier($tableName), $quotedData);
539
    }
540
}
541