Passed
Push — master ( 73fab9...ec4cf3 )
by Ryuichi
01:40
created

ClassLoader.php$0 ➔ load()   A

Complexity

Conditions 2

Size

Total Lines 3

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 2
CRAP Score 2

Importance

Changes 0
Metric Value
dl 0
loc 3
ccs 2
cts 2
cp 1
c 0
b 0
f 0
cc 2
crap 2
rs 10
1
<?php
2
3
namespace WebStream\ClassLoader;
4
5
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...
6
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...
7
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...
8
9
/**
10
 * クラスローダ
11
 * @author Ryuichi TANAKA.
12
 * @since 2013/09/02
13
 * @version 0.7
14
 */
15
class ClassLoader
16
{
17
    use Injector;
18
19
    /**
20
     * @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...
21
     */
22
    private $logger;
23
24
    /**
25
     * @var string アプリケーションルートパス
26
     */
27
    private $applicationRoot;
28
29
    /**
30
     * constructor
31
     * @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...
32
     */
33 16
    public function __construct(string $applicationRoot)
34
    {
35
        $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...
36 16
        $this->applicationRoot = $applicationRoot;
37
    }
38
39
    /**
40
     * クラスをロードする
41
     * @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...
42
     * @return array<string> ロード済みクラスリスト
43
     */
44 7
    public function load($target): array
45
    {
46 7
        return is_array($target) ? $this->loadClassList($target) : $this->loadClass($target);
47
    }
48
49
    /**
50
     * ファイルをインポートする
51
     * @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...
52
     * @param callable フィルタリング無名関数 trueを返すとインポート
53
     * @return bool インポート結果
54
     */
55 3
    public function import($filepath, callable $filter = null): bool
56
    {
57 3
        $file = new File($this->applicationRoot . "/" . $filepath);
58 3
        if ($file->isFile()) {
59 2
            if ($file->getFileExtension() === 'php') {
60 2
                if ($filter === null || (is_callable($filter) && $filter($file->getFilePath()) === true)) {
61 2
                    include_once $file->getFilePath();
62 2
                    $this->logger->debug($file->getAbsoluteFilePath() . " import success.");
63
                }
64
            }
65
66 2
            return true;
67
        }
68
69 1
        return false;
70
    }
71
72
    /**
73
     * 指定ディレクトリのファイルをインポートする
74
     * @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...
75
     * @param callable フィルタリング無名関数 trueを返すとインポート
76
     * @return bool インポート結果
77
     */
78 3
    public function importAll($dirPath, callable $filter = null): bool
79
    {
80 3
        $dir = new File($this->applicationRoot . "/" . $dirPath);
81 3
        $isSuccess = true;
82 3
        if ($dir->isDirectory()) {
83 3
            $iterator = $this->getFileSearchIterator($dir->getAbsoluteFilePath());
84 3
            foreach ($iterator as $filepath => $fileObject) {
85 3
                if (preg_match("/(?:\/\.|\/\.\.|\.DS_Store)$/", $filepath)) {
86 3
                    continue;
87
                }
88 3
                $file = new File($filepath);
89 3
                if ($file->isFile()) {
90 3
                    if ($file->getFileExtension() === 'php') {
91 3
                        if ($filter === null || (is_callable($filter) && $filter($file->getFilePath()) === true)) {
92 1
                            include_once $file->getFilePath();
93 1
                            $this->logger->debug($file->getAbsoluteFilePath() . " import success.");
94
                        }
95
                    }
96
                } else {
97
                    $this->logger->warn($filepath . " import failure.");
98
                    $isSuccess = false;
99
                }
100
            }
101
        }
102
103 3
        return $isSuccess;
104
    }
105
106
    /**
107
     * 名前空間リストを返却する
108
     * @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...
109
     * @return array<string> 名前空間リスト
110
     */
111 3
    public function getNamespaces($fileName): array
112
    {
113 3
        $dir = new File($this->applicationRoot);
114 3
        $namespaces = [];
115 3
        if ($dir->isDirectory()) {
116 3
            $iterator = $this->getFileSearchIterator($dir->getAbsoluteFilePath());
117 3
            foreach ($iterator as $filepath => $fileObject) {
118 3
                if (preg_match("/(?:\/\.|\/\.\.|\.DS_Store)$/", $filepath)) {
119 3
                    continue;
120
                }
121 3
                $file = new File($filepath);
122 3
                if ($file->isFile() && $file->getFileName() === $fileName) {
123 2
                    $fis = new FileInputStream($file);
124 2
                    while (($line = $fis->readLine()) !== null) {
125 2
                        if (preg_match("/^namespace\s(.*);$/", $line, $matches)) {
126 2
                            $namespaces[] = $matches[1];
127
                        }
128
                    }
129 2
                    $fis->close();
130
                }
131
            }
132
        }
133
134 3
        return $namespaces;
135
    }
136
137
    /**
138
    * ロード可能なクラスを返却する
139
    * @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...
140
    * @return array<string> ロード可能クラス
141
     */
142 7
    private function loadClass(string $className): array
143
    {
144 7
        $rootDir = $this->applicationRoot;
145 7
        $logger = $this->logger;
146
147
        // 名前空間セパレータをパスセパレータに置換
148 7
        if (DIRECTORY_SEPARATOR === '/') {
149 7
            $className = str_replace("\\", DIRECTORY_SEPARATOR, $className);
150
        }
151
152
        $search = function ($dirPath, $searchFilePath) use ($logger) {
153 7
            $includeList = [];
154 7
            $dir = new File($dirPath);
155 7
            if (!$dir->isDirectory()) {
156 1
                $logger->error("Invalid search directory path: " . $dir->getFilePath());
157 1
                return $includeList;
158
            }
159 6
            $iterator = $this->getFileSearchIterator($dir->getAbsoluteFilePath());
160 6
            foreach ($iterator as $filepath => $fileObject) {
161 6
                if (!$fileObject->isFile()) {
162 6
                    continue;
163
                }
164 6
                if (strpos($filepath, $searchFilePath) !== false) {
165 5
                    $file = new File($filepath);
166 5
                    $absoluteFilePath = $file->getAbsoluteFilePath();
167 5
                    include_once $absoluteFilePath;
168 5
                    $includeList[] = $absoluteFilePath;
169 5
                    $logger->debug($absoluteFilePath . " load success. (search from " . $dir->getAbsoluteFilePath() . ")");
170
                }
171
            }
172
173 6
            return $includeList;
174 7
        };
175
176 7
        return $search("${rootDir}", DIRECTORY_SEPARATOR . "${className}.php");
177
    }
178
179
    /**
180
     * ロード可能なクラスを複数返却する
181
     * @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...
182
     * @return array<string> ロード済みクラスリスト
183
     */
184
    private function loadClassList(array $classList): array
185
    {
186
        $includedlist = [];
187
        foreach ($classList as $className) {
188
            $result = $this->loadClass($className);
189
            if (is_array($result)) {
190
                $includedlist = array_merge($includedlist, $result);
191
            }
192
        }
193
194
        return $includedlist;
195
    }
196
197
    /**
198
     * ファイル検索イテレータを返却する
199
     * @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...
200
     * @return RecursiveIteratorIterator イテレータ
201
     */
202 12
    private function getFileSearchIterator(string $path): \RecursiveIteratorIterator
203
    {
204 12
        $iterator = [];
205 12
        $file = new File($path);
206 12
        if ($file->isDirectory()) {
207 12
            $iterator = new \RecursiveIteratorIterator(
208 12
                new \RecursiveDirectoryIterator($path),
209 12
                \RecursiveIteratorIterator::LEAVES_ONLY,
210 12
                \RecursiveIteratorIterator::CATCH_GET_CHILD // for Permission deny
211
            );
212
        }
213 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...
214
    }
215
}
216