Completed
Pull Request — master (#15)
by
unknown
01:02
created

ComponentFinder::addNamespace()   A

Complexity

Conditions 1
Paths 1

Size

Total Lines 5

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
dl 0
loc 5
rs 10
c 0
b 0
f 0
cc 1
nc 1
nop 2
1
<?php
2
3
namespace Spatie\ViewComponents;
4
5
use Illuminate\Support\Str;
6
use InvalidArgumentException;
7
use Illuminate\Contracts\Support\Htmlable;
8
9
final class ComponentFinder
10
{
11
    /** @var string */
12
    private $rootNamespace;
13
14
    /** @var array */
15
    private $namespaces;
16
17
    public function __construct(string $rootNamespace, array $namespaces)
18
    {
19
        $this->rootNamespace = $rootNamespace;
20
        $this->namespaces = $namespaces;
21
    }
22
23
    public function find(string $identifier): string
24
    {
25
        $identifier = $this->sanitizeIdentifier($identifier);
26
27
        $componentClass = class_exists($identifier)
28
            ? $identifier
29
            : $this->expandComponentClassPath($identifier);
30
31
        if (! class_exists($componentClass)) {
32
            throw new InvalidArgumentException("View component [{$componentClass}] not found.");
33
        }
34
35
        if (! array_key_exists(Htmlable::class, class_implements($componentClass))) {
36
            throw new InvalidArgumentException(
37
                "View component [{$componentClass}] must implement Illuminate\Support\Htmlable."
38
            );
39
        }
40
41
        return $componentClass;
42
    }
43
44
    public function addNamespace($namespace, $path)
45
    {
46
        $this->namespaces[$namespace] = $path;
47
        return $this;
48
    }
49
50
    private function expandComponentClassPath(string $path): string
51
    {
52
        if (Str::contains($path, '::')) {
53
            list($namespaceAlias, $path) = explode('::', $path, 2);
54
        }
55
56
        $namespace = isset($namespaceAlias)
57
            ? $this->resolveNamespaceFromAlias($namespaceAlias)
58
            : $this->rootNamespace;
59
60
        return collect(explode('.', $path))
61
            ->map(function (string $part) {
62
                return ucfirst($part);
63
            })
64
            ->prepend($namespace)
65
            ->implode('\\');
66
    }
67
68
    private function resolveNamespaceFromAlias(string $alias): string
69
    {
70
        $namespace = $this->namespaces[$alias] ?? null;
71
72
        if (! $namespace) {
73
            throw new InvalidArgumentException("View component namespace [$alias] doesn't exist.");
74
        }
75
76
        return $namespace;
77
    }
78
79
    private function sanitizeIdentifier(string $identifier): string
80
    {
81
        $identifier = trim($identifier, '\'" ');
82
83
        return str_replace('::class', '', $identifier);
84
    }
85
}
86