-
Notifications
You must be signed in to change notification settings - Fork 98
Expand file tree
/
Copy pathBakePlugin.php
More file actions
154 lines (134 loc) · 4.65 KB
/
BakePlugin.php
File metadata and controls
154 lines (134 loc) · 4.65 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
<?php
declare(strict_types=1);
/**
* CakePHP(tm) : Rapid Development Framework (https://cakephp.org)
* Copyright (c) Cake Software Foundation, Inc. (https://cakefoundation.org)
*
* Licensed under The MIT License
* For full copyright and license information, please see the LICENSE.txt
* Redistributions of files must retain the above copyright notice.
*
* @copyright Copyright (c) Cake Software Foundation, Inc. (https://cakefoundation.org)
* @link https://cakephp.org CakePHP(tm) Project
* @since 1.7.2
* @license https://www.opensource.org/licenses/mit-license.php MIT License
*/
namespace Bake;
use Bake\Command\BakeCommand;
use Bake\Command\EntryCommand;
use Cake\Console\CommandCollection;
use Cake\Core\BasePlugin;
use Cake\Core\Configure;
use Cake\Core\Plugin;
use Cake\Core\PluginApplicationInterface;
use Cake\Http\BaseApplication;
use DirectoryIterator;
use ReflectionClass;
/**
* Plugin class for bake
*/
class BakePlugin extends BasePlugin
{
/**
* Plugin name.
*/
protected ?string $name = 'Bake';
/**
* Load routes or not
*/
protected bool $routesEnabled = false;
/**
* Load the TwigView plugin.
*
* @param \Cake\Core\PluginApplicationInterface $app The host application
* @return void
*/
public function bootstrap(PluginApplicationInterface $app): void
{
assert($app instanceof BaseApplication);
if (!$app->getPlugins()->has('Cake/TwigView')) {
$app->addPlugin('Cake/TwigView');
}
}
/**
* Define the console commands for an application.
*
* @param \Cake\Console\CommandCollection $commands The CommandCollection to add commands into.
* @return \Cake\Console\CommandCollection The updated collection.
*/
public function console(CommandCollection $commands): CommandCollection
{
// Add commands in plugins and app.
$commands = $this->discoverCommands($commands);
// Add entry command to handle entry point and backwards compat.
$commands->add(EntryCommand::defaultName(), EntryCommand::class);
return $commands;
}
/**
* Scan plugins and application to find commands that are intended
* to be used with bake.
*
* Non-Abstract commands extending `Bake\Command\BakeCommand` are included.
* Plugins are scanned in the order they are listed in `Plugin::loaded()`
*
* @param \Cake\Console\CommandCollection $commands The CommandCollection to add commands into.
* @return \Cake\Console\CommandCollection The updated collection.
*/
protected function discoverCommands(CommandCollection $commands): CommandCollection
{
foreach (Plugin::getCollection()->with('console') as $plugin) {
$namespace = str_replace('/', '\\', $plugin->getName());
$pluginPath = $plugin->getClassPath();
$found = $this->findInPath($namespace, $pluginPath);
if ($found !== []) {
$commands->addMany($found);
}
}
$found = $this->findInPath(Configure::read('App.namespace'), APP);
if ($found !== []) {
$commands->addMany($found);
}
return $commands;
}
/**
* Search a path for commands.
*
* @param string $namespace The namespace classes are expected to be in.
* @param string $path The path to look in.
* @return array<string>
* @phpstan-return array<string, class-string<\Bake\Command\BakeCommand>>
*/
protected function findInPath(string $namespace, string $path): array
{
$hasSubfolder = false;
$path .= 'Command/';
$namespace .= '\Command\\';
if (file_exists($path . 'Bake/')) {
$hasSubfolder = true;
$path .= 'Bake/';
$namespace .= 'Bake\\';
} elseif (!file_exists($path)) {
return [];
}
$iterator = new DirectoryIterator($path);
$candidates = [];
foreach ($iterator as $item) {
if ($item->isDot() || $item->isDir()) {
continue;
}
$class = $namespace . $item->getBasename('.php');
if (!$hasSubfolder) {
if (!class_exists($class)) {
continue;
}
$reflection = new ReflectionClass($class);
if (!$reflection->isInstantiable() || !$reflection->isSubclassOf(BakeCommand::class)) {
continue;
}
}
/** @var class-string<\Bake\Command\BakeCommand> $class */
$candidates[$class::defaultName()] = $class;
}
return $candidates;
}
}