Passed
Push — main ( 4cd58e...3399b6 )
by Dimitri
03:02
created

RouteBuilder::map()   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 2
dl 0
loc 3
rs 10
1
<?php
2
3
namespace BlitzPHP\Router;
4
5
use BadMethodCallException;
6
use BlitzPHP\Loader\Services;
7
use BlitzPHP\Utilities\Iterable\Arr;
8
use Closure;
9
use InvalidArgumentException;
10
11
/**
12
 * @method $this addPlaceholder($placeholder, ?string $pattern = null) Enregistre une nouvelle contrainte auprès du système.
13
 * @method $this setDefaultNamespace(string $value) Définit l'espace de noms par défaut à utiliser pour les contrôleurs lorsqu'aucun autre n'a été spécifié.
14
 * @method $this setDefaultController(string $value) Définit le contrôleur par défaut à utiliser lorsqu'aucun autre contrôleur n'a été spécifié.
15
 * @method $this setDefaultMethod(string $value) Définit la méthode par défaut pour appeler le contrôleur lorsqu'aucun autre méthode a été définie dans la route.
16
 * @method $this setTranslateURIDashes(bool $value) Indique au système s'il faut convertir les tirets des chaînes URI en traits de soulignement.
17
 * @method $this setAutoRoute(bool $value) Si TRUE, le système tentera de faire correspondre l'URI avec
18
     * Contrôleurs en faisant correspondre chaque segment avec des dossiers/fichiers
19
     * dans CONTROLLER_PATH, lorsqu'aucune correspondance n'a été trouvée pour les routes définies.
20
 * @method $this set404Override($callable = null) Définit la classe/méthode qui doit être appelée si le routage ne trouver pas une correspondance.
21
 * @method $this setDefaultConstraint(string $placeholder) Définit la contrainte par défaut à utiliser dans le système. Typiquement à utiliser avec la méthode 'ressource'.
22
 * @method $this setPrioritize(bool $enabled = true) Activer ou désactiver le tri des routes par priorité
23
 * @method $this addRedirect(string $from, string $to, int $status = 302) Ajoute une redirection temporaire d'une route à une autre.
24
 * @method $this as(string $name)
25
 * @method $this controller(string $controller)
26
 * @method $this domain(string $domain)
27
 * @method $this hostname(string $hostname)
28
 * @method $this middleware(array|string $middleware)
29
 * @method $this name(string $name)
30
 * @method $this namespace(string $namespace)
31
 * @method $this placeholder(string $placeholder)
32
 * @method $this prefix(string $prefix)
33
 * @method $this priority(int $priority)
34
 * @method $this subdomain(string $subdomain)
35
 * @method void add(string $from, array|callable|string $to, array $options = []) Enregistre une seule route à la collection.
36
 * @method void cli(string $from, array|callable|string $to, array $options = []) Enregistre une route qui ne sera disponible que pour les requêtes de ligne de commande.
37
 * @method void delete(string $from, array|callable|string $to, array $options = []) Enregistre une route qui ne sera disponible que pour les requêtes DELETE.
38
 * @method void get(string $from, array|callable|string $to, array $options = []) Enregistre une route qui ne sera disponible que pour les requêtes GET.
39
 * @method void head(string $from, array|callable|string $to, array $options = []) Enregistre une route qui ne sera disponible que pour les requêtes HEAD.
40
 * @method void options(string $from, array|callable|string $to, array $options = []) Enregistre une route qui ne sera disponible que pour les requêtes OPTIONS.
41
 * @method void patch(string $from, array|callable|string $to, array $options = []) Enregistre une route qui ne sera disponible que pour les requêtes PATCH.
42
 * @method void post(string $from, array|callable|string $to, array $options = []) Enregistre une route qui ne sera disponible que pour les requêtes POST.
43
 * @method void put(string $from, array|callable|string $to, array $options = []) Enregistre une route qui ne sera disponible que pour les requêtes PUT.
44
 */
