Completed
Push — master ( f2dfe9...84d91c )
by André
35:37 queued 16:15
created

DoctrineDatabase::loadLanguageListData()   A

Complexity

Conditions 1
Paths 1

Size

Total Lines 9

Duplication

Lines 9
Ratio 100 %

Importance

Changes 0
Metric Value
cc 1
nc 1
nop 1
dl 9
loc 9
rs 9.9666
c 0
b 0
f 0
1
<?php
2
3
/**
4
 * File containing the DoctrineDatabase Language Gateway class.
5
 *
6
 * @copyright Copyright (C) eZ Systems AS. All rights reserved.
7
 * @license For full copyright and license information view LICENSE file distributed with this source code.
8
 */
9
namespace eZ\Publish\Core\Persistence\Legacy\Content\Language\Gateway;
10
11
use Doctrine\DBAL\Connection;
12
use Doctrine\DBAL\Query\QueryBuilder;
13
use eZ\Publish\Core\Persistence\Legacy\Content\Language\Gateway;
14
use eZ\Publish\SPI\Persistence\Content\Language;
15
use eZ\Publish\Core\Persistence\Database\DatabaseHandler;
16
use eZ\Publish\Core\Persistence\Database\Query;
17
use RuntimeException;
18
19
/**
20
 * Doctrine database based Language Gateway.
21
 */
