Completed
Push — EZP-31084-part2-poc ( f20bda )
by André
19:16
created

Base   A

Complexity

Total Complexity 20

Size/Duplication

Total Lines 143
Duplicated Lines 0 %

Coupling/Cohesion

Components 1
Dependencies 4

Importance

Changes 0
Metric Value
dl 0
loc 143
rs 10
c 0
b 0
f 0
wmc 20
lcom 1
cbo 4

6 Methods

Rating   Name   Duplication   Size   Complexity  
A operateInt() 0 19 3
A operateString() 0 19 3
A addMainLocationTableIfNeeded() 0 14 2
A addInnerJoinIfNeeded() 0 8 2
A addLeftJoinIfNeeded() 0 8 2
B queryPartExists() 0 14 8
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\Query\CriterionHandler;
10
11
use Doctrine\DBAL\Connection;
12
use Doctrine\DBAL\ParameterType;
13
use eZ\Publish\API\Repository\Exceptions\NotImplementedException;
14
use eZ\Publish\API\Repository\Values\Content\Query\Criterion;
15
use Doctrine\DBAL\Query\QueryBuilder;
16
use eZ\Publish\Core\Persistence\Legacy\Content\Query\CriterionHandler;
17
18
/**
19
 * Optional abstract Base with utility functions for common needs.
20
 */
21
abstract class Base implements CriterionHandler
22
{
23
    /**
24
     * Map of criterion operators to the respective function names
25
     * in the DoctrineDatabase DBAL.
26
     *
27
     * @var array
28
     */
29
    protected const DBAL_COMPARIONS_MAP = [
30
        Criterion\Operator::EQ => 'eq',
31
        Criterion\Operator::GT => 'gt',
32
        Criterion\Operator::GTE => 'gte',
33
        Criterion\Operator::LT => 'lt',
34
        Criterion\Operator::LTE => 'lte',
35
    ];
36
37
38
    protected function operateInt(QueryBuilder $query, string $column, Criterion $criterion): string
39
    {
40
        if ($criterion->operator === Criterion\Operator::IN) {
41
            return $query->expr()->in(
42
                $column,
43
                $query->createNamedParameter((array)$criterion->value, Connection::PARAM_INT_ARRAY)
44
            );
45
        }
46
47
        if (!isset(self::DBAL_COMPARIONS_MAP[$criterion->operator])) {
48
            throw new NotImplementedException(sprintf("Operator '%s' not implemented for criterion '%s'", $criterion->operator, get_class($criterion)));
49
        }
50
51
        $functionName = self::DBAL_COMPARIONS_MAP[$criterion->operator];
52
        return $query->expr()->$functionName(
53
            $column,
54
            $query->createNamedParameter((array)$criterion->value, ParameterType::INTEGER)
55
        );
56
    }
57
58
59
    protected function operateString(QueryBuilder $query, string $column, Criterion $criterion): string
60
    {
61
        if ($criterion->operator === Criterion\Operator::IN) {
62
            return $query->expr()->in(
63
                $column,
64
                $query->createNamedParameter((array)$criterion->value, Connection::PARAM_STR_ARRAY)
65
            );
66
        }
67
68
        if (!isset(self::DBAL_COMPARIONS_MAP[$criterion->operator])) {
69
            throw new NotImplementedException(sprintf("Operator '%s' not implemented for criterion '%s'", $criterion->operator, get_class($criterion)));
70
        }
71
72
        $functionName = self::DBAL_COMPARIONS_MAP[$criterion->operator];
73
        return $query->expr()->$functionName(
74
            $column,
75
            $query->createNamedParameter((array)$criterion->value, ParameterType::STRING)
76
        );
77
    }
78
79
    /**
80
     * Adds main location left join, if location is not already present as from OR join.
81
     *
82
     * @param QueryBuilder $query
83
     */
84
    protected function addMainLocationTableIfNeeded(QueryBuilder $query): void
85
    {
86
        if ($this->queryPartExists($query, 'from', 'l')) {
87
            return;
88
        }
89
90
        $this->addLeftJoinIfNeeded(
91
            $query,
92
            'content',
93
            'ezcontentobject_tree',
94
            'location',
95
            'location.contentobject_id = content.id AND location.node_id = location.main_node_id'
96
        );
97
    }
98
99
100
    /**
101
     * Adds a inner join if needed, unique key needs to be $alias across all joins.
102
     *
103
     * <code>
104
     *     $this->addInnerJoinIfNeeded($queryBuilder, 'u', 'phonenumbers', 'p', 'p.is_primary = 1');
105
     * </code>
106
     *
107
     * @param QueryBuilder $query
108
     * @param string $fromAlias The alias that points to a from clause.
109
     * @param string $join      The table name to join.
110
     * @param string $alias     The alias of the join table.
111
     * @param string $condition The condition for the join.
112
     */
113
    protected function addInnerJoinIfNeeded(QueryBuilder $query, string $fromAlias, string $join, string $alias, string $condition = null): void
114
    {
115
        if ($this->queryPartExists($query, 'join', $alias)) {
116
            return;
117
        }
118
119
        $query->innerJoin($fromAlias, $join, $alias, $condition);
120
    }
121
122
    /**
123
     * Adds a left "outer" join if needed, unique key needs to be $alias across all joins.
124
     *
125
     * Warning: Any where on joined table will be ignored if there is no matching row(s) within $condition.
126
     *
127
     * <code>
128
     *     $this->addLeftJoinIfNeeded($queryBuilder, 'u', 'phonenumbers', 'p', 'p.is_primary = 1');
129
     * </code>
130
     *
131
     * @param QueryBuilder $query
132
     * @param string $fromAlias The alias that points to a from clause.
133
     * @param string $join      The table name to join.
134
     * @param string $alias     The alias of the join table.
135
     * @param string $condition The condition for the join.
136
     */
137
    protected function addLeftJoinIfNeeded(QueryBuilder $query, string $fromAlias, string $join, string $alias, string $condition = null): void
138
    {
139
        if ($this->queryPartExists($query, 'join', $alias)) {
140
            return;
141
        }
142
143
        $query->leftJoin($fromAlias, $join, $alias, $condition);
144
    }
145
146
    /**
147
     * @internal
148
     */
149
    private function queryPartExists(QueryBuilder $query, string $queryPartName, string $alias): bool
150
    {
151
        foreach ($query->getQueryPart($queryPartName) as $part){
152
153
            if ($queryPartName === 'join' && isset($part['joinAlias']) && $part['joinAlias'] === $alias) {
154
                return true;
155
            }
156
            if ($queryPartName === 'from' && isset($part['alias']) && $part['alias'] === $alias) {
157
                return true;
158
            }
159
        }
160
161
        return false;
162
    }
163
}
164