Completed
Push — develop ( 009567...fb0a26 )
by Nate
08:31
created

modifyElementsQueryForStringValue()   A

Complexity

Conditions 4
Paths 4

Size

Total Lines 15

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 0
CRAP Score 20

Importance

Changes 0
Metric Value
dl 0
loc 15
c 0
b 0
f 0
ccs 0
cts 13
cp 0
rs 9.7666
cc 4
nc 4
nop 2
crap 20
1
<?php
2
3
/**
4
 * @copyright  Copyright (c) Flipbox Digital Limited
5
 * @license    https://github.com/flipboxfactory/craft-integration/blob/master/LICENSE
6
 * @link       https://github.com/flipboxfactory/craft-integration/
7
 */
8
9
namespace flipbox\craft\integration\fields;
10
11
use craft\elements\db\ElementQuery;
12
use craft\elements\db\ElementQueryInterface;
13
use craft\helpers\Db;
14
use flipbox\craft\integration\records\IntegrationAssociation;
15
16
/**
17
 * @author Flipbox Factory <[email protected]>
18
 * @since 2.0.0
19
 *
20
 * @property int $id
21
 * @property int $elementId
22
 * @property int $objectId
23
 */
24
trait ModifyElementQueryTrait
25
{
26
    /**
27
     * @return string
28
     */
29
    abstract public static function recordClass(): string;
30
31
    /*******************************************
32
     * MODIFY ELEMENT QUERY
33
     *******************************************/
34
35
    /**
36
     * @inheritdoc
37
     */
38
    public function modifyElementsQuery(
39
        ElementQueryInterface $query,
40
        $value
41
    ) {
42
        if ($value === null || !$query instanceof ElementQuery) {
43
            return null;
44
        }
45
46
        if ($value === false) {
47
            return false;
48
        }
49
50
        if (is_string($value)) {
51
            $this->modifyElementsQueryForStringValue($query, $value);
52
            return null;
53
        }
54
55
        $this->modifyElementsQueryForTargetValue($query, $value);
56
        return null;
57
    }
58
59
    /**
60
     * @param ElementQuery $query
61
     * @param string $value
62
     */
63
    protected function modifyElementsQueryForStringValue(
64
        ElementQuery $query,
65
        string $value
66
    ) {
67
        if ($value === 'not :empty:') {
68
            $value = ':notempty:';
69
        }
70
71
        if ($value === ':notempty:' || $value === ':empty:') {
72
            $this->modifyElementsQueryForEmptyValue($query, $value);
73
            return;
74
        }
75
76
        $this->modifyElementsQueryForTargetValue($query, $value);
77
    }
78
79
    /**
80
     * @param ElementQuery $query
81
     * @param $value
82
     */
83
    protected function modifyElementsQueryForTargetValue(
84
        ElementQuery $query,
85
        $value
86
    ) {
87
        /** @var IntegrationAssociation $recordClass */
88
        $recordClass = static::recordClass();
89
90
        $alias = $recordClass::tableAlias();
91
        $name = $recordClass::tableName();
92
93
        $joinTable = "{$name} {$alias}";
94
        $query->query->innerJoin($joinTable, "[[{$alias}.elementId]] = [[subquery.elementsId]]");
95
        $query->subQuery->innerJoin($joinTable, "[[{$alias}.elementId]] = [[elements.id]]");
96
97
        $query->subQuery->andWhere(
98
            Db::parseParam($alias . '.fieldId', $this->id)
1 ignored issue
show
Bug introduced by
It seems like \craft\helpers\Db::parse... '.fieldId', $this->id) targeting craft\helpers\Db::parseParam() can also be of type string; however, craft\db\Query::andWhere() does only seem to accept array, maybe add an additional type check?

This check looks at variables that are passed out again to other methods.

If the outgoing method call has stricter type requirements than the method itself, an issue is raised.

An additional type check may prevent trouble.

Loading history...
99
        );
100
101
        $query->subQuery->andWhere(
102
            Db::parseParam($alias . '.objectId', $value)
1 ignored issue
show
Bug introduced by
It seems like \craft\helpers\Db::parse... . '.objectId', $value) targeting craft\helpers\Db::parseParam() can also be of type string; however, craft\db\Query::andWhere() does only seem to accept array, maybe add an additional type check?

This check looks at variables that are passed out again to other methods.

If the outgoing method call has stricter type requirements than the method itself, an issue is raised.

An additional type check may prevent trouble.

Loading history...
103
        );
104
105
        $query->query->distinct(true);
106
    }
107
108
    /**
109
     * @param ElementQuery $query
110
     * @param string $value
111
     */
112
    protected function modifyElementsQueryForEmptyValue(
113
        ElementQuery $query,
114
        string $value
115
    ) {
116
        $operator = ($value === ':notempty:' ? '!=' : '=');
117
        $query->subQuery->andWhere(
118
            $this->emptyValueSubSelect(
0 ignored issues
show
Documentation introduced by
$this->emptyValueSubSelect($operator) is of type string, but the function expects a array.

It seems like the type of the argument is not accepted by the function/method which you are calling.

In some cases, in particular if PHP’s automatic type-juggling kicks in this might be fine. In other cases, however this might be a bug.

We suggest to add an explicit type cast like in the following example:

function acceptsInteger($int) { }

$x = '123'; // string "123"

// Instead of
acceptsInteger($x);

// we recommend to use
acceptsInteger((integer) $x);
Loading history...
119
                $operator
120
            )
121
        );
122
    }
123
124
    /**
125
     * @param string $operator
126
     * @return string
127
     */
128
    protected function emptyValueSubSelect(
129
        string $operator
130
    ): string {
131
132
        /** @var IntegrationAssociation $recordClass */
133
        $recordClass = static::recordClass();
134
135
        $alias = $recordClass::tableAlias();
136
        $name = $recordClass::tableName();
137
138
        return "(select count([[{$alias}.elementId]]) from " .
139
            $name .
140
            " {{{$alias}}} where [[{$alias}.elementId" .
141
            "]] = [[elements.id]] and [[{$alias}.fieldId]] = {$this->id}) {$operator} 0";
142
    }
143
}
144