Skip to content

HTTPS clone URL

Subversion checkout URL

You can clone with
or
.
Download ZIP

Comparing changes

Choose two branches to see what’s changed or to start a new pull request. If you need to, you can also compare across forks.

Open a pull request

Create a new pull request by comparing changes across two branches. If you need to, you can also compare across forks.
base fork: UnionOfRAD/lithium
...
head fork: UnionOfRAD/lithium
Checking mergeability… Don’t worry, you can still create the pull request.
  • 3 commits
  • 5 files changed
  • 0 commit comments
  • 1 contributor
View
83 console/command/Create.php
@@ -11,6 +11,7 @@
use lithium\util\String;
use lithium\core\Libraries;
use lithium\util\Inflector;
+use lithium\analysis\Inspector;
use lithium\core\ClassNotFoundException;
/**
@@ -39,6 +40,14 @@ class Create extends \lithium\console\Command {
public $template = null;
/**
+ * Specifies the service location path of the sub-commands used to generate classes or other
+ * files. Defaults to `'command.create'`.
+ *
+ * @var string
+ */
+ public $commandPath = 'command.create';
+
+ /**
* Holds library data from `lithium\core\Libraries::get()`.
*
* @var array
@@ -46,6 +55,25 @@ class Create extends \lithium\console\Command {
protected $_library = array();
/**
+ * Contains the list of `Create` sub-commands.
+ *
+ * @var array
+ */
+ protected $_commands = array();
+
+ /**
+ * List of commands to run when executing against a name rather than a command.
+ *
+ * @var array
+ */
+ protected $_defaultCommands = array(
+ array('model'),
+ array('controller'),
+ array('test', 'model'),
+ array('test', 'controller')
+ );
+
+ /**
* Class initializer. Parses template and sets up params that need to be filled.
*
* @return void
@@ -55,16 +83,26 @@ protected function _init() {
$this->library = $this->library ?: true;
$defaults = array('prefix' => null, 'path' => null);
$this->_library = (array) Libraries::get($this->library) + $defaults;
+ $commands = Libraries::locate($this->commandPath);
+
+ $map = function($cmd) {
+ return str_replace('_', '-', Inflector::underscore(
+ substr($cmd, strrpos($cmd, '\\') + 1)
+ ));
+ };
+ $this->_commands = array_combine($commands, array_map($map, $commands));
}
/**
* Run the create command. Takes `$command` and delegates to `$command::$method`
*
- * @param string $command
+ * @param string $command The name of the command to run, which specifies what type of file to
+ * generate. Available options can be determined by running the `generators`
+ * command.
* @return boolean
*/
public function run($command = null) {
- if ($command && !$this->request->args()) {
+ if ($command && !in_array($command, $this->_commands) && !$this->request->args()) {
return $this->_default($command);
}
$this->request->shift();
@@ -81,6 +119,35 @@ public function run($command = null) {
}
/**
+ * Lists the available generator commands that can be used to produce stub classes and files.
+ *
+ * @return boolean
+ */
+ public function generators() {
+ $this->out('');
+ $this->out('Available console generators:');
+ $this->out('');
+
+ foreach ($this->_commands as $class => $title) {
+ $this->out("- {$title}");
+ $info = Inspector::info($class);
+
+ if ($info['description']) {
+ $this->out($info['description']);
+ }
+ if ($info['description'] && $info['text']) {
+ $this->out('');
+ }
+ if ($info['text']) {
+ $this->out($info['text']);
+ }
+ $this->out('');
+ $this->out('');
+ }
+ return true;
+ }
+
+ /**
* Execute the given sub-command for the current request.
*
* @param string $command The sub-command name. example: Model, Controller, Test
@@ -115,13 +182,9 @@ protected function _execute($command) {
* @return boolean
*/
protected function _default($name) {
- $commands = array(
- array('model', $name),
- array('controller', $name),
- array('test', 'model', $name),
- array('test', 'controller', $name)
- );
- foreach ($commands as $args) {
+ foreach ($this->_defaultCommands as $args) {
+ array_push($args, Inflector::pluralize($name));
+
$command = $this->template = $this->request->params['command'] = array_shift($args);
$this->request->params['action'] = array_shift($args);
$this->request->params['args'] = $args;
@@ -140,7 +203,7 @@ protected function _default($name) {
* @param array $options
* @return string
*/
- protected function _namespace($request, $options = array()) {
+ protected function _namespace($request, $options = array()) {
$name = $request->command;
$defaults = array(
'prefix' => $this->_library['prefix'],
View
179 console/command/create/Adapter.php
@@ -0,0 +1,179 @@
+<?php
+/**
+ * Lithium: the most rad php framework
+ *
+ * @copyright Copyright 2012, Union of RAD (http://union-of-rad.org)
+ * @license http://opensource.org/licenses/bsd-license.php The BSD License
+ */
+
+namespace lithium\console\command\create;
+
+use RuntimeException;
+use lithium\util\String;
+use lithium\util\Inflector;
+use lithium\core\Libraries;
+use lithium\analysis\Inspector;
+
+/**
+ * Generate an adapter class in the `--library` namespace, according to the `--type` specified.
+ */
+class Adapter extends \lithium\console\command\Create {
+
+ /**
+ * The class to create an adapter for. Can be a short class name, i.e. `Cache`, or a
+ * fully-qualified class name, i.e. `lithium\storage\Session`. The class must have an
+ * `$_adapters` property defined, and may also have a custom class type registered with
+ * `Libraries::paths()`.
+ *
+ * @see lithium\core\Adaptable::$_adapters
+ * @see lithium\core\Libraries::paths()
+ * @var string
+ */
+ public $type;
+
+ /**
+ * The base class that the generated adapter should extend.
+ *
+ * @var string
+ */
+ public $parent = '\lithium\core\Object';
+
+ protected $_methodDef = "\tpublic function {:name}({:params}) {\n\t\t\n\t}";
+
+ protected $_methodDefEnabled = "\tpublic static function enabled() {\n\t\t\n\t}";
+
+ protected $_typeClass;
+
+ protected function _init() {
+ parent::_init();
+
+ $findOptions = array(
+ 'recursive' => true,
+ 'filter' => '/' . preg_quote($this->type, '/') . '/',
+ 'exclude' => '/Mock|Test|\\\\adapter\\\\/i'
+ );
+
+ switch (true) {
+ case (class_exists($this->type)):
+ $this->_typeClass = $this->type;
+ break;
+ case (($located = Libraries::find(true, $findOptions)) && count($located) == 1):
+ $this->_typeClass = reset($located);
+ break;
+ case ($located && count($located) > 1):
+ $this->out("Multiple matches found for '{$this->type}'");
+
+ foreach ($located as $i => $class) {
+ $i++;
+ $this->out("$i) {$class}");
+ }
+ $located = $located[intval($this->in('Please select one:')) - 1];
+ break;
+ default:
+ $msg = "Unabled to find class for which to generate adapter. Please use the ";
+ $msg .= "--type flag to specify a fully-qualified class name.";
+ throw new RuntimeException($msg);
+ }
+ }
+
+ /**
+ * Get the class name for the adapter.
+ *
+ * @param string $request
+ * @return string
+ */
+ protected function _class($request) {
+ return Inflector::camelize($request->action);
+ }
+
+ protected function _namespace($request, $options = array()) {
+ $path = explode('.', $this->_adapterPath($this->_typeClass));
+ $type = array_shift($path);
+ $paths = Libraries::paths($type);
+
+ $result = str_replace('\\\\', '\\', String::insert(reset($paths), array(
+ 'library' => $this->_library['prefix'],
+ 'namespace' => join('\\', $path),
+ 'class' => null,
+ 'name' => null
+ )));
+ return rtrim($result, '\\');
+ }
+
+ /**
+ * Gets the dot-separated adapter lookup path for the given adaptable class.
+ *
+ * @param string $class The fully-namespaced class name of the class to get the path for.
+ * @return string Returns the dot-separated service lookup path used to find adapters for the
+ * given class.
+ */
+ protected function _adapterPath($class) {
+ if (!$result = Inspector::info($class . '::$_adapters')) {
+ $msg = "Class `{$class}` is not a valid adapter-supporting class, ";
+ $msg .= "no `\$_adapters` class property found.";
+ throw new RuntimeException($msg);
+ }
+ return $result['value'];
+ }
+
+ protected function _parent($request) {
+ if (class_exists($this->parent)) {
+ return '\\' . ltrim($this->parent, '\\');
+ }
+ $result = Libraries::find(true, array(
+ 'recursive' => true,
+ 'filter' => '/' . preg_quote($this->parent, '/') . '/',
+ 'exclude' => '/Mock|Test|\\\\adapter\\\\/i'
+ ));
+ return reset($result);
+ }
+
+ protected function _methods($request) {
+ $methods = array();
+
+ Inspector::methods($this->_typeClass)->map(function($method) use (&$methods) {
+ $methods[$method->getName()] = array_map(
+ function($param) {
+ $name = '$' . $param->getName();
+
+ if (!$param->isOptional()) {
+ return $name;
+ }
+ $name .= ' = ';
+
+ switch (true) {
+ case ($param->getDefaultValue() === null):
+ $name .= 'null';
+ break;
+ case ($param->getDefaultValue() === array()):
+ $name .= 'array()';
+ break;
+ default:
+ $name .= var_export($param->getDefaultValue(), true);
+ break;
+ }
+
+ if ($name === '$options = array()' || $name === '$config = array()') {
+ $name = "array {$name}";
+ }
+ return $name;
+ },
+ $method->getParameters()
+ );
+ });
+ $result = array();
+
+ foreach ($methods as $name => $params) {
+ if (!$params || array_shift($params) !== '$name') {
+ continue;
+ }
+ $params = join(', ', $params);
+ $result[] = String::insert($this->_methodDef, compact('name', 'params'));
+ }
+ $result[] = $this->_methodDefEnabled;
+
+ return join("\n\n", $result);
+ }
+}
+
+?>
View
6 console/command/create/template/adapter.txt.php
@@ -0,0 +1,6 @@
+namespace {:namespace};
+
+class {:class} extends {:parent} {
+
+{:methods}
+}
View
16 tests/cases/console/command/HelpTest.php
@@ -172,6 +172,22 @@ public function testApiProperties() {
$result = $help->response->output;
$this->assertPattern("/{$expected}/s", $result);
}
+
+ /**
+ * Tests that the `Help` command prints a class' full description with all lines, not just the
+ * first.
+ */
+ public function testPrintFullClassDoc() {
+ $command = new Help(array(
+ 'request' => $this->request, 'classes' => $this->classes
+ ));
+
+ $this->assertTrue($command->run('Create'));
+ $lines = explode(PHP_EOL, $command->response->output);
+
+ $offset = array_search('DESCRIPTION', $lines);
+ $this->assertEqual('OPTIONS', $lines[$offset + 3]);
+ }
}
?>
View
1  tests/cases/core/LibrariesTest.php
@@ -601,6 +601,7 @@ public function testLocateCommandInLithiumRecursiveTrue() {
'lithium\console\command\Route',
'lithium\console\command\Test',
'lithium\console\command\g11n\Extract',
+ 'lithium\console\command\create\Adapter',
'lithium\console\command\create\Controller',
'lithium\console\command\create\Mock',
'lithium\console\command\create\Model',

No commit comments for this range

Something went wrong with that request. Please try again.