We could not synchronize checks via GitHub's checks API since Scrutinizer's GitHub App is not installed for this repository.
| Total Complexity | 43 |
| Total Lines | 233 |
| Duplicated Lines | 0 % |
| Changes | 3 | ||
| Bugs | 2 | Features | 0 |
Complex classes like Input often do a lot of different things. To break such a class down, we need to identify a cohesive component within that class. A common approach to find such a component is to look for fields/methods that share the same prefixes, or suffixes.
Once you have determined the fields that belong together, you can apply the Extract Class refactoring. If the component makes sense as a sub-class, Extract Subclass is also a candidate, and is often faster.
While breaking up the class, it is a good idea to analyze how other classes use Input, and based on these observations, apply Extract Interface, too.
| 1 | <?php |
||
| 8 | trait Input |
||
| 9 | { |
||
| 10 | /** |
||
| 11 | * --------------- |
||
| 12 | * PRIVATE METHODS |
||
| 13 | * ---------------. |
||
| 14 | */ |
||
| 15 | |||
| 16 | /** |
||
| 17 | * Returns the direct inputs parsed for model and relationship creation. |
||
| 18 | * |
||
| 19 | * @param array $inputs |
||
| 20 | * @param null|array $relationDetails |
||
| 21 | * @param bool|string $relationMethod |
||
| 22 | * @return array |
||
| 23 | */ |
||
| 24 | private function splitInputIntoDirectAndRelations($inputs, $relationDetails = null, $relationMethod = false) |
||
| 25 | { |
||
| 26 | $crudFields = $relationDetails['crudFields'] ?? []; |
||
| 27 | $model = $relationDetails['model'] ?? false; |
||
| 28 | |||
| 29 | $directInputs = $this->getDirectInputsFromInput($inputs, $model, $crudFields, $relationMethod); |
||
| 30 | $relationInputs = $this->getRelationDetailsFromInput($inputs, $crudFields, $relationMethod); |
||
| 31 | |||
| 32 | return [$directInputs, $relationInputs]; |
||
| 33 | } |
||
| 34 | |||
| 35 | /** |
||
| 36 | * Returns the attributes with relationships stripped out from the input. |
||
| 37 | * BelongsTo relations are ensured to have the correct foreign key set. |
||
| 38 | * ALL other relations are stripped from the input. |
||
| 39 | * |
||
| 40 | * @param array $input - the input array |
||
| 41 | * @param mixed $model - the model of what we want to get the attributtes for |
||
| 42 | * @param array $fields - the fields used in this relation |
||
| 43 | * @param mixed $relationMethod - the relation method |
||
| 44 | * @return array |
||
| 45 | */ |
||
| 46 | private function getDirectInputsFromInput($input, $model = false, $fields = [], $relationMethod = false) |
||
| 57 | } |
||
| 58 | |||
| 59 | /** |
||
| 60 | * Get a relation data array from the form data. For each relation defined in the fields |
||
| 61 | * through the entity attribute, and set some relation details. |
||
| 62 | * |
||
| 63 | * We traverse this relation array later to create the relations, for example: |
||
| 64 | * - Current model HasOne Address |
||
| 65 | * - Address (line_1, country_id) BelongsTo Country through country_id in Address Model |
||
| 66 | * |
||
| 67 | * So when editing current model crud user have two fields |
||
| 68 | * - address.line_1 |
||
| 69 | * - address.country |
||
| 70 | * (we infer country_id from relation) |
||
| 71 | * |
||
| 72 | * Those will be nested accordingly in this relation array, so address relation |
||
| 73 | * will have a nested relation with country. |
||
| 74 | * |
||
| 75 | * @param array $input The form input. |
||
| 76 | * @param array $crudFields - present when getting the relation details for other relations. |
||
| 77 | * @param mixed $relationMethod |
||
| 78 | * @return array The formatted relation details. |
||
| 79 | */ |
||
| 80 | private function getRelationDetailsFromInput($input, $crudFields = [], $relationMethod = false) |
||
| 81 | { |
||
| 82 | // main entity |
||
| 83 | if (empty($crudFields)) { |
||
| 84 | $relationFields = $this->getRelationFields(); |
||
| 85 | } else { |
||
| 86 | // relations sends the fields that represent them so we can parse the input accordingly. |
||
| 87 | $relationFields = $crudFields; |
||
| 88 | |||
| 89 | foreach ($crudFields as $key => $crudField) { |
||
| 90 | if (isset($crudField['subfields'])) { |
||
| 91 | foreach ($crudField['subfields'] as $crudSubField) { |
||
| 92 | if (isset($crudSubField['relation_type'])) { |
||
| 93 | $relationFields[] = $crudSubField; |
||
| 94 | } |
||
| 95 | } |
||
| 96 | } |
||
| 97 | } |
||
| 98 | } |
||
| 99 | |||
| 100 | //remove fields that are not in the submitted form input |
||
| 101 | $relationFields = array_filter($relationFields, function ($field) use ($input) { |
||
| 102 | return Arr::has($input, $field['name']) || isset($input[$field['name']]) || Arr::has($input, Str::afterLast($field['name'], '.')); |
||
| 103 | }); |
||
| 104 | |||
| 105 | $relationDetails = []; |
||
| 106 | |||
| 107 | foreach ($relationFields as $field) { |
||
| 108 | // if relationMethod is set we strip it out of the fieldName that we use to create the relations array |
||
| 109 | $fieldName = $relationMethod ? Str::after($field['name'], $relationMethod.'.') : $field['name']; |
||
| 110 | |||
| 111 | $key = Str::before($this->getOnlyRelationEntity(['entity' => $fieldName]), '.'); |
||
| 112 | |||
| 113 | // if the field entity contains the attribute we want to add that attribute in the correct relation key. |
||
| 114 | // eg: address.street, we want to add `street` as an attribute in `address` relation, `street` is not |
||
| 115 | // a relation of `address` |
||
| 116 | if ($this->getOnlyRelationEntity($field) !== $field['entity']) { |
||
| 117 | if (Str::before($field['entity'], '.') === $relationMethod) { |
||
| 118 | $key = Str::before($this->getOnlyRelationEntity($field), '.'); |
||
| 119 | } |
||
| 120 | } |
||
| 121 | |||
| 122 | $attributeName = (string) Str::of($field['name'])->afterLast('.'); |
||
| 123 | |||
| 124 | switch ($field['relation_type']) { |
||
| 125 | case 'BelongsTo': |
||
| 126 | // when it's a nested belongsTo relation we want to make sure |
||
| 127 | // the key used to store the values is the main relation key |
||
| 128 | $key = Str::beforeLast($this->getOnlyRelationEntity($field), '.'); |
||
| 129 | |||
| 130 | if (! isset($field['parentFieldName']) && isset($field['entity'])) { |
||
| 131 | $mainField = $field; |
||
| 132 | $mainField['entity'] = Str::beforeLast($field['entity'], '.'); |
||
| 133 | |||
| 134 | $inferredRelation = $this->inferRelationTypeFromRelationship($mainField); |
||
| 135 | } |
||
| 136 | |||
| 137 | break; |
||
| 138 | } |
||
| 139 | |||
| 140 | // we don't need to re-setup this relation method values, we just want the relations |
||
| 141 | if ($key === $relationMethod) { |
||
| 142 | unset($inferredRelation); |
||
| 143 | continue; |
||
| 144 | } |
||
| 145 | |||
| 146 | $fieldDetails = Arr::get($relationDetails, $key, []); |
||
| 147 | $fieldDetails['values'][$attributeName] = Arr::get($input, $fieldName); |
||
| 148 | $fieldDetails['model'] = $fieldDetails['model'] ?? $field['model']; |
||
| 149 | $fieldDetails['relation_type'] = $fieldDetails['relation_type'] ?? $inferredRelation ?? $field['relation_type']; |
||
| 150 | $fieldDetails['crudFields'][] = $field; |
||
| 151 | $fieldDetails['entity'] = $this->getOnlyRelationEntity($field); |
||
| 152 | |||
| 153 | if (isset($field['fallback_id'])) { |
||
| 154 | $fieldDetails['fallback_id'] = $field['fallback_id']; |
||
| 155 | } |
||
| 156 | if (isset($field['force_delete'])) { |
||
| 157 | $fieldDetails['force_delete'] = $field['force_delete']; |
||
| 158 | } |
||
| 159 | |||
| 160 | Arr::set($relationDetails, $key, $fieldDetails); |
||
| 161 | unset($inferredRelation); |
||
| 162 | } |
||
| 163 | |||
| 164 | return $relationDetails; |
||
| 165 | } |
||
| 166 | |||
| 167 | /** |
||
| 168 | * Return the input without relations except BelongsTo that we are going to properly match |
||
| 169 | * with the relation foreign_key in a later stage of the saving process. |
||
| 170 | * |
||
| 171 | * @param array $fields |
||
| 172 | * @param mixed $relationMethod |
||
| 173 | * @return array |
||
| 174 | */ |
||
| 175 | private function excludeRelationFieldsExceptBelongsTo($input, $fields, $relationMethod) |
||
| 204 | }); |
||
| 205 | } |
||
| 206 | |||
| 207 | /** |
||
| 208 | * Decode attributes that are casted as array/object/json in the model. |
||
| 209 | * So that they are not json_encoded twice before they are stored in the db |
||
| 210 | * (once by Backpack in front-end, once by Laravel Attribute Casting). |
||
| 211 | * |
||
| 212 | * @param array $input |
||
| 213 | * @param mixed $model |
||
| 214 | * @return array |
||
| 215 | */ |
||
| 216 | public function decodeJsonCastedAttributes($input, $model = false) |
||
| 243 |