Completed
Push — master ( b3827e...6a4c7f )
by
unknown
10:08
created

MiniCrud::setup()   A

Complexity

Conditions 1
Paths 1

Size

Total Lines 4
Code Lines 2

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 3
CRAP Score 1

Importance

Changes 3
Bugs 0 Features 0
Metric Value
c 3
b 0
f 0
dl 0
loc 4
ccs 3
cts 3
cp 1
rs 10
cc 1
eloc 2
nc 1
nop 0
crap 1
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
    {
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 2
                if (!empty($secondaryRelations)) {
92 2 View Code Duplication
                    foreach ($secondaryRelations as $secondaryRelationKey => $secondaryRelation) {
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...
93 2
                        foreach ($secondaryRelation->getEditFields($secondaryRelationKey) as $editGroupName => $editGroup) {
94
                            if ($secondaryRelation->getType() === 'Anavel\Crud\Abstractor\Eloquent\Relation\Select') {
95
                                $tempFields[key($editGroup)] = $editGroup[key($editGroup)];
96
                            } else {
97
                                $tempFields[$editGroupName] = $editGroup;
98
                            }
99 2
                        };
100 2
                    }
101 2
                }
102
103 2
                $fields[$arrayKey][$index] = $tempFields;
104 2
            }
105 2
        }
106
107 2
        return $fields;
108
    }
109
110 4
    public function getEditFieldsBase()
111
    {
112 4
        $fields = [];
113 4
        $columns = $this->modelAbstractor->getColumns('edit');
114 4
        $this->readConfig('edit');
115
116 4
        if (!empty($columns)) {
117 4
            $readOnly = [Model::CREATED_AT, Model::UPDATED_AT];
118
119
            //Add field for model deletion
120
            $config = [
121 4
                'name' => '__delete',
122 4
                'presentation' => 'Delete',
123 4
                'form_type' => 'checkbox',
124 4
                'no_validate' => true,
125 4
                'validation' => null,
126
                'functions' => null
127 4
            ];
128
129
            /** @var Field $field */
130 4
            $field = $this->fieldFactory
131 4
                ->setConfig($config)
132 4
                ->get();
133 4
            $fields['__delete'] = $field;
134
135
136 4
            foreach ($columns as $columnName => $column) {
137 4
                if (in_array($columnName, $readOnly, true)) {
138
                    continue;
139
                }
140
141 4
                $formType = null;
142 4
                if ($columnName === $this->eloquentRelation->getParent()->getKeyName()) {
143
                    $formType = 'hidden';
144
                }
145
146
                $config = [
147 4
                    'name' => $columnName,
148 4
                    'presentation' => $this->name . ' ' . ucfirst(transcrud($columnName)),
149 4
                    'form_type' => $formType,
150 4
                    'no_validate' => true,
151 4
                    'validation' => null,
152
                    'functions' => null
153 4
                ];
154
155 4
                $config = $this->setConfig($config, $columnName);
156
157
                /** @var Field $field */
158 4
                $field = $this->fieldFactory
159 4
                    ->setColumn($column)
160 4
                    ->setConfig($config)
161 4
                    ->get();
162
163 4
                $fields[$columnName] = $field;
164
165 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...
166
                    $field = $this->fieldFactory
167
                        ->setColumn($column)
168
                        ->setConfig([
169
                            'name' => $columnName . '__delete',
170
                            'presentation' => null,
171
                            'form_type' => 'checkbox',
172
                            'no_validate' => true,
173
                            'validation' => null,
174
                            'functions' => null
175
                        ])
176
                        ->get();
177
                    $fields[$columnName . '__delete'] = $field;
178
                }
179 4
            }
180 4
        }
181
182 4
        return $fields;
183
    }
184
185
    /**
186
     * @param array|null $relationArray
187
     * @return mixed
188
     */
189 2
    public function persist(array $relationArray = null, Request $request)
