Completed
Push — master ( 98a062...441031 )
by Ryan
10:10
created

EloquentQueryBuilder::orderByDefault()   C

Complexity

Conditions 9
Paths 8

Size

Total Lines 46
Code Lines 31

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
cc 9
eloc 31
nc 8
nop 0
dl 0
loc 46
rs 5.0942
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
            && PHP_SAPI != 'cli'
47
            && env('DB_CACHE') !== false
48
            && $this->model instanceof EntryModel
49
            && isset(self::$cache[$this->model->getCacheCollectionKey()][$key])
50
        ) {
51
            return self::$cache[$this->model->getCacheCollectionKey()][$key];
52
        }
53
54
        $this->orderByDefault();
55
56
        if (PHP_SAPI != 'cli' && env('DB_CACHE') && $this->model->getTtl()) {
57
58
            $this->rememberIndex();
59
60
            try {
61
                return app('cache')->remember(
62
                    $this->getCacheKey(),
63
                    $this->model->getTtl(),
64
                    function () use ($columns) {
65
                        return parent::get($columns);
66
                    }
67
                );
68
            } catch (\Exception $e) {
69
                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 69 which is incompatible with the return type documented by Anomaly\Streams\Platform...oquentQueryBuilder::get of type Illuminate\Database\Eloq...\EloquentQueryBuilder[].
Loading history...
70
            }
71
        }
72
73
        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 73 which is incompatible with the return type documented by Anomaly\Streams\Platform...oquentQueryBuilder::get of type Illuminate\Database\Eloq...\EloquentQueryBuilder[].
Loading history...
74
    }
75
76
    /**
77
     * Return if a table has been joined or not.
78
     *
79
     * @param $table
80
     * @return bool
81
     */
82
    public function hasJoin($table)
83
    {
84
        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...
85
            return false;
86
        }
87
88
        /* @var JoinClause $join */
89
        foreach ($this->query->joins as $join) {
90
            if ($join->table === $table) {
91
                return true;
92
            }
93
        }
94
95
        return false;
96
    }
97
98
    /**
99
     * Remember and index.
100
     *
101
     * @return $this
102
     */
103
    protected function rememberIndex()
104
    {
105
        if ($this->model->getTtl()) {
106
            $this->indexCacheCollection();
107
        }
108
109
        return $this;
110
    }
111
112
    /**
113
     * Index cache collection
114
     *
115
     * @return object
116
     */
117
    protected function indexCacheCollection()
118
    {
119
        (new CacheCollection())
120
            ->make([$this->getCacheKey()])
121
            ->setKey($this->model->getCacheCollectionKey())
122
            ->index();
123
124
        return $this;
125
    }
126
127
    /**
128
     * Drop a cache collection
129
     * from runtime cache.
130
     *
131
     * @param $collection
132
     */
133
    public static function dropRuntimeCache($collection)
134
    {
135
        unset(self::$cache[$collection]);
136
    }
137
138
    /**
139
     * Get the unique cache key for the query.
140
     *
141
     * @return string
142
     */
143
    public function getCacheKey()
144
    {
145
        $name = $this->model->getConnectionName();
146
147
        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...
148
    }
149
150
    /**
151
     * Set the model TTl.
152
     *
153
     * @param $ttl
154
     * @return $this
155
     */
156
    public function cache($ttl)
157
    {
158
        $this->model->setTtl($ttl);
159
160
        return $this;
161
    }
162
163
    /**
164
     * Get fresh models / disable cache
165
     *
166
     * @param  boolean $fresh
167
     * @return object
168
     */
169
    public function fresh($fresh = true)
170
    {
171
        if ($fresh) {
172
            $this->model->setTtl(0);
173
        }
174
175
        return $this;
176
    }
177
178
    /**
179
     * Update a record in the database.
180
     *
181
     * @param  array $values
182
     * @return int
183
     */
184
    public function update(array $values)
185
    {
186
        $this->model->fireEvent('updatingMultiple');
187
188
        $return = parent::update($values);
189
190
        $this->model->fireEvent('updatedMultiple');
191
192
        return $return;
193
    }
194
195
    /**
196
     * Delete a record from the database.
197
     *
198
     * @return mixed
199
     */
200
    public function delete()
201
    {
202
        $this->model->fireEvent('deletingMultiple');
203
204
        $return = parent::delete();
205
206
        $this->model->fireEvent('deletedMultiple');
207
208
        return $return;
209
    }
210
211
    /**
212
     * Order by sort_order if null.
213
     */
214
    protected function orderByDefault()
215
    {
216
        $model = $this->getModel();
217
        $query = $this->getQuery();
218
219
        if ($query->orders === null) {
220
            if ($model instanceof AssignmentModel) {
221
                $query->orderBy('sort_order', 'ASC');
222
            } elseif ($model instanceof EntryInterface) {
223
                if ($model->getStream()->isSortable()) {
224
                    $query->orderBy('sort_order', 'ASC');
225
                } elseif ($model->titleColumnIsTranslatable()) {
226
                    if (!$this->hasJoin($model->getTranslationsTableName())) {
227
                        $this->query->leftJoin(
228
                            $model->getTranslationsTableName(),
229
                            $model->getTableName() . '.id',
230
                            '=',
231
                            $model->getTranslationsTableName() . '.entry_id'
232
                        );
233
                    }
234
235
                    $this
0 ignored issues
show
Documentation Bug introduced by
The method groupBy 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...
236
                        ->groupBy(
237
                            [
238
                                $model->getTableName() . '.id',
239
                                $model->getTranslationsTableName() . '.' . $model->getTitleName(),
240
                            ]
241
                        )
242
                        ->select($model->getTableName() . '.*')
243
                        ->where(
244
                            function (Builder $query) use ($model) {
245
                                $query->where($model->getTranslationsTableName() . '.locale', config('app.locale'));
246
                                $query->orWhere(
247
                                    $model->getTranslationsTableName() . '.locale',
248
                                    config('app.fallback_locale')
249
                                );
250
                                $query->orWhereNull($model->getTranslationsTableName() . '.locale');
251
                            }
252
                        )
253
                        ->orderBy($model->getTranslationsTableName() . '.' . $model->getTitleName(), 'ASC');
254
                } elseif ($model->getTitleName() && $model->getTitleName() !== 'id') {
255
                    $query->orderBy($model->getTitleName(), 'ASC');
256
                }
257
            }
258
        }
259
    }
260
}
261