Completed
Push — master ( d98642...6fd523 )
by recca
02:22
created

Generator   A

Complexity

Total Complexity 33

Size/Duplication

Total Lines 346
Duplicated Lines 11.85 %

Coupling/Cohesion

Components 1
Dependencies 4

Test Coverage

Coverage 97.92%

Importance

Changes 6
Bugs 4 Features 0
Metric Value
wmc 33
c 6
b 4
f 0
lcom 1
cbo 4
dl 41
loc 346
ccs 141
cts 144
cp 0.9792
rs 9.3999

17 Methods

Rating   Name   Duplication   Size   Complexity  
A __construct() 0 6 3
B parseAttribute() 0 29 3
A setFullBaseClass() 0 12 2
A setFullRepositoryInterface() 9 9 1
A setFullRepositoryClass() 0 10 1
A setFullModelClass() 0 12 1
A setFullPresenterClass() 9 9 1
A setFullRequestClass() 9 9 1
A setFullControllerClass() 0 14 1
B set() 0 14 5
A get() 0 4 1
A remove() 0 4 1
A render() 0 9 2
B renderServiceProvider() 14 37 5
A replaceServieProviderCallback() 0 16 2
A getNamespace() 0 4 1
A orderedUses() 0 6 2

How to fix   Duplicated Code   

Duplicated Code

Duplicate code is one of the most pungent code smells. A rule that is often used is to re-structure code once it is duplicated in three or more places.

Common duplication problems, and corresponding solutions are:

