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

FileLocator::helper()   C

Complexity

Conditions 12
Paths 78

Size

Total Lines 69
Code Lines 36

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 16
CRAP Score 16.0575

Importance

Changes 0
Metric Value
cc 12
eloc 36
c 0
b 0
f 0
nc 78
nop 1
dl 0
loc 69
ccs 16
cts 23
cp 0.6957
crap 16.0575
rs 6.9666

How to fix   Long Method    Complexity   

Long Method

Small methods make your code easier to understand, in particular if combined with a good name. Besides, if your method is small, finding a good name is usually much easier.

For example, if you find yourself adding comments to a method's body, this is usually a good sign to extract the commented part to a new method, and use the comment as a starting point when coming up with a good name for this new method.

Commonly applied refactorings include:

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\Loader;
13
14
use BlitzPHP\Container\Services;
0 ignored issues
show
Bug introduced by
This use statement conflicts with another class in this namespace, BlitzPHP\Loader\Services. 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...
15
use BlitzPHP\Contracts\Database\ConnectionInterface;
16
use BlitzPHP\Exceptions\LoadException;
17
use BlitzPHP\Utilities\String\Text;
18
use Nette\Schema\Expect;
19
use Nette\Schema\Schema;
20
21
class FileLocator
22
{
23
    /**
24
     * Charge un fichier d'aide en mémoire.
25
     * Prend en charge les helpers d'espace de noms, à la fois dans et hors du répertoire 'helpers' d'un répertoire d'espace de noms.
26
     *
27
     * Chargera TOUS les helpers du nom correspondant, dans l'ordre suivant :
28
     *   1. app/Helpers
29
     *   2. {namespace}/Helpers
30
     *   3. system/Helpers
31
     *
32
     * @throws LoadException
33
     */
34
    public static function helper(array|string $filenames)
35
    {
36 34
        static $loaded = [];
37
38 34
        $loader = Services::locator();
39
40
        if (! is_array($filenames)) {
0 ignored issues
show
introduced by
The condition is_array($filenames) is always true.
Loading history...
41 34
            $filenames = [$filenames];
42
        }
43
44
        // Enregistrez une liste de tous les fichiers à inclure...
45 34
        $includes = [];
46
47
        foreach ($filenames as $filename) {
48
            // Stockez nos versions d'helpers système et d'application afin que nous puissions contrôler l'ordre de chargement.
49 34
            $systemHelper  = null;
50 34
            $appHelper     = null;
51 34
            $localIncludes = [];
52
53
            // Vérifiez si ce helper a déjà été chargé
54
            if (in_array($filename, $loaded, true)) {
55 32
                continue;
56
            }
57
58
            // Si le fichier est dans un espace de noms, nous allons simplement saisir ce fichier et ne pas en rechercher d'autres
59
            if (str_contains($filename, '\\')) {
60 6
                $path = $loader->locateFile($filename, 'Helpers');
61
62
                if (empty($path)) {
63
                    throw LoadException::helperNotFound($filename);
64
                }
65
66
                $includes[] = $path;
67
                $loaded[]   = $filename;
68
            } else {
69
                // Pas d'espaces de noms, donc recherchez dans tous les emplacements disponibles
70 6
                $paths = $loader->search('Helpers/' . $filename);
71
72
                foreach ($paths as $path) {
73
                    if (str_starts_with($path, APP_PATH . 'Helpers' . DS)) {
74
                        $appHelper = $path;
75
                    } elseif (str_starts_with($path, SYST_PATH . 'Helpers' . DS)) {
76 6
                        $systemHelper = $path;
77
                    } else {
78
                        $localIncludes[] = $path;
79
                        $loaded[]        = $filename;
80
                    }
81
                }
82
83
                // Les helpers au niveau de l'application doivent remplacer tous les autres
84
                if (! empty($appHelper)) {
85 6
                    $includes[] = $appHelper;
86
                    $loaded[]   = $filename;
87
                }
88
89
                // Tous les fichiers avec espace de noms sont ajoutés ensuite
90 6
                $includes = [...$includes, ...$localIncludes];
91
92
                // Et celui par défaut du système doit être ajouté en dernier.
93
                if (! empty($systemHelper)) {
94 6
                    $includes[] = $systemHelper;
95 6
                    $loaded[]   = $filename;
96
                }
97
            }
98
        }
99
100
        // Incluez maintenant tous les fichiers
101
        foreach ($includes as $path) {
102 6
            include_once $path;
103
        }
104
    }
105
106
    /**
107
     * Charge un fichier d'aide en mémoire.
108
     * Prend en charge les helpers d'espace de noms, à la fois dans et hors du répertoire 'helpers' d'un répertoire d'espace de noms.
109
     */
110
    public static function schema(string $name): Schema
111
    {
112
        static $loadedSchema = [];
113
114
        $loader = Services::locator();
115
116
        // Stockez nos versions de schame système et d'application afin que nous puissions contrôler l'ordre de chargement.
117
        $systemSchema = null;
118
        $appSchema    = null;
119
        $vendorSchema = null;
120
121
        // Le fichier de schema qui sera finalement utiliser
122
        $file = null;
123
124
        // Vérifiez si ce schama a déjà été chargé
125
        if (in_array($name, $loadedSchema, true)) {
126
            return $loadedSchema[$name];
127
        }
128
129
        // Si le fichier est dans un espace de noms, nous allons simplement saisir ce fichier et ne pas en rechercher d'autres
130
        if (str_contains($name, '\\')) {
131
            if (! empty($path = $loader->locateFile($name, 'schemas'))) {
132
                $file = $path;
133
            }
134
        } else {
135
            // Pas d'espaces de noms, donc recherchez dans tous les emplacements disponibles
136
            $paths = $loader->search('schemas/' . $name);
137
138
            foreach ($paths as $path) {
139
                if (str_starts_with($path, CONFIG_PATH . 'schemas' . DS)) {
140
                    $appSchema = $path;
141
                } elseif (str_starts_with($path, SYST_PATH . 'Constants' . DS . 'schemas' . DS)) {
142
                    $systemSchema = $path;
143
                } else {
144
                    $vendorSchema = $path;
145
                }
146
            }
147
148
            // Les schema des vendor sont prioritaire, ensuite vienne ceux de l'application
149
            if (! empty($vendorSchema)) {
0 ignored issues
show
introduced by
The condition empty($vendorSchema) is always false.
Loading history...
150
                $file = $vendorSchema;
151
            } elseif (! empty($appSchema)) {
152
                $file = $appSchema;
153
            } elseif (! empty($systemSchema)) {
154
                $file = $systemSchema;
155
            }
156
        }
157
158
        $schema = ! empty($file) ? require $file : null;
159
160
        if (empty($schema) || ! ($schema instanceof Schema)) {
161
            $schema = Expect::mixed();
162
        }
163
164
        return $loadedSchema[$name] = $schema;
165
    }
166
167
    /**
168
     * Cree et renvoi un model donné
169
     *
170
     * @template T
171
     *
172
     * @param class-string<T> $model
0 ignored issues
show
Documentation Bug introduced by
The doc comment class-string<T> at position 0 could not be parsed: Unknown type name 'class-string' at position 0 in class-string<T>.
Loading history...
173
     *
174
     * @return T
175
     */
176
    public static function model(string $model, ?ConnectionInterface $connection = null)
177
    {
178
        if (! class_exists($model) && ! Text::endsWith($model, 'Model')) {
0 ignored issues
show
Bug introduced by
'Model' of type string is incompatible with the type iterable expected by parameter $needles of BlitzPHP\Utilities\String\Text::endsWith(). ( Ignorable by Annotation )

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

178
        if (! class_exists($model) && ! Text::endsWith($model, /** @scrutinizer ignore-type */ 'Model')) {
Loading history...
179
            $model .= 'Model';
180
        }
181
182
        if (! class_exists($model)) {
183
            $model = str_replace(APP_NAMESPACE . '\\Models\\', '', $model);
184
            $model = APP_NAMESPACE . '\\Models\\' . $model;
185
        }
186
187
        if (! class_exists($model)) {
188
            throw LoadException::modelNotFound($model);
189
        }
190
191
        return Services::container()->make($model, ['db' => $connection]);
192
    }
193
194
    /**
195
     * Recupere le nom de base a partir du nom de la classe, namespacé ou non.
196
     */
197
    public static function getBasename(string $name): string
198
    {
199
        // Determine le basename
200
        if ($basename = strrchr($name, '\\')) {
201
            return substr($basename, 1);
202
        }
203
204
        return $name;
205
    }
206
207
    /**
208
     * Verifie si la classe satisfait l'option "preferApp"
209
     *
210
     * @param array  $options directives specifier pqr le composant
211
     * @param string $name    Nom de la classe, namespace optionel
212
     */
213
    protected static function verifyPreferApp(array $options, string $name): bool
214
    {
215
        // Tout element sans restriction passe
216
        if (! $options['preferApp']) {
217
            return true;
218
        }
219
220
        return str_starts_with($name, APP_NAMESPACE);
221
    }
222
}
223