diff options
Diffstat (limited to '')
-rw-r--r-- | library/Icinga/Cli/Documentation.php | 162 | ||||
-rw-r--r-- | library/Icinga/Cli/Documentation/CommentParser.php | 85 |
2 files changed, 247 insertions, 0 deletions
diff --git a/library/Icinga/Cli/Documentation.php b/library/Icinga/Cli/Documentation.php new file mode 100644 index 0000000..111745e --- /dev/null +++ b/library/Icinga/Cli/Documentation.php @@ -0,0 +1,162 @@ +<?php +/* Icinga Web 2 | (c) 2013 Icinga Development Team | GPLv2+ */ + +namespace Icinga\Cli; + +use Icinga\Application\ApplicationBootstrap as App; +use Icinga\Cli\Documentation\CommentParser; +use ReflectionClass; +use ReflectionMethod; + +class Documentation +{ + protected $icinga; + + public function __construct(App $app) + { + $this->app = $app; + $this->loader = $app->cliLoader(); + } + + public function usage($module = null, $command = null, $action = null) + { + if ($module) { + $module = $this->loader->resolveModuleName($module); + return $this->moduleUsage($module, $command, $action); + } + if ($command) { + $command = $this->loader->resolveCommandName($command); + return $this->commandUsage($command, $action); + } + return $this->globalUsage(); + } + + public function globalUsage() + { + $d = "USAGE: icingacli [module] <command> [action] [options]\n\n" + . "Available commands:\n\n"; + foreach ($this->loader->listCommands() as $command) { + if ($command !== 'autocomplete') { + $obj = $this->loader->getCommandInstance($command); + $d .= sprintf( + " %-14s %s\n", + $command, + $this->getClassTitle($obj) + ); + } + } + $d .= "\nAvailable modules:\n\n"; + foreach ($this->loader->listModules() as $module) { + $d .= ' ' . $module . "\n"; + } + $d .= "\nGlobal options:\n\n" + . " --log [t] Log to <t>, either stderr, file or syslog (default: stderr)\n" + . " --log-path <f> Which file to log into in case of --log file\n" + . " --verbose Be verbose\n" + . " --debug Show debug output\n" + . " --help Show help\n" + . " --benchmark Show benchmark summary\n" + . " --watch [s] Refresh output every <s> seconds (default: 5)\n" + . " --version Shows version of Icinga Web 2, loaded modules and PHP\n" + ; + $d .= "\nShow help on a specific command : icingacli help <command>" + . "\nShow help on a specific module : icingacli help <module>" + . "\n"; + return $d; + } + + public function moduleUsage($module, $command = null, $action = null) + { + $commands = $this->loader->listModuleCommands($module); + + if (empty($commands)) { + return "The '$module' module does not provide any CLI commands\n"; + } + $d = ''; + if ($command) { + $obj = $this->loader->getModuleCommandInstance($module, $command); + } + if ($command === null) { + $d = "USAGE: icingacli $module <command> [<action>] [options]\n\n" + . "Available commands:\n\n"; + foreach ($commands as $command) { + $d .= ' ' . $command . "\n"; + } + $d .= "\nShow help on a specific command: icingacli help $module <command>\n"; + } elseif ($action === null) { + $d .= $this->showCommandActions($obj, $command); + } else { + $action = $this->loader->resolveObjectActionName($obj, $action); + $d .= $this->getMethodDocumentation($obj, $action); + } + return $d; + } + + /** + * @param Command $command + * @param string $name + * + * @return string + */ + protected function showCommandActions($command, $name) + { + $actions = $command->listActions(); + $d = $this->getClassDocumentation($command) + . "Available actions:\n\n"; + foreach ($actions as $action) { + $d .= sprintf( + " %-14s %s\n", + $action, + $this->getMethodTitle($command, $action) + ); + } + $d .= "\nShow help on a specific action: icingacli help "; + if ($command->isModule()) { + $d .= $command->getModuleName() . ' '; + } + $d .= "$name <action>\n"; + return $d; + } + + public function commandUsage($command, $action = null) + { + $obj = $this->loader->getCommandInstance($command); + $action = $this->loader->resolveObjectActionName($obj, $action); + + $d = "\n"; + if ($action) { + $d .= $this->getMethodDocumentation($obj, $action); + } else { + $d .= $this->showCommandActions($obj, $command); + } + return $d; + } + + protected function getClassTitle($class) + { + $ref = new ReflectionClass($class); + $comment = new CommentParser($ref->getDocComment()); + return $comment->getTitle(); + } + + protected function getClassDocumentation($class) + { + $ref = new ReflectionClass($class); + $comment = new CommentParser($ref->getDocComment()); + return $comment->dump(); + } + + protected function getMethodTitle($class, $method) + { + $ref = new ReflectionMethod($class, $method . 'Action'); + $comment = new CommentParser($ref->getDocComment()); + return $comment->getTitle(); + } + + protected function getMethodDocumentation($class, $method) + { + $ref = new ReflectionMethod($class, $method . 'Action'); + $comment = new CommentParser($ref->getDocComment()); + return $comment->dump(); + } +} diff --git a/library/Icinga/Cli/Documentation/CommentParser.php b/library/Icinga/Cli/Documentation/CommentParser.php new file mode 100644 index 0000000..4104848 --- /dev/null +++ b/library/Icinga/Cli/Documentation/CommentParser.php @@ -0,0 +1,85 @@ +<?php +/* Icinga Web 2 | (c) 2013 Icinga Development Team | GPLv2+ */ + +namespace Icinga\Cli\Documentation; + +use Icinga\Cli\Screen; + +class CommentParser +{ + protected $raw; + protected $plain; + protected $title; + protected $paragraphs = array(); + + public function __construct($raw) + { + $this->raw = $raw; + if ($raw) { + $this->parse(); + } + } + + public function getTitle() + { + return $this->title; + } + + protected function parse() + { + $plain = $this->raw; + + // Strip comment start /** + $plain = preg_replace('~^/\s*\*\*\n~s', '', $plain); + + // Strip comment end */ + $plain = preg_replace('~\n\s*\*/\s*~s', "\n", $plain); + $p = null; + foreach (preg_split('~\n~', $plain) as $line) { + // Strip * at line start + $line = preg_replace('~^\s*\*\s?~', '', $line); + $line = rtrim($line); + if ($this->title === null) { + $this->title = $line; + continue; + } + if ($p === null && empty($this->paragraphs)) { + $p = & $this->paragraphs[]; + } + + if ($line === '') { + if ($p !== null) { + $p = & $this->paragraphs[]; + } + continue; + } + if ($p === null) { + $p = $line; + } else { + if (substr($line, 0, 2) === ' ') { + $p .= "\n" . $line; + } else { + $p .= ' ' . $line; + } + } + } + if ($p === null) { + array_pop($this->paragraphs); + } + } + + public function dump() + { + if ($this->title) { + $res = $this->title . "\n" . str_repeat('=', strlen($this->title)) . "\n\n"; + } else { + $res = ''; + } + + foreach ($this->paragraphs as $p) { + $res .= wordwrap($p, Screen::instance()->getColumns()) . "\n\n"; + } + + return $res; + } +} |