Browse Source

Added plugin shell: load and unload

Bob 11 years ago
parent
commit
fec52c9220

+ 62 - 0
src/Shell/PluginShell.php

@@ -0,0 +1,62 @@
+<?php
+/**
+ * CakePHP(tm) : Rapid Development Framework (http://cakephp.org)
+ * Copyright (c) Cake Software Foundation, Inc. (http://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. (http://cakefoundation.org)
+ * @link          http://cakephp.org CakePHP(tm) Project
+ * @since         3.0.0
+ * @license       http://www.opensource.org/licenses/mit-license.php MIT License
+ * @author        Bob Mulder <bobmulder@outlook.com>
+ */
+
+namespace Cake\Shell;
+
+use Cake\Console\Shell;
+
+/**
+ * Shell for tasks related to plugins.
+ *
+ */
+class PluginShell extends Shell
+{
+    /**
+     * Tasks to load
+     *
+     * @var array
+     */
+    public $tasks = [
+        'Load',
+        'Unload',
+    ];
+
+    /**
+     * Gets the option parser instance and configures it.
+     *
+     * @return \Cake\Console\ConsoleOptionParser
+     */
+    public function getOptionParser()
+    {
+        $parser = parent::getOptionParser();
+        $parser->addSubcommand(
+            'load',
+            [
+            'help' => 'Loads a plugin',
+            'parser' => $this->Load->getOptionParser(),
+            ]
+        );
+        $parser->addSubcommand(
+            'unload',
+            [
+            'help' => 'Unloads a plugin',
+            'parser' => $this->Unload->getOptionParser(),
+            ]
+        );
+
+        return $parser;
+    }
+}

+ 116 - 0
src/Shell/Task/LoadTask.php

@@ -0,0 +1,116 @@
+<?php
+/**
+ * CakePHP(tm) : Rapid Development Framework (http://cakephp.org)
+ * Copyright (c) Cake Software Foundation, Inc. (http://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. (http://cakefoundation.org)
+ * @link          http://cakephp.org CakePHP(tm) Project
+ * @since         3.0.0
+ * @license       http://www.opensource.org/licenses/mit-license.php MIT License
+ * @author        Bob Mulder <bobmulder@outlook.com>
+ */
+
+namespace Cake\Shell\Task;
+
+use Cake\Console\Shell;
+use Cake\Core\App;
+use Cake\Filesystem\File;
+
+/**
+ * Task for loading plugins.
+ *
+ */
+class LoadTask extends Shell
+{
+
+    public $path = null;
+    public $bootstrap = null;
+
+    /**
+     * Execution method always used for tasks
+     *
+     * @return boolean if action passed
+     *
+     */
+    public function main($plugin = null)
+    {
+
+        $this->path = current(App::path('Plugin'));
+        $this->bootstrap = ROOT . DS . 'config' . DS . 'bootstrap.php';
+
+        if (empty($plugin)) {
+            $this->err('<error>You must provide a plugin name in CamelCase format.</error>');
+            $this->err('To load an "Example" plugin, run <info>`cake plugin load Example`</info>.');
+            return false;
+        }
+
+
+        $write = $this->_modifyBootstrap($plugin, $this->params['bootstrap'], $this->params['routes'], false);
+
+        if ($write) {
+            return true;
+        }
+
+        return false;
+    }
+
+    /**
+     * Update the applications bootstrap.php file.
+     *
+     * @param string $plugin Name of plugin
+     * @param bool $hasAutoloader Whether or not there is an autoloader configured for
+     * the plugin
+     * @return void
+     */
+    protected function _modifyBootstrap($plugin, $hasBootstrap, $hasRoutes, $hasAutoloader)
+    {
+        $bootstrap = new File($this->bootstrap, false);
+        $contents = $bootstrap->read();
+        if (!preg_match("@\n\s*Plugin::loadAll@", $contents)) {
+            $autoload = $hasAutoloader ? null : "'autoload' => true, ";
+            $bootstrap->append(sprintf(
+                "\nPlugin::load('%s', [%s'bootstrap' => " . ($hasBootstrap ? 'true' : 'false') . ", 'routes' => " . ($hasRoutes ? 'true' : 'false') . "]);\n",
+                $plugin,
+                $autoload
+            ));
+            $this->out('');
+            $this->out(sprintf('%s modified', $this->bootstrap));
+            return true;
+        }
+        return false;
+    }
+
+    /**
+     * GetOptionParser method.
+     *
+     * @return type
+     */
+    public function getOptionParser()
+    {
+        $parser = parent::getOptionParser();
+
+        $parser->addOption('bootstrap', [
+            'short'   => 'b',
+            'help'    => 'Will load bootstrap.php from plugin.',
+            'boolean' => true,
+            'default' => false,
+        ]);
+
+        $parser->addOption('routes', [
+            'short'   => 'r',
+            'help'    => 'Will load routes.php from plugin.',
+            'boolean' => true,
+            'default' => false,
+        ]);
+
+        $parser->addArgument('plugin', [
+            'help' => 'Name of the plugin to load.',
+        ]);
+
+        return $parser;
+    }
+}

