Browse Source

Start adding MacroRegistry and tests.

The MacroRegistry will allow macros to be wired into ConsoleIo in the
future.
Mark Story 11 years ago
parent
commit
5361d0cceb

+ 27 - 1
src/Console/ConsoleIo.php

@@ -16,6 +16,7 @@ namespace Cake\Console;
 
 use Cake\Console\ConsoleInput;
 use Cake\Console\ConsoleOutput;
+use Cake\Console\MacroRegistry;
 use Cake\Log\Engine\ConsoleLog;
 use Cake\Log\Log;
 
@@ -51,6 +52,13 @@ class ConsoleIo
     protected $_in;
 
     /**
+     * The macro registry.
+     *
+     * @var \Cake\Console\MacroRegistry
+     */
+    protected $_macros;
+
+    /**
      * Output constant making verbose shells.
      *
      * @var int
@@ -92,12 +100,14 @@ class ConsoleIo
      * @param \Cake\Console\ConsoleOutput|null $out A ConsoleOutput object for stdout.
      * @param \Cake\Console\ConsoleOutput|null $err A ConsoleOutput object for stderr.
      * @param \Cake\Console\ConsoleInput|null $in A ConsoleInput object for stdin.
+     * @param \Cake\Console\MacroRegistry|null $macros A MacroRegistry instance
      */
-    public function __construct(ConsoleOutput $out = null, ConsoleOutput $err = null, ConsoleInput $in = null)
+    public function __construct(ConsoleOutput $out = null, ConsoleOutput $err = null, ConsoleInput $in = null, MacroRegistry $macros = null)
     {
         $this->_out = $out ? $out : new ConsoleOutput('php://stdout');
         $this->_err = $err ? $err : new ConsoleOutput('php://stderr');
         $this->_in = $in ? $in : new ConsoleInput('php://stdin');
+        $this->_macros = $macros ? $macros : new MacroRegistry($this);
     }
 
     /**
@@ -363,4 +373,20 @@ class ConsoleIo
         ]);
         Log::config('stderr', ['engine' => $stderr]);
     }
+
+    /**
+     * Render a Console Macro
+     *
+     * Create and render the output for a macro object. If the macro
+     * object has not already been loaded, it will be loaded and constructed.
+     *
+     * This method accepts variadic arguments that are
+     *
+     * @param string $name The name of the macro to render
+     * @param array $args The arguments for the macro output.
+     * @return void
+     */
+    public function macro($name, $args)
+    {
+    }
 }

+ 25 - 0
src/Console/Exception/MissingMacroException.php

@@ -0,0 +1,25 @@
+<?php
+/**
+ * CakePHP(tm) : Rapid Development Framework (http://cakephp.org)
+ * Copyright (c) Cake Software Foundation, Inc. (http://cakefoundation.org)
+ *
+ * Licensed under The MIT License
+ * Redistributions of files must retain the above copyright notice.
+ *
+ * @copyright     Copyright (c) Cake Software Foundation, Inc. (http://cakefoundation.org)
+ * @since         3.1.0
+ * @license       http://www.opensource.org/licenses/mit-license.php MIT License
+ */
+namespace Cake\Console\Exception;
+
+use Cake\Core\Exception\Exception;
+
+/**
+ * Used when a Macro cannot be found.
+ *
+ */
+class MissingMacroException extends Exception
+{
+
+    protected $_messageTemplate = 'Macro class %s could not be found.';
+}

+ 40 - 0
src/Console/Macro.php

@@ -0,0 +1,40 @@
+<?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.1.0
+ * @license       http://www.opensource.org/licenses/mit-license.php MIT License
+ */
+namespace Cake\Console;
+
+use Cake\Console\ConsoleIo;
+
+/**
+ * Base class for Macros.
+ *
+ * Console Macros allow you to package up reusable blocks
+ * of Console output logic. For example creating tables,
+ * progress bars or ascii art.
+ */
+abstract class Macro
+{
+    public function __construct(ConsoleIo $io)
+    {
+        $this->_io = $io;
+    }
+
+    /**
+     * This method should output content using `$this->_io`.
+     *
+     * @param array $args The arguments for the macro.
+     * @return void
+     */
+    abstract public function output($args);
+}

+ 91 - 0
src/Console/MacroRegistry.php

