1
|
|
|
<?php |
2
|
|
|
|
3
|
|
|
namespace Magium\Cli\Command; |
4
|
|
|
|
5
|
|
|
use Magium\InvalidConfigurationException; |
6
|
|
|
use Magium\NotFoundException; |
7
|
|
|
use Symfony\Component\Console\Command\Command; |
8
|
|
|
use Symfony\Component\Console\Input\InputArgument; |
9
|
|
|
use Symfony\Component\Console\Input\InputInterface; |
10
|
|
|
use Symfony\Component\Console\Input\InputOption; |
11
|
|
|
use Symfony\Component\Console\Output\OutputInterface; |
12
|
|
|
|
13
|
|
|
class ListElements extends Command |
14
|
|
|
{ |
15
|
|
|
protected static $dirs = []; |
16
|
|
|
|
17
|
|
|
public static function addDirectory($dir, $namespace) |
18
|
|
|
{ |
19
|
|
|
if ($dir != realpath($dir)) { |
20
|
|
|
throw new InvalidConfigurationException('Path not found. Please ensure that you pass the realpath() in: ' . $dir); |
21
|
|
|
} |
22
|
|
|
self::$dirs[$dir] = $namespace; |
23
|
|
|
} |
24
|
|
|
|
25
|
|
|
protected function configure() |
26
|
|
|
{ |
27
|
|
|
$this->setName('element:list'); |
28
|
|
|
$this->setDescription('Extracts all of the AbstractConfigurableElement-based objects'); |
29
|
|
|
$this->setHelp(<<<HELP |
30
|
|
|
This command will traverse all known directories, or a specific directory, and return a list of all the classes found that extend Magium\\AbstractConfigurableElement in some way. |
31
|
|
|
|
32
|
|
|
It can be used in conjunction with the magium:element:get to narrow down exactly which configuration value you are looking for. |
33
|
|
|
|
34
|
|
|
There are two modes of operation to be aware of. |
35
|
|
|
|
36
|
|
|
1. Argument mode |
37
|
|
|
|
38
|
|
|
If you run with the "directory" and "namespace" arguments (if one is provided both are required) then this command will recursively descend into this directory and find all configurable elements. |
39
|
|
|
|
40
|
|
|
2. Argument-less mode |
41
|
|
|
|
42
|
|
|
Running without the options will cause the command to search through all registered paths. |
43
|
|
|
|
44
|
|
|
An individual module is responsible to register its paths and does so by creating an autoload register.php file which contains at least the following code |
45
|
|
|
|
46
|
|
|
<?php |
47
|
|
|
|
48
|
|
|
Magium\Cli\Command\ListElements::addDirectory('my test dir', 'my\\test\\namespace'); |
49
|
|
|
|
50
|
|
|
Again, all classes must be defined in PSR-4-autoload format. Custom autoloaders may be used, but the PSR-4 format is there to deduce the name of the class based on the file name. |
51
|
|
|
|
52
|
|
|
HELP |
53
|
|
|
); |
54
|
|
|
$this->addArgument( |
55
|
|
|
'directory', |
56
|
|
|
InputArgument::OPTIONAL, |
57
|
|
|
'The name of the directory to traverse' |
58
|
|
|
); |
59
|
|
|
|
60
|
|
|
$this->addArgument( |
61
|
|
|
'namespace', |
62
|
|
|
InputArgument::OPTIONAL, |
63
|
|
|
'The psr-4 base namespace of the directory. Required if <directory> is used' |
64
|
|
|
); |
65
|
|
|
$this->addArgument( |
66
|
|
|
'filter', |
67
|
|
|
InputArgument::OPTIONAL, |
68
|
|
|
'A stripos()-compatible filter' |
69
|
|
|
); |
70
|
|
|
|
71
|
|
|
$this->addOption( |
72
|
|
|
'escape', |
73
|
|
|
'--esc', |
74
|
|
|
InputOption::VALUE_NONE, |
75
|
|
|
'Set if you want the namespace output escaped (useful for copy and paste)' |
76
|
|
|
); |
77
|
|
|
|
78
|
|
|
self::addDirectory(realpath(__DIR__ . '/../..'), 'Magium'); |
79
|
|
|
} |
80
|
|
|
|
81
|
|
|
protected function execute(InputInterface $input, OutputInterface $output) |
82
|
|
|
{ |
83
|
|
|
if ($input->getArgument('directory') || $input->getArgument('namespace')) { |
84
|
|
|
if (!$input->getArgument('directory') || !$input->getArgument('namespace')) { |
85
|
|
|
throw new NotFoundException('Missing either the directory or namespace argument. If one is used, then both are required'); |
86
|
|
|
} |
87
|
|
|
} |
88
|
|
|
|
89
|
|
|
$paths = []; |
90
|
|
|
if ($input->getArgument('directory') || $input->getArgument('namespace')) { |
91
|
|
|
$paths = $this->traverseDirectory(realpath($input->getArgument('directory')), $input->getArgument('namespace')); |
92
|
|
|
} else { |
93
|
|
|
foreach (self::$dirs as $dir => $namespace) { |
94
|
|
|
$result = $this->traverseDirectory($dir, $namespace); |
95
|
|
|
$paths = array_merge($paths, $result); |
96
|
|
|
} |
97
|
|
|
} |
98
|
|
|
|
99
|
|
|
sort($paths); |
100
|
|
|
$filter = $input->getArgument('filter'); |
101
|
|
|
if (count($paths) > 0 ) { |
102
|
|
|
$output->writeln('Classes found: '); |
103
|
|
|
$escape = $input->getOption('escape'); |
104
|
|
|
|
105
|
|
|
foreach ($paths as $path) { |
106
|
|
|
if ($escape) { |
107
|
|
|
$path = str_replace('\\', '\\\\', $path); |
108
|
|
|
} |
109
|
|
|
if ($filter && stripos($path, $filter) !== false) { |
110
|
|
|
$output->writeln("\t" . $path); |
111
|
|
|
} |
112
|
|
|
} |
113
|
|
|
} else { |
114
|
|
|
$output->writeln('No classes found. If you were expecting to find some you might need to escape your namespace separators'); |
115
|
|
|
$output->writeln('e.g. Namespace\Class should be written as Namespace\\\\Class'); |
116
|
|
|
} |
117
|
|
|
} |
118
|
|
|
|
119
|
|
|
/** |
120
|
|
|
* @param $dir |
121
|
|
|
* @param $namespace |
122
|
|
|
* @return array |
123
|
|
|
*/ |
124
|
|
|
|
125
|
|
|
protected function traverseDirectory($dir, $namespace) |
126
|
|
|
{ |
127
|
|
|
$classes = []; |
128
|
|
|
$dirIterator = new \RecursiveDirectoryIterator($dir); |
129
|
|
|
$iterator = new \RecursiveIteratorIterator($dirIterator); |
130
|
|
|
$phpFiles = new \RegexIterator($iterator, '/.*\.php$/', \RegexIterator::GET_MATCH); |
131
|
|
|
foreach ($phpFiles as $file) { |
132
|
|
|
if (is_array($file)) { |
133
|
|
|
$file = array_shift($file); |
134
|
|
|
} |
135
|
|
|
if (strpos($file, $dir) === 0) { |
136
|
|
|
$eCls = explode('\\', $namespace); |
137
|
|
|
$cls = substr($file, strlen($dir), -4); |
138
|
|
|
$matches = null; |
139
|
|
|
preg_match_all('/(\w*)/', $cls, $matches); |
140
|
|
|
if ($matches) { |
141
|
|
|
foreach ($matches[0] as $match) { |
142
|
|
|
if ($match) { |
143
|
|
|
$eCls[] = $match; |
144
|
|
|
} |
145
|
|
|
} |
146
|
|
|
$class = implode('\\', $eCls); |
147
|
|
|
if (class_exists($class) && is_subclass_of($class, 'Magium\AbstractConfigurableElement')) { |
148
|
|
|
$classes [] = $class; |
149
|
|
|
} |
150
|
|
|
} |
151
|
|
|
|
152
|
|
|
} |
153
|
|
|
} |
154
|
|
|
return $classes; |
155
|
|
|
} |
156
|
|
|
|
157
|
|
|
} |