| Total Complexity | 43 |
| Total Lines | 310 |
| Duplicated Lines | 0 % |
| Changes | 23 | ||
| Bugs | 1 | Features | 2 |
Complex classes like StubParser 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 StubParser, and based on these observations, apply Extract Interface, too.
| 1 | <?php |
||
| 11 | class StubParser |
||
| 12 | { |
||
| 13 | |||
| 14 | public $texts = []; |
||
| 15 | private $inputName; |
||
| 16 | private $parsedModel; |
||
| 17 | |||
| 18 | private $fields; |
||
| 19 | private $inputs; |
||
| 20 | private $validationRules; |
||
| 21 | private $hasAuth; |
||
| 22 | private $store; |
||
| 23 | |||
| 24 | public function __construct($inputName, $parsedModel) |
||
| 25 | { |
||
| 26 | $this->inputName = $inputName; |
||
| 27 | $this->parsedModel = $parsedModel; |
||
| 28 | } |
||
| 29 | |||
| 30 | public function setValidationRules($rules) |
||
| 31 | { |
||
| 32 | $this->validationRules = $rules; |
||
| 33 | } |
||
| 34 | |||
| 35 | public function setStore($store) |
||
| 36 | { |
||
| 37 | $this->store = $store; |
||
| 38 | } |
||
| 39 | |||
| 40 | public function setAuthType(bool $hasAuth){ |
||
| 41 | $this->hasAuth = $hasAuth; |
||
| 42 | } |
||
| 43 | |||
| 44 | public function setFields(array $fields){ |
||
| 45 | $this->fields = $fields; |
||
| 46 | } |
||
| 47 | |||
| 48 | public function setInputs(array $inputs){ |
||
| 49 | $this->inputs = $inputs; |
||
| 50 | } |
||
| 51 | |||
| 52 | public function replaceModel($stub) |
||
| 53 | { |
||
| 54 | $modelNamespace = $this->parsedModel; |
||
| 55 | $modelName = $this->getModelName($modelNamespace); |
||
| 56 | |||
| 57 | $array = [ |
||
| 58 | '{{ modelName }}' => ucfirst($modelName), |
||
| 59 | '{{ modelNamespace }}' => $modelNamespace, |
||
| 60 | '{{ uploadFile }}' => $this->uploadCodeParser(), |
||
| 61 | '{{ model }}' => strtolower($modelName), |
||
| 62 | '{{ properties }}' => $this->parseProperties(), |
||
| 63 | '{{ rules }}' => $this->parseValidationRules(), |
||
| 64 | '{{ fields }}' => $this->parseActionInComponent(), |
||
| 65 | '{{ setProperties }}' => $this->parseSetPropertiesValue(), |
||
| 66 | ]; |
||
| 67 | |||
| 68 | return str_replace(array_keys($array), array_values($array), $stub); |
||
| 69 | } |
||
| 70 | |||
| 71 | /** |
||
| 72 | * Make Locale files |
||
| 73 | */ |
||
| 74 | public function setLocaleTexts() |
||
| 75 | { |
||
| 76 | $this->texts[ucfirst($this->inputName)] = ucfirst($this->inputName); |
||
| 77 | $this->texts[ucfirst(Str::plural($this->inputName))] = ucfirst(Str::plural($this->inputName)); |
||
| 78 | $files = File::glob(resource_path('lang').'/*_panel.json'); |
||
| 79 | |||
| 80 | foreach ($files as $file) { |
||
| 81 | $decodedFile = json_decode(File::get($file), 1); |
||
| 82 | $texts = $this->texts; |
||
| 83 | foreach ($texts as $key => $text) { |
||
| 84 | if (array_key_exists($key, $decodedFile)){ |
||
| 85 | unset($texts[$text]); |
||
| 86 | } |
||
| 87 | } |
||
| 88 | $array = array_merge($decodedFile, $texts); |
||
| 89 | File::put($file, json_encode($array, JSON_PRETTY_PRINT | JSON_UNESCAPED_UNICODE)); |
||
| 90 | } |
||
| 91 | } |
||
| 92 | |||
| 93 | /** |
||
| 94 | * Get model name from namespace |
||
| 95 | */ |
||
| 96 | public function getModelName($modelNamespace) |
||
| 101 | } |
||
| 102 | |||
| 103 | /** |
||
| 104 | * Parse properties in Livewire component |
||
| 105 | */ |
||
| 106 | public function parseProperties() |
||
| 121 | } |
||
| 122 | |||
| 123 | /** |
||
| 124 | * Parse Uploading Code |
||
| 125 | */ |
||
| 126 | public function uploadCodeParser() |
||
| 142 | } |
||
| 143 | |||
| 144 | /** |
||
| 145 | * parse values for mount method in Livewire |
||
| 146 | */ |
||
| 147 | public function parseSetPropertiesValue() |
||
| 158 | } |
||
| 159 | |||
| 160 | /** |
||
| 161 | * Parse Validation rules |
||
| 162 | */ |
||
| 163 | public function parseValidationRules() |
||
| 164 | { |
||
| 165 | $str = ''; |
||
| 166 | |||
| 167 | foreach ($this->validationRules as $key => $rule) { |
||
| 168 | $str .= "'$key' => '$rule',"; |
||
| 169 | $str .= $this->makeTab(2, $key != array_key_last($this->validationRules)); |
||
| 170 | } |
||
| 171 | |||
| 172 | return $str; |
||
| 173 | } |
||
| 174 | |||
| 175 | /** |
||
| 176 | * Create an array of properties in Livewire component for actions |
||
| 177 | */ |
||
| 178 | public function parseActionInComponent() |
||
| 179 | { |
||
| 180 | $str = ''; |
||
| 181 | |||
| 182 | foreach ($this->inputs as $key => $field) { |
||
| 183 | $newLine = ($field != end($this->inputs) or $this->hasAuth); |
||
| 184 | $str .= "'$key' => " . '$this' . "->$key,".$this->makeTab(3, $newLine); |
||
| 185 | } |
||
| 186 | |||
| 187 | if($this->hasAuth){ |
||
| 188 | $str .= "'user_id' => auth()->id(),"; |
||
| 189 | } |
||
| 190 | |||
| 191 | return $str; |
||
| 192 | } |
||
| 193 | |||
| 194 | /** |
||
| 195 | * Create Blade from stub |
||
| 196 | */ |
||
| 197 | public function parseBlade($stub){ |
||
| 198 | $modelName = $this->getModelName($this->parsedModel); |
||
| 199 | |||
| 200 | $array = [ |
||
| 201 | '{{ model }}' => strtolower($modelName), |
||
| 202 | '{{ modelName }}' => ucfirst($modelName), |
||
| 203 | '{{ data }}' => $this->parseDataInBlade(), |
||
| 204 | '{{ titles }}' => $this->parseTitlesInBlade(), |
||
| 205 | '{{ inputs }}' => $this->parseInputsInBlade(), |
||
| 206 | '{{ routeName }}' => crud(strtolower($modelName))->route, |
||
| 207 | ]; |
||
| 208 | |||
| 209 | $this->setLocaleTexts(); |
||
| 210 | |||
| 211 | return str_replace(array_keys($array), array_values($array), $stub); |
||
| 212 | } |
||
| 213 | |||
| 214 | /** |
||
| 215 | * Parse <td> tags for data |
||
| 216 | */ |
||
| 217 | public function parseDataInBlade() |
||
| 218 | { |
||
| 219 | $fields = $this->fields; |
||
| 220 | $str = ''; |
||
| 221 | $modelName = strtolower($this->getModelName($this->parsedModel)); |
||
| 222 | foreach ($fields as $key => $field) { |
||
| 223 | $normalizedField = $this->normalizeField($field); |
||
| 224 | $str .= $normalizedField->setModel($modelName)->setKey($key)->renderData(); |
||
| 225 | |||
| 226 | $str .= $this->makeTab(1, false); |
||
| 227 | } |
||
| 228 | |||
| 229 | return $str; |
||
| 230 | } |
||
| 231 | |||
| 232 | /** |
||
| 233 | * Parse <td> tags for head |
||
| 234 | */ |
||
| 235 | public function parseTitlesInBlade() |
||
| 236 | { |
||
| 237 | $fields = $this->fields; |
||
| 238 | $modelName = $this->getModelNameInLowerCase(); |
||
| 239 | |||
| 240 | $str = ''; |
||
| 241 | foreach ($fields as $key => $field) { |
||
| 242 | // We will normalize the field value because most of users prefer to use simple mode |
||
| 243 | // And they pass string and we will change it to a Field class object |
||
| 244 | $normalizedField = $this->normalizeField($field); |
||
| 245 | |||
| 246 | // Then we set the model and key to render the stub and get the string |
||
| 247 | // The returned string concatenates with previous rendered fields |
||
| 248 | $str .= $normalizedField->setModel($modelName)->setKey($key)->renderTitle(); |
||
| 249 | |||
| 250 | // To show the rendered html tag more readable and cleaner in view we make some tab |
||
| 251 | $str .= $this->makeTab(7, false); |
||
| 252 | |||
| 253 | // After all of this process, the Title will be pushed to the translatable list |
||
| 254 | $this->texts[$field->getTitle()] = $field->getTitle(); |
||
| 255 | } |
||
| 256 | |||
| 257 | return $str; |
||
| 258 | } |
||
| 259 | |||
| 260 | /** |
||
| 261 | * Create inputs HTML |
||
| 262 | */ |
||
| 263 | public function parseInputsInBlade() |
||
| 264 | { |
||
| 265 | $str = ''; |
||
| 266 | foreach ($this->inputs as $key => $type) { |
||
| 267 | $inputObject = $this->normalizeInput($key, $type); |
||
| 268 | $str .= $inputObject->setKey($key)->setAction($this->inputName)->render(); |
||
| 269 | |||
| 270 | $this->texts[$inputObject->getTitle()] = $inputObject->getTitle(); |
||
| 271 | if ($placeholder = $inputObject->getPlaceholder()){ |
||
| 272 | $this->texts[$placeholder] = $placeholder; |
||
| 273 | } |
||
| 274 | } |
||
| 275 | |||
| 276 | return $str; |
||
| 277 | } |
||
| 278 | |||
| 279 | /** |
||
| 280 | * Tab Maker (Each tabs mean 4 space) |
||
| 281 | */ |
||
| 282 | public function makeTab($count, $newLine = true){ |
||
| 283 | $count = $count * 4; |
||
| 284 | $tabs = str_repeat(' ', $count); |
||
| 285 | |||
| 286 | return $newLine ? "\n".$tabs : $tabs; |
||
| 287 | } |
||
| 288 | |||
| 289 | public function getInputClassNamespace($type) |
||
| 294 | } |
||
| 295 | |||
| 296 | private function normalizeField($field) |
||
| 297 | { |
||
| 298 | if($field instanceof Field){ |
||
| 299 | return $field; |
||
| 300 | } |
||
| 301 | |||
| 302 | $title = str_replace('.', ' ', $field); |
||
| 303 | $title = ucwords($title); |
||
| 304 | return Field::title($title); |
||
| 305 | } |
||
| 306 | |||
| 307 | private function normalizeInput($key, $input){ |
||
| 308 | if ($input instanceof BaseInput){ |
||
| 309 | return $input; |
||
| 310 | } |
||
| 311 | |||
| 312 | $type = is_array($input) ? array_key_first($input) : $input; |
||
| 313 | $title = ucwords($key); |
||
| 314 | |||
| 315 | return $this->getInputClassNamespace($type)::label($title); |
||
| 316 | } |
||
| 317 | |||
| 318 | private function getModelNameInLowerCase() |
||
| 321 | } |
||
| 322 | |||
| 323 | } |
||
| 324 |
This check looks for calls to methods that do not seem to exist on a given type. It looks for the method on the type itself as well as in inherited classes or implemented interfaces.
This is most likely a typographical error or the method has been renamed.