path = current(App::path('Plugin'));
$this->bootstrap = APP . 'Config' . DS . 'bootstrap.php';
}
/**
* Execution method always used for tasks
*
* @return void
*/
public function execute() {
if (isset($this->args[0])) {
$plugin = Inflector::camelize($this->args[0]);
$pluginPath = $this->_pluginPath($plugin);
if (is_dir($pluginPath)) {
$this->out(__d('cake_console', 'Plugin: %s already exists, no action taken', $plugin));
$this->out(__d('cake_console', 'Path: %s', $pluginPath));
return false;
}
$this->_interactive($plugin);
} else {
return $this->_interactive();
}
}
/**
* Interactive interface
*
* @param string $plugin
* @return void
*/
protected function _interactive($plugin = null) {
while ($plugin === null) {
$plugin = $this->in(__d('cake_console', 'Enter the name of the plugin in CamelCase format'));
}
if (!$this->bake($plugin)) {
$this->error(__d('cake_console', "An error occurred trying to bake: %s in %s", $plugin, $this->path . $plugin));
}
}
/**
* Bake the plugin, create directories and files
*
* @param string $plugin Name of the plugin in CamelCased format
* @return boolean
*/
public function bake($plugin) {
$pathOptions = App::path('Plugin');
if (count($pathOptions) > 1) {
$this->findPath($pathOptions);
}
$this->hr();
$this->out(__d('cake_console', "Plugin Name: %s", $plugin));
$this->out(__d('cake_console', "Plugin Directory: %s", $this->path . $plugin));
$this->hr();
$looksGood = $this->in(__d('cake_console', 'Look okay?'), ['y', 'n', 'q'], 'y');
if (strtolower($looksGood) === 'y') {
$Folder = new Folder($this->path . $plugin);
$directories = [
'Config' . DS . 'Schema',
'Model' . DS . 'Behavior',
'Model' . DS . 'Table',
'Model' . DS . 'Entity',
'Console' . DS . 'Command' . DS . 'Task',
'Controller' . DS . 'Component',
'Lib',
'View' . DS . 'Helper',
'Template',
'Test' . DS . 'TestCase' . DS . 'Controller' . DS . 'Component',
'Test' . DS . 'TestCase' . DS . 'View' . DS . 'Helper',
'Test' . DS . 'TestCase' . DS . 'Model' . DS . 'Behavior',
'Test' . DS . 'Fixture',
'webroot'
];
foreach ($directories as $directory) {
$dirPath = $this->path . $plugin . DS . $directory;
$Folder->create($dirPath);
new File($dirPath . DS . 'empty', true);
}
foreach ($Folder->messages() as $message) {
$this->out($message, 1, Shell::VERBOSE);
}
$errors = $Folder->errors();
if (!empty($errors)) {
foreach ($errors as $message) {
$this->error($message);
}
return false;
}
$controllerFileName = $plugin . 'AppController.php';
$out = "createFile($this->path . $plugin . DS . 'Controller' . DS . $controllerFileName, $out);
$this->_modifyBootstrap($plugin);
$this->_generatePhpunitXml($plugin, $this->path);
$this->_generateTestBootstrap($plugin, $this->path);
$this->hr();
$this->out(__d('cake_console', 'Created: %s in %s', $plugin, $this->path . $plugin), 2);
}
return true;
}
/**
* Update the app's bootstrap.php file.
*
* @param string $plugin Name of plugin
* @return void
*/
protected function _modifyBootstrap($plugin) {
$bootstrap = new File($this->bootstrap, false);
$contents = $bootstrap->read();
if (!preg_match("@\n\s*Plugin::loadAll@", $contents)) {
$bootstrap->append("\nPlugin::load('$plugin', ['bootstrap' => false, 'routes' => false]);\n");
$this->out('');
$this->out(sprintf('%s modified', $this->bootstrap));
}
}
/**
* Generate a phpunit.xml stub for the plugin.
*
* @param string $plugin Name of plugin
* @param string $path The path to save the phpunit.xml file to.
* @return void
*/
protected function _generatePhpunitXml($plugin, $path) {
$this->Template->set([
'plugin' => $plugin,
'path' => $path
]);
$this->out( __d('cake_console', 'Generating phpunit.xml file...'));
$out = $this->Template->generate('test', 'phpunit.xml');
$file = $path . $plugin . DS . 'phpunit.xml';
$this->createFile($file, $out);
}
/**
* Generate a Test/bootstrap.php stub for the plugin.
*
* @param string $plugin Name of plugin
* @param string $path The path to save the phpunit.xml file to.
* @return void
*/
protected function _generateTestBootstrap($plugin, $path) {
$this->Template->set([
'plugin' => $plugin,
'path' => $path,
'root' => ROOT
]);
$this->out( __d('cake_console', 'Generating Test/bootstrap.php file...'));
$out = $this->Template->generate('test', 'bootstrap');
$file = $path . $plugin . DS . 'Test' . DS . 'bootstrap.php';
$this->createFile($file, $out);
}
/**
* find and change $this->path to the user selection
*
* @param array $pathOptions
* @return void
*/
public function findPath($pathOptions) {
$valid = false;
foreach ($pathOptions as $i => $path) {
if (!is_dir($path)) {
unset($pathOptions[$i]);
}
}
$pathOptions = array_values($pathOptions);
$max = count($pathOptions);
while (!$valid) {
foreach ($pathOptions as $i => $option) {
$this->out($i + 1 . '. ' . $option);
}
$prompt = __d('cake_console', 'Choose a plugin path from the paths above.');
$choice = $this->in($prompt, null, 1);
if (intval($choice) > 0 && intval($choice) <= $max) {
$valid = true;
}
}
$this->path = $pathOptions[$choice - 1];
}
/**
* Gets the option parser instance and configures it.
*
* @return \Cake\Console\ConsoleOptionParser
*/
public function getOptionParser() {
$parser = parent::getOptionParser();
$parser->description(__d('cake_console',
'Create the directory structure, AppController class and testing setup for a new plugin. ' .
'Can create plugins in any of your bootstrapped plugin paths.'
))->addArgument('name', [
'help' => __d('cake_console', 'CamelCased name of the plugin to create.')
]);
return $parser;
}
}