+ 108 - 0
src/Shell/Task/UnloadTask.php

@@ -0,0 +1,108 @@
+<?php
+/**
+ * CakePHP(tm) : Rapid Development Framework (http://cakephp.org)
+ * Copyright (c) Cake Software Foundation, Inc. (http://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. (http://cakefoundation.org)
+ * @link          http://cakephp.org CakePHP(tm) Project
+ * @since         3.0.0
+ * @license       http://www.opensource.org/licenses/mit-license.php MIT License
+ * @author        Bob Mulder <bobmulder@outlook.com>
+ */
+
+namespace Cake\Shell\Task;
+
+use Cake\Console\Shell;
+use Cake\Core\App;
+use Cake\Filesystem\File;
+
+/**
+ * Task for unloading plugins.
+ *
+ */
+class UnloadTask extends Shell
+{
+    public $path      = null;
+    public $bootstrap = null;
+
+    /**
+     * Execution method always used for tasks
+     *
+     * @return boolean if action passed
+     *
+     */
+    public function main($plugin = null)
+    {
+
+        $this->path      = current(App::path('Plugin'));
+        $this->bootstrap = ROOT.DS.'config'.DS.'bootstrap.php';
+
+        if (empty($plugin)) {
+            $this->err('<error>You must provide a plugin name in CamelCase format.</error>');
+            $this->err('To unload an "Example" plugin, run <info>`cake plugin unload Example`</info>.');
+            return false;
+        }
+
+
+        $write = $this->_modifyBootstrap($plugin);
+
+        if ($write) {
+            return true;
+        }
+
+        return false;
+    }
+
+    /**
+     * Update the applications bootstrap.php file.
+     *
+     * @param string $plugin Name of plugin
+     * @param bool $hasAutoloader Whether or not there is an autoloader configured for
+     * the plugin
+     * @return void
+     */
+    protected function _modifyBootstrap($plugin)
+    {
+        $finder = "Plugin::load('".$plugin."',";
+
+        $bootstrap = new File($this->bootstrap, false);
+        $contents  = $bootstrap->read();
+        if (!preg_match("@\n\s*Plugin::loadAll@", $contents)) {
+            $_contents = explode("\n", $contents);
+
+            foreach ($_contents as $content) {
+                if (strpos($content, $finder) !== false) {
+                    $loadString = $content;
+                    $loadString .= "\n";
+
+                    $bootstrap->replaceText(sprintf($loadString), null);
+                }
+            }
+
+            $this->out('');
+            $this->out(sprintf('%s modified', $this->bootstrap));
+            return true;
+        }
+        return false;
+    }
+
+    /**
+     * GetOptionParser method.
+     *
+     * @return type
+     */
+    public function getOptionParser()
+    {
+        $parser = parent::getOptionParser();
+
+        $parser->addArgument('plugin', [
+            'help' => 'Name of the plugin to load.',
+        ]);
+
+        return $parser;
+    }
+}

+ 151 - 0
tests/TestCase/Shell/Task/LoadTaskTest.php

@@ -0,0 +1,151 @@
+<?php
+/**
+ * CakePHP :  Rapid Development Framework (http://cakephp.org)
+ * Copyright (c) Cake Software Foundation, Inc. (http://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. (http://cakefoundation.org)
+ * @link          http://cakephp.org CakePHP Project
+ * @since         1.2.0
+ * @license       http://www.opensource.org/licenses/mit-license.php MIT License
+ */
+
+namespace Cake\Test\TestCase\Shell\Task;
+
+use Cake\Core\Plugin;
+use Cake\TestSuite\TestCase;
+use Cake\Filesystem\File;
+
+/**
+ * LoadTaskTest class
+ *
+ */
+class LoadTaskTest extends TestCase
+{
+
+    /**
+     * setUp method
+     *
+     * @return void
+     */
+    public function setUp()
+    {
+        parent::setUp();
+
+        $this->io = $this->getMock('Cake\Console\ConsoleIo', [], [], '', false);
+
+        $this->Task = $this->getMock(
+                'Cake\Shell\Task\LoadTask', ['in', 'out', 'err', '_stop'], [$this->io]
+        );
+
+        $this->bootstrap = ROOT . DS . 'config' . DS . 'bootstrap.php';
+
+        $bootstrap = new File($this->bootstrap, false);
+
+        $this->original_bootstrap_content = $bootstrap->read();
+    }
+
+    /**
+     * tearDown method
+     *
+     * @return void
+     */
+    public function tearDown()
+    {
+        parent::tearDown();
+        unset($this->shell);
+        Plugin::unload();
+
+        $bootstrap = new File($this->bootstrap, false);
+
+        $bootstrap->write($this->original_bootstrap_content);
+    }
+
+    /**
+     * testLoad
+     *
+     * @return void
+     */
+    public function testLoad()
+    {
+        $this->Task->params = [
+            'bootstrap' => false,
+            'routes'    => false,
+        ];
+
+        $action = $this->Task->main('TestPlugin');
+
+        $this->assertTrue($action);
+
+        $expected = "Plugin::load('TestPlugin', ['autoload' => true, 'bootstrap' => false, 'routes' => false]);";
+        $bootstrap = new File($this->bootstrap, false);
+        $this->assertContains($expected, $bootstrap->read());
+    }
+
+    /**
+     * testLoadWithBootstrap
+     *
+     * @return void
+     */
+    public function testLoadWithBootstrap()
+    {
+        $this->Task->params = [
+            'bootstrap' => true,
+            'routes'    => false,
+        ];
+
+        $action = $this->Task->main('TestPlugin');
+
+        $this->assertTrue($action);
+
+        $expected = "Plugin::load('TestPlugin', ['autoload' => true, 'bootstrap' => true, 'routes' => false]);";
+        $bootstrap = new File($this->bootstrap, false);
+        $this->assertContains($expected, $bootstrap->read());
+    }
+
+    /**
+     * testLoadWithRoutes
+     *
+     * @return void
+     */
+    public function testLoadWithRoutes()
+    {
+        $this->Task->params = [
+            'bootstrap' => false,
+            'routes'    => true,
+        ];
+
+        $action = $this->Task->main('TestPlugin');
+
+        $this->assertTrue($action);
+
+        $expected = "Plugin::load('TestPlugin', ['autoload' => true, 'bootstrap' => false, 'routes' => true]);";
+        $bootstrap = new File($this->bootstrap, false);
+        $this->assertContains($expected, $bootstrap->read());
+    }
+
+    /**
+     * testLoadNoName
+     *
+     * @return void
+     */
+    public function testLoadNoName()
+    {
+        $this->Task->params = [
+            'bootstrap' => false,
+            'routes'    => true,
+        ];
+
+        $action = $this->Task->main();
+
+        $this->assertFalse($action);
+
+        $expected = "Plugin::load(";
+        $bootstrap = new File($this->bootstrap, false);
+        $this->assertNotContains($expected, $bootstrap->read());
+    }
+
+}