1
<?php
2
3
namespace Recca0120\Generator;
4
5
use Illuminate\Support\Arr;
6
use Illuminate\Support\Str;
7
use Illuminate\Filesystem\Filesystem;
8
use Recca0120\Generator\Fixers\UseSortFixer;
9
10
class Generator
11
{
12
    /**
13
     * $filesystem.
14
     *
15
     * @var \Illuminate\Filesystem\Filesystem
16
     */
17
    protected $filesystem;
18
19
    /**
20
     * $useSortFixer.
21
     *
22
     * @var \Recca0120\Generator\Fixers\UseSortFixer
23
     */
24
    protected $useSortFixer;
25
26
    /**
27
     * $attributes.
28
     *
29
     * @var array
30
     */
31
    protected $attributes = [];
32
33
    /**
34
     * __construct.
35
     *
36
     * @param \Illuminate\Filesystem\Filesystem $filesystem
37
     * @param \Recca0120\Generator\Fixers\UseSortFixer $useSortFixer
38
     */
39 9
    public function __construct(Filesystem $filesystem = null, UseSortFixer $useSortFixer = null)
40
    {
41 9
        $this->filesystem = $filesystem ?: new Filesystem();
42 9
        $this->useSortFixer = $useSortFixer ?: new UseSortFixer();
43 9
        $this->useSortFixer->setSortType(UseSortFixer::SORT_TYPE_LENGTH);
44 9
    }
45
46
    /**
47
     * parseAttribute.
48
     *
49
     * @param string $value
50
     * @return array
51
     */
52 9
    protected function parseAttribute($value)
53
    {
54 9
        $alias = array_map('trim', explode(' as ', $value));
55 9
        $className = $alias[0];
56
57 9
        $dummyClass = class_basename(isset($alias[1]) === true ? $alias[1] : $className);
58 9
        $dummyNamespace = $this->getNamespace($className);
59
60 9
        $singular = Str::camel(Str::singular(
61 9
            preg_replace('/(Controller|Repository)$/', '', $dummyClass)
62 9
        ));
63 9
        $plural = Str::plural($singular);
64
65 9
        $dummyModel = $singular;
66 9
        $dummyRepository = $plural;
67 9
        $dummyCollection = $singular === $plural ? $singular.'Collection' : $plural;
68 9
        $dummyView = Str::snake($plural);
69 9
        $dummyRoute = Str::snake($plural);
70
71
        return [
72 9
            'DummyNamespace' => $dummyNamespace,
73 9
            'DummyClass' => $dummyClass,
74 9
            'dummyModel' => $dummyModel,
75 9
            'dummyRepository' => $dummyRepository,
76 9
            'dummyCollection' => $dummyCollection,
77 9
            'dummyView' => $dummyView,
78 9
            'dummyRoute' => $dummyRoute,
79 9
        ];
80
    }
81
82
    /**
83
     * setFullBaseClass.
84
     *
85
     * @param string $value
86
     * @return $this
87
     */
88 7
    public function setFullBaseClass($value)
89
    {
90 7
        $this->set('DummyFullBaseClass', $value);
91 7
        $attributes = $this->parseAttribute($value);
92
93 7
        $this->set('DummyBaseClass', $attributes['DummyClass']);
94 7
        if ($this->get('DummyNamespace') === $this->getNamespace($value)) {
95 2
            $this->remove('DummyFullBaseClass');
96 2
        }
97
98 7
        return $this;
99
    }
100
101
    /**
102
     * setFullRepositoryInterface.
103
     *
104
     * @param string $value
105
     * @return $this
106
     */
107 3 View Code Duplication
    public function setFullRepositoryInterface($value)
108
    {
109 3
        $this->set('DummyFullRepositoryInterface', $value);
110 3
        $attributes = $this->parseAttribute($value);
111
112 3
        return $this->set('DummyNamespace', $attributes['DummyNamespace'], false)
113 3
            ->set('DummyClass', $attributes['DummyClass'], false)
114 3
            ->set('DummyRepositoryInterface', $attributes['DummyClass'], false);
115
    }
116
117
    /**
118
     * setFullRepositoryClass.
119
     *
120
     * @param string $value
121
     * @return $this
122
     */
123 3
    public function setFullRepositoryClass($value)
124
    {
125 3
        $this->set('DummyFullRepositoryClass', $value);
126 3
        $attributes = $this->parseAttribute($value);
127
128 3
        return $this->set('DummyNamespace', $attributes['DummyNamespace'], false)
129 3
            ->set('DummyClass', $attributes['DummyClass'], false)
130 3
            ->set('DummyFullRepositoryInterface', $attributes['DummyNamespace'].'\Contracts\\'.$attributes['DummyClass'], false)
131 3
            ->set('DummyRepositoryClass', $attributes['DummyClass']);
132
    }
133
134
    /**
135
     * setFullModelClass.
136
     *
137
     * @param string $value
138
     * @return $this
139
     */
140 4
    public function setFullModelClass($value)
141
    {
142 4
        $this->set('DummyFullModelClass', $value);
143 4
        $attributes = $this->parseAttribute($value);
144
145 4
        return $this->set('DummyNamespace', $attributes['DummyNamespace'], false)
146 4
            ->set('DummyClass', $attributes['DummyClass'], false)
147 4
            ->set('dummyModel', $attributes['dummyModel'], false)
148 4
            ->set('DummyFullPresenterClass', $attributes['DummyNamespace'].'\Presenters\\'.$attributes['DummyClass'].'Presenter', false)
149 4
            ->set('DummyPresenterClass', $attributes['DummyClass'].'Presenter', false)
150 4
            ->set('DummyModelClass', $attributes['DummyClass']);
151
    }
152
153
    /**
154
     * setFullPresenterClass.
155
     *
156
     * @param string $value
157
     * @return $this
158
     */
159 1 View Code Duplication
    public function setFullPresenterClass($value)
160
    {
161 1
        $this->set('DummyFullPresenterClass', $value);
162 1
        $attributes = $this->parseAttribute($value);
163
164 1
        return $this->set('DummyNamespace', $attributes['DummyNamespace'], false)
165 1
            ->set('DummyClass', $attributes['DummyClass'], false)
166 1
            ->set('DummyPresenterClass', $attributes['DummyClass']);
167
    }
168
169
    /**
170
     * setFullRequestClass.
171
     *
172
     * @param string $value
173
     * @return $this
174
     */
175 3 View Code Duplication
    public function setFullRequestClass($value)
176
    {
177 3
        $this->set('DummyFullRequestClass', $value);
178 3
        $attributes = $this->parseAttribute($value);
179
180 3
        return $this->set('DummyNamespace', $attributes['DummyNamespace'], false)
181 3
            ->set('DummyClass', $attributes['DummyClass'], false)
182 3
            ->set('DummyRequestClass', $attributes['DummyClass']);
183
    }
184
185
    /**
186
     * setFullControllerClass.
187
     *
188
     * @param string $value
189
     * @return $this
190
     */
191 2
    public function setFullControllerClass($value)
192
    {
193 2
        $this->set('DummyFullControllerClass', $value);
194 2
        $attributes = $this->parseAttribute($value);
195
196 2
        return $this->set('DummyNamespace', $attributes['DummyNamespace'], false)
197 2
            ->set('DummyClass', $attributes['DummyClass'], false)
198 2
            ->set('dummyRepository', $attributes['dummyRepository'], false)
199 2
            ->set('dummyCollection', $attributes['dummyCollection'], false)
200 2
            ->set('dummyModel', $attributes['dummyModel'], false)
201 2
            ->set('dummyView', $attributes['dummyView'], false)
202 2
            ->set('dummyRoute', $attributes['dummyRoute'], false)
203 2
            ->set('DummyControllerClass', $attributes['DummyClass']);
204
    }
205
206
    /**
207
     * set.
208
     *
209
     * @param string $value
210
     * @return $this
211
     */
212 9
    public function set($key, $value = null, $replace = true)
213
    {
214 9
        if (is_array($key) === true) {
215
            foreach ($key as $k => $v) {
216
                $this->set($k, $v, $replace);
217
            }
218 9
        } else if ($replace === false && isset($this->attributes[$key]) === true) {
219 5
            return $this;
220
        }
221
222 9
        $this->attributes[$key] = $value;
223
224 9
        return $this;
225
    }
226
227
    /**
228
     * get.
229
     *
230
     * @return string
231
     */
232 7
    public function get($key)
233
    {
234 7
        return Arr::get($this->attributes, $key);
235
    }
236
237
    /**
238
     * remove.
239
     *
240
     * @param string $key
241
     * @return bool
242
     */
243 2
    public function remove($key)
244
    {
245 2
        return Arr::forget($this->attributes, $key);
246
    }
247
248
    /**
249
     * render.
250
     *
251
     * @param string $stub
252
     * @param bool $orderedUses
253
     * @return string
254
     */
255 8
    public function render($stub, $orderedUses = true)
256
    {
257 8
        $content = strtr(strtr(strtr($this->filesystem->get($stub), $this->attributes), ["\r\n" => "\n"]), [
258 8
            ' extends DummyBaseClass' => '',
259 8
            'use DummyFullBaseClass;' => '',
260 8
        ]);
261
262 8
        return $orderedUses === true ? $this->orderedUses($content) : $content;
263
    }
264
265
    /**
266
     * renderServiceProvider.
267
     *
268
     * @param string $content
269
     * @return string
270
     */
271 1
    public function renderServiceProvider($content)
272
    {
273 1
        if (strpos($content, '$this->registerRepositories') === false) {
274 1
            $content = preg_replace_callback('/public function register\(.+\n\s+{/', function ($m) {
275 1
                return $m[0]."\n".
276 1
                    str_repeat(' ', 8).
277 1
                    '$this->registerRepositories();';
278 1
            }, $content);
279 1
        }
280
281 1
        if (strpos($content, 'protected function registerRepositories()') === false) {
282 1
            $content = substr($content, 0, strrpos($content, '}')).
283 1
                "\n".str_repeat(' ', 4).
284 1
                'protected function registerRepositories()'.
285 1
                "\n".str_repeat(' ', 4).'{'.
286 1
                "\n".str_repeat(' ', 4).'}'.
287 1
                "\n}\n";
288 1
        }
289
290 1 View Code Duplication
        if (strpos($content, sprintf('use %s;', $this->get('DummyFullRepositoryClass'))) === false) {
291 1
            $content = preg_replace_callback(
292 1
                '/namespace.+/',
293 1
                [$this, 'replaceServieProviderCallback'],
294
                $content
295 1
            );
296 1
        }
297
298 1 View Code Duplication
        if (strpos($content, sprintf('$this->app->singleton(%sContract::class, %s::class);', $this->get('DummyClass'), $this->get('DummyClass'))) === false) {
299 1
            $content = preg_replace_callback(
300 1
                '/protected function registerRepositories.+\n\s+{/',
301 1
                [$this, 'replaceServieProviderCallback'],
302
                $content
303 1
            );
304 1
        }
305
306 1
        return $this->orderedUses($content);
307
    }
308
309
    /**
310
     * replaceServieProviderCallback.
311
     *
312
     * @param  array $match
313
     * @return string
314
     */
315 1
    protected function replaceServieProviderCallback($match)
316
    {
317 1
        $fullRepositoryClass = $this->get('DummyFullRepositoryClass');
318 1
        $fullRepositoryInterface = $this->get('DummyFullRepositoryInterface');
319 1
        $DummyClass = $this->get('DummyClass');
320
321 1
        if (Str::startsWith($match[0], 'namespace') === true) {
322 1
            return $match[0]."\n\n".
323 1
                sprintf("use %s as %sContract;\n", $fullRepositoryInterface, $DummyClass).
324 1
                sprintf("use %s;\n", $fullRepositoryClass);
325
        } else {
326 1
            return $match[0]."\n".
327 1
                str_repeat(' ', 8).
328 1
                sprintf('$this->app->singleton(%sContract::class, %s::class);', $DummyClass, $DummyClass);
329
        }
330
    }
331
332
    /**
333
     * getNamespace.
334
     *
335
     * @param string $name
336
     * @return string
337
     */
338 9
    protected function getNamespace($name)
339
    {
340 9
        return rtrim(preg_replace('/'.class_basename($name).'$/', '', $name), '\\');
341
    }
342
343
    /**
344
     * orderedUses.
345
     *
346
     * @param string $content
347
     * @return string
348
     */
349 9
    protected function orderedUses($content)
350
    {
351 9
        $fix = $this->useSortFixer->fix($content);
352
353 9
        return $fix === false ? $content : strtr($fix, ["\r\n" => "\n"]);
354
    }
355
}
356