Passed
Push — master ( 11ccd8...26a0d2 )
by Quentin
09:37 queued 04:57
created

HandleRepeaters::updateRepeaterMorphMany()   B

Complexity

Conditions 8
Paths 18

Size

Total Lines 45
Code Lines 27

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 0
CRAP Score 72

Importance

Changes 1
Bugs 0 Features 0
Metric Value
cc 8
eloc 27
c 1
b 0
f 0
nc 18
nop 5
dl 0
loc 45
ccs 0
cts 27
cp 0
crap 72
rs 8.4444
1
<?php
2
3
namespace A17\Twill\Repositories\Behaviors;
4
5
use Carbon\Carbon;
6
use Illuminate\Support\Arr;
7
use Illuminate\Support\Collection;
8
use Illuminate\Support\Str;
9
10
trait HandleRepeaters
11
{
12
    /**
13
     * @param \A17\Twill\Models\Model $object
14
     * @param array $fields
15
     * @return void
16
     */
17
    public function afterSaveHandleRepeaters($object, $fields)
18
    {
19
        if (property_exists($this, 'repeaters')) {
20
            foreach ($this->repeaters as $moduleKey => $module) {
21
                if (is_string($module)) {
22
                    $model = Str::studly(Str::singular($module));
23
                    $repeaterName = Str::singular($module);
24
                    $this->updateRepeater($object, $fields, $module, $model, $repeaterName);
25
                } elseif (is_array($module)) {
26
                    $relation = !empty($module['relation']) ? $module['relation'] : $moduleKey;
27
                    $model = isset($module['model']) ? $module['model'] : Str::studly(Str::singular($moduleKey));
28
                    $repeaterName = !empty($module['repeaterName']) ? $module['repeaterName'] : Str::singular($moduleKey);
29
                    $this->updateRepeater($object, $fields, $relation, $model, $repeaterName);
30
                }
31
            }
32
        }
33
    }
34
35
    /**
36
     * @param \A17\Twill\Models\Model $object
37
     * @param array $fields
38
     * @return array
39
     */
40
    public function getFormFieldsHandleRepeaters($object, $fields)
41
    {
42
        if (property_exists($this, 'repeaters')) {
43
            foreach ($this->repeaters as $moduleKey => $module) {
44
                if (is_string($module)) {
45
                    $model = Str::studly(Str::singular($module));
46
                    $repeaterName = Str::singular($module);
47
                    $fields = $this->getFormFieldsForRepeater($object, $fields, $module, $model, $repeaterName);
48
                } elseif (is_array($module)) {
49
                    $model = isset($module['model']) ? $module['model'] : Str::studly(Str::singular($moduleKey));
50
                    $relation = !empty($module['relation']) ? $module['relation'] : $moduleKey;
51
                    $repeaterName = !empty($module['repeaterName']) ? $module['repeaterName'] : Str::singular($moduleKey);
52
                    $fields = $this->getFormFieldsForRepeater($object, $fields, $relation, $model, $repeaterName);
53
                }
54
            }
55
        }
56
57
        return $fields;
58
    }
59
60
    public function updateRepeaterMany($object, $fields, $relation, $keepExisting = true, $model = null)
61
    {
62
        $relationFields = $fields['repeaters'][$relation] ?? [];
63
        $relationRepository = $this->getModelRepository($relation, $model);
0 ignored issues
show
Bug introduced by
It seems like getModelRepository() must be provided by classes using this trait. How about adding it as abstract method to this trait? ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-call  annotation

63
        /** @scrutinizer ignore-call */ 
64
        $relationRepository = $this->getModelRepository($relation, $model);
Loading history...
64
65
        if (!$keepExisting) {
66
            $object->$relation()->each(function ($repeaterElement) {
67
                $repeaterElement->forceDelete();
68
            });
69
        }
70
71
        foreach ($relationFields as $relationField) {
72
            $newRelation = $relationRepository->create($relationField);
73
            $object->$relation()->attach($newRelation->id);
74
        }
75
    }
76
77
78
    public function updateRepeaterMorphMany($object, $fields, $relation, $morph = null, $model = null)
79
    {
80
        $relationFields = $fields['repeaters'][$relation] ?? [];
81
        $relationRepository = $this->getModelRepository($relation, $model);
82
83
        $morph = $morph ?: $relation;
84
85
        $morphFieldType = $morph.'_type';
86
        $morphFieldId = $morph.'_id';
87
88
        // if no relation field submitted, soft deletes all associated rows
89
        if (!$relationFields) {
90
            $relationRepository->updateBasic(null, [
91
                'deleted_at' => Carbon::now(),
92
            ], [
93
                $morphFieldType => $object->getMorphClass(),
94
                $morphFieldId => $object->id,
95
            ]);
96
        }
97
98
        // keep a list of updated and new rows to delete (soft delete?) old rows that were deleted from the frontend
99
        $currentIdList = [];
100
101
        foreach ($relationFields as $index => $relationField) {
102
            $relationField['position'] = $index + 1;
103
            if (isset($relationField['id']) && Str::startsWith($relationField['id'], $relation)) {
104
                // row already exists, let's update
105
                $id = str_replace($relation . '-', '', $relationField['id']);
106
                $relationRepository->update($id, $relationField);
107
                $currentIdList[] = $id;
108
            } else {
109
                // new row, let's attach to our object and create
110
                unset($relationField['id']);
111
                $newRelation = $relationRepository->create($relationField);
112
                $object->$relation()->save($newRelation);
113
                $currentIdList[] = $newRelation['id'];
114
            }
115
        }
116
117
        foreach ($object->$relation->pluck('id') as $id) {
118
            if (!in_array($id, $currentIdList)) {
119
                $relationRepository->updateBasic(null, [
120
                    'deleted_at' => Carbon::now(),
121
                ], [
122
                    'id' => $id,
123
                ]);
124
            }
125
        }
126
    }
127
128
    public function updateRepeater($object, $fields, $relation, $model = null, $repeaterName = null)
129
    {
130
        if (!$repeaterName) {
131
            $repeaterName = $relation;
132
        }
133
134
        $relationFields = $fields['repeaters'][$repeaterName] ?? [];
135
136
        $relationRepository = $this->getModelRepository($relation, $model);
137
138
        // if no relation field submitted, soft deletes all associated rows
139
        if (!$relationFields) {
140
            $relationRepository->updateBasic(null, [
141
                'deleted_at' => Carbon::now(),
142
            ], [
143
                $this->model->getForeignKey() => $object->id,
144
            ]);
145
        }
146
147
        // keep a list of updated and new rows to delete (soft delete?) old rows that were deleted from the frontend
148
        $currentIdList = [];
149
150
        foreach ($relationFields as $index => $relationField) {
151
            $relationField['position'] = $index + 1;
152
            if (isset($relationField['id']) && Str::startsWith($relationField['id'], $relation)) {
153
                // row already exists, let's update
154
                $id = str_replace($relation . '-', '', $relationField['id']);
155
                $relationRepository->update($id, $relationField);
156
                $currentIdList[] = $id;
157
            } else {
158
                // new row, let's attach to our object and create
159
                $relationField[$this->model->getForeignKey()] = $object->id;
160
                unset($relationField['id']);
161
                $newRelation = $relationRepository->create($relationField);
162
                $currentIdList[] = $newRelation['id'];
163
            }
164
        }
165
166
        foreach ($object->$relation->pluck('id') as $id) {
167
            if (!in_array($id, $currentIdList)) {
168
                $relationRepository->updateBasic(null, [
169
                    'deleted_at' => Carbon::now(),
170
                ], [
171
                    'id' => $id,
172
                ]);
173
            }
174
        }
175
    }
176
177
    public function getFormFieldsForRepeater($object, $fields, $relation, $model = null, $repeaterName = null)
178
    {
179
        if (!$repeaterName) {
180
            $repeaterName = $relation;
181
        }
182
183
        $repeaters = [];
184
        $repeatersFields = [];
185
        $repeatersBrowsers = [];
186
        $repeatersMedias = [];
187
        $repeatersFiles = [];
188
        $relationRepository = $this->getModelRepository($relation, $model);
189
        $repeatersConfig = config('twill.block_editor.repeaters');
190
191
        foreach ($object->$relation as $relationItem) {
192
            $repeaters[] = [
193
                'id' => $relation . '-' . $relationItem->id,
194
                'type' => $repeatersConfig[$repeaterName]['component'],
195
                'title' => $repeatersConfig[$repeaterName]['title'],
196
            ];
197
198
            $relatedItemFormFields = $relationRepository->getFormFields($relationItem);
199
            $translatedFields = [];
200
201
            if (isset($relatedItemFormFields['translations'])) {
202
                foreach ($relatedItemFormFields['translations'] as $key => $values) {
203
                    $repeatersFields[] = [
204
                        'name' => "blocks[$relation-$relationItem->id][$key]",
205
                        'value' => $values,
206
                    ];
207
208
                    $translatedFields[] = $key;
209
                }
210
            }
211
212
            if (isset($relatedItemFormFields['medias'])) {
213
                if (config('twill.media_library.translated_form_fields', false)) {
214
                    Collection::make($relatedItemFormFields['medias'])->each(function ($rolesWithMedias, $locale) use (&$repeatersMedias, $relation, $relationItem) {
215
                        $repeatersMedias[] = Collection::make($rolesWithMedias)->mapWithKeys(function ($medias, $role) use ($locale, $relation, $relationItem) {
216
                            return [
217
                                "blocks[$relation-$relationItem->id][$role][$locale]" => $medias,
218
                            ];
219
                        })->toArray();
220
                    });
221
                } else {
222
                    foreach ($relatedItemFormFields['medias'] as $key => $values) {
223
                        $repeatersMedias["blocks[$relation-$relationItem->id][$key]"] = $values;
224
                    }
225
                }
226
            }
227
228
            if (isset($relatedItemFormFields['files'])) {
229
                Collection::make($relatedItemFormFields['files'])->each(function ($rolesWithFiles, $locale) use (&$repeatersFiles, $relation, $relationItem) {
230
                    $repeatersFiles[] = Collection::make($rolesWithFiles)->mapWithKeys(function ($files, $role) use ($locale, $relation, $relationItem) {
231
                        return [
232
                            "blocks[$relation-$relationItem->id][$role][$locale]" => $files,
233
                        ];
234
                    })->toArray();
235
                });
236
            }
237
238
            if (isset($relatedItemFormFields['browsers'])) {
239
                foreach ($relatedItemFormFields['browsers'] as $key => $values) {
240
                    $repeatersBrowsers["blocks[$relation-$relationItem->id][$key]"] = $values;
241
                }
242
            }
243
244
            $itemFields = method_exists($relationItem, 'toRepeaterArray') ? $relationItem->toRepeaterArray() : Arr::except($relationItem->attributesToArray(), $translatedFields);
245
246
            foreach ($itemFields as $key => $value) {
247
                $repeatersFields[] = [
248
                    'name' => "blocks[$relation-$relationItem->id][$key]",
249
                    'value' => $value,
250
                ];
251
            }
252
253
        }
254
255
        if (!empty($repeatersMedias) && config('twill.media_library.translated_form_fields', false)) {
256
            $repeatersMedias = call_user_func_array('array_merge', $repeatersMedias);
257
        }
258
259
        if (!empty($repeatersFiles)) {
260
            $repeatersFiles = call_user_func_array('array_merge', $repeatersFiles);
261
        }
262
263
        $fields['repeaters'][$repeaterName] = $repeaters;
264
        $fields['repeaterFields'][$repeaterName] = $repeatersFields;
265
        $fields['repeaterMedias'][$repeaterName] = $repeatersMedias;
266
        $fields['repeaterFiles'][$repeaterName] = $repeatersFiles;
267
        $fields['repeaterBrowsers'][$repeaterName] = $repeatersBrowsers;
268
269
        return $fields;
270
    }
271
}
272