9 * This source file is subject to the new BSD license that is bundled
10 * with this package in the file LICENSE.
11 * It is also available through the world-wide-web at this URL:
12 * http://phergie.org/license
15 * @package Phergie_Plugin_Help
16 * @author Phergie Development Team <team@phergie.org>
17 * @copyright 2008-2010 Phergie Development Team (http://phergie.org)
18 * @license http://phergie.org/license New BSD License
19 * @link http://pear.phergie.org/package/Phergie_Plugin_Help
23 * Provides access to descriptions of plugins and the commands they provide.
26 * @package Phergie_Plugin_Help
27 * @author Phergie Development Team <team@phergie.org>
28 * @license http://phergie.org/license New BSD License
29 * @link http://pear.phergie.org/package/Phergie_Plugin_Help
30 * @uses Phergie_Plugin_Command pear.phergie.org
32 * @pluginDesc Provides access to plugin help information
34 class Phergie_Plugin_Help extends Phergie_Plugin_Abstract
38 * Holds the registry of help data indexed by plugin name
45 * Whether the registry has been alpha sorted
49 protected $registry_sorted = false;
52 * Checks for dependencies.
56 public function onLoad()
58 $this->getPluginHandler()->getPlugin('Command');
59 $this->register($this);
63 * Displays a list of plugins with help information available or
64 * commands available for a specific plugin.
66 * @param string $plugin Short name of the plugin for which commands
67 * should be returned, else a list of plugins with help
68 * information available is returned
72 * @pluginCmd Show all active plugins with help available
73 * @pluginCmd [plugin] Shows commands line for a specific plugin
75 public function onCommandHelp($plugin = null)
77 $nick = $this->getEvent()->getNick();
80 // protect from sorting the registry each time help is called
81 if (!$this->registry_sorted) {
82 asort($this->registry);
83 $this->registry_sorted = true;
86 $msg = 'These plugins below have help information available.';
87 $this->doPrivMsg($nick, $msg);
89 foreach ($this->registry as $plugin => $data) {
90 $this->doPrivMsg($nick, "{$plugin} - {$data['desc']}");
93 if (isset($this->getPluginHandler()->{$plugin})
94 && isset($this->registry[strtolower($plugin)]['cmd'])
99 ' plugin exposes the commands shown below.';
100 $this->doPrivMsg($nick, $msg);
101 if ($this->getConfig('command.prefix')) {
103 = 'Note that these commands must be prefixed with "' .
104 $this->getConfig('command.prefix') .
105 '" (without quotes) when issued in a public channel.';
106 $this->doPrivMsg($nick, $msg);
109 foreach ($this->registry[strtolower($plugin)]['cmd']
112 foreach ($descs as $desc) {
113 $this->doPrivMsg($nick, "{$cmd} {$desc}");
118 $this->doPrivMsg($nick, 'That plugin is not loaded.');
124 * Sets the description for the plugin instance
126 * @param Phergie_Plugin_Abstract $plugin plugin instance
127 * @param string $description plugin description
131 public function setPluginDescription(
132 Phergie_Plugin_Abstract $plugin,
135 $this->registry[strtolower($plugin->getName())]
136 ['desc'] = $description;
140 * Sets the description for the command on the plugin instance
142 * @param Phergie_Plugin_Abstract $plugin plugin instance
143 * @param string $command from onCommand method
144 * @param string $description command description
148 public function setCommandDescription(
149 Phergie_Plugin_Abstract $plugin,
153 $this->registry[strtolower($plugin->getName())]
154 ['cmd'][$command] = $description;
158 * registers the plugin with the help plugin. this will parse the docblocks
159 * for specific annotations that this plugin will respond with when
162 * @param Phergie_Plugin_Abstract $plugin plugin instance
166 public function register(Phergie_Plugin_Abstract $plugin)
168 $class = new ReflectionClass($plugin);
170 $annotations = self::parseAnnotations($class->getDocComment());
171 if (isset($annotations['pluginDesc'])) {
172 $this->setPluginDescription(
174 join(' ', $annotations['pluginDesc'])
178 foreach ($class->getMethods() as $method) {
179 if (strpos($method->getName(), 'onCommand') !== false) {
180 $annotations = self::parseAnnotations($method->getDocComment());
181 if (isset($annotations['pluginCmd'])) {
182 $cmd = strtolower(substr($method->getName(), 9));
183 $this->setCommandDescription(
186 $annotations['pluginCmd']
194 * Taken from PHPUnit/Util/Test.php:436
198 * Copyright (c) 2002-2010, Sebastian Bergmann <sb@sebastian-bergmann.de>.
199 * All rights reserved.
201 * Redistribution and use in source and binary forms, with or without
202 * modification, are permitted provided that the following conditions
205 * * Redistributions of source code must retain the above copyright
206 * notice, this list of conditions and the following disclaimer.
208 * * Redistributions in binary form must reproduce the above copyright
209 * notice, this list of conditions and the following disclaimer in
210 * the documentation and/or other materials provided with the
213 * * Neither the name of Sebastian Bergmann nor the names of his
214 * contributors may be used to endorse or promote products derived
215 * from this software without specific prior written permission.
217 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
218 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
219 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
220 * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
221 * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
222 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
223 * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
224 * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
225 * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
226 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
227 * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
228 * POSSIBILITY OF SUCH DAMAGE.
230 * @param string $docblock docblock to parse
234 protected static function parseAnnotations($docblock)
236 $annotations = array();
238 $regex = '/@(?P<name>[A-Za-z_-]+)(?:[ \t]+(?P<value>.*?))?[ \t]*\r?$/m';
240 if (preg_match_all($regex, $docblock, $matches)) {
241 $numMatches = count($matches[0]);
243 for ($i = 0; $i < $numMatches; ++$i) {
244 $annotations[$matches['name'][$i]][] = $matches['value'][$i];