+ 117 - 0
tests/TestCase/Shell/Task/UnloadTaskTest.php

@@ -0,0 +1,117 @@
+<?php
+/**
+ * CakePHP :  Rapid Development Framework (http://cakephp.org)
+ * Copyright (c) Cake Software Foundation, Inc. (http://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. (http://cakefoundation.org)
+ * @link          http://cakephp.org CakePHP Project
+ * @since         1.2.0
+ * @license       http://www.opensource.org/licenses/mit-license.php MIT License
+ */
+
+namespace Cake\Test\TestCase\Shell\Task;
+
+use Cake\Core\Plugin;
+use Cake\TestSuite\TestCase;
+use Cake\Filesystem\File;
+
+/**
+ * UnloadTaskTest class
+ *
+ */
+class UnloadTaskTest extends TestCase
+{
+
+    /**
+     * setUp method
+     *
+     * @return void
+     */
+    public function setUp()
+    {
+        parent::setUp();
+
+        $this->io = $this->getMock('Cake\Console\ConsoleIo', [], [], '', false);
+
+        $this->Task = $this->getMock(
+                'Cake\Shell\Task\UnloadTask', ['in', 'out', 'err', '_stop'], [$this->io]
+        );
+
+        $this->bootstrap = ROOT . DS . 'config' . DS . 'bootstrap.php';
+
+        $bootstrap = new File($this->bootstrap, false);
+
+        $this->original_bootstrap_content = $bootstrap->read();
+    }
+
+    /**
+     * tearDown method
+     *
+     * @return void
+     */
+    public function tearDown()
+    {
+        parent::tearDown();
+        unset($this->shell);
+        Plugin::unload();
+
+        $bootstrap = new File($this->bootstrap, false);
+
+        $bootstrap->write($this->original_bootstrap_content);
+    }
+
+    /**
+     * testUnload
+     *
+     * @return void
+     */
+    public function testUnload()
+    {
+        $bootstrap = new File($this->bootstrap, false);
+
+        $this->_addPluginToBootstrap("TestPlugin");
+
+        $expected = "Plugin::load('TestPlugin', ['autoload' => true, 'bootstrap' => false, 'routes' => false]);";
+        $this->assertContains($expected, $bootstrap->read());
+
+        $action = $this->Task->main('TestPlugin');
+
+        $this->assertTrue($action);
+
+        $expected = "Plugin::load('TestPlugin', ['autoload' => true, 'bootstrap' => false, 'routes' => false]);";
+        $this->assertNotContains($expected, $bootstrap->read());
+    }
+
+    /**
+     * testUnloadNoName
+     *
+     * @return void
+     */
+    public function testUnloadNoName()
+    {
+        $bootstrap = new File($this->bootstrap, false);
+
+        $action = $this->Task->main();
+
+        $this->assertFalse($action);
+    }
+
+    /**
+     * _addPluginToBootstrap
+     *
+     * Quick method to add a plugin to the bootstrap file.
+     * This is useful for the tests
+     *
+     * @param string $name
+     */
+    protected function _addPluginToBootstrap($name)
+    {
+        $bootstrap = new File($this->bootstrap, false);
+        $bootstrap->append("Plugin::load('" . $name . "', ['autoload' => true, 'bootstrap' => false, 'routes' => false]);\n");
+    }
+
+}