Completed
Push — master ( 075422...abbf1a )
by
unknown
01:36
created

BladeXCompiler::isOpeningHtmlTag()   A

Complexity

Conditions 1
Paths 1

Size

Total Lines 4

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
dl 0
loc 4
rs 10
c 0
b 0
f 0
cc 1
nc 1
nop 2
1
<?php
2
3
namespace Spatie\BladeX;
4
5
use SimpleXMLElement;
6
7
class BladeXCompiler
8
{
9
    /** @var \Spatie\BladeX\BladeX */
10
    protected $bladeX;
11
12
    public function __construct(BladeX $bladeX)
13
    {
14
        return $this->bladeX = $bladeX;
0 ignored issues
show
Bug introduced by
Constructors do not have meaningful return values, anything that is returned from here is discarded. Are you sure this is correct?
Loading history...
15
    }
16
17
    public function compile(string $viewContents): string
18
    {
19
        return array_reduce(
20
            $this->bladeX->getRegisteredComponents(),
21
            [$this, 'parseComponentHtml'],
22
            $viewContents
23
        );
24
    }
25
26
    protected function parseComponentHtml(string $viewContents, BladeXComponent $bladeXComponent)
27
    {
28
        $viewContents = $this->parseSlots($viewContents);
29
30
        $viewContents = $this->parseSelfClosingTags($viewContents, $bladeXComponent);
31
32
        $viewContents = $this->parseOpeningTags($viewContents, $bladeXComponent);
33
34
        $viewContents = $this->parseClosingTags($viewContents, $bladeXComponent);
35
36
        return $viewContents;
37
    }
38
39
    protected function parseSelfClosingTags(string $viewContents, BladeXComponent $bladeXComponent): string
40
    {
41
        $prefix = $this->bladeX->getPrefix();
42
43
        $pattern = "/<\s*{$prefix}{$bladeXComponent->name}[^>]*\/>/m";
44
45
        return preg_replace_callback($pattern, function (array $regexResult) use ($bladeXComponent) {
46
            $componentHtml = $regexResult[0];
47
48
            return $this->componentString($bladeXComponent, $componentHtml);
49
        }, $viewContents);
50
    }
51
52
    protected function parseOpeningTags(string $viewContents, BladeXComponent $bladeXComponent): string
53
    {
54
        $prefix = $this->bladeX->getPrefix();
55
56
        $pattern = "/<\s*{$prefix}{$bladeXComponent->name}[^>]*(?<!\/)>/m";
57
58
        return preg_replace_callback($pattern, function (array $regexResult) use ($bladeXComponent) {
59
            $componentHtml = $regexResult[0];
60
61
            $attributes = $this->getComponentAttributes($bladeXComponent, $componentHtml);
62
63
            return $this->componentStartString($bladeXComponent, $attributes);
64
        }, $viewContents);
65
    }
66
67
    protected function parseClosingTags(string $viewContents, BladeXComponent $bladeXComponent): string
68
    {
69
        $prefix = $this->bladeX->getPrefix();
70
71
        $pattern = "/<\/\s*{$prefix}{$bladeXComponent->name}[^>]*>/m";
72
73
        return preg_replace($pattern, $this->componentEndString(), $viewContents);
74
    }
75
76
    protected function componentString(BladeXComponent $bladeXComponent, string $componentHtml): string
77
    {
78
        $attributes = $this->getComponentAttributes($bladeXComponent, $componentHtml);
79
80
        return $this->componentStartString($bladeXComponent, $attributes).$this->componentEndString();
81
    }
82
83
    protected function componentStartString(BladeXComponent $bladeXComponent, string $attributes = ''): string
84
    {
85
        return  "@component('{$bladeXComponent->bladeViewName}', [{$attributes}])";
86
    }
87
88
    protected function componentEndString(): string
89
    {
90
        return '@endcomponent';
91
    }
92
93
    protected function getComponentAttributes(BladeXComponent $bladeXComponent, string $componentHtml): string
94
    {
95
        $prefix = $this->bladeX->getPrefix();
96
97
        $elementName = $prefix.$bladeXComponent->name;
98
99
        if ($this->isOpeningHtmlTag($elementName, $componentHtml)) {
100
            $componentHtml .= "</{$elementName}>";
101
        }
102
103
        return $this->getHtmlElementAttributes($componentHtml);
104
    }
105
106
    protected function getHtmlElementAttributes(string $componentHtml): string
107
    {
108
        $componentXml = new SimpleXMLElement($componentHtml);
109
110
        return collect($componentXml->attributes())
111
            ->map(function ($value, $attribute) {
112
                if (preg_match('/{{(.*)}}/', $value, $matches)) {
113
                    $value = trim($matches[1]);
114
115
                    return "'{$attribute}' => {$value},";
116
                }
117
118
                $value = str_replace("'", "\\'", $value);
119
120
                return "'{$attribute}' => '{$value}',";
121
            })->implode('');
122
    }
123
124
    protected function parseSlots(string $viewContents): string
125
    {
126
        $pattern = '/<\s*slot[^>]*name=[\'"](.*)[\'"][^>]*>((.|\n)*?)<\s*\/\s*slot>/m';
127
128
        return preg_replace_callback($pattern, function ($regexResult) {
129
            [$slot, $name, $contents] = $regexResult;
0 ignored issues
show
Bug introduced by
The variable $slot does not exist. Did you forget to declare it?

This check marks access to variables or properties that have not been declared yet. While PHP has no explicit notion of declaring a variable, accessing it before a value is assigned to it is most likely a bug.

Loading history...
Bug introduced by
The variable $name does not exist. Did you forget to declare it?

This check marks access to variables or properties that have not been declared yet. While PHP has no explicit notion of declaring a variable, accessing it before a value is assigned to it is most likely a bug.

Loading history...
Bug introduced by
The variable $contents does not exist. Did you forget to declare it?

This check marks access to variables or properties that have not been declared yet. While PHP has no explicit notion of declaring a variable, accessing it before a value is assigned to it is most likely a bug.

Loading history...
130
131
            return "@slot('{$name}'){$contents}@endslot";
132
        }, $viewContents);
133
    }
134
135
    protected function isOpeningHtmlTag(string $tagName, string $html): bool
136
    {
137
        return ! ends_with($html, ["</{$tagName}>", '/>']);
138
    }
139
}
140