Passed
Branch master (363e66)
by Richard
07:20
created

RoutesGenerator::buildText()   F

Complexity

Conditions 19
Paths 289

Size

Total Lines 88
Code Lines 64

Duplication

Lines 0
Ratio 0 %

Importance

Changes 9
Bugs 0 Features 0
Metric Value
eloc 64
c 9
b 0
f 0
dl 0
loc 88
rs 2.5708
cc 19
nc 289
nop 3

How to fix   Long Method    Complexity   

Long Method

Small methods make your code easier to understand, in particular if combined with a good name. Besides, if your method is small, finding a good name is usually much easier.

For example, if you find yourself adding comments to a method's body, this is usually a good sign to extract the commented part to a new method, and use the comment as a starting point when coming up with a good name for this new method.

Commonly applied refactorings include:

1
<?php
2
3
namespace PWWEB\Artomator\Generators\Scaffold;
4
5
use Illuminate\Support\Arr;
6
use Illuminate\Support\Str;
7
use PWWEB\Artomator\Common\CommandData;
8
9
class RoutesGenerator
10
{
11
    /**
12
     * Command data instance.
13
     *
14
     * @var CommandData
15
     */
16
    private $commandData;
17
18
    /**
19
     * Path variable.
20
     *
21
     * @var string
22
     */
23
    private $path;
24
25
    /**
26
     * Route Contents.
27
     *
28
     * @var string
29
     */
30
    private $routeContents;
31
32
    /**
33
     * Route template.
34
     *
35
     * @var string
36
     */
37
    private $routesTemplate;
38
39
    /**
40
     * Routes array.
41
     *
42
     * @var string
43
     */
44
    private $routes;
45
46
    /**
47
     * Clasess array.
48
     *
49
     * @var string
50
     */
51
    private $classes;
52
53
    /**
54
     * Classes array.
55
     *
56
     * @var string[]
57
     */
58
    private $classNames;
59
60
    /**
61
     * Constructor.
62
     *
63
     * @param CommandData $commandData Command data passed in from above.
64
     */
65
    public function __construct(CommandData $commandData)
66
    {
67
        $this->commandData = $commandData;
68
        $this->path = $commandData->config->pathRoutes;
69
    }
70
71
    /**
72
     * Prepare the routes array.
73
     *
74
     * @return void
75
     */
76
    public function prepareRoutes()
77
    {
78
        $fileName = $this->path.'.json';
79
80
        if (true === file_exists($fileName)) {
81
            // Routes json exists:
82
            $fileRoutes = file_get_contents($fileName);
83
            $fileRoutes = json_decode($fileRoutes, true);
84
        } else {
85
            $fileRoutes = [];
86
        }
87
88
        if (true === empty($this->commandData->config->prefixes['route'])) {
89
            $new = [
90
                'resources' => [$this->commandData->modelName => $this->commandData->modelName],
91
                'name'      => strtolower($this->commandData->modelName),
92
            ];
93
            $routes = [ucfirst($this->commandData->modelName) => $new];
94
        } else {
95
            $prefixes = explode('.', $this->commandData->config->prefixes['route']);
96
            $routes = [];
97
            foreach (array_reverse($prefixes) as $key => $prefix) {
98
                $new = [
99
                    'prefix' => $prefix,
100
                    'name'   => strtolower($prefix),
101
                ];
102
                if (0 === $key) {
103
                    $new['resources'] = [$this->commandData->modelName => $this->commandData->modelName];
104
                } else {
105
                    $new['group'] = $routes;
106
                }
107
                $routes = [ucfirst($prefix) => $new];
108
            }
109
        }
110
        $fileRoutes = array_replace_recursive($fileRoutes, $routes);
111
        file_put_contents($fileName, json_encode($fileRoutes, JSON_PRETTY_PRINT));
112
        $this->commandData->commandComment("\nRoute JSON File saved: ");
113
        $this->commandData->commandInfo($fileName);
114
        $this->routes = $this->buildText($fileRoutes);
0 ignored issues
show
Documentation Bug introduced by
It seems like $this->buildText($fileRoutes) of type void is incompatible with the declared type string of property $routes.

Our type inference engine has found an assignment to a property that is incompatible with the declared type of that property.

Either this assignment is in error or the assigned type should be added to the documentation/type hint for that property..

Loading history...
Bug introduced by
Are you sure the assignment to $this->routes is correct as $this->buildText($fileRoutes) targeting PWWEB\Artomator\Generato...sGenerator::buildText() seems to always return null.

This check looks for function or method calls that always return null and whose return value is assigned to a variable.

class A
{
    function getObject()
    {
        return null;
    }

}

$a = new A();
$object = $a->getObject();

The method getObject() can return nothing but null, so it makes no sense to assign that value to a variable.

The reason is most likely that a function or method is imcomplete or has been reduced for debug purposes.

Loading history...
115
        $this->classes = $this->buildClasses();
116
    }
117
118
    /**
119
     * Generator function.
120
     *
121
     * @return void
122
     */
123
    public function generate()
124
    {
125
        $this->prepareRoutes();
126
        $this->routeContents = file_get_contents($this->path);
127
        if (1 !== preg_match('/\/\/ Artomator Routes Start(.*)\/\/ Artomator Routes Stop/sU', $this->routeContents)) {
128
            $this->routeContents .= "\n\n// Artomator Routes Start\n// Artomator Routes Stop";
129
        }
130
131
        $this->routeContents = preg_replace(
132
            '/(\/\/ Artomator Routes Start)(.*)(\/\/ Artomator Routes Stop)/sU',
133
            "$1\n".$this->routes.'$3',
0 ignored issues
show
Bug introduced by
Are you sure $this->routes of type void can be used in concatenation? ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-type  annotation

133
            "$1\n"./** @scrutinizer ignore-type */ $this->routes.'$3',
Loading history...
134
            $this->routeContents
135
        );
136
137
        if (1 !== preg_match(
138
            '/\/\/ Artomator Class References Start(.*)\/\/ Artomator Class References Stop/sU',
139
            $this->routeContents
140
        )) {
141
            $this->routeContents = preg_replace(
142
                '/(<\?php)/sU',
143
                "<?php\n\n// Artomator Class References Start\n// Artomator Class References Stop",
144
                $this->routeContents
145
            );
146
        }
147
148
        $this->routeContents = preg_replace(
149
            '/(\/\/ Artomator Class References Start)(.*)(\/\/ Artomator Class References Stop)/sU',
150
            "$1\n".$this->classes.'$3',
151
            $this->routeContents
152
        );
153
154
        file_put_contents($this->path, $this->routeContents);
155
        $this->commandData->commandComment("\n".$this->commandData->config->mCamelPlural.' routes added.');
156
    }
157
158
    /**
159
     * Re-generator the routes function.
160
     *
161
     * @return void
162
     */
163
    public function regenerate()
164
    {
165
        $fileName = $this->path.'.json';
166
167
        if (true === file_exists($fileName)) {
168
            // Routes json exists:
169
            $fileRoutes = file_get_contents($fileName);
170
            $fileRoutes = json_decode($fileRoutes, true);
171
        } else {
172
            $fileRoutes = [];
173
        }
174
        $this->routes = $this->buildText($fileRoutes);
0 ignored issues
show
Documentation Bug introduced by
It seems like $this->buildText($fileRoutes) of type void is incompatible with the declared type string of property $routes.

Our type inference engine has found an assignment to a property that is incompatible with the declared type of that property.

Either this assignment is in error or the assigned type should be added to the documentation/type hint for that property..

Loading history...
Bug introduced by
Are you sure the assignment to $this->routes is correct as $this->buildText($fileRoutes) targeting PWWEB\Artomator\Generato...sGenerator::buildText() seems to always return null.

This check looks for function or method calls that always return null and whose return value is assigned to a variable.

class A
{
    function getObject()
    {
        return null;
    }

}

$a = new A();
$object = $a->getObject();

The method getObject() can return nothing but null, so it makes no sense to assign that value to a variable.

The reason is most likely that a function or method is imcomplete or has been reduced for debug purposes.

Loading history...
175
        $this->routeContents = file_get_contents($this->path);
176
        if (1 !== preg_match('/\/\/ Artomator Routes Start(.*)\/\/ Artomator Routes Stop/sU', $this->routeContents)) {
177
            $this->routeContents .= "\n\n// Artomator Routes Start\n// Artomator Routes Stop";
178
        }
179
180
        $this->routeContents = preg_replace(
181
            '/(\/\/ Artomator Routes Start)(.*)(\/\/ Artomator Routes Stop)/sU',
182
            "$1\n".$this->routes.'$3',
0 ignored issues
show
Bug introduced by
Are you sure $this->routes of type void can be used in concatenation? ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-type  annotation

182
            "$1\n"./** @scrutinizer ignore-type */ $this->routes.'$3',
Loading history...
183
            $this->routeContents
184
        );
185
186
        if (1 !== preg_match(
187
            '/\/\/ Artomator Class References Start(.*)\/\/ Artomator Class References Stop/sU',
188
            $this->routeContents
189
        )) {
190
            $this->routeContents = preg_replace(
191
                '/(<\?php)/sU',
192
                "<?php\n\n// Artomator Class References Start\n// Artomator Class References Stop",
193
                $this->routeContents
194
            );
195
        }
196
197
        $this->routeContents = preg_replace(
198
            '/(\/\/ Artomator Class References Start)(.*)(\/\/ Artomator Class References Stop)/sU',
199
            "$1\n".$this->classes.'$3',
200
            $this->routeContents
201
        );
202
203
        file_put_contents($this->path, $this->routeContents);
204
        $this->commandData->commandComment("\nRoutes regenerated.");
205
    }
206
207
    /**
208
     * Rollback function.
209
     *
210
     * @return void
211
     */
212
    public function rollback()
213
    {
214
        if (true === Str::contains($this->routeContents, $this->routesTemplate)) {
215
            $this->routeContents = str_replace($this->routesTemplate, '', $this->routeContents);
216
            file_put_contents($this->path, $this->routeContents);
217
            $this->commandData->commandComment('scaffold routes deleted');
218
        }
219
    }
220
221
    /**
222
     * Template text builder function.
223
     *
224
     * @param array  $routes Routes array to process
225
     * @param int    $indent Indent counter
226
     * @param string $parent Parent prefix for fallback route
227
     *
228
     * @return void
229
     */
230
    private function buildText(array $routes, int $indent = 0, string $parent = '')
231
    {
232
        $templateContent = '';
233
        $fallback = '';
234
        foreach ($routes as $route_key => $route) {
235
            if ('' !== $parent) {
236
                $parent .= '.';
237
            }
238
            $parent .= (true === isset($route['prefix'])) ? $route['prefix'] : '';
239
            $templateString = '';
240
            $tabs = (true === isset($route['prefix'])) ? (($indent * 3) + 3) : 0;
241
            if (true === isset($route['custom'])) {
242
                foreach ($route['custom'] as $custom_key => $custom) {
243
                    if (true === isset($custom['function']) && '' !== $custom['function']) {
244
                        $custom['function'] = '@'.$custom['function'];
245
                    }
246
                    $vars = [
247
                        '$ITERATION_CUSTOM_METHOD$' => $custom['method'],
248
                        '$ITERATION_CUSTOM_ENDPOINT$' => $custom['endpoint'],
249
                        '$ITERATION_CUSTOM_CONTROLLER$' => $custom['controller'],
250
                        '$ITERATION_CUSTOM_FUNCTION$' => $custom['function'],
251
                        '$ITERATION_CUSTOM_NAME$' => $custom['name'],
252
                        '$INDENT$' => infy_tabs($tabs),
253
                    ];
254
                    $templateString .= get_artomator_template('scaffold.routes.prefixed.custom');
255
                    $templateString = fill_template($vars, $templateString);
256
                }
257
            }
258
            if (isset($route['resources'])) {
259
                $tabs = (isset($route['prefix'])) ? (($indent * 3) + 3) : 0;
260
                foreach ($route['resources'] as $resource_key => $only) {
261
                    if ('' === $fallback) {
262
                        $fallback = $parent.'.'.Str::lower($resource_key).'.index';
263
                    }
264
265
                    if ($resource_key !== $only) {
266
                        $only = '->only([\''.implode('\', \'', explode(',', $only)).'\'])';
267
                    } else {
268
                        $only = '';
269
                    }
270
271
                    $className = $parent;
272
                    $className .= (true === isset($route['prefix'])) ? '.'.$route['prefix'] : '';
273
                    $className .= '.'.$resource_key;
274
                    $className = explode('.', $className);
275
                    foreach ($className as &$path) {
276
                        $path = ucfirst($path);
277
                    }
278
                    $className = implode('\\', $className);
279
280
                    $this->classNames[] = $className;
281
282
                    $vars = [
283
                        '$ITERATION_MODEL_NAME_PLURAL_CAMEL$' => Str::camel(Str::plural($resource_key)),
284
                        '$ITERATION_MODEL_NAME$'              => $resource_key,
285
                        '$ITERATION_ONLY$'                    => $only,
286
                        '$INDENT$'                            => infy_tabs($tabs),
287
                    ];
288
                    $templateString .= get_artomator_template('scaffold.routes.prefixed.route');
289
                    $templateString = fill_template($vars, $templateString);
290
                }
291
            }
292
            if (true === (isset($route['group']))) {
293
                $templateString .= $this->buildText($route['group'], ($indent + 1), $parent);
0 ignored issues
show
Bug introduced by
Are you sure the usage of $this->buildText($route[..., $indent + 1, $parent) targeting PWWEB\Artomator\Generato...sGenerator::buildText() seems to always return null.

This check looks for function or method calls that always return null and whose return value is used.

class A
{
    function getObject()
    {
        return null;
    }

}

$a = new A();
if ($a->getObject()) {

The method getObject() can return nothing but null, so it makes no sense to use the return value.

The reason is most likely that a function or method is imcomplete or has been reduced for debug purposes.

Loading history...
294
            }
295
            if (true === (isset($route['prefix']))) {
296
                $vars = [
297
                    '$ITERATION_NAMESPACE_CAMEL$' => ucfirst($route_key),
298
                    '$ITERATION_NAMESPACE_LOWER$' => strtolower($route_key),
299
                    '$FALLBACK_ROUTE$'            => $fallback,
300
                    '$INDENT$'                    => infy_tabs($indent * 3),
301
                ];
302
                if ('' !== $fallback) {
303
                    $fallback_tmp = get_artomator_template('scaffold.routes.prefixed.fallback');
304
                } else {
305
                    $fallback_tmp = '';
306
                }
307
                $templateString = get_artomator_template('scaffold.routes.prefixed.namespace')
308
                    .$templateString
309
                    .$fallback_tmp
310
                    .get_artomator_template('scaffold.routes.prefixed.closure');
311
312
                $templateString = fill_template($vars, $templateString);
313
            }
314
            $templateContent .= $templateString;
315
        }
316
317
        return $templateContent;
0 ignored issues
show
Bug Best Practice introduced by
The expression return $templateContent returns the type string which is incompatible with the documented return type void.
Loading history...
318
    }
319
320
    /**
321
     * Build the class names to be used in the refences.
322
     *
323
     * @return string The string of classnames in the form.
324
     */
325
    private function buildClasses()
326
    {
327
        $this->classNames = Arr::sort($this->classNames);
328
329
        $classContent = '';
330
        foreach ($this->classNames as $key => $value) {
331
            $var = [
332
                '$ITERATION_NAMESPACE_CONTROLLER_NAME$' => $value,
333
            ];
334
335
            $classContent .= get_artomator_template('scaffold.routes.prefixed.reference');
336
337
            $classContent = fill_template($var, $classContent);
338
        }
339
340
        return $classContent;
341
    }
342
}
343