Passed
Push — master ( 5ae5fc...1c3f43 )
by Giuliano
18:52
created

ViewComponent::__construct()   A

Complexity

Conditions 1
Paths 1

Size

Total Lines 3
Code Lines 1

Duplication

Lines 0
Ratio 0 %

Importance

Changes 1
Bugs 0 Features 0
Metric Value
cc 1
eloc 1
c 1
b 0
f 0
nc 1
nop 0
dl 0
loc 3
rs 10
1
<?php
2
3
namespace Maestriam\Samurai\Entities;
4
5
use Illuminate\Support\Str;
6
use Illuminate\View\Component;
0 ignored issues
show
Bug introduced by
This use statement conflicts with another class in this namespace, Maestriam\Samurai\Entities\Component. Consider defining an alias.

Let?s assume that you have a directory layout like this:

.
|-- OtherDir
|   |-- Bar.php
|   `-- Foo.php
`-- SomeDir
    `-- Foo.php

and let?s assume the following content of Bar.php:

// Bar.php
namespace OtherDir;

use SomeDir\Foo; // This now conflicts the class OtherDir\Foo

If both files OtherDir/Foo.php and SomeDir/Foo.php are loaded in the same runtime, you will see a PHP error such as the following:

PHP Fatal error:  Cannot use SomeDir\Foo as Foo because the name is already in use in OtherDir/Foo.php

However, as OtherDir/Foo.php does not necessarily have to be loaded and the error is only triggered if it is loaded before OtherDir/Bar.php, this problem might go unnoticed for a while. In order to prevent this error from surfacing, you must import the namespace with a different alias:

// Bar.php
namespace OtherDir;

use SomeDir\Foo as SomeDirFoo; // There is no conflict anymore.
Loading history...
7
use Maestriam\Samurai\Support\Samurai;
0 ignored issues
show
Bug introduced by
This use statement conflicts with another class in this namespace, Maestriam\Samurai\Entities\Samurai. Consider defining an alias.

Let?s assume that you have a directory layout like this:

.
|-- OtherDir
|   |-- Bar.php
|   `-- Foo.php
`-- SomeDir
    `-- Foo.php

and let?s assume the following content of Bar.php:

// Bar.php
namespace OtherDir;

use SomeDir\Foo; // This now conflicts the class OtherDir\Foo

If both files OtherDir/Foo.php and SomeDir/Foo.php are loaded in the same runtime, you will see a PHP error such as the following:

PHP Fatal error:  Cannot use SomeDir\Foo as Foo because the name is already in use in OtherDir/Foo.php

However, as OtherDir/Foo.php does not necessarily have to be loaded and the error is only triggered if it is loaded before OtherDir/Bar.php, this problem might go unnoticed for a while. In order to prevent this error from surfacing, you must import the namespace with a different alias:

// Bar.php
namespace OtherDir;

use SomeDir\Foo as SomeDirFoo; // There is no conflict anymore.
Loading history...
8
use Maestriam\Samurai\Concerns\WithFileNominator;
9
10
class ViewComponent extends Component
11
{
12
    use WithFileNominator;
13
14
    /**
15
     * Caminho do arquivo blade 
16
     *
17
     * @var string
18
     */
19
    protected ?string $view = null;
20
21
    /**
22
     * Tema atual do projeto. 
23
     *
24
     * @var Theme
25
     */
26
    private Theme $theme;
27
28
    public function __construct()
29
    {
30
        $this->init();
31
    }
32
33
    /**
34
     * Carrega as informações do tema atual e tenta
35
     * encontrar o arquivo blade a este ViewComponent.
36
     *
37
     * @return void
38
     */
39
    protected function init() : ViewComponent
40
    {
41
        return $this->setTheme()->initView();
0 ignored issues
show
Bug Best Practice introduced by
The expression return $this->setTheme()->initView() returns the type Maestriam\Samurai\Entities\ViewComponent which is incompatible with the documented return type void.
Loading history...
42
    }
43
44
    /**
45
     * Define as informações do tema atual no projeto.
46
     *
47
     * @return  ViewComponent
48
     */
49
    private function setTheme() : ViewComponent
50
    {
51
        $this->theme = Samurai::base()->current();
0 ignored issues
show
Bug introduced by
The method base() does not exist on Maestriam\Samurai\Support\Samurai. Since you implemented __callStatic, consider adding a @method annotation. ( Ignorable by Annotation )

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

51
        $this->theme = Samurai::/** @scrutinizer ignore-call */ base()->current();
Loading history...
52
53
        return $this;
54
    }
55
56
    /**
57
     * Tenta encontrar o componente Blade com o mesmo nome da classe
58
     * no tema atual. Se encontrar, vincula o ViewComponent ao 
59
     * componente.  
60
     *
61
     * @return  ViewComponent
62
     */
63
    protected function initView() : ViewComponent
64
    {        
65
        $class = $this->getName(); 
66
67
        $directive = $this->getDirective($class);
68
69
        if (! $directive) {
70
            return $this;
71
        }
72
        
73
        $path = $directive->relative();
74
        
75
        return $this->setView($path);
76
    }
77
    
78
    /**
79
     * Define o caminho do arquivo que será carregado pelo ViewComponent
80
     *
81
     * @param string $path  
82
     *
83
     * @return ViewComponent
84
     */
85
    protected function setView(string $path) : ViewComponent
86
    {
87
        $theme = $this->theme->namespace();
88
89
        $this->view = $this->getBladeFile($theme, $path);
90
91
        return $this;
92
    }
93
    
94
    /**
95
     * Faz uma varredura em todas as diretivas do tema atual e tenta
96
     * encontrar uma diretiva com o mesmo nome do ViewComponent.  
97
     * Se não encontrar, deve retornar nulo.  
98
     *
99
     * @param string 
100
     *
101
     * @return Directive 
102
     */
103
    protected function getDirective(string $name) : ?Directive
104
    {
105
        $components = $this->theme->directives();
106
107
        foreach ($components as $component) {
108
109
            if ($component->name() == $name) {
110
                return $component;
111
            }
112
        }  
113
        
114
        return null;
115
    }
116
    
117
    /**
118
     * Retorna o nome da classe do ViewComponent
119
     *
120
     * @return  string 
121
     */
122
    protected function getName() : string
123
    {
124
        $name = class_basename($this);
125
        
126
        $class = Str::kebab($name);       
127
128
        return $class;
129
    }
130
131
    protected function getBladeFile($theme, $path) : string
132
    {
133
        return $this->nominator()->blade($theme, $path);
134
    }
135
136
    /**
137
     * Retorna o nome do arquivo
138
     *
139
     * @return string  
140
     */
141
    public function getView() : string
142
    {
143
        return $this->view;
0 ignored issues
show
Bug Best Practice introduced by
The expression return $this->view could return the type null which is incompatible with the type-hinted return string. Consider adding an additional type-check to rule them out.
Loading history...
144
    }
145
146
    /**
147
     * Renderiza o arquivo Blade no front.
148
     *
149
     * @return 
150
     */
151
    public function render() 
152
    {
153
        return view($this->view);
154
    }
155
}