Completed
Push — master ( 460b97...b63ecb )
by Ryan
05:27
created

EloquentQueryBuilder::get()   C

Complexity

Conditions 8
Paths 4

Size

Total Lines 34
Code Lines 20

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
cc 8
eloc 20
nc 4
nop 1
dl 0
loc 34
rs 5.3846
c 0
b 0
f 0
1
<?php namespace Anomaly\Streams\Platform\Model;
2
3
use Anomaly\Streams\Platform\Assignment\AssignmentModel;
4
use Anomaly\Streams\Platform\Collection\CacheCollection;
5
use Anomaly\Streams\Platform\Entry\Contract\EntryInterface;
6
use Anomaly\Streams\Platform\Entry\EntryModel;
7
use Database\Query\JoinClause;
8
use Illuminate\Database\Eloquent\Builder;
9
10
/**
11
 * Class EloquentQueryBuilder
12
 *
13
 * @link    http://pyrocms.com/
14
 * @author  PyroCMS, Inc. <[email protected]>
15
 * @author  Ryan Thompson <[email protected]>
16
 */
17
class EloquentQueryBuilder extends Builder
18
{
19
20
    /**
21
     * Runtime cache.
22
     *
23
     * @var array
24
     */
25
    protected static $cache = [];
26
27
    /**
28
     * The model being queried.
29
     *
30
     * @var EloquentModel
31
     */
32
    protected $model;
33
34
    /**
35
     * Execute the query as a "select" statement.
36
     *
37
     * @param  array $columns
38
     * @return \Illuminate\Database\Eloquent\Collection|static[]
39
     */
40
    public function get($columns = ['*'])
41
    {
42
        $key = $this->getCacheKey();
43
44
        if (
45
            env('INSTALLED')
46
            && env('DB_CACHE') !== false
47
            && $this->model instanceof EntryModel
48
            && isset(self::$cache[$this->model->getCacheCollectionKey()][$key])
49
        ) {
50
            return self::$cache[$this->model->getCacheCollectionKey()][$key];
51
        }
52
53
        $this->orderByDefault();
54
55
        if (env('DB_CACHE') && $this->model->getTtl()) {
56
57
            $this->rememberIndex();
58
59
            try {
60
                return app('cache')->remember(
61
                    $this->getCacheKey(),
62
                    $this->model->getTtl(),
63
                    function () use ($columns) {
64
                        return parent::get($columns);
65
                    }
66
                );
67
            } catch (\Exception $e) {
68
                return parent::get($columns);
0 ignored issues
show
Bug Compatibility introduced by
The expression parent::get($columns); of type Illuminate\Database\Eloq...base\Eloquent\Builder[] adds the type Illuminate\Database\Eloquent\Builder[] to the return on line 68 which is incompatible with the return type documented by Anomaly\Streams\Platform...oquentQueryBuilder::get of type Illuminate\Database\Eloq...\EloquentQueryBuilder[].
Loading history...
69
            }
70
        }
71
72
        return self::$cache[$this->model->getCacheCollectionKey()][$key] = parent::get($columns);
0 ignored issues
show
Bug Compatibility introduced by
The expression self::$cache[$this->mode... parent::get($columns); of type Illuminate\Database\Eloq...base\Eloquent\Builder[] adds the type Illuminate\Database\Eloquent\Builder[] to the return on line 72 which is incompatible with the return type documented by Anomaly\Streams\Platform...oquentQueryBuilder::get of type Illuminate\Database\Eloq...\EloquentQueryBuilder[].
Loading history...
73
    }
74
75
    /**
76
     * Return if a table has been joined or not.
77
     *
78
     * @param $table
79
     * @return bool
80
     */
81
    public function hasJoin($table)
82
    {
83
        if (!$this->query->joins) {
0 ignored issues
show
Bug Best Practice introduced by
The expression $this->query->joins of type array is implicitly converted to a boolean; are you sure this is intended? If so, consider using empty($expr) instead to make it clear that you intend to check for an array without elements.

This check marks implicit conversions of arrays to boolean values in a comparison. While in PHP an empty array is considered to be equal (but not identical) to false, this is not always apparent.

Consider making the comparison explicit by using empty(..) or ! empty(...) instead.

Loading history...
84
            return false;
85
        }
86
87
        /* @var JoinClause $join */
88
        foreach ($this->query->joins as $join) {
89
            if ($join->table === $table) {
90
                return true;
91
            }
92
        }
93
94
        return false;
95
    }
96
97
    /**
98
     * Remember and index.
99
     *
100
     * @return $this
101
     */
102
    protected function rememberIndex()
103
    {
104
        if ($this->model->getTtl()) {
105
            $this->indexCacheCollection();
106
        }
107
108
        return $this;
109
    }
110
111
    /**
112
     * Index cache collection
113
     *
114
     * @return object
115
     */
116
    protected function indexCacheCollection()
117
    {
118
        (new CacheCollection())
119
            ->make([$this->getCacheKey()])
120
            ->setKey($this->model->getCacheCollectionKey())
121
            ->index();
122
123
        return $this;
124
    }
125
126
    /**
127
     * Get the unique cache key for the query.
128
     *
129
     * @return string
130
     */
131
    public function getCacheKey()
132
    {
133
        $name = $this->model->getConnectionName();
134
135
        return md5($name . $this->toSql() . serialize($this->getBindings()));
0 ignored issues
show
Documentation Bug introduced by
The method toSql does not exist on object<Anomaly\Streams\P...l\EloquentQueryBuilder>? Since you implemented __call, maybe consider adding a @method annotation.

If you implement __call and you know which methods are available, you can improve IDE auto-completion and static analysis by adding a @method annotation to the class.

This is often the case, when __call is implemented by a parent class and only the child class knows which methods exist:

class ParentClass {
    private $data = array();

    public function __call($method, array $args) {
        if (0 === strpos($method, 'get')) {
            return $this->data[strtolower(substr($method, 3))];
        }

        throw new \LogicException(sprintf('Unsupported method: %s', $method));
    }
}

/**
 * If this class knows which fields exist, you can specify the methods here:
 *
 * @method string getName()
 */
class SomeClass extends ParentClass { }
Loading history...
Documentation Bug introduced by
The method getBindings does not exist on object<Anomaly\Streams\P...l\EloquentQueryBuilder>? Since you implemented __call, maybe consider adding a @method annotation.

If you implement __call and you know which methods are available, you can improve IDE auto-completion and static analysis by adding a @method annotation to the class.

This is often the case, when __call is implemented by a parent class and only the child class knows which methods exist:

class ParentClass {
    private $data = array();

    public function __call($method, array $args) {
        if (0 === strpos($method, 'get')) {
            return $this->data[strtolower(substr($method, 3))];
        }

        throw new \LogicException(sprintf('Unsupported method: %s', $method));
    }
}

/**
 * If this class knows which fields exist, you can specify the methods here:
 *
 * @method string getName()
 */
class SomeClass extends ParentClass { }
Loading history...
136
    }
137
138
    /**
139
     * Set the model TTl.
140
     *
141
     * @param $ttl
142
     * @return $this
143
     */
144
    public function cache($ttl)
145
    {
146
        $this->model->setTtl($ttl);
147
148
        return $this;
149
    }
150
151
    /**
152
     * Get fresh models / disable cache
153
     *
154
     * @param  boolean $fresh
155
     * @return object
156
     */
157
    public function fresh($fresh = true)
158
    {
159
        if ($fresh) {
160
            $this->model->setTtl(0);
161
        }
162
163
        return $this;
164
    }
165
166
    /**
167
     * Update a record in the database.
168
     *
169
     * @param  array $values
170
     * @return int
171
     */
172
    public function update(array $values)
173
    {
174
        $this->model->fireEvent('updatingMultiple');
175
176
        $return = parent::update($values);
177
178
        $this->model->fireEvent('updatedMultiple');
179
180
        return $return;
181
    }
182
183
    /**
184
     * Delete a record from the database.
185
     *
186
     * @return mixed
187
     */
188
    public function delete()
189
    {
190
        $this->model->fireEvent('deletingMultiple');
191
192
        $return = parent::delete();
193
194
        $this->model->fireEvent('deletedMultiple');
195
196
        return $return;
197
    }
198
199
    /**
200
     * Order by sort_order if null.
201
     */
202
    protected function orderByDefault()
203
    {
204
        $model = $this->getModel();
205
        $query = $this->getQuery();
206
207
        if ($query->orders === null) {
208
            if ($model instanceof AssignmentModel) {
209
                $query->orderBy('sort_order', 'ASC');
210
            } elseif ($model instanceof EntryInterface) {
211
                if ($model->getStream()->isSortable()) {
212
                    $query->orderBy('sort_order', 'ASC');
213
                } elseif ($model->titleColumnIsTranslatable()) {
214
                    if (!$this->hasJoin($model->getTranslationsTableName())) {
215
                        $this->query->leftJoin(
216
                            $model->getTranslationsTableName(),
217
                            $model->getTableName() . '.id',
218
                            '=',
219
                            $model->getTranslationsTableName() . '.entry_id'
220
                        );
221
                    }
222
223
                    $this
0 ignored issues
show
Documentation Bug introduced by
The method distinct does not exist on object<Anomaly\Streams\P...l\EloquentQueryBuilder>? Since you implemented __call, maybe consider adding a @method annotation.

If you implement __call and you know which methods are available, you can improve IDE auto-completion and static analysis by adding a @method annotation to the class.

This is often the case, when __call is implemented by a parent class and only the child class knows which methods exist:

class ParentClass {
    private $data = array();

    public function __call($method, array $args) {
        if (0 === strpos($method, 'get')) {
            return $this->data[strtolower(substr($method, 3))];
        }

        throw new \LogicException(sprintf('Unsupported method: %s', $method));
    }
}

/**
 * If this class knows which fields exist, you can specify the methods here:
 *
 * @method string getName()
 */
class SomeClass extends ParentClass { }
Loading history...
224
                        ->distinct()
225
                        ->select($model->getTableName() . '.*')
226
                        ->where(
227
                            function (Builder $query) use ($model) {
228
                                $query->where($model->getTranslationsTableName() . '.locale', config('app.locale'));
229
                                $query->orWhere(
230
                                    $model->getTranslationsTableName() . '.locale',
231
                                    config('app.fallback_locale')
232
                                );
233
                                $query->orWhereNull($model->getTranslationsTableName() . '.locale');
234
                            }
235
                        )
236
                        ->orderBy($model->getTranslationsTableName() . '.' . $model->getTitleName(), 'ASC');
237
                } elseif ($model->getTitleName() && $model->getTitleName() !== 'id') {
238
                    $query->orderBy($model->getTitleName(), 'ASC');
239
                }
240
            }
241
        }
242
    }
243
}
244