22
class DoctrineDatabase extends Gateway
23
{
24
    /**
25
     * Database handler.
26
     *
27
     * @var \eZ\Publish\Core\Persistence\Database\DatabaseHandler
28
     * @deprecated Start to use DBAL $connection instead.
29
     */
30
    protected $dbHandler;
31
32
    /**
33
     * The native Doctrine connection.
34
     *
35
     * @var \Doctrine\DBAL\Connection
36
     */
37
    protected $connection;
38
39
    /**
40
     * Creates a new Doctrine database Section Gateway.
41
     *
42
     * @param \eZ\Publish\Core\Persistence\Database\DatabaseHandler $dbHandler
43
     */
44
    public function __construct(DatabaseHandler $dbHandler)
45
    {
46
        $this->dbHandler = $dbHandler;
47
        $this->connection = $dbHandler->getConnection();
48
    }
49
50
    /**
51
     * Inserts the given $language.
52
     *
53
     * @param Language $language
54
     *
55
     * @return int ID of the new language
56
     */
57
    public function insertLanguage(Language $language)
58
    {
59
        $query = $this->dbHandler->createSelectQuery();
60
        $query->select(
61
            $query->expr->max($this->dbHandler->quoteColumn('id'))
62
        )->from($this->dbHandler->quoteTable('ezcontent_language'));
63
64
        $statement = $query->prepare();
65
        $statement->execute();
66
67
        $lastId = (int)$statement->fetchColumn();
68
69
        // Legacy only supports 8 * PHP_INT_SIZE - 2 languages:
70
        // One bit cannot be used because PHP uses signed integers and a second one is reserved for the
71
        // "always available flag".
72
        if ($lastId == (2 ** (8 * PHP_INT_SIZE - 2))) {
73
            throw new RuntimeException('Maximum number of languages reached!');
74
        }
75
        // Next power of 2 for bit masks
76
        $nextId = ($lastId !== 0 ? $lastId << 1 : 2);
77
78
        $query = $this->dbHandler->createInsertQuery();
79
        $query->insertInto(
80
            $this->dbHandler->quoteTable('ezcontent_language')
81
        )->set(
82
            $this->dbHandler->quoteColumn('id'),
83
            $query->bindValue($nextId, null, \PDO::PARAM_INT)
84
        );
85
        $this->setCommonLanguageColumns($query, $language);
86
87
        $query->prepare()->execute();
88
89
        return $nextId;
90
    }
91
92
    /**
93
     * Sets columns in $query from $language.
94
     *
95
     * @param \eZ\Publish\Core\Persistence\Database\Query $query
96
     * @param \eZ\Publish\SPI\Persistence\Content\Language $language
97
     */
98
    protected function setCommonLanguageColumns(Query $query, Language $language)
99
    {
100
        $query->set(
0 ignored issues
show
Bug introduced by
It seems like you code against a concrete implementation and not the interface eZ\Publish\Core\Persistence\Database\Query as the method set() does only exist in the following implementations of said interface: eZ\Publish\Core\Persiste...ine\InsertDoctrineQuery, eZ\Publish\Core\Persiste...ine\UpdateDoctrineQuery.

Let’s take a look at an example:

interface User
{
    /** @return string */
    public function getPassword();
}

class MyUser implements User
{
    public function getPassword()
    {
        // return something
    }

    public function getDisplayName()
    {
        // return some name.
    }
}

class AuthSystem
{
    public function authenticate(User $user)
    {
        $this->logger->info(sprintf('Authenticating %s.', $user->getDisplayName()));
        // do something.
    }
}

In the above example, the authenticate() method works fine as long as you just pass instances of MyUser. However, if you now also want to pass a different implementation of User which does not have a getDisplayName() method, the code will break.

Available Fixes

  1. Change the type-hint for the parameter:

    class AuthSystem
    {
        public function authenticate(MyUser $user) { /* ... */ }
    }
    
  2. Add an additional type-check:

    class AuthSystem
    {
        public function authenticate(User $user)
        {
            if ($user instanceof MyUser) {
                $this->logger->info(/** ... */);
            }
    
            // or alternatively
            if ( ! $user instanceof MyUser) {
                throw new \LogicException(
                    '$user must be an instance of MyUser, '
                   .'other instances are not supported.'
                );
            }
    
        }
    }
    
Note: PHP Analyzer uses reverse abstract interpretation to narrow down the types inside the if block in such a case.
  1. Add the method to the interface:

    interface User
    {
        /** @return string */
        public function getPassword();
    
        /** @return string */
        public function getDisplayName();
    }
    
Loading history...
101
            $this->dbHandler->quoteColumn('locale'),
102
            $query->bindValue($language->languageCode)
103
        )->set(
104
            $this->dbHandler->quoteColumn('name'),
105
            $query->bindValue($language->name)
106
        )->set(
107
            $this->dbHandler->quoteColumn('disabled'),
108
            $query->bindValue(
109
                ((int)(!$language->isEnabled)),
110
                null,
111
                \PDO::PARAM_INT
112
            )
113
        );
114
    }
115
116
    /**
117
     * Updates the data of the given $language.
118
     *
119
     * @param Language $language
120
     */
121
    public function updateLanguage(Language $language)
122
    {
123
        $query = $this->dbHandler->createUpdateQuery();
124
        $query->update($this->dbHandler->quoteTable('ezcontent_language'));
125
126
        $this->setCommonLanguageColumns($query, $language);
127
128
        $query->where(
129
            $query->expr->eq(
130
                $this->dbHandler->quoteColumn('id'),
131
                $query->bindValue($language->id, null, \PDO::PARAM_INT)
132
            )
133
        );
134
135
        $query->prepare()->execute();
136
    }
137
138
    /**
139
     * {@inheritdoc}
140
     */
141 View Code Duplication
    public function loadLanguageListData(array $ids): iterable
142
    {
143
        $query = $this->createFindQuery();
144
        $query
145
            ->where('id IN (:ids)')
146
            ->setParameter('ids', $ids, Connection::PARAM_INT_ARRAY);
147
148
        return $query->execute()->fetchAll();
149
    }
150
151
    /**
152
     * {@inheritdoc}
153
     */
154 View Code Duplication
    public function loadLanguageListDataByLanguageCode(array $languageCodes): iterable
155
    {
156
        $query = $this->createFindQuery();
157
        $query
158
            ->where('locale IN (:locale)')
159
            ->setParameter('locale', $languageCodes, Connection::PARAM_STR_ARRAY);
160
161
        return $query->execute()->fetchAll();
162
    }
163
164
    /**
165
     * Creates a Language find query.
166
     */
167
    protected function createFindQuery(): QueryBuilder
168
    {
169
        $query = $this->connection->createQueryBuilder();
170
        $query
171
            ->select('id', 'locale', 'name', 'disabled')
172
            ->from('ezcontent_language');
173
174
        return $query;
175
    }
176
177
    /**
178
     * Loads the data for all languages.
179
     *
180
     * @return string[][]
181
     */
182
    public function loadAllLanguagesData()
183
    {
184
        $query = $this->createFindQuery();
185
186
        return $query->execute()->fetchAll();
187
    }
188
189
    /**
190
     * Deletes the language with $id.
191
     *
192
     * @param int $id
193
     */
194
    public function deleteLanguage($id)
195
    {
196
        $query = $this->dbHandler->createDeleteQuery();
197
        $query->deleteFrom(
198
            $this->dbHandler->quoteTable('ezcontent_language')
199
        )->where(
200
            $query->expr->eq(
201
                $this->dbHandler->quoteColumn('id'),
202
                $query->bindValue($id, null, \PDO::PARAM_INT)
203
            )
204
        );
205
206
        $query->prepare()->execute();
207
    }
208
209
    /**
210
     * Check whether a language may be deleted.
211
     *
212
     * @param int $id
213
     *
214
     * @return bool
215
     */
216
    public function canDeleteLanguage($id)
217
    {
218
        $query = $this->dbHandler->createSelectQuery();
219
        $query->select(
220
            $query->alias($query->expr->count('*'), 'count')
221
        )->from(
222
            $this->dbHandler->quoteTable('ezcobj_state')
223
        )->where(
224
            $query->expr->lOr(
225
                $query->expr->eq(
226
                    $this->dbHandler->quoteColumn('default_language_id'),
227
                    $query->bindValue($id, null, \PDO::PARAM_INT)
228
                ),
229
                $query->expr->gt(
230
                    $query->expr->bitAnd(
231
                        $this->dbHandler->quoteColumn('language_mask'),
232
                        $query->bindValue($id, null, \PDO::PARAM_INT)
233
                    ),
234
                    0
235
                )
236
            )
237
        );
238
239
        $statement = $query->prepare();
240
        $statement->execute();
241
242
        if ($statement->fetchColumn() > 0) {
243
            return false;
244
        }
245
246
        $query = $this->dbHandler->createSelectQuery();
247
        $query->select(
248
            $query->alias($query->expr->count('*'), 'count')
249
        )->from(
250
            $this->dbHandler->quoteTable('ezcobj_state_group')
251
        )->where(
252
            $query->expr->lOr(
253
                $query->expr->eq(
254
                    $this->dbHandler->quoteColumn('default_language_id'),
255
                    $query->bindValue($id, null, \PDO::PARAM_INT)
256
                ),
257
                $query->expr->gt(
258
                    $query->expr->bitAnd(
259
                        $this->dbHandler->quoteColumn('language_mask'),
260
                        $query->bindValue($id, null, \PDO::PARAM_INT)
261
                    ),
262
                    0
263
                )
264
            )
265
        );
266
267
        $statement = $query->prepare();
268
        $statement->execute();
269
270
        if ($statement->fetchColumn() > 0) {
271
            return false;
272
        }
273
274
        $query = $this->dbHandler->createSelectQuery();
275
        $query->select(
276
            $query->alias($query->expr->count('*'), 'count')
277
        )->from(
278
            $this->dbHandler->quoteTable('ezcobj_state_group_language')
279
        )->where(
280
            $query->expr->gt(
281
                $query->expr->bitAnd(
282
                    $this->dbHandler->quoteColumn('language_id'),
283
                    $query->bindValue($id, null, \PDO::PARAM_INT)
284
                ),
285
                0
286
            )
287
        );
288
289
        $statement = $query->prepare();
290
        $statement->execute();
291
292
        if ($statement->fetchColumn() > 0) {
293
            return false;
294
        }
295
296
        $query = $this->dbHandler->createSelectQuery();
297
        $query->select(
298
            $query->alias($query->expr->count('*'), 'count')
299
        )->from(
300
            $this->dbHandler->quoteTable('ezcobj_state_language')
301
        )->where(
302
            $query->expr->gt(
303
                $query->expr->bitAnd(
304
                    $this->dbHandler->quoteColumn('language_id'),
305
                    $query->bindValue($id, null, \PDO::PARAM_INT)
306
                ),
307
                0
308
            )
309
        );
310
311
        $statement = $query->prepare();
312
        $statement->execute();
313
314
        if ($statement->fetchColumn() > 0) {
315
            return false;
316
        }
317
318
        $query = $this->dbHandler->createSelectQuery();
319
        $query->select(
320
            $query->alias($query->expr->count('*'), 'count')
321
        )->from(
322
            $this->dbHandler->quoteTable('ezcontentclass')
323
        )->where(
324
            $query->expr->lOr(
325
                $query->expr->eq(
326
                    $this->dbHandler->quoteColumn('initial_language_id'),
327
                    $query->bindValue($id, null, \PDO::PARAM_INT)
328
                ),
329
                $query->expr->gt(
330
                    $query->expr->bitAnd(
331
                        $this->dbHandler->quoteColumn('language_mask'),
332
                        $query->bindValue($id, null, \PDO::PARAM_INT)
333
                    ),
334
                    0
335
                )
336
            )
337
        );
338
339
        $statement = $query->prepare();
340
        $statement->execute();
341
342
        if ($statement->fetchColumn() > 0) {
343
            return false;
344
        }
345
346
        $query = $this->dbHandler->createSelectQuery();
347
        $query->select(
348
            $query->alias($query->expr->count('*'), 'count')
349
        )->from(
350
            $this->dbHandler->quoteTable('ezcontentclass_name')
351
        )->where(
352
            $query->expr->gt(
353
                $query->expr->bitAnd(
354
                    $this->dbHandler->quoteColumn('language_id'),
355
                    $query->bindValue($id, null, \PDO::PARAM_INT)
356
                ),
357
                0
358
            )
359
        );
360
361
        $statement = $query->prepare();
362
        $statement->execute();
363
364
        if ($statement->fetchColumn() > 0) {
365
            return false;
366
        }
367
368
        $query = $this->dbHandler->createSelectQuery();
369
        $query->select(
370
            $query->alias($query->expr->count('*'), 'count')
371
        )->from(
372
            $this->dbHandler->quoteTable('ezcontentobject')
373
        )->where(
374
            $query->expr->lOr(
375
                $query->expr->eq(
376
                    $this->dbHandler->quoteColumn('initial_language_id'),
377
                    $query->bindValue($id, null, \PDO::PARAM_INT)
378
                ),
379
                $query->expr->gt(
380
                    $query->expr->bitAnd(
381
                        $this->dbHandler->quoteColumn('language_mask'),
382
                        $query->bindValue($id, null, \PDO::PARAM_INT)
383
                    ),
384
                    0
385
                )
386
            )
387
        );
388
389
        $statement = $query->prepare();
390
        $statement->execute();
391
392
        if ($statement->fetchColumn() > 0) {
393
            return false;
394
        }
395
396
        $query = $this->dbHandler->createSelectQuery();
397
        $query->select(
398
            $query->alias($query->expr->count('*'), 'count')
399
        )->from(
400
            $this->dbHandler->quoteTable('ezcontentobject_attribute')
401
        )->where(
402
            $query->expr->gt(
403
                $query->expr->bitAnd(
404
                    $this->dbHandler->quoteColumn('language_id'),
405
                    $query->bindValue($id, null, \PDO::PARAM_INT)
406
                ),
407
                0
408
            )
409
        );
410
411
        $statement = $query->prepare();
412
        $statement->execute();
413
414
        if ($statement->fetchColumn() > 0) {
415
            return false;
416
        }
417
418
        $query = $this->dbHandler->createSelectQuery();
419
        $query->select(
420
            $query->alias($query->expr->count('*'), 'count')
421
        )->from(
422
            $this->dbHandler->quoteTable('ezcontentobject_name')
423
        )->where(
424
            $query->expr->gt(
425
                $query->expr->bitAnd(
426
                    $this->dbHandler->quoteColumn('language_id'),
427
                    $query->bindValue($id, null, \PDO::PARAM_INT)
428
                ),
429
                0
430
            )
431
        );
432
433
        $statement = $query->prepare();
434
        $statement->execute();
435
436
        if ($statement->fetchColumn() > 0) {
437
            return false;
438
        }
439
440
        $query = $this->dbHandler->createSelectQuery();
441
        $query->select(
442
            $query->alias($query->expr->count('*'), 'count')
443
        )->from(
444
            $this->dbHandler->quoteTable('ezcontentobject_version')
445
        )->where(
446
            $query->expr->lOr(
447
                $query->expr->eq(
448
                    $this->dbHandler->quoteColumn('initial_language_id'),
449
                    $query->bindValue($id, null, \PDO::PARAM_INT)
450
                ),
451
                $query->expr->gt(
452
                    $query->expr->bitAnd(
453
                        $this->dbHandler->quoteColumn('language_mask'),
454
                        $query->bindValue($id, null, \PDO::PARAM_INT)
455
                    ),
456
                    0
457
                )
458
            )
459
        );
460
461
        $statement = $query->prepare();
462
        $statement->execute();
463
464
        if ($statement->fetchColumn() > 0) {
465
            return false;
466
        }
467
468
        $query = $this->dbHandler->createSelectQuery();
469
        $query->select(
470
            $query->alias($query->expr->count('*'), 'count')
471
        )->from(
472
            $this->dbHandler->quoteTable('ezurlalias_ml')
473
        )->where(
474
            $query->expr->gt(
475
                $query->expr->bitAnd(
476
                    $this->dbHandler->quoteColumn('lang_mask'),
477
                    $query->bindValue($id, null, \PDO::PARAM_INT)
478
                ),
479
                0
480
            )
481
        );
482
483
        $statement = $query->prepare();
484
        $statement->execute();
485
486
        return $statement->fetchColumn() == 0;
487
    }
488
}
489