Passed
Push — main ( d71b68...a743f7 )
by Dimitri
08:12 queued 04:09
created

Component::includeComputedProperties()   A

Complexity

Conditions 4
Paths 4

Size

Total Lines 21
Code Lines 10

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 7
CRAP Score 4

Importance

Changes 1
Bugs 0 Features 0
Metric Value
cc 4
eloc 10
c 1
b 0
f 0
nc 4
nop 1
dl 0
loc 21
ccs 7
cts 7
cp 1
crap 4
rs 9.9332
1
<?php
2
3
/**
4
 * This file is part of Blitz PHP framework.
5
 *
6
 * (c) 2022 Dimitri Sitchet Tomkeu <[email protected]>
7
 *
8
 * For the full copyright and license information, please view
9
 * the LICENSE file that was distributed with this source code.
10
 */
11
12
namespace BlitzPHP\View\Components;
13
14
use BlitzPHP\Traits\PropertiesTrait;
15
use BlitzPHP\Utilities\Helpers;
16
use BlitzPHP\Utilities\String\Text;
17
use LogicException;
18
use ReflectionClass;
19
use Stringable;
20
21
/**
22
 * La classe de base dont etendra tous les composants de vues
23
 * Fournie des fonctionnalites extensible pour gerer/rendre le contenu d'un composant simple.
24
 *
25
 * @function mount()
26
 *
27
 * @credit <a href="http://www.codeigniter.com">CodeIgniter 4.5 - CodeIgniter\View\Cells\Cell</a>
28
 */
29
class Component implements Stringable
30
{
31
    use PropertiesTrait;
32
33
    /**
34
     * Nom de la vue a rendre.
35
     * Si vide, il sera determiné en fonction du nom de la classe de composant.
36
     */
37
    protected string $view = '';
38
39
    /**
40
     * Responsable de la conversion de la vue en HTML.
41
     * Peut etre modifier par les classes filles dans certains cas, mais pas tous.
42
     */
43
    public function render(): string
44
    {
45 2
        return $this->view($this->view);
46
    }
47
48
    /**
49
     * Defini la vue à utiliser lors du rendu.
50
     */
51
    public function setView(string $view): self
52
    {
53
        $this->view = $view;
54
55
        return $this;
56
    }
57
58
    /**
59
     * rend actuellement la vue et renvoie le code HTML.
60
     * Afin de permettre l'accès aux propriétés et méthodes publiques à partir de la vue,
61
     * cette méthode extrait $data dans le champ d'application actuel et capture le tampon de
62
     * sortie au lieu de s'appuyer sur le service de vue.
63
     *
64
     * @throws LogicException
65
     */
66
    final protected function view(?string $view, array $data = []): string
67
    {
68 2
        $properties = $this->getPublicProperties();
69 2
        $properties = $this->includeComputedProperties($properties);
70 2
        $properties = array_merge($properties, $data);
71
72 2
        $view = (string) $view;
73
74
        if ($view === '') {
75 2
            $viewName  = Text::convertTo(Helpers::classBasename(static::class), 'toKebab');
76 2
            $directory = dirname((new ReflectionClass($this))->getFileName()) . DIRECTORY_SEPARATOR;
77
78 2
            $possibleView1 = $directory . substr($viewName, 0, strrpos($viewName, '-component')) . '.php';
79 2
            $possibleView2 = $directory . $viewName . '.php';
80
        }
81
82
        if ($view !== '' && ! is_file($view)) {
83 2
            $directory = dirname((new ReflectionClass($this))->getFileName()) . DIRECTORY_SEPARATOR;
84
85 2
            $view = $directory . $view . '.php';
86
        }
87
88
        $candidateViews = array_filter(
89
            [$view, $possibleView1 ?? '', $possibleView2 ?? ''],
90
            static fn (string $path): bool => $path !== '' && is_file($path)
91 2
        );
92
93
        if ($candidateViews === []) {
94
            throw new LogicException(sprintf(
95
                'Impossible de localiser le fichier de vue pour le composant "%s".',
96
                static::class
97 2
            ));
98
        }
99
100 2
        $foundView = current($candidateViews);
101
102
        return (function () use ($properties, $foundView): string {
103 2
            extract($properties);
104 2
            ob_start();
105 2
            include $foundView;
106
107 2
            return ob_get_clean();
108 2
        })();
109
    }
110
111
    /**
112
     * {@inheritDoc}
113
     */
114
    public function __toString(): string
115
    {
116
        return $this->render();
117
    }
118
119
    /**
120
     * Permet au développeur de définir les propriétés calculées comme des méthodes
121
     * avec `get` préfixé au nom de la propriété protégée/privée.
122
     */
123
    private function includeComputedProperties(array $properties): array
124
    {
125 2
        $reservedProperties = ['data', 'view'];
126 2
        $privateProperties  = $this->getNonPublicProperties();
127
128
        foreach ($privateProperties as $property) {
129 2
            $name = $property->getName();
130
131
            //  ne pas inclure de méthodes dans la classe de base
132
            if (in_array($name, $reservedProperties, true)) {
133 2
                continue;
134
            }
135
136 2
            $computedMethod = 'get' . ucfirst($name) . 'Property';
137
138
            if (method_exists($this, $computedMethod)) {
139 2
                $properties[$name] = $this->{$computedMethod}();
140
            }
141
        }
142
143 2
        return $properties;
144
    }
145
}
146