summaryrefslogtreecommitdiffstats
path: root/library/Icinga/Cli/Documentation
diff options
context:
space:
mode:
Diffstat (limited to '')
-rw-r--r--library/Icinga/Cli/Documentation.php162
-rw-r--r--library/Icinga/Cli/Documentation/CommentParser.php85
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;
+ }
+}