From 10271e4e9782a9dfd448d684a16fd529c45c95df Mon Sep 17 00:00:00 2001 From: Matthew Weier O'Phinney Date: Thu, 27 Sep 2012 16:08:03 -0500 Subject: [PATCH] Allow duck-typing Console provider features - Updated getConsoleUsage() to allow either using strict type of Zend\ModuleManager\Feature\ConsoleUsageProviderInterface, or duck-typing on the getConsoleUsage() method. - Updated getConsoleBanner() to allow either using strict type of Zend\ModuleManager\Feature\ConsoleBannerProviderInterface, or duck-typing on the getConsoleBanner() method. - Fixed CS issues: - trailing whitespace - missing braces on conditionals - docblocks in method bodies - Streamlined logic when possible, eliminating else and elseif conditions --- .../View/Console/RouteNotFoundStrategy.php | 197 ++++++++++-------- 1 file changed, 109 insertions(+), 88 deletions(-) diff --git a/library/Zend/Mvc/View/Console/RouteNotFoundStrategy.php b/library/Zend/Mvc/View/Console/RouteNotFoundStrategy.php index 292617b3ae0..518d7768f2a 100644 --- a/library/Zend/Mvc/View/Console/RouteNotFoundStrategy.php +++ b/library/Zend/Mvc/View/Console/RouteNotFoundStrategy.php @@ -27,6 +27,7 @@ use Zend\View\Model\ConsoleModel; use Zend\Version\Version; use Zend\Stdlib\ResponseInterface as Response; +use Zend\Text\Table; /** * @category Zend @@ -92,7 +93,7 @@ public function handleRouteNotFoundError(MvcEvent $e) } $response = $e->getResponse(); - $request = $e->getRequest(); + $request = $e->getRequest(); switch ($error) { case Application::ERROR_CONTROLLER_NOT_FOUND: @@ -123,11 +124,11 @@ public function handleRouteNotFoundError(MvcEvent $e) $sm = $e->getApplication()->getServiceManager(); // Try to fetch module manager + $mm = null; try{ $mm = $sm->get('ModuleManager'); } catch (ServiceNotFoundException $e) { // The application does not have or use module manager, so we cannot use it - $mm = null; } // Try to fetch current console adapter @@ -142,18 +143,17 @@ public function handleRouteNotFoundError(MvcEvent $e) } // Try to fetch router + $router = null; try{ $router = $sm->get('Router'); } catch (ServiceNotFoundException $e) { // The application does not have a router - $router = null; } // Retrieve the script's name (entry point) + $scriptName = ''; if ($request instanceof ConsoleRequest) { $scriptName = basename($request->getScriptName()); - } else { - $scriptName = ''; } // Get application banner @@ -163,8 +163,9 @@ public function handleRouteNotFoundError(MvcEvent $e) $usage = $this->getConsoleUsage($console, $scriptName, $mm, $router); // Inject the text into view model - $result = $banner ? rtrim($banner,"\r\n") : ''; - $result .= $usage ? "\n\n" . trim($usage,"\r\n") : ''; + $result = $banner ? rtrim($banner, "\r\n") : ''; + $result .= $usage ? "\n\n" . trim($usage, "\r\n") : ''; + $result .= "\n"; // to ensure we output a final newline $model->setResult($result); // Inject the result into MvcEvent @@ -181,32 +182,35 @@ public function handleRouteNotFoundError(MvcEvent $e) */ protected function getConsoleBanner(ConsoleAdapter $console, ModuleManagerInterface $moduleManager = null) { - /** + /* * Loop through all loaded modules and collect banners */ $banners = array(); if ($moduleManager !== null) { foreach ($moduleManager->getLoadedModules(false) as $module) { - if (!$module instanceof ConsoleBannerProviderInterface) { + // Strict-type on ConsoleBannerProviderInterface, or duck-type + // on the method it defines + if (!$module instanceof ConsoleBannerProviderInterface + && !method_exists($module, 'getConsoleBanner') + ) { continue; // this module does not provide a banner } - /* @var $module ConsoleBannerProviderInterface */ $banners[] = $module->getConsoleBanner($console); } } - /** + /* * Handle an application with no defined banners */ if (!count($banners)) { - return "Zend Framework " . Version::VERSION . " application.\nUsage:\n"; + return sprintf("Zend Framework %s application\nUsage:\n", Version::VERSION); } - /** + /* * Join the banners by a newline character */ - return join("\n", $banners); + return implode("\n", $banners); } /** @@ -223,29 +227,33 @@ protected function getConsoleUsage( $scriptName, ModuleManagerInterface $moduleManager = null ) { - /** + /* * Loop through all loaded modules and collect usage info */ $usageInfo = array(); if ($moduleManager !== null) { foreach ($moduleManager->getLoadedModules(false) as $name => $module) { - if (!$module instanceof ConsoleUsageProviderInterface) { + // Strict-type on ConsoleUsageProviderInterface, or duck-type + // on the method it defines + if (!$module instanceof ConsoleUsageProviderInterface + && !method_exists($module, 'getConsoleUsage') + ) { continue; // this module does not provide usage info } - /* @var $module ConsoleUsageProviderInterface */ $usage = $module->getConsoleUsage($console); // Normalize what we got from the module or discard - if (is_array($usage)) + if (is_array($usage)) { $usageInfo[$name] = $usage; - elseif (is_string($usage)) + } elseif (is_string($usage)) { $usageInfo[$name] = array($usage); + } } } - /** + /* * Handle an application with no usage information */ if (!count($usageInfo)) { @@ -253,71 +261,81 @@ protected function getConsoleUsage( return ''; } - /** + /* * Transform arrays in usage info into columns, otherwise join everything together */ - $result = ''; - $table = false; + $result = ''; + $table = false; $tableCols = 0; $tableType = 0; foreach ($usageInfo as $moduleName => $usage) { + if (!is_string($usage) && !is_array($usage)) { + throw new RuntimeException(sprintf( + 'Cannot understand usage info for module "%s"', + $moduleName + )); + } + if (is_string($usage)) { // It's a plain string - output as is $result .= $usage . "\n"; - } elseif (is_array($usage)) { - // It's an array, analyze it - foreach ($usage as $a => $b) { - if (is_string($a) && is_string($b)) { - /** - * 'ivocation method' => 'explanation' - */ - if (($tableCols !== 2 || $tableType != 1) && $table !== false) { - // render last table - $result .= $this->renderTable($table, $tableCols, $console->getWidth()); - $table = false; - - // add extra newline for clarity - $result .= "\n"; - } - - $tableCols = 2; - $tableType = 1; - $table[] = array($scriptName . ' ' . $a, $b); - } elseif (is_array($b)) { - /** - * array( '--param', '--explanation' ) - */ - if ((count($b) != $tableCols || $tableType != 2) && $table !== false) { - // render last table - $result .= $this->renderTable($table, $tableCols, $console->getWidth()); - $table = false; - - // add extra newline for clarity - $result .= "\n"; - } - - $tableCols = count($b); - $tableType = 2; - $table[] = $b; - } else { - /** - * 'A single line of text' - */ - if ($table !== false) { - // render last table - $result .= $this->renderTable($table, $tableCols, $console->getWidth()); - $table = false; + continue; + } + + // It's an array, analyze it + foreach ($usage as $a => $b) { + /* + * 'invocation method' => 'explanation' + */ + if (is_string($a) && is_string($b)) { + if (($tableCols !== 2 || $tableType != 1) && $table !== false) { + // render last table + $result .= $this->renderTable($table, $tableCols, $console->getWidth()); + $table = false; // add extra newline for clarity - $result .= "\n"; - } + $result .= "\n"; + } + + $tableCols = 2; + $tableType = 1; + $table[] = array($scriptName . ' ' . $a, $b); + continue; + } - $tableType = 0; - $result .= $b . "\n"; + /* + * array('--param', '--explanation') + */ + if (is_array($b)) { + if ((count($b) != $tableCols || $tableType != 2) && $table !== false) { + // render last table + $result .= $this->renderTable($table, $tableCols, $console->getWidth()); + $table = false; + + // add extra newline for clarity + $result .= "\n"; } + + $tableCols = count($b); + $tableType = 2; + $table[] = $b; + continue; } - } else { - throw new RuntimeException('Cannot understand usage info for module ' . $moduleName); + + /* + * 'A single line of text' + */ + if ($table !== false) { + // render last table + $result .= $this->renderTable($table, $tableCols, $console->getWidth()); + $table = false; + + // add extra newline for clarity + $result .= "\n"; + } + + $tableType = 0; + $result .= $b . "\n"; } } @@ -332,14 +350,14 @@ protected function getConsoleUsage( /** * Render a text table containing the data provided, that will fit inside console window's width. * - * @param $data - * @param $cols - * @param $consoleWidth + * @param $data + * @param $cols + * @param $consoleWidth * @return string */ protected function renderTable($data, $cols, $consoleWidth) { - $result = ''; + $result = ''; $padding = 2; // If there is only 1 column, just concatenate it @@ -352,37 +370,40 @@ protected function renderTable($data, $cols, $consoleWidth) // Determine max width for each column $maxW = array(); - for ($x=1;$x<=$cols;$x++) { + for ($x = 1; $x <= $cols; $x += 1) { $maxW[$x] = 0; foreach ($data as $row) { - $maxW[$x] = max($maxW[$x], mb_strlen($row[$x-1],'utf-8') + $padding*2); + $maxW[$x] = max($maxW[$x], mb_strlen($row[$x-1],'utf-8') + $padding * 2); } } - /** - * Check if the sum of x-1 columns fit inside console window width - 10 chars. If columns do not fit inside - * console window, then we'll just concatenate them and output as is. + /* + * Check if the sum of x-1 columns fit inside console window width - 10 + * chars. If columns do not fit inside console window, then we'll just + * concatenate them and output as is. */ $width = 0; - for ($x=1;$x<$cols;$x++) { + for ($x = 1; $x < $cols; $x += 1) { $width += $maxW[$x]; } + if ($width >= $consoleWidth - 10) { foreach ($data as $row) { - $result .= join(" ", $row) . "\n"; + $result .= implode(" ", $row) . "\n"; } return $result; } - /** + /* * Use Zend\Text\Table to render the table. - * The last column will use the remaining space in console window (minus 1 character to prevent double - * wrapping at the edge of the screen). + * The last column will use the remaining space in console window + * (minus 1 character to prevent double wrapping at the edge of the + * screen). */ $maxW[$cols] = $consoleWidth - $width -1; - $table = new \Zend\Text\Table\Table(); + $table = new Table\Table(); $table->setColumnWidths($maxW); - $table->setDecorator(new \Zend\Text\Table\Decorator\Blank()); + $table->setDecorator(new Table\Decorator\Blank()); $table->setPadding(2); foreach ($data as $row) {