MetaQuery::beforePrepare()   A
last analyzed

Complexity

Conditions 5
Paths 2

Size

Total Lines 22

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 0
CRAP Score 30

Importance

Changes 0
Metric Value
dl 0
loc 22
ccs 0
cts 17
cp 0
rs 9.2568
c 0
b 0
f 0
cc 5
nc 2
nop 0
crap 30
1
<?php
2
3
/**
4
 * @copyright  Copyright (c) Flipbox Digital Limited
5
 * @license    https://flipboxfactory.com/software/meta/license
6
 * @link       https://www.flipboxfactory.com/software/meta/
7
 */
8
9
namespace flipbox\meta\db;
10
11
use Craft;
12
use craft\db\Query;
13
use craft\elements\db\ElementQuery;
14
use craft\models\Site;
15
use flipbox\craft\sortable\associations\db\SortableAssociationQueryInterface;
16
use flipbox\meta\elements\Meta as MetaElement;
17
use flipbox\meta\fields\Meta as MetaField;
18
use flipbox\meta\helpers\Field as FieldHelper;
19
use flipbox\meta\records\Meta as MetaRecord;
20
21
/**
22
 * @author Flipbox Factory <[email protected]>
23
 * @since 1.0.0
24
 *
25
 * @property string|string[]|Site $ownerSite The handle(s) of the site(s) that the owner element should be in
26
 *
27
 * @method MetaElement[]|array all($db = null)
28
 * @method MetaElement|null one($db = null)
29
 */
30
class MetaQuery extends ElementQuery implements SortableAssociationQueryInterface
31
{
32
    use traits\Attributes;
33
34
    /**
35
     * @inheritdoc
36
     */
37
    public $orderBy = 'meta.sortOrder';
38
39
    /**
40
     * @inheritdoc
41
     */
42
    protected function beforePrepare(): bool
43
    {
44
        // If we don't have an owner, we won't have any results
45
        if (($this->ownerId !== null && empty($this->ownerId)) ||
46
            ($this->id !== null && empty($this->id))
47
        ) {
48
            return false;
49
        }
50
51
        $this->joinTables();
52
53
        $this->query->select([
54
            MetaRecord::tableAlias() . '.fieldId',
55
            MetaRecord::tableAlias() . '.ownerId',
56
            MetaRecord::tableAlias() . '.ownerSiteId',
57
            MetaRecord::tableAlias() . '.sortOrder',
58
        ]);
59
60
        $this->applyConditions($this->subQuery);
0 ignored issues
show
Bug introduced by
It seems like $this->subQuery can be null; however, applyConditions() does not accept null, maybe add an additional type check?

Unless you are absolutely sure that the expression can never be null because of other conditions, we strongly recommend to add an additional type check to your code:

/** @return stdClass|null */
function mayReturnNull() { }

function doesNotAcceptNull(stdClass $x) { }

// With potential error.
function withoutCheck() {
    $x = mayReturnNull();
    doesNotAcceptNull($x); // Potential error here.
}

// Safe - Alternative 1
function withCheck1() {
    $x = mayReturnNull();
    if ( ! $x instanceof stdClass) {
        throw new \LogicException('$x must be defined.');
    }
    doesNotAcceptNull($x);
}

// Safe - Alternative 2
function withCheck2() {
    $x = mayReturnNull();
    if ($x instanceof stdClass) {
        doesNotAcceptNull($x);
    }
}
Loading history...
61
62
        return parent::beforePrepare();
63
    }
64
65
    /**
66
     * Sets the [[ownerSiteId]] and [[siteId]] properties.
67
     *
68
     * @param int|null $value The property value
69
     * @return static self reference
70
     */
71
    public function ownerSiteId($value)
72
    {
73
        $this->ownerSiteId = $value;
74
75
        if ($value && strtolower($value) !== ':empty:') {
0 ignored issues
show
Bug Best Practice introduced by
The expression $value of type integer|null is loosely compared to true; this is ambiguous if the integer can be zero. You might want to explicitly use !== null instead.

In PHP, under loose comparison (like ==, or !=, or switch conditions), values of different types might be equal.

For integer values, zero is a special case, in particular the following results might be unexpected:

0   == false // true
0   == null  // true
123 == false // false
123 == null  // false

// It is often better to use strict comparison
0 === false // false
0 === null  // false
Loading history...
76
            // A block will never exist in a site that is different than its ownerSiteId,
77
            // so let's set the siteId param here too.
78
            $this->siteId = (int)$value;
79
        }
80
81
        return $this;
82
    }
83
84
    /**
85
     * Join element/content tables
86
     */
87
    private function joinTables()
88
    {
89
        $this->joinElementTable(MetaRecord::tableAlias());
90
91
        // Figure out which content table to use
92
        $this->contentTable = null;
93
94
        if (!$this->fieldId && $this->id && is_numeric($this->id)) {
95
            $fieldId = (new Query())
96
                ->select('fieldId')
97
                ->from(MetaRecord::tableName())
98
                ->where(['id' => $this->id])
99
                ->scalar();
100
101
            if (empty($fieldId)) {
102
                return;
103
            }
104
105
            $this->fieldId = (int) $fieldId;
106
        }
107
108
        if ($this->fieldId && is_numeric($this->fieldId)) {
109
            /** @var MetaField $field */
110
            $field = Craft::$app->getFields()->getFieldById($this->fieldId);
111
112
            if ($field) {
113
                $this->contentTable = FieldHelper::getContentTableName($field->id);
114
            }
115
        }
116
    }
117
118
    /**
119
     * @inheritdoc
120
     */
121
    protected function customFields(): array
122
    {
123
        return Craft::$app->getFields()->getAllFields(
124
            FieldHelper::getContextById($this->fieldId)
125
        );
126
    }
127
}
128