Skip to content

Commit

Permalink
Merge pull request #1007 from cakephp/feature/plugin-vendor
Browse files Browse the repository at this point in the history
Add `standalone-path` option for plugin commmand.
  • Loading branch information
markstory authored Oct 7, 2024
2 parents 1f1a4d0 + 04b86ae commit b6ced75
Show file tree
Hide file tree
Showing 8 changed files with 73 additions and 152 deletions.
71 changes: 54 additions & 17 deletions src/Command/PluginCommand.php
Original file line number Diff line number Diff line change
Expand Up @@ -43,6 +43,8 @@ class PluginCommand extends BakeCommand
*/
public string $path;

protected bool $isVendor = false;

/**
* initialize
*
Expand Down Expand Up @@ -73,6 +75,18 @@ public function execute(Arguments $args, ConsoleIo $io): ?int
$parts = explode('/', $name);
$plugin = implode('/', array_map([Inflector::class, 'camelize'], $parts));

if ($args->getOption('standalone-path')) {
$this->path = $args->getOption('standalone-path');
$this->path = rtrim($this->path, DIRECTORY_SEPARATOR) . DIRECTORY_SEPARATOR;
$this->isVendor = true;

if (!is_dir($this->path)) {
$io->err(sprintf('Path `%s` does not exist.', $this->path));

return static::CODE_ERROR;
}
}

$pluginPath = $this->_pluginPath($plugin);
if (is_dir($pluginPath)) {
$io->out(sprintf('Plugin: %s already exists, no action taken', $plugin));
Expand Down Expand Up @@ -115,24 +129,27 @@ public function bake(string $plugin, Arguments $args, ConsoleIo $io): ?bool
}

$this->_generateFiles($plugin, $this->path, $args, $io);
$this->_modifyApplication($plugin, $io);

$composer = $this->findComposer($args, $io);
if (!$this->isVendor) {
$this->_modifyApplication($plugin, $io);

try {
$cwd = getcwd();
$composer = $this->findComposer($args, $io);

// Windows makes running multiple commands at once hard.
chdir(dirname($this->_rootComposerFilePath()));
$command = 'php ' . escapeshellarg($composer) . ' dump-autoload';
$process = new Process($io);
$io->out($process->call($command));
try {
$cwd = getcwd();

chdir($cwd);
} catch (RuntimeException $e) {
$error = $e->getMessage();
$io->error(sprintf('Could not run `composer dump-autoload`: %s', $error));
$this->abort();
// Windows makes running multiple commands at once hard.
chdir(dirname($this->_rootComposerFilePath()));
$command = 'php ' . escapeshellarg($composer) . ' dump-autoload';
$process = new Process($io);
$io->out($process->call($command));

chdir($cwd);
} catch (RuntimeException $e) {
$error = $e->getMessage();
$io->error(sprintf('Could not run `composer dump-autoload`: %s', $error));
$this->abort();
}
}

$io->hr();
Expand Down Expand Up @@ -219,9 +236,24 @@ protected function _generateFiles(
do {
$templatesPath = array_shift($paths) . BakeView::BAKE_TEMPLATE_FOLDER . '/Plugin';
if (is_dir($templatesPath)) {
$templates = array_keys(iterator_to_array(
$files = iterator_to_array(
$fs->findRecursive($templatesPath, '/\.twig$/')
));
);

if (!$this->isVendor) {
$vendorFiles = [
'.gitignore.twig', 'README.md.twig', 'composer.json.twig', 'phpunit.xml.dist.twig',
'bootstrap.php.twig', 'schema.sql.twig',
];

foreach ($files as $key => $file) {
if (in_array($file->getFilename(), $vendorFiles, true)) {
unset($files[$key]);
}
}
}

$templates = array_keys($files);
}
} while (!$templates);

Expand Down Expand Up @@ -326,7 +358,8 @@ public function buildOptionParser(ConsoleOptionParser $parser): ConsoleOptionPar
'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' => 'CamelCased name of the plugin to create.',
'help' => 'CamelCased name of the plugin to create.'
. ' For standalone plugins you can use vendor prefixed names like MyVendor/MyPlugin.',
])->addOption('composer', [
'default' => ROOT . DS . 'composer.phar',
'help' => 'The path to the composer executable.',
Expand All @@ -339,6 +372,10 @@ public function buildOptionParser(ConsoleOptionParser $parser): ConsoleOptionPar
'help' => 'The theme to use when baking code.',
'default' => Configure::read('Bake.theme') ?: null,
'choices' => $this->_getBakeThemes(),
])
->addOption('standalone-path', [
'short' => 'p',
'help' => 'Generate a standalone plugin in the provided path.',
]);

return $parser;
Expand Down
25 changes: 19 additions & 6 deletions tests/TestCase/Command/PluginCommandTest.php
Original file line number Diff line number Diff line change
Expand Up @@ -36,6 +36,8 @@ class PluginCommandTest extends TestCase

protected $pluginsPath = TMP . 'plugin_task' . DS;

protected string $pluginsStandalonePath = TMP . 'plugin_standalone_task' . DS;

/**
* setUp method
*
Expand All @@ -55,6 +57,11 @@ public function setUp(): void
mkdir($this->pluginsPath, 0777, true);
}

// Create the test output path
if (!file_exists($this->pluginsStandalonePath)) {
mkdir($this->pluginsStandalonePath, 0777, true);
}

if (file_exists(APP . 'Application.php.bak')) {
rename(APP . 'Application.php.bak', APP . 'Application.php');
} else {
Expand All @@ -71,6 +78,7 @@ public function tearDown(): void
{
$fs = new Filesystem();
$fs->deleteDir($this->pluginsPath);
$fs->deleteDir($this->pluginsStandalonePath);

if (file_exists(APP . 'Application.php.bak')) {
rename(APP . 'Application.php.bak', APP . 'Application.php');
Expand Down Expand Up @@ -123,9 +131,9 @@ public function testMainCustomAppNamespace()
*/
public function testMainVendorName()
{
$this->exec('bake plugin Company/Example', ['y', 'n']);
$this->exec('bake plugin Company/Example --standalone-path ' . $this->pluginsStandalonePath, ['y', 'n']);
$this->assertExitCode(CommandInterface::CODE_SUCCESS);
$this->assertPluginContents('Company/Example');
$this->assertPluginContents('Company/Example', true);
}

