Completed
Pull Request — master (#74)
by
unknown
13:28 queued 09:37
created

MiniCrud::getEditFields()   C

Complexity

Conditions 15
Paths 4

Size

Total Lines 63
Code Lines 35

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 39
CRAP Score 15.3298

Importance

Changes 0
Metric Value
cc 15
eloc 35
nc 4
nop 1
dl 0
loc 63
ccs 39
cts 44
cp 0.8864
crap 15.3298
rs 6.0778
c 0
b 0
f 0

How to fix   Long Method    Complexity   

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
namespace Anavel\Crud\Abstractor\Eloquent\Relation;
3
4
use Anavel\Crud\Abstractor\Eloquent\Relation\Traits\CheckRelationCompatibility;
5
use Anavel\Crud\Abstractor\Eloquent\Traits\HandleFiles;
6
use Anavel\Crud\Contracts\Abstractor\Field;
7
use Anavel\Crud\Contracts\Abstractor\Relation as RelationContract;
8
use App;
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 = array(
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
        return $this->results;
37
    }
38
39 8
    public function setup()
40
    {
41 8
        $this->checkRelationCompatibility();
42 6
    }
43
44
    /**
45
     * @return array
46
     */
47 2
    public function getEditFields($arrayKey = null)
48
    {
49 2
        $fields = [];
50 2
        if (empty($arrayKey)) {
51 2
            $arrayKey = $this->name;
52 2
        }
53
54 2
        $fieldsBase = $this->getEditFieldsBase();
55
56
57
        /** @var Collection $results */
58 2
        $results = $this->getResults();
59
60
61 2
        $results->put('emptyResult', '');
62 2
        if (!empty($fieldsBase)) {
63 2
            foreach ($results as $key => $result) {
64 2
                $tempFields = [];
65 2
                $index = $key === 'emptyResult' ? 0 : $result->id;
66
67 2
                foreach ($fieldsBase as $columnName => $fieldBase) {
68 2
                    $field = clone $fieldBase;
69 2
                    if ($this->skipField($columnName, $key)) {
70
                        continue;
71
                    }
72
73 2
                    if ($columnName != '__delete') {
74 2
                        if ($key !== 'emptyResult') {
75 2
                            $field->setValue($result->getAttribute($columnName));
76 2
                        }
77 2
                    } elseif ($key === 'emptyResult') {
78 2
                        continue;
79
                    }
80 2
                    $tempFields[$columnName] = $field;
81 2
                }
82
83
84 2
                $relationModel = $this->eloquentRelation->getRelated()->newInstance();
85 2
                if (!empty($result)) {
86 2
                    $relationModel = $result;
87 2
                }
88
89 2
                $this->modelAbstractor->setInstance($relationModel);
90 2
                $secondaryRelations = $this->getSecondaryRelations();
91
92 2
                if (!empty($secondaryRelations)) {
93 2
                    foreach ($secondaryRelations as $secondaryRelationKey => $secondaryRelation) {
94 2
                        foreach ($secondaryRelation->getEditFields($secondaryRelationKey) as $editGroupName => $editGroup) {
95
                            if ($secondaryRelation->getType() === 'Anavel\Crud\Abstractor\Eloquent\Relation\Select') {
96
                                $tempFields[$editGroup[key($editGroup)]->getName()] = $editGroup[key($editGroup)];
97
                            } else {
98
                                $tempFields[$editGroupName] = $editGroup;
99
                            }
100 2
                        }
101 2
                    }
102 2
                }
103
104 2
                $fields[$arrayKey][$index] = $tempFields;
105 2
            }
106 2
        }
107
108 2
        return $fields;
109
    }
110
111 4
    public function getEditFieldsBase()
112
    {
113 4
        $fields = [];
114 4
        $columns = $this->modelAbstractor->getColumns('edit');
115 4
        $this->readConfig('edit');
116
117 4
        if (!empty($columns)) {
118 4
            $readOnly = [Model::CREATED_AT, Model::UPDATED_AT];
119
120
            //Add field for model deletion
121
            $config = [
122 4
                'name' => '__delete',
123 4
                'presentation' => 'Delete',
124 4
                'form_type' => 'checkbox',
125 4
                'no_validate' => true,
126 4
                'validation' => null,
127
                'functions' => null
128 4
            ];
129
130
            /** @var Field $field */
131 4
            $field = $this->fieldFactory
132 4
                ->setColumn($columns[key($columns)]) //Set any column, we are not really using it
133 4
                ->setConfig($config)
134 4
                ->get();
135 4
            $fields['__delete'] = $field;
136
137
138 4
            foreach ($columns as $columnName => $column) {
139 4
                if (in_array($columnName, $readOnly, true)) {
140
                    continue;
141
                }
142
143 4
                $formType = null;
144 4
                if ($columnName === $this->eloquentRelation->getParent()->getKeyName()) {
145
                    $formType = 'hidden';
146
                }
147
148
                $config = [
149 4
                    'name' => $columnName,
150 4
                    'presentation' => $this->name . ' ' . ucfirst(transcrud($columnName)),
151 4
                    'form_type' => $formType,
152 4
                    'no_validate' => true,
153 4
                    'validation' => null,
154
                    'functions' => null
155 4
                ];
156
157 4
                $config = $this->setConfig($config, $columnName);
158
159
                /** @var Field $field */
160 4
                $field = $this->fieldFactory
161 4
                    ->setColumn($column)
162 4
                    ->setConfig($config)
163 4
                    ->get();
164
165 4
                $fields[$columnName] = $field;
166
167 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...
168
                    $field = $this->fieldFactory
169
                        ->setColumn($column)
170
                        ->setConfig([
171
                            'name' => $columnName . '__delete',
172
                            'presentation' => null,
173
                            'form_type' => 'checkbox',
174
                            'no_validate' => true,
175
                            'validation' => null,
176
                            'functions' => null
177
                        ])
178
                        ->get();
179
                    $fields[$columnName . '__delete'] = $field;
180
                }
181 4
            }
182 4
        }
183
184 4
        return $fields;
185
    }
