Completed
Push — master ( 0e9bc5...7ef25f )
by Ryan
15:00
created

EloquentQueryBuilder::dropRuntimeCache()   A

Complexity

Conditions 1
Paths 1

Size

Total Lines 4
Code Lines 2

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
cc 1
eloc 2
nc 1
nop 1
dl 0
loc 4
rs 10
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
     * Drop a cache collection
128
     * from runtime cache.
129
     *
130
     * @param $collection
131
     */
132
    public static function dropRuntimeCache($collection)
133
    {
134
        unset(self::$cache[$collection]);
135
    }
136
137
    /**
138
     * Get the unique cache key for the query.
139
     *
140
     * @return string
141
     */
142
    public function getCacheKey()
143
    {
144
        $name = $this->model->getConnectionName();
145
146
        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...
147
    }
148
149
    /**
150
     * Set the model TTl.
151
     *
152
     * @param $ttl
153
     * @return $this
154
     */
155
    public function cache($ttl)
156
    {
157
        $this->model->setTtl($ttl);
158
159
        return $this;
160
    }
161
162
    /**
163
     * Get fresh models / disable cache
164
     *
165
     * @param  boolean $fresh
166
     * @return object
167
     */
168
    public function fresh($fresh = true)
169
    {
170
        if ($fresh) {
171
            $this->model->setTtl(0);
172
        }
173
174
        return $this;
175
    }
176
177
    /**
178
     * Update a record in the database.
179
     *
180
     * @param  array $values
181
     * @return int
182
     */
183
    public function update(array $values)
184
    {
185
        $this->model->fireEvent('updatingMultiple');
186
187
        $return = parent::update($values);
188
189
        $this->model->fireEvent('updatedMultiple');
190
191
        return $return;
192
    }
193
194
    /**
195
     * Delete a record from the database.
196
     *
197
     * @return mixed
198
     */
199
    public function delete()
200
    {
201
        $this->model->fireEvent('deletingMultiple');
202
203
        $return = parent::delete();
204
205
        $this->model->fireEvent('deletedMultiple');
206
207
        return $return;
208
    }
209
210
    /**
211
     * Order by sort_order if null.
212
     */
213
    protected function orderByDefault()
214
    {
215
        $model = $this->getModel();
216
        $query = $this->getQuery();
217
218
        if ($query->orders === null) {
219
            if ($model instanceof AssignmentModel) {
220
                $query->orderBy('sort_order', 'ASC');
221
            } elseif ($model instanceof EntryInterface) {
222
                if ($model->getStream()->isSortable()) {
223
                    $query->orderBy('sort_order', 'ASC');
224
                } elseif ($model->titleColumnIsTranslatable()) {
225
                    if (!$this->hasJoin($model->getTranslationsTableName())) {
226
                        $this->query->leftJoin(
227
                            $model->getTranslationsTableName(),
228
                            $model->getTableName() . '.id',
229
                            '=',
230
                            $model->getTranslationsTableName() . '.entry_id'
231
                        );
232
                    }
233
234
                    $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...
235
                        ->distinct()
236
                        ->select($model->getTableName() . '.*')
237
                        ->where(
238
                            function (Builder $query) use ($model) {
239
                                $query->where($model->getTranslationsTableName() . '.locale', config('app.locale'));
240
                                $query->orWhere(
241
                                    $model->getTranslationsTableName() . '.locale',
242
                                    config('app.fallback_locale')
243
                                );
244
                                $query->orWhereNull($model->getTranslationsTableName() . '.locale');
245
                            }
246
                        )
247
                        ->orderBy($model->getTranslationsTableName() . '.' . $model->getTitleName(), 'ASC');
248
                } elseif ($model->getTitleName() && $model->getTitleName() !== 'id') {
249
                    $query->orderBy($model->getTitleName(), 'ASC');
250
                }
251
            }
252
        }
253
    }
254
}
255