190
    {
191 2
        if (!empty($relationArray)) {
192 2
            $keyName = $this->eloquentRelation->getParent()->getKeyName();
193 2
            $currentRelations = $this->getResults()->keyBy($keyName);
194
195 2
            $this->readConfig('edit');
196 2
            $fieldsBase = $this->getEditFieldsBase();
197
198 2
            foreach ($relationArray as $relationIndex => &$relation) {
199 2
                if (!empty($relation[$keyName])
200 2
                    && ($currentRelations->has($relation[$keyName]))
201 2
                ) {
202
                    $relationModel = $currentRelations->get($relation[$keyName]);
203
                } else {
204 2
                    $relationModel = $this->eloquentRelation->getRelated()->newInstance();
205
                }
206
207 2
                $this->modelAbstractor->setInstance($relationModel);
208 2
                $secondaryRelations = $this->getSecondaryRelations();
209
210
211 2
                $this->setKeys($relationModel);
212
213 2
                $shouldBeSkipped = true;
214 2
                $delayedRelations = collect();
215
216 2
                $skip = null;
217 2
                foreach ($fieldsBase as $fieldBaseKey => $field) {
218 2
                    $fieldName = $field->getName();
219
220 2
                    if (get_class($field->getFormField()) === \FormManager\Fields\File::class) {
221
                        $handleResult = $this->handleField($request, $relationModel, $fieldsBase, $this->name . ".$relationIndex", $fieldName);
222
                        if (! empty($handleResult['skip'])) {
223
                            $skip = $handleResult['skip'];
224
                            unset($relationArray[$relationIndex][$skip]);
225
                        }
226
                        if (! empty($handleResult['requestValue'])) {
227
                            $relationArray[$relationIndex][$fieldName] = $handleResult['requestValue'];
228
                        }
229
                    }
230
231 2
                    if ($fieldName !== '__delete' && ($fieldName != $skip && (get_class($field->getFormField()) === \FormManager\Fields\Checkbox::class))) {
232
                        if (empty($relationArray[$relationIndex][$fieldName])) {
233
                            // Unchecked checkboxes are not sent, so we force setting them to false
234
                            $relationModel->setAttribute($fieldName, null);
235
                        } else {
236
                            $relationArray[$relationIndex][$fieldName] = true;
237
                        }
238
                    }
239 2
                }
240
241
242 2
                foreach ($relation as $fieldKey => $fieldValue) {
243 2
                    if ($secondaryRelations->has($fieldKey)) {
244 1
                        $delayedRelations->put($fieldKey, $fieldValue);
245 1
                        continue;
246
                    }
247
248
                    // This field can only come from existing models
249 2
                    if ($fieldKey === '__delete') {
250
                        $relationModel->delete();
251
                        $shouldBeSkipped = true;
252
                        break;
253
                    }
254
255 2
                    if ($shouldBeSkipped) {
256 2
                        $shouldBeSkipped = ($shouldBeSkipped === ($fieldValue === ''));
257 2
                    }
258
259 2
                    $relationModel->setAttribute($fieldKey, $fieldValue);
260 2
                }
261
262 2
                if (!$shouldBeSkipped) {
263 2
                    $relationModel->save();
264
265 2
                    if (!$delayedRelations->isEmpty()) {
266 1
                        foreach ($delayedRelations as $relationKey => $delayedRelation) {
267
                            /** @var RelationContract $secondaryRelation */
268 1
                            $secondaryRelation = $secondaryRelations->get($relationKey);
269
270 1
                            $secondaryRelation->persist($delayedRelation, $request);
271 1
                        }
272 1
                    }
273 2
                }
274 2
            }
275 2
        }
276 2
    }
277
278 1
    protected function setKeys(Model $relationModel)
279
    {
280 1
        $relationModel->setAttribute($this->eloquentRelation->getForeignKey(), $this->relatedModel->id);
281 1
    }
282
283 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...
284
    {
285 1
        if ($columnName === $this->eloquentRelation->getPlainForeignKey()) {
286
            return true;
287
        }
288
289 1
        if ($key === 'emptyResult' && ($columnName === $this->eloquentRelation->getParent()->getKeyName())) {
290
            return true;
291
        }
292
293 1
        return false;
294
    }
295
296
    /**
297
     * @return string
298
     */
299
    public function getDisplayType()
300
    {
301
        return self::DISPLAY_TYPE_TAB;
302
    }
303
304
    /**
305
     * @param array $fields
306
     * @return array
307
     */
308
    public function addSecondaryRelationFields(array $fields)
309
    {
310
        $tempFields = [];
311 View Code Duplication
        foreach ($this->getSecondaryRelations() as $relationKey => $relation) {
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...
312
            foreach ($relation->getEditFields($relationKey) as $editGroupName => $editGroup) {
313
                if ($relation->getType() === 'Anavel\Crud\Abstractor\Eloquent\Relation\Select') {
314
                    $tempFields[key($editGroup)] = $editGroup[key($editGroup)];
315
                } else {
316
                    $tempFields[$editGroupName] = $editGroup;
317
                }
318
            };
319
        }
320
        foreach ($fields[$this->name] as $groupKey => $mainFields) {
321
            $combinedFields = array_merge($mainFields, $tempFields);
322
            $fields[$this->name][$groupKey] = $combinedFields;
323
        }
324
325
        return $fields;
326
    }
327
}
328
329