186
187
    /**
188
     * @param array|null $relationArray
189
     * @return mixed
190
     */
191 2
    public function persist(array $relationArray = null, Request $request)
192
    {
193 2
        if (!empty($relationArray)) {
194 2
            $keyName = $this->eloquentRelation->getParent()->getKeyName();
195 2
            $currentRelations = $this->getResults()->keyBy($keyName);
196
197 2
            $this->readConfig('edit');
198 2
            $fieldsBase = $this->getEditFieldsBase();
199
200 2
            foreach ($relationArray as $relationIndex => &$relation) {
201 2
                if (!empty($relation[$keyName])
202 2
                    && ($currentRelations->has($relation[$keyName]))
203 2
                ) {
204
                    $relationModel = $currentRelations->get($relation[$keyName]);
205
                } else {
206 2
                    $relationModel = $this->eloquentRelation->getRelated()->newInstance();
207
                }
208
209 2
                $this->modelAbstractor->setInstance($relationModel);
210 2
                $secondaryRelations = $this->getSecondaryRelations();
211
212
213 2
                $this->setKeys($relationModel);
214
215 2
                $shouldBeSkipped = true;
216 2
                $delayedRelations = collect();
217
218 2
                $skip = null;
219 2
                foreach ($fieldsBase as $fieldBaseKey => $field) {
220 2
                    $fieldName = $field->getName();
221
222 2
                    if (get_class($field->getFormField()) === \FormManager\Fields\File::class) {
223
                        $handleResult = $this->handleField($request, $relationModel, $fieldsBase,
224
                            $this->name . ".$relationIndex", $fieldName, $this->modelAbstractor->mustDeleteFilesInFilesystem());
225
                        if (! empty($handleResult['skip'])) {
226
                            $skip = $handleResult['skip'];
227
                            unset($relationArray[$relationIndex][$skip]);
228
                        }
229
                        if (! empty($handleResult['requestValue'])) {
230
                            $relationArray[$relationIndex][$fieldName] = $handleResult['requestValue'];
231
                        }
232
                    }
233
234 2
                    if ($fieldName !== '__delete' && ($fieldName != $skip && (get_class($field->getFormField()) === \FormManager\Fields\Checkbox::class))) {
235
                        if (empty($relationArray[$relationIndex][$fieldName])) {
236
                            // Unchecked checkboxes are not sent, so we force setting them to false
237
                            $relationModel->setAttribute($fieldName, null);
238
                        } else {
239
                            $relationArray[$relationIndex][$fieldName] = true;
240
                        }
241
                    }
242 2
                }
243
244
245 2
                foreach ($relation as $fieldKey => $fieldValue) {
246 2
                    if ($secondaryRelations->has($fieldKey)) {
247 1
                        $delayedRelations->put($fieldKey, $fieldValue);
248 1
                        continue;
249
                    }
250
251
                    // This field can only come from existing models
252 2
                    if ($fieldKey === '__delete') {
253
                        $relationModel->delete();
254
                        $shouldBeSkipped = true;
255
                        break;
256
                    }
257
258 2
                    if ($shouldBeSkipped) {
259 2
                        $shouldBeSkipped = ($shouldBeSkipped === ($fieldValue === ''));
260 2
                    }
261
262 2
                    $relationModel->setAttribute($fieldKey, $fieldValue);
263 2
                }
264
265 2
                if (!$shouldBeSkipped) {
266 2
                    $relationModel->save();
267
268 2
                    if (!$delayedRelations->isEmpty()) {
269 1
                        foreach ($delayedRelations as $relationKey => $delayedRelation) {
270
                            /** @var RelationContract $secondaryRelation */
271 1
                            $secondaryRelation = $secondaryRelations->get($relationKey);
272
273 1
                            $secondaryRelation->persist($delayedRelation, $request);
274 1
                        }
275 1
                    }
276 2
                }
277 2
            }
278 2
        }
279 2
    }