/**
Expand All @@ -135,9 +143,9 @@ public function testMainVendorName()
*/
public function testMainVendorNameCasingFix()
{
$this->exec('bake plugin company/example', ['y', 'n']);
$this->exec('bake plugin company/example --standalone-path ' . $this->pluginsStandalonePath, ['y', 'n']);
$this->assertExitCode(CommandInterface::CODE_SUCCESS);
$this->assertPluginContents('Company/Example');
$this->assertPluginContents('Company/Example', true);
}

/**
Expand Down Expand Up @@ -231,15 +239,20 @@ public function testFindPathEmpty()
* Compare to a static copy of the plugin in the comparison folder
*
* @param string $pluginName the name of the plugin to compare to
* @param bool $vendor Whether testing a vendor plugin generation
* @return void
*/
public function assertPluginContents($pluginName)
public function assertPluginContents($pluginName, bool $vendor = false): void
{
$pluginName = str_replace('/', DS, $pluginName);
$comparisonRoot = $this->_compareBasePath . $pluginName . DS;
$comparisonFiles = $this->getFiles($comparisonRoot);

$bakedRoot = App::path('plugins')[0] . $pluginName . DS;
if ($vendor) {
$bakedRoot = $this->pluginsStandalonePath . $pluginName . DS;
} else {
$bakedRoot = App::path('plugins')[0] . $pluginName . DS;
}
$bakedFiles = $this->getFiles($bakedRoot);

$this->assertCount(
Expand Down
8 changes: 0 additions & 8 deletions tests/comparisons/Plugin/SimpleExample/.gitignore

This file was deleted.

11 changes: 0 additions & 11 deletions tests/comparisons/Plugin/SimpleExample/README.md

This file was deleted.

24 changes: 0 additions & 24 deletions tests/comparisons/Plugin/SimpleExample/composer.json

This file was deleted.

30 changes: 0 additions & 30 deletions tests/comparisons/Plugin/SimpleExample/phpunit.xml.dist

This file was deleted.

55 changes: 0 additions & 55 deletions tests/comparisons/Plugin/SimpleExample/tests/bootstrap.php

This file was deleted.

1 change: 0 additions & 1 deletion tests/comparisons/Plugin/SimpleExample/tests/schema.sql

This file was deleted.

0 comments on commit b6ced75

Please sign in to comment.