@@ -0,0 +1,91 @@
+<?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.1.0
+ * @license       http://www.opensource.org/licenses/mit-license.php MIT License
+ */
+namespace Cake\Console;
+
+use Cake\Console\Exception\MissingMacroException;
+use Cake\Core\App;
+use Cake\Core\ObjectRegistry;
+use Cake\Console\ConsoleIo;
+
+/**
+ * Registry for Macros. Provides features
+ * for lazily loading macros.
+ */
+class MacroRegistry extends ObjectRegistry
+{
+
+    /**
+     * Shell to use to set params to tasks.
+     *
+     * @var \Cake\Console\ConsoleIo
+     */
+    protected $_io;
+
+    /**
+     * Constructor
+     *
+     * @param Shell $Shell Shell instance
+     */
+    public function __construct(ConsoleIo $io)
+    {
+        $this->_io = $io;
+    }
+
+    /**
+     * Resolve a macro classname.
+     *
+     * Part of the template method for Cake\Core\ObjectRegistry::load()
+     *
+     * @param string $class Partial classname to resolve.
+     * @return string|false Either the correct classname or false.
+     */
+    protected function _resolveClassName($class)
+    {
+        return App::className($class, 'Shell/Macro', 'Macro');
+    }
+
+    /**
+     * Throws an exception when a macro is missing.
+     *
+     * Part of the template method for Cake\Core\ObjectRegistry::load()
+     *
+     * @param string $class The classname that is missing.
+     * @param string $plugin The plugin the macro is missing in.
+     * @return void
+     * @throws \Cake\Console\Exception\MissingMacroException
+     */
+    protected function _throwMissingClassError($class, $plugin)
+    {
+        throw new MissingMacroException([
+            'class' => $class,
+            'plugin' => $plugin
+        ]);
+    }
+
+    /**
+     * Create the macro instance.
+     *
+     * Part of the template method for Cake\Core\ObjectRegistry::load()
+     *
+     * @param string $class The classname to create.
+     * @param string $alias The alias of the macro.
+     * @param array $settings An array of settings to use for the macro.
+     * @return \Cake\Console\Macro The constructed macro class.
+     */
+    protected function _create($class, $alias, $settings)
+    {
+        return new $class($this->_io);
+    }
+}

+ 102 - 0
tests/TestCase/Console/MacroRegistryTest.php

@@ -0,0 +1,102 @@
+<?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://book.cakephp.org/2.0/en/development/testing.html CakePHP(tm) Tests
+ * @since         3.1.0
+ * @license       http://www.opensource.org/licenses/mit-license.php MIT License
+ */
+namespace Cake\Test\TestCase\Console;
+
+use Cake\Console\MacroRegistry;
+use Cake\Core\Configure;
+use Cake\Core\Plugin;
+use Cake\TestSuite\TestCase;
+
+/**
+ * Class MacroRegistryTest
+ *
+ */
+class MacroRegistryTest extends TestCase
+{
+
+    /**
+     * setUp
+     *
+     * @return void
+     */
+    public function setUp()
+    {
+        parent::setUp();
+        Configure::write('App.namespace', 'TestApp');
+        $io = $this->getMock('Cake\Console\ConsoleIo', [], [], '', false);
+        $this->macros = new MacroRegistry($io);
+    }
+
+    /**
+     * tearDown
+     *
+     * @return void
+     */
+    public function tearDown()
+    {
+        unset($this->macros);
+        parent::tearDown();
+    }
+
+    /**
+     * test triggering callbacks on loaded tasks
+     *
+     * @return void
+     */
+    public function testLoad()
+    {
+        $result = $this->macros->load('Simple');
+        $this->assertInstanceOf('TestApp\Shell\Macro\SimpleMacro', $result);
+        $this->assertInstanceOf('TestApp\Shell\Macro\SimpleMacro', $this->macros->Simple);
+
+        $result = $this->macros->loaded();
+        $this->assertEquals(['Simple'], $result, 'loaded() results are wrong.');
+    }
+
+    /**
+     * test missingtask exception
+     *
+     * @expectedException \Cake\Console\Exception\MissingMacroException
+     * @return void
+     */
+    public function testLoadMissingMacro()
+    {
+        $this->macros->load('ThisTaskShouldAlwaysBeMissing');
+    }
+
+    /**
+     * Tests loading as an alias
+     *
+     * @return void
+     */
+    public function testLoadWithAlias()
+    {
+        Plugin::load('TestPlugin');
+
+        $result = $this->macros->load('SimpleAliased', ['className' => 'Simple']);
+        $this->assertInstanceOf('TestApp\Shell\Macro\SimpleMacro', $result);
+        $this->assertInstanceOf('TestApp\Shell\Macro\SimpleMacro', $this->macros->SimpleAliased);
+
+        $result = $this->macros->loaded();
+        $this->assertEquals(['SimpleAliased'], $result, 'loaded() results are wrong.');
+
+        $result = $this->macros->load('SomeMacro', ['className' => 'TestPlugin.Example']);
+        $this->assertInstanceOf('TestPlugin\Shell\Macro\ExampleMacro', $result);
+        $this->assertInstanceOf('TestPlugin\Shell\Macro\ExampleMacro', $this->macros->SomeMacro);
+
+        $result = $this->macros->loaded();
+        $this->assertEquals(['SimpleAliased', 'SomeMacro'], $result, 'loaded() results are wrong.');
+    }
+}

+ 12 - 0
tests/test_app/Plugin/TestPlugin/src/Shell/Macro/ExampleMacro.php

@@ -0,0 +1,12 @@
+<?php
+namespace TestPlugin\Shell\Macro;
+
+use Cake\Console\Macro;
+
+class ExampleMacro extends Macro
+{
+    public function output($args)
+    {
+        $this->_io->out('Plugins work!');
+    }
+}

+ 12 - 0
tests/test_app/TestApp/Shell/Macro/SimpleMacro.php

@@ -0,0 +1,12 @@
+<?php
+namespace TestApp\Shell\Macro;
+
+use Cake\Console\Macro;
+
+class SimpleMacro extends Macro
+{
+    public function output($args)
+    {
+        $this->_io->out('It works!');
+    }
+}