280
281 1
    protected function setKeys(Model $relationModel)
282
    {
283 1
        $relationModel->setAttribute($this->eloquentRelation->getForeignKey(), $this->relatedModel->id);
284 1
    }
285
286 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...
287
    {
288 1
        if ($columnName === $this->eloquentRelation->getPlainForeignKey()) {
289
            return true;
290
        }
291
292 1
        if ($key === 'emptyResult' && ($columnName === $this->eloquentRelation->getParent()->getKeyName())) {
293
            return true;
294
        }
295
296 1
        return false;
297
    }
298
299
    /**
300
     * @return string
301
     */
302
    public function getDisplayType()
303
    {
304
        return self::DISPLAY_TYPE_TAB;
305
    }
306
307
    /**
308
     * @param array $fields
309
     * @return array
310
     */
311
    public function addSecondaryRelationFields(array $fields)
312
    {
313
        $tempFields = [];
314
        foreach ($this->getSecondaryRelations() as $relationKey => $relation) {
315
            foreach ($relation->getEditFields($relationKey) as $editGroupName => $editGroup) {
316
                if ($relation->getType() === 'Anavel\Crud\Abstractor\Eloquent\Relation\Select') {
317
                    $tempFields[key($editGroup)] = $editGroup[key($editGroup)];
318
                } else {
319
                    $tempFields[$editGroupName] = $editGroup;
320
                }
321
            };
322
        }
323
        foreach ($fields[$this->name] as $groupKey => $mainFields) {
324
            $combinedFields = array_merge($mainFields, $tempFields);
325
            $fields[$this->name][$groupKey] = $combinedFields;
326
        }
327
328
        return $fields;
329
    }
330
}
331