ClassLoader.php$0 ➔ loadClassList()   A
last analyzed

Complexity

Conditions 3

Size

Total Lines 11

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 0
CRAP Score 12

Importance

Changes 0
Metric Value
cc 3
dl 0
loc 11
ccs 0
cts 7
cp 0
crap 12
rs 9.9
c 0
b 0
f 0
1
<?php
2
3
namespace WebStream\ClassLoader;
4
5
use RecursiveIteratorIterator;
6
use WebStream\DI\Injector;
0 ignored issues
show
Bug introduced by
The type WebStream\DI\Injector was not found. Maybe you did not declare it correctly or list all dependencies?

The issue could also be caused by a filter entry in the build configuration. If the path has been excluded in your configuration, e.g. excluded_paths: ["lib/*"], you can move it to the dependency path list as follows:

filter:
    dependency_paths: ["lib/*"]

For further information see https://scrutinizer-ci.com/docs/tools/php/php-scrutinizer/#list-dependency-paths

Loading history...
7
use WebStream\IO\File;
0 ignored issues
show
Bug introduced by
The type WebStream\IO\File was not found. Maybe you did not declare it correctly or list all dependencies?

The issue could also be caused by a filter entry in the build configuration. If the path has been excluded in your configuration, e.g. excluded_paths: ["lib/*"], you can move it to the dependency path list as follows:

filter:
    dependency_paths: ["lib/*"]

For further information see https://scrutinizer-ci.com/docs/tools/php/php-scrutinizer/#list-dependency-paths

Loading history...
8
use WebStream\IO\FileInputStream;
0 ignored issues
show
Bug introduced by
The type WebStream\IO\FileInputStream was not found. Maybe you did not declare it correctly or list all dependencies?

The issue could also be caused by a filter entry in the build configuration. If the path has been excluded in your configuration, e.g. excluded_paths: ["lib/*"], you can move it to the dependency path list as follows:

filter:
    dependency_paths: ["lib/*"]

For further information see https://scrutinizer-ci.com/docs/tools/php/php-scrutinizer/#list-dependency-paths

Loading history...
9
10
/**
11
 * クラスローダ
12
 * @author Ryuichi TANAKA.
13
 * @since 2013/09/02
14
 * @version 0.7
15
 */
