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

MiniCrud::getEditFieldsBase()   C

Complexity

Conditions 7
Paths 2

Size

Total Lines 75
Code Lines 50

Duplication

Lines 14
Ratio 18.67 %

Code Coverage

Tests 39
CRAP Score 8.2062

Importance

Changes 0
Metric Value
cc 7
eloc 50
nc 2
nop 0
dl 14
loc 75
ccs 39
cts 55
cp 0.709
crap 8.2062
rs 6.5862
c 0
b 0
f 0

How to fix   Long Method   

Long Method

Small methods make your code easier to understand, in particular if combined with a good name. Besides, if your method is small, finding a good name is usually much easier.

For example, if you find yourself adding comments to a method's body, this is usually a good sign to extract the commented part to a new method, and use the comment as a starting point when coming up with a good name for this new method.

Commonly applied refactorings include:

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