Issues (25)

src/Builder.php (1 issue)

1
<?php
2
3
namespace Laraplus\Data;
4
5
use Illuminate\Database\Eloquent\Builder as EloquentBuilder;
6
7
class Builder extends EloquentBuilder
8
{
9
    /**
10
     * Update a record in the database.
11
     *
12
     * @param array $values
13
     *
14
     * @return int
15
     */
16
    public function update(array $values)
17
    {
18
        $updated = 0;
19
        $modelKey = $this->getModel()->getKey();
20
        $modelKeyName = $this->model->getKeyName();
21
        $values = $this->addUpdatedAtColumn($values);
22
        [$values, $i18nValues] = $this->filterValues($values);
23
        $ids = $modelKey ? [$modelKey] : $this->pluck($modelKeyName)->all();
24
25
        if ($values) {
26
            $updated += $this->updateBase($values, $ids);
27
        }
28
29
        if ($i18nValues) {
30
            $updated += $this->updateI18n($i18nValues, $ids);
31
        }
32
33
        return $updated;
34
    }
35
36
    /**
37
     * Increment a column's value by a given amount.
38
     *
39
     * @param string $column
40
     * @param int $amount
41
     * @param array $extra
42
     *
43
     * @return int
44
     */
45
    public function increment($column, $amount = 1, array $extra = [])
46
    {
47
        $extra = $this->addUpdatedAtColumn($extra);
48
49
        return $this->noTranslationsQuery()->increment($column, $amount, $extra);
50
    }
51
52
    /**
53
     * Decrement a column's value by a given amount.
54
     *
55
     * @param string $column
56
     * @param int $amount
57
     * @param array $extra
58
     *
59
     * @return int
60
     */
61
    public function decrement($column, $amount = 1, array $extra = [])
62
    {
63
        $extra = $this->addUpdatedAtColumn($extra);
64
65
        return $this->noTranslationsQuery()->decrement($column, $amount, $extra);
66
    }
67
68
    /**
69
     * Insert a new record into the database.
70
     *
71
     * @param array $values
72
     *
73
     * @return bool
74
     */
75
    public function insert(array $values)
76
    {
77
        [$values, $i18nValues] = $this->filterValues($values);
78
79
        if ($this->query->insert($values)) {
80
            return $this->insertI18n($i18nValues, $values[$this->model->getKeyName()]);
81
        }
82
83
        return false;
84
    }
85
86
    /**
87
     * Insert a new record and get the value of the primary key.
88
     *
89
     * @param array $values
90
     * @param string $sequence
91
     *
92
     * @return int
93
     */
94
    public function insertGetId(array $values, $sequence = null)
95
    {
96
        [$values, $i18nValues] = $this->filterValues($values);
97
98
        if ($id = $this->query->insertGetId($values, $sequence)) {
99
            if ($this->insertI18n($i18nValues, $id)) {
100
                return $id;
101
            }
102
        }
103
104
        return false;
0 ignored issues
show
Bug Best Practice introduced by
The expression return false returns the type false which is incompatible with the documented return type integer.
Loading history...
105
    }
106
107
    /**
108
     * Delete a record from the database.
109
     *
110
     * @return mixed
111
     */
112
    public function delete()
113
    {
114
        if (isset($this->onDelete)) {
115
            return call_user_func($this->onDelete, $this);
116
        }
117
118
        return $this->i18nDeleteQuery()->delete() | $this->toBase()->delete();
119
    }
120
121
    /**
122
     * Run the default delete function on the builder.
123
     *
124
     * @return mixed
125
     */
126
    public function forceDelete()
127
    {
128
        return $this->i18nDeleteQuery(false)->delete() & $this->query->delete();
129
    }
130
131
    /**
132
     * Filters translatable values from non-translatable.
133
     *
134
     * @param array $values
135
     *
136
     * @return array
137
     */
138
    protected function filterValues(array $values)
139
    {
140
        $attributes = $this->model->translatableAttributes();
141
        $translatable = [];
142
143
        foreach ($attributes as $key) {
144
            if (array_key_exists($key, $values)) {
145
                $translatable[$key] = $values[$key];
146
147
                unset($values[$key]);
148
            }
149
        }
150
151
        return [$values, $translatable];
152
    }
153
154
    /**
155
     * Insert translation.
156
     *
157
     * @param array $values
158
     * @param mixed $key
159
     *
160
     * @return bool
161
     */
162
    protected function insertI18n(array $values, $key)
163
    {
164
        if (count($values) == 0) {
165
            return true;
166
        }
167
168
        $values[$this->model->getForeignKey()] = $key;
169
        $values[$this->model->getLocaleKey()] = $this->model->getLocale();
170
171
        return $this->i18nQuery()->insert($values);
172
    }
173
174
    /**
175
     * Update values in base table.
176
     *
177
     * @param array $values
178
     * @param array $ids
179
     *
180
     * @return mixed
181
     */
182
    private function updateBase(array $values, array $ids)
183
    {
184
        $query = $this->model
185
            ->newQuery()
186
            ->whereIn($this->model->getKeyName(), $ids)
187
            ->getQuery();
188
189
        return $query->update($values);
190
    }
191
192
    /**
193
     * Update translations.
194
     *
195
     * @param array $values
196
     * @param array $ids
197
     *
198
     * @return bool
199
     */
200
    protected function updateI18n(array $values, array $ids)
201
    {
202
        if (count($values) == 0) {
203
            return true;
204
        }
205
206
        $updated = 0;
207
208
        foreach ($ids as $id) {
209
            $query = $this->i18nQuery()
210
                ->whereOriginal($this->model->getForeignKey(), $id)
211
                ->whereOriginal($this->model->getLocaleKey(), $this->model->getLocale());
212
213
            if ($query->exists()) {
214
                unset($values[$this->model->getLocaleKey()]);
215
216
                $updated += $query->update($values);
217
            } else {
218
                $updated += $this->insertI18n($values, $id);
219
            }
220
        }
221
222
        return $updated;
223
    }
224
225
    /**
226
     * Get the query builder instance for translation table.
227
     *
228
     * @return \Illuminate\Database\Query\Builder
229
     */
230
    public function i18nQuery()
231
    {
232
        $query = $this->getModel()->newQueryWithoutScopes()->getQuery();
233
234
        $query->from($this->model->getI18nTable());
235
236
        return $query;
237
    }
238
239
    /**
240
     * Get the delete query instance for translation table.
241
     *
242
     * @param bool $withGlobalScopes
243
     *
244
     * @return \Illuminate\Database\Query\Builder
245
     */
246
    protected function i18nDeleteQuery($withGlobalScopes = true)
247
    {
248
        $subQuery = $withGlobalScopes ? $this->toBase() : $this->getQuery();
249
250
        $subQuery->select($this->model->getQualifiedKeyName());
251
252
        return $this->i18nQuery()->whereIn(
253
            $this->model->getForeignKey(), $subQuery->pluck($this->model->getKeyName())
254
        );
255
    }
256
257
    /**
258
     * Get the base query without translations.
259
     *
260
     * @return \Illuminate\Database\Query\Builder
261
     */
262
    protected function noTranslationsQuery()
263
    {
264
        return $this->withoutGlobalScope(TranslatableScope::class)->toBase();
265
    }
266
}
267