45
final class RouteBuilder 
46
{
47
    /**
48
     * Les attributs à transmettre au routeur.
49
     */
50
    private array $attributes = [];
51
52
    /**
53
     * Les méthodes à transmettre dynamiquement au routeur.
54
     */
55
    private array $passthru = [
56
        'add', 'cli', 'delete', 'get', 'head', 'options', 'post', 'put', 'patch',
57
    ];
58
59
    /**
60
     * Les attributs qui peuvent être définis via cette classe.
61
     */
62
    private array $allowedAttributes = [
63
        'as', 'controller', 'domain', 'hostname', 'middlewares', 'middleware', 
64
        'name', 'namespace', 'placeholder', 'prefix', 'priority', 'subdomain',
65
    ];
66
67
    /**
68
     * Les attributs qui sont des alias.
69
     */
70
    private array $aliases = [
71
        'name'        => 'as',
72
        'middlewares' => 'middleware',
73
    ];
74
75
    private array $allowedMethods = [
76
        'addPlaceholder', 'addRedirect',       
77
        'set404Override', 'setAutoRoute',
78
        'setDefaultConstraint', 'setDefaultController', 'setDefaultMethod', 'setDefaultNamespace',
79
        'setTranslateURIDashes', 'setPrioritize',
80
    ];
81
82
    
83
    /**
84
     * Constructeur
85
     *
86
     * @param RouteCollection $collection
87
     */
88
    public function __construct(private RouteCollection $collection)
89
    {
90
91
    }
92
93
    /**
94
     * Gérez dynamiquement les appels dans le registraire de routage.
95
     *
96
     * @return self
97
     *
98
     * @throws BadMethodCallException
99
     */
100
    public function __call(string $method, array $parameters = [])
101
    {
102
        if (in_array($method, $this->passthru)) {
103
            return $this->registerRoute($method, ...$parameters);
104
        }
105
106
        if (in_array($method, $this->allowedAttributes)) {
107
            if (in_array($method, ['middleware', 'middlewares'], true)) {
108
                $parameters = is_array($parameters[0]) ? $parameters[0] : $parameters;
109
110
                return $this->attribute($method, array_merge($this->attributes[$method] ?? [], $parameters));
111
            }
112
113
            return $this->attribute($method, $parameters[0]);
114
        }
115
116
        if (in_array($method, $this->allowedMethods)) {
117
            $collection = $this->collection->{$method}(...$parameters);
118
119
            if ($collection instanceof RouteCollection) {
120
                Services::set(RouteCollection::class, $collection);
121
                $this->collection = $collection;
122
            }
123
124
            return $this;
125
        }
126
127
        throw new BadMethodCallException(sprintf('La méthode %s::%s n\'existe pas.', static::class, $method));
128
    }
129
130
    public function configure(callable $callback)
131
    {
132
        $callback($this);    
133
    }
134
135
    /**
136
     * Limite les routes à un ENVIRONNEMENT spécifié ou ils ne fonctionneront pas.
137
     */
138
    public function environment(string $env, Closure $callback): void
139
    {
140
        if ($env === config('app.environment')) {
141
            $callback($this);
142
        }
143
    }
144
145
    public function form(string $from, $to, array $options = []): void
146
    {
147
        $this->match(['get', 'post'], $from, $to, $options);
148
    }
149
150
    /**
151
     * Create a route group with shared attributes.
152
     */
153
    public function group(callable $callback): void
154
    {
155
        $this->collection->group($this->attributes['prefix'] ?? '', $this->attributes, fn () => $callback($this));
156
       
157
        // $callback($this);
158
    }
159
160
    /**
161
     * Ajoute une seule route à faire correspondre pour plusieurs verbes HTTP.
162
     *
163
     * Exemple:
164
     *  $route->match( ['get', 'post'], 'users/(:num)', 'users/$1);
165
     *
166
     * @param array|Closure|string $to
167
     */
168
    public function match(array $verbs = [], string $from = '', $to = '', array $options = []): void
169
    {
170
        $this->collection->match($verbs, $from, $to, $this->attributes + $options);
171
    }
172
173
    /**
174
     * Crée une collection de routes basées sur les verbes HTTP pour un contrôleur de présentation.
175
     *
176
     * Options possibles :
177
     * 'controller' - Personnalisez le nom du contrôleur utilisé dans la route 'to'
178
     * 'placeholder' - L'expression régulière utilisée par le routeur. La valeur par défaut est '(:any)'
179
     *
180
     * Example:
181
     *
182
     *      $route->presenter('photos');
183
     *
184
     *      // Génère les routes suivantes
185
     *      HTTP Verb | Path        | Action        | Used for...
186
     *      ----------+-------------+---------------+-----------------
187
     *      GET         /photos             index           affiche le tableau des tous les objets photo
188
     *      GET         /photos/show/{id}   show            affiche un objet photo spécifique, toutes les propriétés
189
     *      GET         /photos/new         new             affiche un formulaire pour un objet photo vide, avec les propriétés par défaut
190
     *      POST        /photos/create      create          traitement du formulaire pour une nouvelle photo
191
     *      GET         /photos/edit/{id}   edit            affiche un formulaire d'édition pour un objet photo spécifique, propriétés modifiables
192
     *      POST        /photos/update/{id} update          traitement des données du formulaire d'édition
193
     *      GET         /photos/remove/{id} remove          affiche un formulaire pour confirmer la suppression d'un objet photo spécifique
194
     *      POST        /photos/delete/{id} delete          suppression de l'objet photo spécifié
195
     *
196
     * @param string     $name    Le nom du contrôleur vers lequel router.
197
     * @param array|null $options Une liste des façons possibles de personnaliser le routage.
198
     */
199
    public function presenter(string $name, array $options = []): void
200
    {
201
        $this->collection->presenter($name, $this->attributes + $options);
202
    }
203
204
    /**
205
     * Crée une collection de routes basés sur HTTP-verb pour un contrôleur.
206
     *
207
     * Options possibles :
208
     * 'controller' - Personnalisez le nom du contrôleur utilisé dans la route 'to'
209
     * 'placeholder' - L'expression régulière utilisée par le routeur. La valeur par défaut est '(:any)'
210
     * 'websafe' - - '1' si seuls les verbes HTTP GET et POST sont pris en charge
211
     *
212
     * Exemple:
213
     *
214
     *      $route->resource('photos');
215
     *
216
     *      // Genère les routes suivantes:
217
     *      HTTP Verb | Path        | Action        | Used for...
218
     *      ----------+-------------+---------------+-----------------
219
     *      GET         /photos             index           un tableau d'objets photo
220
     *      GET         /photos/new         new             un objet photo vide, avec des propriétés par défaut
221
     *      GET         /photos/{id}/edit   edit            un objet photo spécifique, propriétés modifiables
222
     *      GET         /photos/{id}        show            un objet photo spécifique, toutes les propriétés
223
     *      POST        /photos             create          un nouvel objet photo, à ajouter à la ressource
224
     *      DELETE      /photos/{id}        delete          supprime l'objet photo spécifié
225
     *      PUT/PATCH   /photos/{id}        update          propriétés de remplacement pour la photo existante
226
     *
227
     *  Si l'option 'websafe' est présente, les chemins suivants sont également disponibles :
228
     *
229
     *      POST		/photos/{id}/delete delete
230
     *      POST        /photos/{id}        update
231
     *
232
     * @param string     $name    Le nom de la ressource/du contrôleur vers lequel router.
233
     * @param array|null $options Une liste des façons possibles de personnaliser le routage.
234
     */
235
    public function resource(string $name, array $options = []): void
236
    {
237
        $this->collection->resource($name, $this->attributes + $options);
238
    }
239
240
    /**
241
     * Une méthode de raccourci pour ajouter un certain nombre de routes en une seule fois.
242
     * Il ne permet pas de définir des options sur la route, ou de définir la méthode utilisée.
243
     */
244
    public function map(array $routes = [], array $options = []): void
245
    {
246
        $this->collection->map($routes, $this->attributes + $options);
247
    }
248
249
    /**
250
     * Spécifie une route qui n'affichera qu'une vue.
251
     * Ne fonctionne que pour les requêtes GET.
252
     */
253
    public function view(string $from, string $view, array $options = []): void
254
    {
255
        $this->collection->view($from, $view, $this->attributes + $options);
256
    }
257
258
    /**
259
     * Defini une valeur pour l'attribut donné
260
     *
261
     * @throws InvalidArgumentException
262
     */
263
    private function attribute(string $key, $value): self
264
    {
265
        if (! in_array($key, $this->allowedAttributes)) {
266
            throw new InvalidArgumentException("L'attribute [{$key}] n'existe pas.");
267
        }
268
269
        $this->attributes[Arr::get($this->aliases, $key, $key)] = $value;
270
271
        return $this;
272
    }
273
274
    /**
275
     * Enregistre une nouvelle route avec le routeur.
276
     */
277
    private function registerRoute(string $method, string $from, $to, array $options = []): self
278
    {
279
        $this->collection->{$method}($from, $to, $this->attributes + $options);
280
281
        return $this;
282
    }
283
}