ControllerFinder::getControllerClasses()   A
last analyzed

Complexity

Conditions 2
Paths 2

Size

Total Lines 5

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
dl 0
loc 5
rs 10
c 0
b 0
f 0
cc 2
nc 2
nop 0
1
<?php
2
/**
3
 * This file is part of the silex-annotation-provider package.
4
 * For the full copyright and license information, please view the LICENSE
5
 * file that was distributed with this source code.
6
 *
7
 * @license       MIT License
8
 * @copyright (c) 2018, Dana Desrosiers <[email protected]>
9
 */
10
11
declare(strict_types=1);
12
13
namespace DDesrosiers\SilexAnnotations;
14
15
/**
16
 * Class ControllerFinder searches file directories for potential Controller classes.
17
 *
18
 * @author Dana Desrosiers <[email protected]>
19
 */
20
class ControllerFinder
21
{
22
    /** @var null|string */
23
    private $controllerDir;
24
25
    /** @var string[] */
26
    private $controllers;
27
28
    /**
29
     * ControllerFinder constructor.
30
     *
31
     * @param string|null $controllerDir
32
     * @param string[]    $controllers
33
     */
34
    public function __construct(string $controllerDir = null, array $controllers = [])
35
    {
36
        $this->controllerDir = $controllerDir;
37
        $this->controllers = $controllers;
38
    }
39
40
    /**
41
     * @return string[]
42
     */
43
    public function getControllerClasses(): array
44
    {
45
        $controllers = isset($this->controllerDir) ? $this->getClassesInDirectory($this->controllerDir) : [];
46
        return array_merge($controllers, $this->controllers);
47
    }
48
49
    /**
50
     * Recursively walk the file tree starting from $dir to find potential controller class files.
51
     * Returns array of fully qualified class names.
52
     * Namespace detection works with PSR-0 or PSR-4 autoloading.
53
     *
54
     * @param string   $dir
55
     * @param string   $namespace
56
     * @param string[] $files
57
     * @return string[]
58
     */
59
    private function getClassesInDirectory(string $dir, string $namespace = '', $files = []): array
60
    {
61
        if (!is_dir($dir)) {
62
            throw new \RuntimeException("Controller directory: {$dir} does not exist.");
63
        }
64
65
        if ($handle = opendir($dir)) {
66
            while (false !== ($entry = readdir($handle))) {
67
                if (!in_array($entry, array('.', '..'))) {
68
                    $filePath = "$dir/$entry";
69
                    if (is_dir($filePath)) {
70
                        $subNamespace = $namespace ? $namespace."$entry\\" : '';
71
                        $files = $this->getClassesInDirectory($filePath, $subNamespace, $files);
72
                    } else {
73
                        if (!$namespace) {
74
                            $namespace = $this->parseNamespace($filePath);
75
                        }
76
                        $className = trim($namespace.pathinfo($entry)['filename']);
77
                        if (class_exists($className)) {
78
                            $files[] = $className;
79
                        }
80
                    }
81
                }
82
            }
83
            closedir($handle);
84
        }
85
86
        return $files;
87
    }
88
89
    /**
90
     * Parse the given file to find the namespace.
91
     *
92
     * @param $filePath
93
     * @return string
94
     */
95
    private function parseNamespace($filePath): string
96
    {
97
        preg_match('/namespace(.*);/', file_get_contents($filePath), $result);
98
        return isset($result[1]) ? $result[1] . "\\" : '';
99
    }
100
}