Completed
Push — master ( 737f06...12c136 )
by
unknown
06:05
created

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