16
class ClassLoader
17
{
18
    use Injector;
19
20
    /**
21
     * @var Psr\Log\LoggerInterface
0 ignored issues
show
Bug introduced by
The type WebStream\ClassLoader\Psr\Log\LoggerInterface was not found. Maybe you did not declare it correctly or list all dependencies?

The issue could also be caused by a filter entry in the build configuration. If the path has been excluded in your configuration, e.g. excluded_paths: ["lib/*"], you can move it to the dependency path list as follows:

filter:
    dependency_paths: ["lib/*"]

For further information see https://scrutinizer-ci.com/docs/tools/php/php-scrutinizer/#list-dependency-paths

Loading history...
22
     */
23
    private $logger;
24
25
    /**
26
     * @var string アプリケーションルートパス
27
     */
28
    private string $applicationRoot;
29
30
    /**
31
     * constructor
32
     * @param string アプリケーションルートパス
0 ignored issues
show
Documentation Bug introduced by
The doc comment アプリケーションルートパス at position 0 could not be parsed: Unknown type name 'アプリケーションルートパス' at position 0 in アプリケーションルートパス.
Loading history...
33
     */
34 16
    public function __construct(string $applicationRoot)
35
    {
36 16
        $this->logger = new class () { public function __call($name, $args) {} };
0 ignored issues
show
Coding Style introduced by
Closing brace must not be followed by any comment or statement on the same line
Loading history...
Coding Style introduced by
The closing brace for the class must go on the next line after the body
Loading history...
Documentation Bug introduced by
It seems like new ClassNode() of type anonymous//ClassLoader.php$0 is incompatible with the declared type WebStream\ClassLoader\Psr\Log\LoggerInterface of property $logger.

Our type inference engine has found an assignment to a property that is incompatible with the declared type of that property.

Either this assignment is in error or the assigned type should be added to the documentation/type hint for that property..

Loading history...
37 16
        $this->applicationRoot = $applicationRoot;
38
    }
39
40
    /**
41
     * クラスをロードする
42
     * @param mixed クラスまたはクラスリスト
0 ignored issues
show
Documentation Bug introduced by
The doc comment クラスまたはクラスリスト at position 0 could not be parsed: Unknown type name 'クラスまたはクラスリスト' at position 0 in クラスまたはクラスリスト.
Loading history...
43
     * @return array<string> ロード済みクラスリスト
44
     */
45 7
    public function load($target): array
46
    {
47 7
        return is_array($target) ? $this->loadClassList($target) : $this->loadClass($target);
48
    }
49
50
    /**
51
     * ファイルをインポートする
52
     * @param string ファイルパス
0 ignored issues
show
Documentation Bug introduced by
The doc comment ファイルパス at position 0 could not be parsed: Unknown type name 'ファイルパス' at position 0 in ファイルパス.
Loading history...
53
     * @param callable|null $filter フィルタリング無名関数 trueを返すとインポート
54
     * @return bool インポート結果
55
     * @throws \WebStream\Exception\Extend\IOException
56
     */
57 3
    public function import($filepath, callable $filter = null): bool
58
    {
59 3
        $file = new File($this->applicationRoot . "/" . $filepath);
60 3
        if ($file->isFile()) {
61 2
            if ($file->getFileExtension() === 'php') {
62 2
                if ($filter === null || (is_callable($filter) && $filter($file->getFilePath()) === true)) {
63 2
                    include_once $file->getFilePath();
64 2
                    $this->logger->debug($file->getAbsoluteFilePath() . " import success.");
65
                }
66
            }
67
68 2
            return true;
69
        }
70
71 1
        return false;
72
    }
73
74
    /**
75
     * 指定ディレクトリのファイルをインポートする
76
     * @param string ディレクトリパス
0 ignored issues
show
Documentation Bug introduced by
The doc comment ディレクトリパス at position 0 could not be parsed: Unknown type name 'ディレクトリパス' at position 0 in ディレクトリパス.
Loading history...
77
     * @param callable|null $filter フィルタリング無名関数 trueを返すとインポート
78
     * @return bool インポート結果
79
     * @throws \WebStream\Exception\Extend\IOException
80
     */
81 3
    public function importAll($dirPath, callable $filter = null): bool
82
    {
83 3
        $dir = new File($this->applicationRoot . "/" . $dirPath);
84 3
        $isSuccess = true;
85 3
        if ($dir->isDirectory()) {
86 3
            $iterator = $this->getFileSearchIterator($dir->getAbsoluteFilePath());
87 3
            foreach ($iterator as $filepath => $fileObject) {
88 3
                if (preg_match("/(?:\/\.|\/\.\.|\.DS_Store)$/", $filepath)) {
89 3
                    continue;
90
                }
91 3
                $file = new File($filepath);
92 3
                if ($file->isFile()) {
93 3
                    if ($file->getFileExtension() === 'php') {
94 3
                        if ($filter === null || (is_callable($filter) && $filter($file->getFilePath()) === true)) {
95 1
                            include_once $file->getFilePath();
96 1
                            $this->logger->debug($file->getAbsoluteFilePath() . " import success.");
97
                        }
98
                    }
99
                } else {
100
                    $this->logger->warn($filepath . " import failure.");
101
                    $isSuccess = false;
102
                }
103
            }
104
        }
105
106 3
        return $isSuccess;
107
    }
108
109
    /**
110
     * 名前空間リストを返却する
111
     * @param string ファイル名
0 ignored issues
show
Documentation Bug introduced by
The doc comment ファイル名 at position 0 could not be parsed: Unknown type name 'ファイル名' at position 0 in ファイル名.
Loading history...
112
     * @return array<string> 名前空間リスト
113
     * @throws \WebStream\Exception\Extend\IOException
114
     * @throws \WebStream\Exception\Extend\InvalidArgumentException
115
     */
116 3
    public function getNamespaces($fileName): array
117
    {
118 3
        $dir = new File($this->applicationRoot);
119 3
        $namespaces = [];
120 3
        if ($dir->isDirectory()) {
121 3
            $iterator = $this->getFileSearchIterator($dir->getAbsoluteFilePath());
122 3
            foreach ($iterator as $filepath => $fileObject) {
123 3
                if (preg_match("/(?:\/\.|\/\.\.|\.DS_Store)$/", $filepath)) {
124 3
                    continue;
125
                }
126 3
                $file = new File($filepath);
127 3
                if ($file->isFile() && $file->getFileName() === $fileName) {
128 2
                    $fis = new FileInputStream($file);
129 2
                    while (($line = $fis->readLine()) !== null) {
130 2
                        if (preg_match("/^namespace\s(.*);$/", $line, $matches)) {
131 2
                            $namespaces[] = $matches[1];
132
                        }
133
                    }
134 2
                    $fis->close();
135
                }
136
            }
137
        }
138
139 3
        return $namespaces;
140
    }
141
142
    /**
143
     * ロード可能なクラスを返却する
144
     * @param string クラス名(フルパス指定の場合はクラスパス)
0 ignored issues
show
Documentation Bug introduced by
The doc comment ... at position 0 could not be parsed: Unknown type name 'クラス名' at position 0 in クラス名(フルパス指定の場合はクラスパス).
Loading history...
145
     * @return array<string> ロード可能クラス
146
     * @throws \WebStream\Exception\Extend\IOException
147
     */
148 7
    private function loadClass(string $className): array
149
    {
150 7
        $rootDir = $this->applicationRoot;
151 7
        $logger = $this->logger;
152
153
        // 名前空間セパレータをパスセパレータに置換
154 7
        if (DIRECTORY_SEPARATOR === '/') {
155 7
            $className = str_replace("\\", DIRECTORY_SEPARATOR, $className);
156
        }
157
158 7
        $search = function ($dirPath, $searchFilePath) use ($logger) {
159 7
            $includeList = [];
160 7
            $dir = new File($dirPath);
161 7
            if (!$dir->isDirectory()) {
162 1
                $logger->error("Invalid search directory path: " . $dir->getFilePath());
163 1
                return $includeList;
164
            }
165 6
            $iterator = $this->getFileSearchIterator($dir->getAbsoluteFilePath());
166 6
            foreach ($iterator as $filepath => $fileObject) {
167 6
                if (!$fileObject->isFile()) {
168 6
                    continue;
169
                }
170 6
                if (strpos($filepath, $searchFilePath) !== false) {
171 5
                    $file = new File($filepath);
172 5
                    $absoluteFilePath = $file->getAbsoluteFilePath();
173 5
                    include_once $absoluteFilePath;
174 5
                    $includeList[] = $absoluteFilePath;
175 5
                    $logger->debug($absoluteFilePath . " load success. (search from " . $dir->getAbsoluteFilePath() . ")");
176
                }
177
            }
178
179 6
            return $includeList;
180 7
        };
181
182 7
        return $search("${rootDir}", DIRECTORY_SEPARATOR . "${className}.php");
183
    }
184
185
    /**
186
     * ロード可能なクラスを複数返却する
187
     * @param array クラス名
0 ignored issues
show
Documentation Bug introduced by
The doc comment クラス名 at position 0 could not be parsed: Unknown type name 'クラス名' at position 0 in クラス名.
Loading history...
188
     * @return array<string> ロード済みクラスリスト
189
     * @throws \WebStream\Exception\Extend\IOException
190
     */
191
    private function loadClassList(array $classList): array
192
    {
193
        $includedList = [];
194
        foreach ($classList as $className) {
195
            $result = $this->loadClass($className);
196
            if (is_array($result)) {
197
                $includedList = array_merge($includedList, $result);
198
            }
199
        }
200
201
        return $includedList;
202
    }
203
204
    /**
205
     * ファイル検索イテレータを返却する
206
     * @param string ディレクトリパス
0 ignored issues
show
Documentation Bug introduced by
The doc comment ディレクトリパス at position 0 could not be parsed: Unknown type name 'ディレクトリパス' at position 0 in ディレクトリパス.
Loading history...
207
     * @return RecursiveIteratorIterator イテレータ
208
     */
209 12
    private function getFileSearchIterator(string $path): \RecursiveIteratorIterator
210
    {
211 12
        $iterator = [];
212 12
        $file = new File($path);
213 12
        if ($file->isDirectory()) {
214 12
            $iterator = new \RecursiveIteratorIterator(
215 12
                new \RecursiveDirectoryIterator($path),
216 12
                \RecursiveIteratorIterator::LEAVES_ONLY,
217 12
                \RecursiveIteratorIterator::CATCH_GET_CHILD // for Permission deny
218
            );
219
        }
220 12
        return $iterator;
0 ignored issues
show
Bug Best Practice introduced by
The expression return $iterator could return the type array which is incompatible with the type-hinted return RecursiveIteratorIterator. Consider adding an additional type-check to rule them out.
Loading history...
221
    }
222
}
223