Directive   A
last analyzed

Complexity

Total Complexity 34

Size/Duplication

Total Lines 374
Duplicated Lines 0 %

Importance

Changes 1
Bugs 0 Features 0
Metric Value
eloc 85
c 1
b 0
f 0
dl 0
loc 374
rs 9.68
wmc 34

24 Methods

Rating   Name   Duplication   Size   Complexity  
A alias() 0 5 1
A type() 0 3 1
A load() 0 21 3
A setAlias() 0 6 1
A relative() 0 8 1
A setType() 0 8 2
A setSentence() 0 14 3
A loadComponent() 0 5 1
A getViewComponent() 0 17 3
A placeholders() 0 3 1
A name() 0 3 1
A path() 0 3 1
A init() 0 8 1
A __construct() 0 3 1
A filename() 0 3 1
A setName() 0 7 1
A loadKebabAlias() 0 5 1
A loadViewComponent() 0 5 1
A isViewComponent() 0 11 3
A create() 0 10 2
A exists() 0 3 1
A sentence() 0 3 1
A setPath() 0 4 1
A loadInclude() 0 5 1
1
<?php
2
3
namespace Maestriam\Samurai\Entities;
4
5
use Illuminate\Support\Str;
6
use Maestriam\Samurai\Entities\Theme;
7
use Illuminate\Support\Facades\Blade;
8
use Maestriam\FileSystem\Support\FileSystem;
9
use Maestriam\Samurai\Contracts\Entities\DirectiveContract;
10
use Maestriam\Samurai\Exceptions\DirectiveExistsException;
11
use Maestriam\Samurai\Exceptions\InvalidDirectiveNameException;
12
use Maestriam\Samurai\Exceptions\InvalidTypeDirectiveException;
13
use ReflectionClass;
14
15
abstract class Directive extends Source implements DirectiveContract
16
{
17
    /**
18
     * Nome da diretiva
19
     *
20
     * @var string
21
     */
22
    protected string $name;
23
24
    /**
25
     * Sentença que foi inserida pelo usuário,
26
     * que irá fornecer o nome/sub-diretório
27
     *
28
     * @var string
29
     */
30
    protected string $sentence;
31
32
    /**
33
     * Tipo da diretiva
34
     *
35
     * @var string
36
     */
37
    protected string $type;
38
39
    /**
40
     * Tema de origem
41
     *
42
     * @var Theme
43
     */
44
    protected $theme;
45
46
    /**
47
     * Caminho do arquivo
48
     *
49
     * @var string
50
     */
51
    protected string $path;
52
53
    /**
54
     * Apelido pelo qual é chamado dentro do projeto,
55
     * como camel-case
56
     * 
57
     * @var string
58
     */
59
    protected string $camelAlias;
60
61
    /**
62
     * Apelido pelo qual é chamado dentro do projeto,
63
     * como camel-case
64
     * 
65
     * @var string
66
     */
67
    protected string $kebabAlias;
68
69
    /**
70
     * Instância as regras de negócio de uma diretiva
71
     *
72
     * @param Theme  $theme
73
     * @param string $sentence
74
     */
75
    public function __construct(Theme $theme, string $sentence)
76
    {
77
        $this->init($theme, $sentence, $this->type());
78
    }
79
80
    /**
81
     * {@inheritDoc}
82
     */
83
    public function sentence() : string
84
    {
85
        return $this->sentence;
86
    }
87
88
    /**
89
     * {@inheritDoc}
90
     */
91
    public function type() : string
92
    {
93
        return $this->type;
94
    }
95
96
    /**
97
     * {@inheritDoc}
98
     */
99
    public function path() : string
100
    {
101
        return $this->path;
102
    }
103
104
    /**
105
     * {@inheritDoc}
106
     */
107
    public function alias() : object
108
    {
109
        return (object) [
110
            'camel' => $this->camelAlias,
111
            'kebab' => $this->kebabAlias,
112
        ];
113
    }
114
115
    /**
116
     * {@inheritDoc}
117
     */
118
    public function filename() : string
119
    {        
120
        return $this->nominator()->filename($this->sentence(), $this->type());
121
    }
122
123
    /**
124
     * {@inheritDoc}
125
     */
126
    public function placeholders() : array
127
    {
128
        return ['name' => $this->name];
129
    }
130
131
    /**
132
     * Retorna o nome da diretiva.  
133
     *
134
     * @return string
135
     */
136
    public function name() : string
137
    {
138
        return $this->name;
139
    }
140
141
    /**
142
     * {@inheritDoc}
143
     */
144
    public function create() : Component|Includer
145
    {
146
        if ($this->exists()) {
147
            throw new DirectiveExistsException($this->name(), $this->theme()->package());
148
        }
149
150
        $this->createFile();
151
        $this->setPath();
152
153
        return $this;
0 ignored issues
show
Bug Best Practice introduced by
The expression return $this returns the type Maestriam\Samurai\Entities\Directive which includes types incompatible with the type-hinted return Maestriam\Samurai\Entiti...murai\Entities\Includer.
Loading history...
154
    }
155
156
    /**
157
     * {@inheritDoc}
158
     */
159
    public function load() : Component|Includer
160
    {                
161
        $alias = $this->alias();
162
        $view  = $this->getViewComponent();
163
164
        if ($view) {
165
            return $this->loadViewComponent($alias->kebab, $view);
0 ignored issues
show
Bug Best Practice introduced by
The expression return $this->loadViewCo...t($alias->kebab, $view) returns the type Maestriam\Samurai\Entities\Directive which includes types incompatible with the type-hinted return Maestriam\Samurai\Entiti...murai\Entities\Includer.
Loading history...
166
        }
167
168
        $namespace = $this->theme()->namespace();
169
        
170
        $path = $this->relative();
171
        $file = $this->nominator()->blade($namespace, $path);
172
173
        $this->loadKebabAlias($file, $alias->kebab);
174
175
        if ($this->type() == 'include') {
176
            return $this->loadInclude($file, $alias->camel);
0 ignored issues
show
Bug Best Practice introduced by
The expression return $this->loadInclude($file, $alias->camel) returns the type Maestriam\Samurai\Entities\Directive which includes types incompatible with the type-hinted return Maestriam\Samurai\Entiti...murai\Entities\Includer.
Loading history...
177
        }
178
        
179
        return $this->loadComponent($file, $alias->camel);
0 ignored issues
show
Bug Best Practice introduced by
The expression return $this->loadComponent($file, $alias->camel) returns the type Maestriam\Samurai\Entities\Directive which includes types incompatible with the type-hinted return Maestriam\Samurai\Entiti...murai\Entities\Includer.
Loading history...
180
    }
181
182
    private function loadViewComponent($alias, $view) : Directive
183
    {
184
        Blade::component($alias,  $view);
185
186
        return $this;
187
    }
188
189
    private function getViewComponent() : ?string
190
    {        
191
        $view = null;
192
        $name = Str::studly($this->name);
193
     
194
        $classes = get_declared_classes();
195
196
        foreach($classes as $class) {     
197
            
198
            if (! $this->isViewComponent($class, $name)) {
199
                continue;
200
            }
201
202
            $view = $class;
203
        }
204
205
        return $view;
206
    }
207
208
    private function isViewComponent(string $class, string $name) : bool
209
    {
210
        if (! is_subclass_of($class, ViewComponent::class)) {
211
            return false;
212
        }
213
214
        if ($name != class_basename($class)) {
215
            return false;
216
        }
217
218
        return true;
219
    }
220
    
221
    /**
222
     * Retorna o caminho relativo da diretiva dentro do tema
223
     *
224
     * @return string
225
     */
226
    public function relative() : string
227
    {
228
        $path = $this->path();
229
230
        $base = $this->theme()->paths()->root() . DS;
231
        $base = FileSystem::folder($base)->sanitize();    
232
233
        return str_replace($base, '', $path);
234
    }
235
236
    /**
237
     * Retorna se a diretiva existe ou não dentro do projeto.  
238
     *
239
     * @return boolean
240
     */
241
    public function exists() : bool
242
    {
243
        return $this->fileExists();
244
    }
245
246
    /**
247
     * Carrega a diretiva (include/component) dentro do projeto como kebab-case.  
248
     * Padrão utilizado no Blade UI.  
249
     *
250
     * @param  string $file
251
     * @param  string $alias
252
     * @return Directive
253
     */
254
    private function loadKebabAlias(string $file, string $alias) : Directive
255
    {       
256
        Blade::component($file, $alias);
257
        
258
        return $this;
259
    }
260
    
261
    /**
262
     * Carrega o include dentro do projeto como camel-case.  
263
     * Padrão utilizado no Blade padrão.
264
     *
265
     * @param  string $file
266
     * @param  string $alias
267
     * @return Directive
268
     */
269
    protected function loadInclude(string $file, string $alias) : Directive
270
    {        
271
        Blade::aliasInclude($file, $alias);   
272
273
        return $this;
274
    }
275
276
    /**
277
     * Carrega o include dentro do projeto como camel-case.  
278
     * Padrão utilizado no Blade padrão.
279
     *
280
     * @param  string $file
281
     * @param  string $alias
282
     * @return Directive
283
     */
284
    protected function loadComponent(string $file, string $alias) : Directive
285
    {
286
        Blade::aliasComponent($file, $alias);   
287
        
288
        return $this;
289
    }
290
291
    /**
292
     * Carrega todas as informações da diretiva através do tema,
293
     * nome da diretiva e com seu tipo
294
     *
295
     * @param  Theme  $theme
296
     * @param  string $sentence
297
     * @param  string $type
298
     * @return void
299
     */
300
    protected function init(Theme $theme, string $sentence, string $type) : void
301
    {
302
        $this->setTheme($theme);        
303
        $this->setType($type);
304
        $this->setSentence($sentence);
305
        $this->setName($sentence);
306
        $this->setAlias();
307
        $this->setPath();
308
    }
309
310
    /**
311
     * Define a sentença que foi inserida pelo usuário via console,
312
     * que irá fornecer o nome/sub-diretório
313
     *
314
     * @param  Theme $theme
315
     * @return Directive
316
     * @throws InvalidDirectiveNameException
317
     */
318
    protected function setSentence(string $sentence) : Directive
319
    {
320
        $parsed = $this->parser()->filename($sentence);
0 ignored issues
show
Bug introduced by
Are you sure the assignment to $parsed is correct as $this->parser()->filename($sentence) targeting Maestriam\Samurai\Founda...enameParser::filename() 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...
321
322
        if (! $parsed) {
0 ignored issues
show
introduced by
$parsed is of type null, thus it always evaluated to false.
Loading history...
323
            throw new InvalidDirectiveNameException($sentence);
324
        }
325
326
        if (! $this->valid()->directive($parsed->name)) {
327
            throw new InvalidDirectiveNameException($sentence);
328
        }
329
330
        $this->sentence = strtolower($sentence);
331
        return $this;
332
    }
333
    
334
    /**
335
     * Define o tipo da diretiva
336
     *
337
     * @param  string $type
338
     * @return Directive
339
     * @throws InvalidDirectiveNameException
340
     */
341
    protected function setType(string $type) : Directive
342
    {
343
        if (! $this->valid()->type($type)) {
344
            throw new InvalidTypeDirectiveException($type);
345
        }
346
347
        $this->type = $type;
348
        return $this;
349
    }
350
351
    /**
352
     * Define o caminho absoluto do arquivo composer.json dentro do tema
353
     *
354
     * @param  string $path
355
     * @return Composer
356
     */
357
    protected function setPath() : Directive
358
    {
359
        $this->path = $this->filePath();
360
        return $this;
0 ignored issues
show
Bug Best Practice introduced by
The expression return $this returns the type Maestriam\Samurai\Entities\Directive which is incompatible with the documented return type Maestriam\Samurai\Entities\Composer.
Loading history...
361
    }
362
363
    /**
364
     * Define o nome da diretiva
365
     *
366
     * @param  string $name
367
     * @return Directive
368
     */
369
    protected function setName(string $name) : Directive
370
    {
371
        $parsed = $this->parser()->filename($name);
0 ignored issues
show
Bug introduced by
Are you sure the assignment to $parsed is correct as $this->parser()->filename($name) targeting Maestriam\Samurai\Founda...enameParser::filename() 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...
372
373
        $this->name = Str::slug($parsed->name);
374
375
        return $this;
376
    }
377
378
    /**
379
     * Define o alias para ser chamado dentro do projeto
380
     *
381
     * @return Directive
382
     */
383
    protected function setAlias() : Directive
384
    {
385
        $this->camelAlias = $this->nominator()->camelAlias($this->name);
386
        $this->kebabAlias = $this->nominator()->kebabAlias($this->name);
387
388
        return $this;
389
    }
390
}
391