Completed
Push — master ( 5fe226...5c1a79 )
by Adrian
22:45 queued 18:50
created

MiniCrud::skipField()   A

Complexity

Conditions 4
Paths 3

Size

Total Lines 12
Code Lines 6

Duplication

Lines 12
Ratio 100 %

Code Coverage

Tests 4
CRAP Score 4.5923

Importance

Changes 0
Metric Value
cc 4
eloc 6
nc 3
nop 2
dl 12
loc 12
ccs 4
cts 6
cp 0.6667
crap 4.5923
rs 9.2
c 0
b 0
f 0
1
<?php
2
3
namespace Anavel\Crud\Abstractor\Eloquent\Relation;
4
5
use Anavel\Crud\Abstractor\Eloquent\Relation\Traits\CheckRelationCompatibility;
6
use Anavel\Crud\Abstractor\Eloquent\Traits\HandleFiles;
7
use Anavel\Crud\Contracts\Abstractor\Field;
8
use Anavel\Crud\Contracts\Abstractor\Relation as RelationContract;
9
use Illuminate\Database\Eloquent\Model;
10
use Illuminate\Http\Request;
11
use Illuminate\Support\Collection;
12
13
class MiniCrud extends Relation
14
{
15
    use CheckRelationCompatibility;
16
    use HandleFiles;
17
18
    /** @var \ANavallaSuiza\Laravel\Database\Contracts\Dbal\AbstractionLayer $dbal */
19
    protected $dbal;
20
21
    /** @var Collection */
22
    protected $results;
23
24
    protected $compatibleEloquentRelations = [
25
        'Illuminate\Database\Eloquent\Relations\HasMany',
26
    ];
27
28
    /**
29
     * @return Collection
30
     */
31 4
    protected function getResults()
32 1
    {
33 4
        if (empty($this->results)) {
34 4
            return $this->results = $this->eloquentRelation->getResults();
35
        }
36
37
        return $this->results;
38
    }
39
40 8
    public function setup()
41
    {
42 8
        $this->checkRelationCompatibility();
43 6
    }
44
45
    /**
46
     * @return array
47
     */
48 2
    public function getEditFields($arrayKey = null)
49
    {
50 2
        $fields = [];
51 2
        if (empty($arrayKey)) {
52 2
            $arrayKey = $this->name;
53 2
        }
54
55 2
        $fieldsBase = $this->getEditFieldsBase();
56
57
58
        /** @var Collection $results */
59 2
        $results = $this->getResults();
60
61
62 2
        $results->put('emptyResult', '');
63 2
        if (!empty($fieldsBase)) {
64 2
            foreach ($results as $key => $result) {
65 2
                $tempFields = [];
66 2
                $index = $key === 'emptyResult' ? 0 : $result->id;
67
68 2
                foreach ($fieldsBase as $columnName => $fieldBase) {
69 2
                    $field = clone $fieldBase;
70 2
                    if ($this->skipField($columnName, $key)) {
71
                        continue;
72
                    }
73
74 2
                    if ($columnName != '__delete') {
75 2
                        if ($key !== 'emptyResult') {
76 2
                            $field->setValue($result->getAttribute($columnName));
77 2
                        }
78 2
                    } elseif ($key === 'emptyResult') {
79 2
                        continue;
80
                    }
81 2
                    $tempFields[$columnName] = $field;
82 2
                }
83
84
85 2
                $relationModel = $this->eloquentRelation->getRelated()->newInstance();
86 2
                if (!empty($result)) {
87 2
                    $relationModel = $result;
88 2
                }
89
90 2
                $this->modelAbstractor->setInstance($relationModel);
91 2
                $secondaryRelations = $this->getSecondaryRelations();
92
93 2
                if (!empty($secondaryRelations)) {
94 2
                    foreach ($secondaryRelations as $secondaryRelationKey => $secondaryRelation) {
95 2
                        foreach ($secondaryRelation->getEditFields($secondaryRelationKey) as $editGroupName => $editGroup) {
96
                            if ($secondaryRelation->getType() === 'Anavel\Crud\Abstractor\Eloquent\Relation\Select') {
97
                                $tempFields[$editGroup[key($editGroup)]->getName()] = $editGroup[key($editGroup)];
98
                            } else {
99
                                $tempFields[$editGroupName] = $editGroup;
100
                            }
101 2
                        }
102 2
                    }
103 2
                }
104
105 2
                $fields[$arrayKey][$index] = $tempFields;
106 2
            }
107 2
        }
108
109 2
        return $fields;
110
    }
111
112 4
    public function getEditFieldsBase()
113
    {
114 4
        $fields = [];
115 4
        $columns = $this->modelAbstractor->getColumns('edit');
116 4
        $this->readConfig('edit');
117
118 4
        if (!empty($columns)) {
119 4
            $readOnly = [Model::CREATED_AT, Model::UPDATED_AT];
120
121
            //Add field for model deletion
122
            $config = [
123 4
                'name'         => '__delete',
124 4
                'presentation' => 'Delete',
125 4
                'form_type'    => 'checkbox',
126 4
                'no_validate'  => true,
127 4
                'validation'   => null,
128 4
                'functions'    => null,
129 4
            ];
130
131
            /** @var Field $field */
132 4
            $field = $this->fieldFactory
133 4
                ->setColumn($columns[key($columns)]) //Set any column, we are not really using it
134 4
                ->setConfig($config)
135 4
                ->get();
136 4
            $fields['__delete'] = $field;
137
138
139 4
            foreach ($columns as $columnName => $column) {
140 4
                if (in_array($columnName, $readOnly, true)) {
141
                    continue;
142
                }
143
144 4
                $formType = null;
145 4
                if ($columnName === $this->eloquentRelation->getParent()->getKeyName()) {
146
                    $formType = 'hidden';
147
                }
148
149
                $config = [
150 4
                    'name'         => $columnName,
151 4
                    'presentation' => $this->name.' '.ucfirst(transcrud($columnName)),
152 4
                    'form_type'    => $formType,
153 4
                    'no_validate'  => true,
154 4
                    'validation'   => null,
155 4
                    'functions'    => null,
156 4
                ];
157
158 4
                $config = $this->setConfig($config, $columnName);
159
160
                /** @var Field $field */
161 4
                $field = $this->fieldFactory
162 4
                    ->setColumn($column)
163 4
                    ->setConfig($config)
164 4
                    ->get();
165
166 4
                $fields[$columnName] = $field;
167
168 4 View Code Duplication
                if (!empty($config['form_type']) && $config['form_type'] === 'file') {
0 ignored issues
show
Duplication introduced by
This code seems to be duplicated across your project.

Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation.

You can also find more detailed suggestions in the “Code” section of your repository.

Loading history...
169
                    $field = $this->fieldFactory
170
                        ->setColumn($column)
171
                        ->setConfig([
172
                            'name'         => $columnName.'__delete',
173
                            'presentation' => null,
174
                            'form_type'    => 'checkbox',
175
                            'no_validate'  => true,
176
                            'validation'   => null,
177
                            'functions'    => null,
178
                        ])
179
                        ->get();
180
                    $fields[$columnName.'__delete'] = $field;
181
                }
182 4
            }
183 4
        }
184
185 4
        return $fields;
186
    }
187
188
    /**
189
     * @param array|null $relationArray
190
     *
191
     * @return mixed
192
     */
193 2
    public function persist(array $relationArray = null, Request $request)
194
    {
195 2
        if (!empty($relationArray)) {
196 2
            $keyName = $this->eloquentRelation->getParent()->getKeyName();
197 2
            $currentRelations = $this->getResults()->keyBy($keyName);
198
199 2
            $this->readConfig('edit');
200 2
            $fieldsBase = $this->getEditFieldsBase();
201
202 2
            foreach ($relationArray as $relationIndex => &$relation) {
203 2
                if (!empty($relation[$keyName])
204 2
                    && ($currentRelations->has($relation[$keyName]))
205 2
                ) {
206
                    $relationModel = $currentRelations->get($relation[$keyName]);
207
                } else {
208 2
                    $relationModel = $this->eloquentRelation->getRelated()->newInstance();
209
                }
210
211 2
                $this->modelAbstractor->setInstance($relationModel);
212 2
                $secondaryRelations = $this->getSecondaryRelations();
213
214
215 2
                $this->setKeys($relationModel);
216
217 2
                $shouldBeSkipped = true;
218 2
                $delayedRelations = collect();
219
220 2
                $skip = null;
221 2
                foreach ($fieldsBase as $fieldBaseKey => $field) {
222 2
                    $fieldName = $field->getName();
223
224 2
                    if (get_class($field->getFormField()) === \FormManager\Fields\File::class) {
225
                        $handleResult = $this->handleField($request, $relationModel, $fieldsBase,
226
                            $this->name.".$relationIndex", $fieldName, $this->modelAbstractor->mustDeleteFilesInFilesystem());
227
                        if (!empty($handleResult['skip'])) {
228
                            $skip = $handleResult['skip'];
229
                            unset($relationArray[$relationIndex][$skip]);
230
                        }
231
                        if (!empty($handleResult['requestValue'])) {
232
                            $relationArray[$relationIndex][$fieldName] = $handleResult['requestValue'];
233
                        }
234
                    }
235
236 2
                    if ($fieldName !== '__delete' && ($fieldName != $skip && (get_class($field->getFormField()) === \FormManager\Fields\Checkbox::class))) {
237
                        if (empty($relationArray[$relationIndex][$fieldName])) {
238
                            // Unchecked checkboxes are not sent, so we force setting them to false
239
                            $relationModel->setAttribute($fieldName, null);
240
                        } else {
241
                            $relationArray[$relationIndex][$fieldName] = true;
242
                        }
243
                    }
244 2
                }
245
246
247 2
                foreach ($relation as $fieldKey => $fieldValue) {
248 2
                    if ($secondaryRelations->has($fieldKey)) {
249 1
                        $delayedRelations->put($fieldKey, $fieldValue);
250 1
                        continue;
251
                    }
252
253
                    // This field can only come from existing models
254 2
                    if ($fieldKey === '__delete') {
255
                        $relationModel->delete();
256
                        $shouldBeSkipped = true;
257
                        break;
258
                    }
259
260 2
                    if ($shouldBeSkipped) {
261 2
                        $shouldBeSkipped = ($shouldBeSkipped === ($fieldValue === ''));
262 2
                    }
263
264 2
                    $relationModel->setAttribute($fieldKey, $fieldValue);
265 2
                }
266
267 2
                if (!$shouldBeSkipped) {
268 2
                    $relationModel->save();
269
270 2
                    if (!$delayedRelations->isEmpty()) {
271 1
                        foreach ($delayedRelations as $relationKey => $delayedRelation) {
272
                            /** @var RelationContract $secondaryRelation */
273 1
                            $secondaryRelation = $secondaryRelations->get($relationKey);
274
275 1
                            $secondaryRelation->persist($delayedRelation, $request);
276 1
                        }
277 1
                    }
278 2
                }
279 2
            }
280 2
        }
281 2
    }
282
283 1
    protected function setKeys(Model $relationModel)
284
    {
285 1
        $relationModel->setAttribute($this->eloquentRelation->getForeignKey(), $this->relatedModel->id);
286 1
    }
287
288 1 View Code Duplication
    protected function skipField($columnName, $key)
0 ignored issues
show
Duplication introduced by
This method seems to be duplicated in your project.

Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation.

You can also find more detailed suggestions in the “Code” section of your repository.

Loading history...
289
    {
290 1
        if ($columnName === $this->eloquentRelation->getPlainForeignKey()) {
291
            return true;
292
        }
293
294 1
        if ($key === 'emptyResult' && ($columnName === $this->eloquentRelation->getParent()->getKeyName())) {
295
            return true;
296
        }
297
298 1
        return false;
299
    }
300
301
    /**
302
     * @return string
303
     */
304
    public function getDisplayType()
305
    {
306
        return self::DISPLAY_TYPE_TAB;
307
    }
308
309
    /**
310
     * @param array $fields
311
     *
312
     * @return array
313
     */
314
    public function addSecondaryRelationFields(array $fields)
315
    {
316
        $tempFields = [];
317
        foreach ($this->getSecondaryRelations() as $relationKey => $relation) {
318
            foreach ($relation->getEditFields($relationKey) as $editGroupName => $editGroup) {
319
                if ($relation->getType() === 'Anavel\Crud\Abstractor\Eloquent\Relation\Select') {
320
                    $tempFields[key($editGroup)] = $editGroup[key($editGroup)];
321
                } else {
322
                    $tempFields[$editGroupName] = $editGroup;
323
                }
324
            }
325
        }
326
        foreach ($fields[$this->name] as $groupKey => $mainFields) {
327
            $combinedFields = array_merge($mainFields, $tempFields);
328
            $fields[$this->name][$groupKey] = $combinedFields;
329
        }
330
331
        return $fields;
332
    }
333
}
334