Viewing file: Method.php (12.94 KB) -rw-rw-rw- Select action/file-type: (+) | (+) | (+) | Code (+) | Session (+) | (+) | SDB (+) | (+) | (+) | (+) | (+) | (+) |
<?php
/* vim: set expandtab tabstop=4 shiftwidth=4 softtabstop=4 foldmethod=marker: */
// LICENSE AGREEMENT. If folded, press za here to unfold and read license {{{
/** * +-----------------------------------------------------------------------------+ * | Copyright (c) 2004-2006 Sergio Gonalves Carvalho | * +-----------------------------------------------------------------------------+ * | This file is part of XML_RPC2. | * | | * | XML_RPC2 is free software; you can redistribute it and/or modify | * | it under the terms of the GNU Lesser General Public License as published by | * | the Free Software Foundation; either version 2.1 of the License, or | * | (at your option) any later version. | * | | * | XML_RPC2 is distributed in the hope that it will be useful, | * | but WITHOUT ANY WARRANTY; without even the implied warranty of | * | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | * | GNU Lesser General Public License for more details. | * | | * | You should have received a copy of the GNU Lesser General Public License | * | along with XML_RPC2; if not, write to the Free Software | * | Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA | * | 02111-1307 USA | * +-----------------------------------------------------------------------------+ * | Author: Sergio Carvalho <sergio.carvalho@portugalmail.com> | * +-----------------------------------------------------------------------------+ * * @category XML * @package XML_RPC2 * @author Sergio Carvalho <sergio.carvalho@portugalmail.com> * @copyright 2004-2006 Sergio Carvalho * @license http://www.gnu.org/copyleft/lesser.html LGPL License 2.1 * @version CVS: $Id: Method.php 308638 2011-02-24 20:32:21Z sergiosgc $ * @link http://pear.php.net/package/XML_RPC2 */
// }}}
// dependencies {{{ require_once 'XML/RPC2/Exception.php'; // }}}
/** * Class representing an XML-RPC exported method. * * This class is used internally by XML_RPC2_Server. External users of the * package should not need to ever instantiate XML_RPC2_Server_Method * * @category XML * @package XML_RPC2 * @author Sergio Carvalho <sergio.carvalho@portugalmail.com> * @copyright 2004-2006 Sergio Carvalho * @license http://www.gnu.org/copyleft/lesser.html LGPL License 2.1 * @link http://pear.php.net/package/XML_RPC2 */ class XML_RPC2_Server_Method { // {{{ properties /** * Method signature parameters * * @var array */ private $_parameters; /** * Method signature return type * * @var string */ private $_returns ; /** * Method help, for introspection * * @var string */ private $_help; /** * internalMethod field : method name in PHP-land * * @var string */ private $_internalMethod; /** * hidden field : true if the method is hidden * * @var boolean */ private $_hidden; /** * name Field : external method name * * @var string */ private $_name; /** * Number of required parameters * * @var int */ private $_numberOfRequiredParameters; // }}} // {{{ getInternalMethod() /** * internalMethod getter * * @return string internalMethod */ public function getInternalMethod() { return $this->_internalMethod; } // }}} // {{{ isHidden() /** * hidden getter * * @return boolean hidden value */ public function isHidden() { return $this->_hidden; } // }}} // {{{ getName() /** * name getter * * @return string name */ public function getName() { return $this->_name; } // }}} // {{{ constructor /** * Create a new XML-RPC method by introspecting a PHP method * * @param ReflectionMethod The PHP method to introspect * @param string default prefix */ public function __construct(ReflectionMethod $method, $defaultPrefix) { $hidden = false; $docs = $method->getDocComment(); if (!$docs) { $hidden = true; } $docs = explode("\n", $docs);
$parameters = array(); $methodname = null; $returns = 'mixed'; $shortdesc = ''; $paramcount = -1; $prefix = $defaultPrefix;
// Extract info from Docblock $paramDocs = array(); foreach ($docs as $i => $doc) { $doc = trim($doc, " \r\t/*"); if (strlen($doc) && strpos($doc, '@') !== 0) { if ($shortdesc) { $shortdesc .= "\n"; } $shortdesc .= $doc; continue; } if (strpos($doc, '@xmlrpc.hidden') === 0) { $hidden = true; } if ((strpos($doc, '@xmlrpc.prefix') === 0) && preg_match('/@xmlrpc.prefix( )*(.*)/', $doc, $matches)) { $prefix = $matches[2]; } if ((strpos($doc, '@xmlrpc.methodname') === 0) && preg_match('/@xmlrpc.methodname( )*(.*)/', $doc, $matches)) { $methodname = $matches[2]; } if (strpos($doc, '@param') === 0) { // Save doctag for usage later when filling parameters $paramDocs[] = $doc; }
if (strpos($doc, '@return') === 0) { $param = preg_split("/\s+/", $doc); if (isset($param[1])) { $param = $param[1]; $returns = $param; } } } $this->_numberOfRequiredParameters = $method->getNumberOfRequiredParameters(); // we don't use isOptional() because of bugs in the reflection API // Fill in info for each method parameter foreach ($method->getParameters() as $parameterIndex => $parameter) { // Parameter defaults $newParameter = array('type' => 'mixed');
// Attempt to extract type and doc from docblock if (array_key_exists($parameterIndex, $paramDocs) && preg_match('/@param\s+(\S+)(\s+(.+))/', $paramDocs[$parameterIndex], $matches)) { if (strpos($matches[1], '|')) { $newParameter['type'] = XML_RPC2_Server_Method::_limitPHPType(explode('|', $matches[1])); } else { $newParameter['type'] = XML_RPC2_Server_Method::_limitPHPType($matches[1]); } $tmp = '$' . $parameter->getName() . ' '; if (strpos($matches[3], '$' . $tmp) === 0) { $newParameter['doc'] = $matches[3]; } else { // The phpdoc comment is something like "@param string $param description of param" // Let's keep only "description of param" as documentation (remove $param) $newParameter['doc'] = substr($matches[3], strlen($tmp)); } $newParameter['doc'] = preg_replace('_^\s*_', '', $newParameter['doc']); }
$parameters[$parameter->getName()] = $newParameter; }
if (is_null($methodname)) { $methodname = $prefix . $method->getName(); }
$this->_internalMethod = $method->getName(); $this->_parameters = $parameters; $this->_returns = $returns; $this->_help = $shortdesc; $this->_name = $methodname; $this->_hidden = $hidden; } // }}} // {{{ matchesSignature() /** * Check if method matches provided call signature * * Compare the provided call signature with this methods' signature and * return true iff they match. * * @param string Signature to compare method name * @param array Array of parameter values for method call. * @return boolean True if call matches signature, false otherwise */ public function matchesSignature($methodName, $callParams) { if ($methodName != $this->_name) return false; if (count($callParams) < $this->_numberOfRequiredParameters) return false; if (count($callParams) > $this->_parameters) return false; $paramIndex = 0; foreach($this->_parameters as $param) { $paramIndex++; if ($paramIndex <= $this->_numberOfRequiredParameters) { // the parameter is not optional $callParamType = XML_RPC2_Server_Method::_limitPHPType(gettype($callParams[$paramIndex-1])); if ((!($param['type'] == 'mixed')) and ($param['type'] != $callParamType)) { return false; } } } return true; } // }}} // {{{ getHTMLSignature() /** * Return a HTML signature of the method * * @return string HTML signature */ public function getHTMLSignature() { $name = $this->_name; $returnType = $this->_returns; $result = "<span class=\"type\">($returnType)</span> "; $result .= "<span class=\"name\">$name</span>"; $result .= "<span class=\"other\">(</span>"; $first = true; $nbr = 0; while (list($name, $parameter) = each($this->_parameters)) { $nbr++; if ($nbr == $this->_numberOfRequiredParameters + 1) { $result .= "<span class=\"other\"> [ </span>"; } if ($first) { $first = false; } else { $result .= ', '; } $type = $parameter['type']; $result .= "<span class=\"paratype\">($type) </span>"; $result .= "<span class=\"paraname\">$name</span>"; } reset($this->_parameters); if ($nbr > $this->_numberOfRequiredParameters) { $result .= "<span class=\"other\"> ] </span>"; } $result .= "<span class=\"other\">)</span>"; return $result; } // }}} // {{{ autoDocument() /** * Print a complete HTML description of the method */ public function autoDocument() { $name = $this->getName(); $signature = $this->getHTMLSignature(); $id = md5($name); $help = nl2br(htmlentities($this->_help)); print " <h3><a name=\"$id\">$signature</a></h3>\n"; print " <p><b>Description :</b></p>\n"; print " <div class=\"description\">\n"; print " $help\n"; print " </div>\n"; if (count($this->_parameters)>0) { print " <p><b>Parameters : </b></p>\n"; if (count($this->_parameters)>0) { print " <table>\n"; print " <tr><td><b>Type</b></td><td><b>Name</b></td><td><b>Documentation</b></td></tr>\n"; while (list($name, $parameter) = each($this->_parameters)) { $type = $parameter['type']; $doc = isset($parameter['doc']) ? htmlentities($parameter['doc']) : 'Method is not documented. No PHPDoc block was found associated with the method in the source code.'; print " <tr><td>$type</td><td>$name</td><td>$doc</td></tr>\n"; } reset($this->_parameters); print " </table>\n"; } } } // }}} // {{{ _limitPHPType() /** * standardise type names between gettype php function and phpdoc comments (and limit to xmlrpc available types) * * @var string $type * @return string standardised type */ private static function _limitPHPType($type) { $tmp = strtolower($type); $convertArray = array( 'int' => 'integer', 'i4' => 'integer', 'integer' => 'integer', 'string' => 'string', 'str' => 'string', 'char' => 'string', 'bool' => 'boolean', 'boolean' => 'boolean', 'array' => 'array', 'float' => 'double', 'double' => 'double', 'array' => 'array', 'struct' => 'array', 'assoc' => 'array', 'structure' => 'array', 'datetime' => 'mixed', 'datetime.iso8601' => 'mixed', 'iso8601' => 'mixed', 'base64' => 'string' ); if (isset($convertArray[$tmp])) { return $convertArray[$tmp]; } return 'mixed'; } }
?>
|