Issues (3103)

Branch: master

Security Analysis    not enabled

This project does not seem to handle request data directly as such no vulnerable execution paths were found.

  Cross-Site Scripting
Cross-Site Scripting enables an attacker to inject code into the response of a web-request that is viewed by other users. It can for example be used to bypass access controls, or even to take over other users' accounts.
  File Exposure
File Exposure allows an attacker to gain access to local files that he should not be able to access. These files can for example include database credentials, or other configuration files.
  File Manipulation
File Manipulation enables an attacker to write custom data to files. This potentially leads to injection of arbitrary code on the server.
  Object Injection
Object Injection enables an attacker to inject an object into PHP code, and can lead to arbitrary code execution, file exposure, or file manipulation attacks.
  Code Injection
Code Injection enables an attacker to execute arbitrary code on the server.
  Response Splitting
Response Splitting can be used to send arbitrary responses.
  File Inclusion
File Inclusion enables an attacker to inject custom files into PHP's file loading mechanism, either explicitly passed to include, or for example via PHP's auto-loading mechanism.
  Command Injection
Command Injection enables an attacker to inject a shell command that is execute with the privileges of the web-server. This can be used to expose sensitive data, or gain access of your server.
  SQL Injection
SQL Injection enables an attacker to execute arbitrary SQL code on your database server gaining access to user data, or manipulating user data.
  XPath Injection
XPath Injection enables an attacker to modify the parts of XML document that are read. If that XML document is for example used for authentication, this can lead to further vulnerabilities similar to SQL Injection.
  LDAP Injection
LDAP Injection enables an attacker to inject LDAP statements potentially granting permission to run unauthorized queries, or modify content inside the LDAP tree.
  Header Injection
  Other Vulnerability
This category comprises other attack vectors such as manipulating the PHP runtime, loading custom extensions, freezing the runtime, or similar.
  Regex Injection
Regex Injection enables an attacker to execute arbitrary code in your PHP process.
  XML Injection
XML Injection enables an attacker to read files on your local filesystem including configuration files, or can be abused to freeze your web-server process.
  Variable Injection
Variable Injection enables an attacker to overwrite program variables with custom data, and can lead to further vulnerabilities.
Unfortunately, the security analysis is currently not available for your project. If you are a non-commercial open-source project, please contact support to gain access.

Content/ObjectState/Gateway/DoctrineDatabase.php (1 issue)

Labels
Severity

Upgrade to new PHP Analysis Engine

These results are based on our legacy PHP analysis, consider migrating to our new PHP analysis engine instead. Learn more

1
<?php
2
3
/**
4
 * @copyright Copyright (C) eZ Systems AS. All rights reserved.
5
 * @license For full copyright and license information view LICENSE file distributed with this source code.
6
 */
7
declare(strict_types=1);
8
9
namespace eZ\Publish\Core\Persistence\Legacy\Content\ObjectState\Gateway;
10
11
use Doctrine\DBAL\Connection;
12
use Doctrine\DBAL\FetchMode;
13
use Doctrine\DBAL\ParameterType;
14
use Doctrine\DBAL\Query\QueryBuilder;
15
use eZ\Publish\Core\Persistence\Legacy\Content\ObjectState\Gateway;
16
use eZ\Publish\Core\Persistence\Legacy\Content\Language\MaskGenerator;
17
use eZ\Publish\SPI\Persistence\Content\ObjectState;
18
use eZ\Publish\SPI\Persistence\Content\ObjectState\Group;
19
20
/**
21
 * Object State gateway implementation using the Doctrine database.
22
 *
23
 * @internal Gateway implementation is considered internal. Use Persistence Location Handler instead.
24
 *
25
 * @see \eZ\Publish\SPI\Persistence\Content\ObjectState\Handler
26
 */
