Passed
Pull Request — master (#68)
by David
03:59 queued 44s
created

TDBMAbstractServiceTest   A

Complexity

Total Complexity 25

Size/Duplication

Total Lines 468
Duplicated Lines 0 %

Importance

Changes 0
Metric Value
wmc 25
dl 0
loc 468
rs 10
c 0
b 0
f 0

11 Methods

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