Completed
Push — master ( 9af83e...139fb8 )
by Thomas
21s
created

CustomExtensionDiscovery   A

Complexity

Total Complexity 17

Size/Duplication

Total Lines 149
Duplicated Lines 0 %

Test Coverage

Coverage 91.49%

Importance

Changes 0
Metric Value
eloc 52
dl 0
loc 149
ccs 43
cts 47
cp 0.9149
rs 10
c 0
b 0
f 0
wmc 17

7 Methods

Rating   Name   Duplication   Size   Complexity  
A getCustomModules() 0 6 1
A __construct() 0 3 1
A create() 0 9 3
A getCustomThemes() 0 6 1
A get() 0 17 5
A searchRecursively() 0 17 3
A getExistingRootPaths() 0 18 3
1
<?php
2
3
declare(strict_types=1);
4
5
/*
6
 * This file is part of the ekino Drupal Debug project.
7
 *
8
 * (c) ekino
9
 *
10
 * For the full copyright and license information, please view the LICENSE
11
 * file that was distributed with this source code.
12
 */
13
14
namespace Ekino\Drupal\Debug\Extension;
15
16
use Ekino\Drupal\Debug\Extension\Iterator\RecursiveCustomExtensionFilterIterator;
17
use Ekino\Drupal\Debug\Extension\Model\AbstractCustomExtension;
18
use Ekino\Drupal\Debug\Extension\Model\CustomModule;
19
use Ekino\Drupal\Debug\Extension\Model\CustomTheme;
20
21
class CustomExtensionDiscovery
22
{
23
    /**
24
     * @var string[]
25
     */
26
    const POSSIBLE_CUSTOM_MODULES_ROOT_PATHS = array(
27
        'modules',
28
        'sites/all/modules',
29
    );
30
31
    /**
32
     * @var string[]
33
     */
34
    const POSSIBLE_CUSTOM_THEMES_ROOT_PATHS = array(
35
        'themes',
36
    );
37
38
    /**
39
     * @var string
40
     */
41
    private $appRoot;
42
43
    /**
44
     * @var array
45
     */
46
    private static $cache = array(
47
        'module' => array(),
48
        'theme' => array(),
49
    );
50
51
    /**
52
     * @param string $appRoot
53
     */
54 2
    public function __construct(string $appRoot)
55
    {
56 2
        $this->appRoot = $appRoot;
57 2
    }
58
59
    /**
60
     * @return CustomModule[]
61
     */
62 1
    public function getCustomModules(): array
63
    {
64
        /** @var CustomModule[] $customModules */
65 1
        $customModules = $this->get('module');
66
67 1
        return $customModules;
68
    }
69
70
    /**
71
     * @return CustomTheme[]
72
     */
73 1
    public function getCustomThemes(): array
74
    {
75
        /** @var CustomTheme[] $customThemes */
76 1
        $customThemes = $this->get('theme');
77
78 1
        return $customThemes;
79
    }
80
81
    /**
82
     * @param string $type
83
     *
84
     * @return CustomModule[]|CustomTheme[]
85
     */
86 2
    private function get(string $type): array
87
    {
88 2
        if (!isset(self::$cache[$type])) {
89
            throw new \InvalidArgumentException(\sprintf('The "%s" type is invalid.', $type));
90
        }
91
92 2
        if (!isset(self::$cache[$type][$this->appRoot])) {
93 2
            self::$cache[$type][$this->appRoot] = array();
94
95 2
            foreach ($this->getExistingRootPaths($type) as $existingCustomExtensionRootPath) {
96 2
                foreach ($this->searchRecursively($type, new \SplFileInfo($existingCustomExtensionRootPath)) as $customExtension) {
97 2
                    self::$cache[$type][$this->appRoot][] = $customExtension;
98
                }
99
            }
100
        }
101
102 2
        return self::$cache[$type][$this->appRoot];
103
    }
104
105
    /**
106
     * @param string $type
107
     *
108
     * @return string[]
109
     */
110 2
    private function getExistingRootPaths(string $type): array
111
    {
112 2
        switch ($type) {
113 2
            case 'module':
114 1
                $possibleRootPaths = self::POSSIBLE_CUSTOM_MODULES_ROOT_PATHS;
115
116 1
                break;
117 1
            case 'theme':
118 1
                $possibleRootPaths = self::POSSIBLE_CUSTOM_THEMES_ROOT_PATHS;
119
120 1
                break;
121
            default:
122
                throw new \LogicException('The type should be "module" or "theme".');
123
        }
124
125
        return \array_filter(\array_map(function ($possibleRootPath) {
126 2
            return \sprintf('%s/%s', $this->appRoot, $possibleRootPath);
127 2
        }, $possibleRootPaths), 'is_dir');
128
    }
129
130
    /**
131
     * @param string       $type
132
     * @param \SplFileInfo $splFileInfo
133
     *
134
     * @return AbstractCustomExtension[]
135
     */
136 2
    private function searchRecursively(string $type, \SplFileInfo $splFileInfo): array
137
    {
138 2
        $customExtensions = array();
139
140 2
        $realPath = $splFileInfo->getRealPath();
141 2
        if (!\is_string($realPath)) {
0 ignored issues
show
introduced by
The condition is_string($realPath) is always true.
Loading history...
142
            throw new \RuntimeException('The path should be a string.');
143
        }
144
145 2
        $directoryIterator = new \RecursiveDirectoryIterator($realPath, \FilesystemIterator::UNIX_PATHS | \FilesystemIterator::SKIP_DOTS | \FilesystemIterator::FOLLOW_SYMLINKS | \FilesystemIterator::CURRENT_AS_SELF);
146 2
        $filter = new RecursiveCustomExtensionFilterIterator($directoryIterator);
147 2
        $iterator = new \RecursiveIteratorIterator($filter, \RecursiveIteratorIterator::LEAVES_ONLY, \RecursiveIteratorIterator::CATCH_GET_CHILD);
148 2
        foreach ($iterator as $splFileInfo) {
149 2
            $customExtensions[] = $this->create($type, $splFileInfo);
150
        }
151
152 2
        return $customExtensions;
153
    }
154
155
    /**
156
     * @param string       $type
157
     * @param \SplFileInfo $splFileInfo
158
     *
159
     * @return AbstractCustomExtension
160
     */
161 2
    private function create(string $type, \SplFileInfo $splFileInfo): AbstractCustomExtension
162
    {
163 2
        switch ($type) {
164 2
            case 'module':
165 1
                return new CustomModule($splFileInfo->getPath(), $splFileInfo->getBasename('.info.yml'));
166 1
            case 'theme':
167 1
                return new CustomTheme($splFileInfo->getPath(), $splFileInfo->getBasename('.info.yml'));
168
            default:
169
                throw new \LogicException('The type should be "module" or "theme".');
170
        }
171
    }
172
}
173