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