27
final class DoctrineDatabase extends Gateway
28
{
29
    /**
30
     * Language mask generator.
31
     *
32
     * @var \eZ\Publish\Core\Persistence\Legacy\Content\Language\MaskGenerator
33
     */
34
    private $maskGenerator;
35
36
    /** @var \Doctrine\DBAL\Connection */
37
    private $connection;
38
39
    /** @var \Doctrine\DBAL\Platforms\AbstractPlatform */
40
    private $dbPlatform;
41
42
    /**
43
     * @throws \Doctrine\DBAL\DBALException
44
     */
45
    public function __construct(Connection $connection, MaskGenerator $maskGenerator)
46
    {
47
        $this->connection = $connection;
48
        $this->dbPlatform = $this->connection->getDatabasePlatform();
49
        $this->maskGenerator = $maskGenerator;
50
    }
51
52
    public function loadObjectStateData(int $stateId): array
53
    {
54
        $query = $this->createObjectStateFindQuery();
55
        $query->where(
56
            $query->expr()->eq(
57
                'state.id',
58
                $query->createPositionalParameter($stateId, ParameterType::INTEGER)
59
            )
60
        );
61
62
        $statement = $query->execute();
63
64
        return $statement->fetchAll(FetchMode::ASSOCIATIVE);
65
    }
66
67
    public function loadObjectStateDataByIdentifier(string $identifier, int $groupId): array
68
    {
69
        $query = $this->createObjectStateFindQuery();
70
        $query->where(
71
            $query->expr()->andX(
72
                $query->expr()->eq(
73
                    'state.identifier',
74
                    $query->createPositionalParameter($identifier, ParameterType::STRING)
75
                ),
76
                $query->expr()->eq(
77
                    'state.group_id',
78
                    $query->createPositionalParameter($groupId, ParameterType::INTEGER)
79
                )
80
            )
81
        );
82
83
        $statement = $query->execute();
84
85
        return $statement->fetchAll(FetchMode::ASSOCIATIVE);
86
    }
87
88
    public function loadObjectStateListData(int $groupId): array
89
    {
90
        $query = $this->createObjectStateFindQuery();
91
        $query->where(
92
            $query->expr()->eq(
93
                'state.group_id',
94
                $query->createPositionalParameter($groupId, ParameterType::INTEGER)
95
            )
96
        )->orderBy('state.priority', 'ASC');
97
98
        $statement = $query->execute();
99
100
        $rows = [];
101
        while ($row = $statement->fetch(FetchMode::ASSOCIATIVE)) {
102
            $rows[$row['ezcobj_state_id']][] = $row;
103
        }
104
105
        return array_values($rows);
106
    }
107
108
    public function loadObjectStateGroupData(int $groupId): array
109
    {
110
        $query = $this->createObjectStateGroupFindQuery();
111
        $query->where(
112
            $query->expr()->eq(
113
                'state_group.id',
114
                $query->createPositionalParameter($groupId, ParameterType::INTEGER)
115
            )
116
        );
117
118
        $statement = $query->execute();
119
120
        return $statement->fetchAll(FetchMode::ASSOCIATIVE);
121
    }
122
123
    public function loadObjectStateGroupDataByIdentifier(string $identifier): array
124
    {
125
        $query = $this->createObjectStateGroupFindQuery();
126
        $query->where(
127
            $query->expr()->eq(
128
                'state_group.identifier',
129
                $query->createPositionalParameter($identifier, ParameterType::STRING)
130
            )
131
        );
132
133
        $statement = $query->execute();
134
135
        return $statement->fetchAll(FetchMode::ASSOCIATIVE);
136
    }
137
138
    public function loadObjectStateGroupListData(int $offset, int $limit): array
139
    {
140
        $query = $this->createObjectStateGroupFindQuery();
141
        if ($limit > 0) {
142
            $query->setMaxResults($limit);
143
            $query->setFirstResult($offset);
144
        }
145
146
        $statement = $query->execute();
147
148
        $rows = [];
149
        while ($row = $statement->fetch(FetchMode::ASSOCIATIVE)) {
150
            $rows[$row['ezcobj_state_group_id']][] = $row;
151
        }
152
153
        return array_values($rows);
154
    }
155
156
    /**
157
     * @throws \Doctrine\DBAL\DBALException
158
     * @throws \eZ\Publish\API\Repository\Exceptions\NotFoundException
159
     */
160
    public function insertObjectState(ObjectState $objectState, int $groupId): void
161
    {
162
        $maxPriority = $this->getMaxPriorityForObjectStatesInGroup($groupId);
163
164
        $objectState->priority = $maxPriority === null ? 0 : (int)$maxPriority + 1;
165
        $objectState->groupId = (int)$groupId;
166
167
        $query = $this->connection->createQueryBuilder();
168
        $query
169
            ->insert(self::OBJECT_STATE_TABLE)
170
            ->values(
171
                [
172
                    'group_id' => $query->createPositionalParameter(
173
                        $objectState->groupId,
174
                        ParameterType::INTEGER
175
                    ),
176
                    'default_language_id' => $query->createPositionalParameter(
177
                        $this->maskGenerator->generateLanguageIndicator(
178
                            $objectState->defaultLanguage,
179
                            false
180
                        ),
181
                        ParameterType::INTEGER
182
                    ),
183
                    'identifier' => $query->createPositionalParameter(
184
                        $objectState->identifier,
185
                        ParameterType::STRING
186
                    ),
187
                    'language_mask' => $query->createPositionalParameter(
188
                        $this->maskGenerator->generateLanguageMaskFromLanguageCodes(
189
                            $objectState->languageCodes,
190
                            true
191
                        ),
192
                        ParameterType::INTEGER
193
                    ),
194
                    'priority' => $query->createPositionalParameter(
195
                        $objectState->priority,
196
                        ParameterType::INTEGER
197
                    ),
198
                ]
199
            );
200
201
        $query->execute();
202
203
        $objectState->id = (int)$this->connection->lastInsertId(self::OBJECT_STATE_TABLE_SEQ);
204
205
        $this->insertObjectStateTranslations($objectState);
206
207
        // If this is a first state in group, assign it to all content objects
208
        if ($maxPriority === null) {
209
            $this->connection->executeUpdate(
210
                'INSERT INTO ezcobj_state_link (contentobject_id, contentobject_state_id) ' .
211
                "SELECT id, {$objectState->id} FROM ezcontentobject"
212
            );
213
        }
214
    }
215
216
    /**
217
     * @param string[] $languageCodes
218
     *
219
     * @throws \eZ\Publish\API\Repository\Exceptions\NotFoundException
220
     */
221
    private function updateObjectStateCommonFields(
222
        string $tableName,
223
        int $id,
224
        string $identifier,
225
        string $defaultLanguageCode,
226
        array $languageCodes
227
    ): void {
228
        $query = $this->connection->createQueryBuilder();
229
        $query
230
            ->update($tableName)
231
            ->set(
232
                'default_language_id',
233
                $query->createPositionalParameter(
234
                    $this->maskGenerator->generateLanguageIndicator(
235
                        $defaultLanguageCode,
236
                        false
237
                    ),
238
                    ParameterType::INTEGER
239
                )
240
            )
241
            ->set(
242
                'identifier',
243
                $query->createPositionalParameter(
244
                    $identifier,
245
                    ParameterType::STRING
246
                )
247
            )
248
            ->set(
249
                'language_mask',
250
                $query->createPositionalParameter(
251
                    $this->maskGenerator->generateLanguageMaskFromLanguageCodes(
252
                        $languageCodes,
253
                        true
254
                    ),
255
                    ParameterType::INTEGER
256
                )
257
            )
258
            ->where(
259
                $query->expr()->eq(
260
                    'id',
261
                    $query->createPositionalParameter($id, ParameterType::INTEGER)
262
                )
263
            );
264
265
        $query->execute();
266
    }
267
268
    public function updateObjectState(ObjectState $objectState): void
269
    {
270
        // First update the state
271
        $this->updateObjectStateCommonFields(
272
            self::OBJECT_STATE_TABLE,
273
            $objectState->id,
274
            $objectState->identifier,
275
            $objectState->defaultLanguage,
276
            $objectState->languageCodes
277
        );
278
279
        // And then refresh object state translations
280
        // by removing existing ones and adding new ones
281
        $this->deleteObjectStateTranslations($objectState->id);
282
        $this->insertObjectStateTranslations($objectState);
283
    }
284
285
    public function deleteObjectState(int $stateId): void
286
    {
287
        $this->deleteObjectStateTranslations($stateId);
288
289
        $query = $this->connection->createQueryBuilder();
290
        $query
291
            ->delete(self::OBJECT_STATE_TABLE)
292
            ->where(
293
                $query->expr()->eq(
294
                    'id',
295
                    $query->createPositionalParameter($stateId, ParameterType::INTEGER)
296
                )
297
        );
298
299
        $query->execute();
300
    }
301
302
    public function updateObjectStateLinks(int $oldStateId, int $newStateId): void
303
    {
304
        $query = $this->connection->createQueryBuilder();
305
        $query
306
            ->update(self::OBJECT_STATE_LINK_TABLE)
307
            ->set(
308
                'contentobject_state_id',
309
                $query->createPositionalParameter($newStateId, ParameterType::INTEGER)
310
            )
311
            ->where(
312
                $query->expr()->eq(
313
                    'contentobject_state_id',
314
                    $query->createPositionalParameter($oldStateId, ParameterType::INTEGER)
315
                )
316
            )
317
        ;
318
319
        $query->execute();
320
    }
321
322
    /**
323
     * Change Content to object state assignment.
324
     */
325
    private function updateContentStateAssignment(
326
        int $contentId,
327
        int $stateId,
328
        int $assignedStateId
329
    ): void {
330
        // no action required if there's no change
331
        if ($stateId === $assignedStateId) {
332
            return;
333
        }
334
335
        $query = $this->connection->createQueryBuilder();
336
        $query
337
            ->update(self::OBJECT_STATE_LINK_TABLE)
338
            ->set(
339
                'contentobject_state_id',
340
                $query->createPositionalParameter($stateId, ParameterType::INTEGER)
341
            )
342
            ->where(
343
                $query->expr()->eq(
344
                    'contentobject_id',
345
                    $query->createPositionalParameter($contentId, ParameterType::INTEGER)
346
                )
347
            )
348
            ->andWhere(
349
                $query->expr()->eq(
350
                    'contentobject_state_id',
351
                    $query->createPositionalParameter($assignedStateId, ParameterType::INTEGER)
352
                )
353
            )
354
        ;
355
356
        $query->execute();
357
    }
358
359
    public function deleteObjectStateLinks(int $stateId): void
360
    {
361
        $query = $this->connection->createQueryBuilder();
362
        $query
363
            ->delete(self::OBJECT_STATE_LINK_TABLE)
364
            ->where(
365
                $query->expr()->eq(
366
                    'contentobject_state_id',
367
                    $query->createPositionalParameter($stateId, ParameterType::INTEGER)
368
                )
369
        );
370
371
        $query->execute();
372
    }
373
374
    public function insertObjectStateGroup(Group $objectStateGroup): void
375
    {
376
        $query = $this->connection->createQueryBuilder();
377
        $query
378
            ->insert(self::OBJECT_STATE_GROUP_TABLE)
379
            ->values(
380
                [
381
                    'default_language_id' => $query->createPositionalParameter(
382
                        $this->maskGenerator->generateLanguageIndicator(
383
                            $objectStateGroup->defaultLanguage,
384
                            false
385
                        ),
386
                        ParameterType::INTEGER
387
                    ),
388
                    'identifier' => $query->createPositionalParameter(
389
                        $objectStateGroup->identifier,
390
                        ParameterType::STRING
391
                    ),
392
                    'language_mask' => $query->createPositionalParameter(
393
                        $this->maskGenerator->generateLanguageMaskFromLanguageCodes(
394
                            $objectStateGroup->languageCodes,
395
                            true
396
                        ),
397
                        ParameterType::INTEGER
398
                    ),
399
                ]
400
            )
401
        ;
402
403
        $query->execute();
404
405
        $objectStateGroup->id = (int)$this->connection->lastInsertId(
406
            self::OBJECT_STATE_GROUP_TABLE_SEQ
407
        );
408
409
        $this->insertObjectStateGroupTranslations($objectStateGroup);
410
    }
411
412
    public function updateObjectStateGroup(Group $objectStateGroup): void
413
    {
414
        // First update the group
415
        $this->updateObjectStateCommonFields(
416
            self::OBJECT_STATE_GROUP_TABLE,
417
            $objectStateGroup->id,
418
            $objectStateGroup->identifier,
419
            $objectStateGroup->defaultLanguage,
420
            $objectStateGroup->languageCodes
421
        );
422
423
        // And then refresh group translations
424
        // by removing old ones and adding new ones
425
        $this->deleteObjectStateGroupTranslations($objectStateGroup->id);
426
        $this->insertObjectStateGroupTranslations($objectStateGroup);
427
    }
428
429
    public function deleteObjectStateGroup(int $groupId): void
430
    {
431
        $this->deleteObjectStateGroupTranslations($groupId);
432
433
        $query = $this->connection->createQueryBuilder();
434
        $query
435
            ->delete(self::OBJECT_STATE_GROUP_TABLE)
436
            ->where(
437
                $query->expr()->eq(
438
                    'id',
439
                    $query->createPositionalParameter($groupId, ParameterType::INTEGER)
440
                )
441
            )
442
        ;
443
444
        $query->execute();
445
    }
446
447
    public function setContentState(int $contentId, int $groupId, int $stateId): void
448
    {
449
        // First find out if $contentId is related to existing states in $groupId
450
        $assignedStateId = $this->getContentStateId($contentId, $groupId);
451
452
        if (null !== $assignedStateId) {
453
            // We already have a state assigned to $contentId, update to new one
454
            $this->updateContentStateAssignment($contentId, $stateId, $assignedStateId);
455
        } else {
456
            // No state assigned to $contentId from specified group, create assignment
457
            $this->insertContentStateAssignment($contentId, $stateId);
458
        }
459
    }
460
461
    public function loadObjectStateDataForContent(int $contentId, int $stateGroupId): array
462
    {
463
        $query = $this->createObjectStateFindQuery();
464
        $expr = $query->expr();
465
        $query
466
            ->innerJoin(
467
                'state',
468
                'ezcobj_state_link',
469
                'link',
470
                'state.id = link.contentobject_state_id'
471
            )
472
            ->where(
473
                $expr->eq(
474
                    'state.group_id',
475
                    $query->createPositionalParameter($stateGroupId, ParameterType::INTEGER)
476
                )
477
            )
478
            ->andWhere(
479
                $expr->eq(
480
                    'link.contentobject_id',
481
                    $query->createPositionalParameter($contentId, ParameterType::INTEGER)
482
                )
483
            );
484
485
        $statement = $query->execute();
486
487
        return $statement->fetchAll(FetchMode::ASSOCIATIVE);
488
    }
489
490
    public function getContentCount(int $stateId): int
491
    {
492
        $query = $this->connection->createQueryBuilder();
493
        $query
494
            ->select(
495
                $this->dbPlatform->getCountExpression('contentobject_id')
496
            )
497
            ->from(self::OBJECT_STATE_LINK_TABLE)
498
            ->where(
499
                $query->expr()->eq(
500
                    'contentobject_state_id',
501
                    $query->createPositionalParameter($stateId, ParameterType::INTEGER)
502
                )
503
            );
504
505
        return (int)$query->execute()->fetchColumn();
506
    }
507
508
    public function updateObjectStatePriority(int $stateId, int $priority): void
509
    {
510
        $query = $this->connection->createQueryBuilder();
511
        $query
512
            ->update(self::OBJECT_STATE_TABLE)
513
            ->set('priority', $query->createPositionalParameter($priority, ParameterType::INTEGER))
514
            ->where(
515
                $query->expr()->eq(
516
                    'id',
517
                    $query->createPositionalParameter($stateId, ParameterType::INTEGER)
518
                )
519
            )
520
        ;
521
522
        $query->execute();
523
    }
524
525
    /**
526
     * Create a generic query for fetching object state(s).
527
     */
528
    private function createObjectStateFindQuery(): QueryBuilder
529
    {
530
        $query = $this->connection->createQueryBuilder();
531
        $query
532
            ->select(
533
                // Object state
534
                'state.default_language_id AS ezcobj_state_default_language_id',
535
                'state.group_id AS ezcobj_state_group_id',
536
                'state.id AS ezcobj_state_id',
537
                'state.identifier AS ezcobj_state_identifier',
538
                'state.language_mask AS ezcobj_state_language_mask',
539
                'state.priority AS ezcobj_state_priority',
540
                // Object state language
541
                'lang.description AS ezcobj_state_language_description',
542
                'lang.language_id AS ezcobj_state_language_language_id',
543
                'lang.name AS ezcobj_state_language_name'
544
            )
545
            ->from(self::OBJECT_STATE_TABLE, 'state')
546
            ->innerJoin(
547
                'state',
548
                self::OBJECT_STATE_LANGUAGE_TABLE,
549
                'lang',
550
                'state.id = lang.contentobject_state_id',
551
                );
0 ignored issues
show
This code did not parse for me. Apparently, there is an error somewhere around this line:

Syntax error, unexpected ')'
Loading history...
552
553
        return $query;
554
    }
555
556
    /**
557
     * Create a generic query for fetching object state group(s).
558
     */
559
    private function createObjectStateGroupFindQuery(): QueryBuilder
560
    {
561
        $query = $this->connection->createQueryBuilder();
562
        $query
563
            ->select(
564
                // Object state group
565
                'state_group.default_language_id AS ezcobj_state_group_default_language_id',
566
                'state_group.id AS ezcobj_state_group_id',
567
                'state_group.identifier AS ezcobj_state_group_identifier',
568
                'state_group.language_mask AS ezcobj_state_group_language_mask',
569
                // Object state group language
570
                'state_group_lang.description AS ezcobj_state_group_language_description',
571
                'state_group_lang.language_id AS ezcobj_state_group_language_language_id',
572
                'state_group_lang.real_language_id AS ezcobj_state_group_language_real_language_id',
573
                'state_group_lang.name AS ezcobj_state_group_language_name'
574
            )
575
            ->from(self::OBJECT_STATE_GROUP_TABLE, 'state_group')
576
            ->innerJoin(
577
                'state_group',
578
                self::OBJECT_STATE_GROUP_LANGUAGE_TABLE,
579
                'state_group_lang',
580
                'state_group.id = state_group_lang.contentobject_state_group_id'
581
            );
582
583
        return $query;
584
    }
585
586
    /**
587
     * Insert object state group translations into database.
588
     *
589
     * @throws \eZ\Publish\API\Repository\Exceptions\NotFoundException if Object State language does not exist
590
     */
591
    private function insertObjectStateTranslations(ObjectState $objectState): void
592
    {
593
        foreach ($objectState->languageCodes as $languageCode) {
594
            $query = $this->connection->createQueryBuilder();
595
            $query
596
                ->insert(self::OBJECT_STATE_LANGUAGE_TABLE)
597
                ->values(
598
                    [
599
                        'contentobject_state_id' => $query->createPositionalParameter(
600
                            $objectState->id,
601
                            ParameterType::INTEGER
602
                        ),
603
                        'description' => $query->createPositionalParameter(
604
                            $objectState->description[$languageCode],
605
                            ParameterType::STRING
606
                        ),
607
                        'name' => $query->createPositionalParameter(
608
                            $objectState->name[$languageCode],
609
                            ParameterType::STRING
610
                        ),
611
                        'language_id' => $query->createPositionalParameter(
612
                            $this->maskGenerator->generateLanguageIndicator(
613
                                $languageCode,
614
                                $languageCode === $objectState->defaultLanguage
615
                            ),
616
                            ParameterType::INTEGER
617
                        ),
618
                    ]
619
                );
620
621
            $query->execute();
622
        }
623
    }
624
625
    /**
626
     * Deletes all translations of the $stateId state.
627
     *
628
     * @param mixed $stateId
629
     */
630
    private function deleteObjectStateTranslations(int $stateId): void
631
    {
632
        $query = $this->connection->createQueryBuilder();
633
        $query
634
            ->delete(self::OBJECT_STATE_LANGUAGE_TABLE)
635
            ->where(
636
                $query->expr()->eq(
637
                    'contentobject_state_id',
638
                    $query->createPositionalParameter($stateId, ParameterType::INTEGER)
639
                )
640
        );
641
642
        $query->execute();
643
    }
644
645
    /**
646
     * Insert object state group translations into database.
647
     *
648
     * @throws \eZ\Publish\API\Repository\Exceptions\NotFoundException if Object State Group language does not exist
649
     */
650
    private function insertObjectStateGroupTranslations(Group $objectStateGroup): void
651
    {
652
        $query = $this->connection->createQueryBuilder();
653
        $query
654
            ->insert(self::OBJECT_STATE_GROUP_LANGUAGE_TABLE)
655
            ->values(
656
                [
657
                    'contentobject_state_group_id' => ':contentobject_state_group_id',
658
                    'description' => ':description',
659
                    'name' => ':name',
660
                    'language_id' => ':language_id',
661
                    'real_language_id' => ':real_language_id',
662
                ]
663
            )
664
        ;
665
        foreach ($objectStateGroup->languageCodes as $languageCode) {
666
            $languageId = $this->maskGenerator->generateLanguageIndicator(
667
                $languageCode,
668
                $languageCode === $objectStateGroup->defaultLanguage
669
            );
670
            $query
671
                ->setParameter('contentobject_state_group_id', $objectStateGroup->id, ParameterType::INTEGER)
672
                ->setParameter('description', $objectStateGroup->description[$languageCode], ParameterType::STRING)
673
                ->setParameter('name', $objectStateGroup->name[$languageCode], ParameterType::STRING)
674
                ->setParameter('language_id', $languageId, ParameterType::INTEGER)
675
                ->setParameter('real_language_id', $languageId & ~1, ParameterType::INTEGER);
676
677
            $query->execute();
678
        }
679
    }
680
681
    /**
682
     * Delete all translations of the $groupId state group.
683
     */
684
    private function deleteObjectStateGroupTranslations(int $groupId): void
685
    {
686
        $query = $this->connection->createQueryBuilder();
687
        $query
688
            ->delete(self::OBJECT_STATE_GROUP_LANGUAGE_TABLE)
689
            ->where(
690
                $query->expr()->eq(
691
                    'contentobject_state_group_id',
692
                    $query->createPositionalParameter($groupId, ParameterType::INTEGER)
693
                )
694
        );
695
696
        $query->execute();
697
    }
698
699
    private function getMaxPriorityForObjectStatesInGroup(int $groupId): ?int
700
    {
701
        $query = $this->connection->createQueryBuilder();
702
        $query
703
            ->select(
704
                $this->dbPlatform->getMaxExpression('priority')
705
            )
706
            ->from(self::OBJECT_STATE_TABLE)
707
            ->where(
708
                $query->expr()->eq(
709
                    'group_id',
710
                    $query->createPositionalParameter($groupId, ParameterType::INTEGER)
711
                )
712
            );
713
714
        $priority = $query->execute()->fetchColumn();
715
716
        return null !== $priority ? (int)$priority : null;
717
    }
718
719
    private function getContentStateId(int $contentId, int $groupId): ?int
720
    {
721
        $query = $this->connection->createQueryBuilder();
722
        $query
723
            ->select('state.id')
724
            ->from(self::OBJECT_STATE_TABLE, 'state')
725
            ->innerJoin(
726
                'state',
727
                self::OBJECT_STATE_LINK_TABLE,
728
                'link',
729
                'state.id = link.contentobject_state_id'
730
            )
731
            ->where(
732
                $query->expr()->eq(
733
                    'state.group_id',
734
                    $query->createPositionalParameter($groupId, ParameterType::INTEGER)
735
                )
736
            )
737
            ->andWhere(
738
                $query->expr()->eq(
739
                    'link.contentobject_id',
740
                    $query->createPositionalParameter($contentId, ParameterType::INTEGER)
741
                )
742
            );
743
744
        $stateId = $query->execute()->fetch(FetchMode::COLUMN);
745
746
        return false !== $stateId ? (int)$stateId : null;
747
    }
748
749
    private function insertContentStateAssignment(int $contentId, int $stateId): void
750
    {
751
        $query = $this->connection->createQueryBuilder();
752
        $query
753
            ->insert(self::OBJECT_STATE_LINK_TABLE)
754
            ->values(
755
                [
756
                    'contentobject_id' => $query->createPositionalParameter(
757
                        $contentId,
758
                        ParameterType::INTEGER
759
                    ),
760
                    'contentobject_state_id' => $query->createPositionalParameter(
761
                        $stateId,
762
                        ParameterType::INTEGER
763
                    ),
764
                ]
765
            );
766
767
        $query->execute();
768
    }
769
}
770