This commit is contained in:
Xes
2025-08-14 22:41:49 +02:00
parent 2de81ccc46
commit 8ce45119b6
39774 changed files with 4309466 additions and 0 deletions

View File

@@ -0,0 +1,116 @@
# Changelog
All notable changes to this project will be documented in this file, in reverse chronological order by release.
## 2.8.1 - 2019-10-16
### Added
- [#27](https://github.com/zendframework/zend-server/pull/27) adds support for PHP 7.3.
### Changed
- Nothing.
### Deprecated
- Nothing.
### Removed
- Nothing.
### Fixed
- [#30](https://github.com/zendframework/zend-server/pull/30) provides fixes to ensure the various Reflection classes can be safely de/serialized under PHP 7.4.
## 2.8.0 - 2018-04-30
### Added
- [#26](https://github.com/zendframework/zend-server/pull/26) adds support for PHP 7.1 and 7.2.
- [#19](https://github.com/zendframework/zend-server/pull/19) adds the ability to register any PHP callable with `Zend\Server\Method\Callback`.
### Changed
- Nothing.
### Deprecated
- Nothing.
### Removed
- [#26](https://github.com/zendframework/zend-server/pull/26) removes support for HHVM.
### Fixed
- [#20](https://github.com/zendframework/zend-server/pull/20) fixes how `Cache::save()` works when `Server::getFunctions()` returns an
associative array instead of a `Definition`, ensuring it will also skip
any blacklisted methods when used in this way.
## 2.7.0 - 2016-06-20
### Added
- [#13](https://github.com/zendframework/zend-server/pull/13) adds and publishes
the documentation to https://zendframework.github.io/zend-server
- [#14](https://github.com/zendframework/zend-server/pull/14) adds support for
zend-code v3 (while retaining support for zend-code v2).
### Deprecated
- [#14](https://github.com/zendframework/zend-server/pull/14) deprecates all
underscore-prefixed methods of `AbstractServer`; they will be renamed in
version 3 to remove the prefix (though, in the case of `_dispatch()`, it will
be renamed entirely, likely to `performDispatch()`).
### Removed
- [#14](https://github.com/zendframework/zend-server/pull/14) removes support
for PHP 5.5; the new minimum supported version of PHP is 5.6.
### Fixed
- Nothing.
## 2.6.1 - 2016-02-04
### Added
- Nothing.
### Deprecated
- Nothing.
### Removed
- Nothing.
### Fixed
- [#11](https://github.com/zendframework/zend-server/pull/11) updates the
dependencies to use zend-stdlib `^2.5 || ^3.0`.
## 2.6.0 - 2015-12-17
### Added
- [#3](https://github.com/zendframework/zend-server/pull/3) adds support for
resolving `{@inheritdoc}` annotations to the original parent during
reflection.
### Deprecated
- Nothing.
### Removed
- Nothing.
### Fixed
- [#2](https://github.com/zendframework/zend-server/pull/2) fixes misleading
exception in reflectFunction that referenced reflectClass.

View File

@@ -0,0 +1,27 @@
Copyright (c) 2005-2018, Zend Technologies USA, Inc.
All rights reserved.
Redistribution and use in source and binary forms, with or without modification,
are permitted provided that the following conditions are met:
- Redistributions of source code must retain the above copyright notice, this
list of conditions and the following disclaimer.
- Redistributions in binary form must reproduce the above copyright notice, this
list of conditions and the following disclaimer in the documentation and/or
other materials provided with the distribution.
- Neither the name of Zend Technologies USA, Inc. nor the names of its
contributors may be used to endorse or promote products derived from this
software without specific prior written permission.
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR
ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.

View File

@@ -0,0 +1,13 @@
# zend-server
[![Build Status](https://secure.travis-ci.org/zendframework/zend-server.svg?branch=master)](https://secure.travis-ci.org/zendframework/zend-server)
[![Coverage Status](https://coveralls.io/repos/github/zendframework/zend-server/badge.svg?branch=master)](https://coveralls.io/github/zendframework/zend-server?branch=master)
The zend-server family of classes provides functionality for the various server
classes, including `Zend\XmlRpc\Server` and `Zend\Json\Server`.
`Zend\Server\Server` provides an interface that mimics PHP 5s SoapServer class;
all server classes should implement this interface in order to provide a standard
server API.
- File issues at https://github.com/zendframework/zend-server/issues
- Documentation is at https://docs.zendframework.com/zend-server/

View File

@@ -0,0 +1,59 @@
{
"name": "zendframework/zend-server",
"description": "Create Reflection-based RPC servers",
"license": "BSD-3-Clause",
"keywords": [
"zf",
"zendframework",
"server"
],
"support": {
"docs": "https://docs.zendframework.com/zend-server/",
"issues": "https://github.com/zendframework/zend-server/issues",
"source": "https://github.com/zendframework/zend-server",
"rss": "https://github.com/zendframework/zend-server/releases.atom",
"chat": "https://zendframework-slack.herokuapp.com",
"forum": "https://discourse.zendframework.com/c/questions/components"
},
"require": {
"php": "^5.6 || ^7.0",
"zendframework/zend-code": "^2.5 || ^3.0",
"zendframework/zend-stdlib": "^2.5 || ^3.0"
},
"require-dev": {
"phpunit/phpunit": "^5.7.27 || ^6.5.8 || ^7.1.4",
"zendframework/zend-coding-standard": "~1.0.0"
},
"autoload": {
"psr-4": {
"Zend\\Server\\": "src/"
}
},
"autoload-dev": {
"psr-4": {
"ZendTest\\Server\\": "test/"
},
"files": [
"test/TestAsset/reflectionTestFunction.php"
]
},
"config": {
"sort-packages": true
},
"extra": {
"branch-alias": {
"dev-master": "2.8.x-dev",
"dev-develop": "2.9.x-dev"
}
},
"scripts": {
"check": [
"@cs-check",
"@test"
],
"cs-check": "phpcs",
"cs-fix": "phpcbf",
"test": "phpunit --colors=always",
"test-coverage": "phpunit --colors=always --coverage-clover clover.xml"
}
}

View File

@@ -0,0 +1,177 @@
<?php
/**
* @see https://github.com/zendframework/zend-server for the canonical source repository
* @copyright Copyright (c) 2005-2018 Zend Technologies USA Inc. (https://www.zend.com)
* @license https://github.com/zendframework/zend-server/blob/master/LICENSE.md New BSD License
*/
namespace Zend\Server;
use ReflectionClass;
/**
* Abstract Server implementation
*/
abstract class AbstractServer implements Server
{
/**
* @var bool Flag; whether or not overwriting existing methods is allowed
*/
protected $overwriteExistingMethods = false;
/**
* @var Definition
*/
protected $table;
/**
* Constructor
*
* Setup server description
*
*/
public function __construct()
{
$this->table = new Definition();
$this->table->setOverwriteExistingMethods($this->overwriteExistingMethods);
}
/**
* Returns a list of registered methods
*
* Returns an array of method definitions.
*
* @return Definition
*/
public function getFunctions()
{
return $this->table;
}
/**
* Build callback for method signature
*
* @deprecated Since 2.7.0; method will have private visibility starting in 3.0.
* @param Reflection\AbstractFunction $reflection
* @return Method\Callback
*/
// @codingStandardsIgnoreStart
protected function _buildCallback(Reflection\AbstractFunction $reflection)
{
// @codingStandardsIgnoreEnd
$callback = new Method\Callback();
if ($reflection instanceof Reflection\ReflectionMethod) {
$callback->setType($reflection->isStatic() ? 'static' : 'instance')
->setClass($reflection->getDeclaringClass()->getName())
->setMethod($reflection->getName());
} elseif ($reflection instanceof Reflection\ReflectionFunction) {
$callback->setType('function')
->setFunction($reflection->getName());
}
return $callback;
}
/**
* Build a method signature
*
* @deprecated Since 2.7.0; method will be renamed to remove underscore
* prefix in 3.0.
* @param Reflection\AbstractFunction $reflection
* @param null|string|object $class
* @return Method\Definition
* @throws Exception\RuntimeException on duplicate entry
*/
// @codingStandardsIgnoreStart
protected function _buildSignature(Reflection\AbstractFunction $reflection, $class = null)
{
// @codingStandardsIgnoreEnd
$ns = $reflection->getNamespace();
$name = $reflection->getName();
$method = empty($ns) ? $name : $ns . '.' . $name;
if (! $this->overwriteExistingMethods && $this->table->hasMethod($method)) {
throw new Exception\RuntimeException('Duplicate method registered: ' . $method);
}
$definition = new Method\Definition();
$definition->setName($method)
->setCallback($this->_buildCallback($reflection))
->setMethodHelp($reflection->getDescription())
->setInvokeArguments($reflection->getInvokeArguments());
foreach ($reflection->getPrototypes() as $proto) {
$prototype = new Method\Prototype();
$prototype->setReturnType($this->_fixType($proto->getReturnType()));
foreach ($proto->getParameters() as $parameter) {
$param = new Method\Parameter([
'type' => $this->_fixType($parameter->getType()),
'name' => $parameter->getName(),
'optional' => $parameter->isOptional(),
]);
if ($parameter->isDefaultValueAvailable()) {
$param->setDefaultValue($parameter->getDefaultValue());
}
$prototype->addParameter($param);
}
$definition->addPrototype($prototype);
}
if (is_object($class)) {
$definition->setObject($class);
}
$this->table->addMethod($definition);
return $definition;
}
/**
* Dispatch method
*
* @deprecated Since 2.7.0; method will be renamed to remove underscore
* prefix in 3.0.
* @param Method\Definition $invokable
* @param array $params
* @return mixed
*/
// @codingStandardsIgnoreStart
protected function _dispatch(Method\Definition $invokable, array $params)
{
// @codingStandardsIgnoreEnd
$callback = $invokable->getCallback();
$type = $callback->getType();
if ('function' == $type) {
$function = $callback->getFunction();
return call_user_func_array($function, $params);
}
$class = $callback->getClass();
$method = $callback->getMethod();
if ('static' == $type) {
return call_user_func_array([$class, $method], $params);
}
$object = $invokable->getObject();
if (! is_object($object)) {
$invokeArgs = $invokable->getInvokeArguments();
if (! empty($invokeArgs)) {
$reflection = new ReflectionClass($class);
$object = $reflection->newInstanceArgs($invokeArgs);
} else {
$object = new $class;
}
}
return call_user_func_array([$object, $method], $params);
}
// @codingStandardsIgnoreStart
/**
* Map PHP type to protocol type
*
* @deprecated Since 2.7.0; method will be renamed to remove underscore
* prefix in 3.0.
* @param string $type
* @return string
*/
abstract protected function _fixType($type);
// @codingStandardsIgnoreEnd
}

View File

@@ -0,0 +1,169 @@
<?php
/**
* @see https://github.com/zendframework/zend-server for the canonical source repository
* @copyright Copyright (c) 2005-2018 Zend Technologies USA Inc. (https://www.zend.com)
* @license https://github.com/zendframework/zend-server/blob/master/LICENSE.md New BSD License
*/
namespace Zend\Server;
use Zend\Stdlib\ErrorHandler;
/**
* \Zend\Server\Cache: cache server definitions
*/
class Cache
{
/**
* @var array Methods to skip when caching server
*/
protected static $skipMethods = [];
/**
* Cache a file containing the dispatch list.
*
* Serializes the server definition stores the information
* in $filename.
*
* Returns false on any error (typically, inability to write to file), true
* on success.
*
* @param string $filename
* @param \Zend\Server\Server $server
* @return bool
*/
public static function save($filename, Server $server)
{
if (! is_string($filename) || (! file_exists($filename) && ! is_writable(dirname($filename)))) {
return false;
}
$methods = self::createDefinition($server->getFunctions());
ErrorHandler::start();
$test = file_put_contents($filename, serialize($methods));
ErrorHandler::stop();
if (0 === $test) {
return false;
}
return true;
}
/**
* Load server definition from a file
*
* Unserializes a stored server definition from $filename. Returns false if
* it fails in any way, true on success.
*
* Useful to prevent needing to build the server definition on each
* request. Sample usage:
*
* <code>
* if (!Zend\Server\Cache::get($filename, $server)) {
* require_once 'Some/Service/ServiceClass.php';
* require_once 'Another/Service/ServiceClass.php';
*
* // Attach Some\Service\ServiceClass with namespace 'some'
* $server->attach('Some\Service\ServiceClass', 'some');
*
* // Attach Another\Service\ServiceClass with namespace 'another'
* $server->attach('Another\Service\ServiceClass', 'another');
*
* Zend\Server\Cache::save($filename, $server);
* }
*
* $response = $server->handle();
* echo $response;
* </code>
*
* @param string $filename
* @param \Zend\Server\Server $server
* @return bool
*/
public static function get($filename, Server $server)
{
if (! is_string($filename) || ! file_exists($filename) || ! is_readable($filename)) {
return false;
}
ErrorHandler::start();
$dispatch = file_get_contents($filename);
ErrorHandler::stop();
if (false === $dispatch) {
return false;
}
ErrorHandler::start(E_NOTICE);
$dispatchArray = unserialize($dispatch);
ErrorHandler::stop();
if (false === $dispatchArray) {
return false;
}
$server->loadFunctions($dispatchArray);
return true;
}
/**
* Remove a cache file
*
* @param string $filename
* @return bool
*/
public static function delete($filename)
{
if (is_string($filename) && file_exists($filename)) {
unlink($filename);
return true;
}
return false;
}
/**
* @var array|Definition $methods
* @return array|Definition
*/
private static function createDefinition($methods)
{
if ($methods instanceof Definition) {
return self::createDefinitionFromMethodsDefinition($methods);
}
if (is_array($methods)) {
return self::createDefinitionFromMethodsArray($methods);
}
return $methods;
}
/**
* @return Definition
*/
private static function createDefinitionFromMethodsDefinition(Definition $methods)
{
$definition = new Definition();
foreach ($methods as $method) {
if (in_array($method->getName(), static::$skipMethods, true)) {
continue;
}
$definition->addMethod($method);
}
return $definition;
}
/**
* @return array
*/
private static function createDefinitionFromMethodsArray(array $methods)
{
foreach (array_keys($methods) as $methodName) {
if (in_array($methodName, static::$skipMethods, true)) {
unset($methods[$methodName]);
}
}
return $methods;
}
}

View File

@@ -0,0 +1,25 @@
<?php
/**
* @see https://github.com/zendframework/zend-server for the canonical source repository
* @copyright Copyright (c) 2005-2018 Zend Technologies USA Inc. (https://www.zend.com)
* @license https://github.com/zendframework/zend-server/blob/master/LICENSE.md New BSD License
*/
namespace Zend\Server;
/**
* Client Interface
*/
interface Client
{
/**
* Executes remote call
*
* Unified interface for calling custom remote methods.
*
* @param string $method Remote call name.
* @param array $params Call parameters.
* @return mixed Remote call results.
*/
public function call($method, $params = []);
}

View File

@@ -0,0 +1,247 @@
<?php
/**
* @see https://github.com/zendframework/zend-server for the canonical source repository
* @copyright Copyright (c) 2005-2018 Zend Technologies USA Inc. (https://www.zend.com)
* @license https://github.com/zendframework/zend-server/blob/master/LICENSE.md New BSD License
*/
namespace Zend\Server;
use Countable;
use Iterator;
/**
* Server methods metadata
*/
class Definition implements Countable, Iterator
{
/**
* @var array Array of \Zend\Server\Method\Definition objects
*/
protected $methods = [];
/**
* @var bool Whether or not overwriting existing methods is allowed
*/
protected $overwriteExistingMethods = false;
/**
* Constructor
*
* @param null|array $methods
*/
public function __construct($methods = null)
{
if (is_array($methods)) {
$this->setMethods($methods);
}
}
/**
* Set flag indicating whether or not overwriting existing methods is allowed
*
* @param mixed $flag
* @return \Zend\Server\Definition
*/
public function setOverwriteExistingMethods($flag)
{
$this->overwriteExistingMethods = (bool) $flag;
return $this;
}
/**
* Add method to definition
*
* @param array|\Zend\Server\Method\Definition $method
* @param null|string $name
* @return \Zend\Server\Definition
* @throws \Zend\Server\Exception\InvalidArgumentException if duplicate or invalid method provided
*/
public function addMethod($method, $name = null)
{
if (is_array($method)) {
$method = new Method\Definition($method);
} elseif (! $method instanceof Method\Definition) {
throw new Exception\InvalidArgumentException('Invalid method provided');
}
if (is_numeric($name)) {
$name = null;
}
if (null !== $name) {
$method->setName($name);
} else {
$name = $method->getName();
}
if (null === $name) {
throw new Exception\InvalidArgumentException('No method name provided');
}
if (! $this->overwriteExistingMethods && array_key_exists($name, $this->methods)) {
throw new Exception\InvalidArgumentException(sprintf('Method by name of "%s" already exists', $name));
}
$this->methods[$name] = $method;
return $this;
}
/**
* Add multiple methods
*
* @param array $methods Array of \Zend\Server\Method\Definition objects or arrays
* @return \Zend\Server\Definition
*/
public function addMethods(array $methods)
{
foreach ($methods as $key => $method) {
$this->addMethod($method, $key);
}
return $this;
}
/**
* Set all methods at once (overwrite)
*
* @param array $methods Array of \Zend\Server\Method\Definition objects or arrays
* @return \Zend\Server\Definition
*/
public function setMethods(array $methods)
{
$this->clearMethods();
$this->addMethods($methods);
return $this;
}
/**
* Does the definition have the given method?
*
* @param string $method
* @return bool
*/
public function hasMethod($method)
{
return array_key_exists($method, $this->methods);
}
/**
* Get a given method definition
*
* @param string $method
* @return null|\Zend\Server\Method\Definition
*/
public function getMethod($method)
{
if ($this->hasMethod($method)) {
return $this->methods[$method];
}
return false;
}
/**
* Get all method definitions
*
* @return array Array of \Zend\Server\Method\Definition objects
*/
public function getMethods()
{
return $this->methods;
}
/**
* Remove a method definition
*
* @param string $method
* @return \Zend\Server\Definition
*/
public function removeMethod($method)
{
if ($this->hasMethod($method)) {
unset($this->methods[$method]);
}
return $this;
}
/**
* Clear all method definitions
*
* @return \Zend\Server\Definition
*/
public function clearMethods()
{
$this->methods = [];
return $this;
}
/**
* Cast definition to an array
*
* @return array
*/
public function toArray()
{
$methods = [];
foreach ($this->getMethods() as $key => $method) {
$methods[$key] = $method->toArray();
}
return $methods;
}
/**
* Countable: count of methods
*
* @return int
*/
public function count()
{
return count($this->methods);
}
/**
* Iterator: current item
*
* @return Method\Definition
*/
public function current()
{
return current($this->methods);
}
/**
* Iterator: current item key
*
* @return int|string
*/
public function key()
{
return key($this->methods);
}
/**
* Iterator: advance to next method
*
* @return Method\Definition
*/
public function next()
{
return next($this->methods);
}
/**
* Iterator: return to first method
*
* @return void
*/
public function rewind()
{
reset($this->methods);
}
/**
* Iterator: is the current index valid?
*
* @return bool
*/
public function valid()
{
return (bool) $this->current();
}
}

View File

@@ -0,0 +1,12 @@
<?php
/**
* @see https://github.com/zendframework/zend-server for the canonical source repository
* @copyright Copyright (c) 2005-2018 Zend Technologies USA Inc. (https://www.zend.com)
* @license https://github.com/zendframework/zend-server/blob/master/LICENSE.md New BSD License
*/
namespace Zend\Server\Exception;
class BadMethodCallException extends \BadMethodCallException implements ExceptionInterface
{
}

View File

@@ -0,0 +1,15 @@
<?php
/**
* @see https://github.com/zendframework/zend-server for the canonical source repository
* @copyright Copyright (c) 2005-2018 Zend Technologies USA Inc. (https://www.zend.com)
* @license https://github.com/zendframework/zend-server/blob/master/LICENSE.md New BSD License
*/
namespace Zend\Server\Exception;
/**
* Zend\Server exceptions
*/
interface ExceptionInterface
{
}

View File

@@ -0,0 +1,12 @@
<?php
/**
* @see https://github.com/zendframework/zend-server for the canonical source repository
* @copyright Copyright (c) 2005-2018 Zend Technologies USA Inc. (https://www.zend.com)
* @license https://github.com/zendframework/zend-server/blob/master/LICENSE.md New BSD License
*/
namespace Zend\Server\Exception;
class InvalidArgumentException extends \InvalidArgumentException implements ExceptionInterface
{
}

View File

@@ -0,0 +1,12 @@
<?php
/**
* @see https://github.com/zendframework/zend-server for the canonical source repository
* @copyright Copyright (c) 2005-2018 Zend Technologies USA Inc. (https://www.zend.com)
* @license https://github.com/zendframework/zend-server/blob/master/LICENSE.md New BSD License
*/
namespace Zend\Server\Exception;
class RuntimeException extends \RuntimeException implements ExceptionInterface
{
}

View File

@@ -0,0 +1,190 @@
<?php
/**
* @see https://github.com/zendframework/zend-server for the canonical source repository
* @copyright Copyright (c) 2005-2018 Zend Technologies USA Inc. (https://www.zend.com)
* @license https://github.com/zendframework/zend-server/blob/master/LICENSE.md New BSD License
*/
namespace Zend\Server\Method;
use Zend\Server;
/**
* Method callback metadata
*/
class Callback
{
/**
* @var string Class name for class method callback
*/
protected $class;
/**
* @var string|callable Function name or callable for function callback
*/
protected $function;
/**
* @var string Method name for class method callback
*/
protected $method;
/**
* @var string Callback type
*/
protected $type;
/**
* @var array Valid callback types
*/
protected $types = ['function', 'static', 'instance'];
/**
* Constructor
*
* @param null|array $options
*/
public function __construct($options = null)
{
if ((null !== $options) && is_array($options)) {
$this->setOptions($options);
}
}
/**
* Set object state from array of options
*
* @param array $options
* @return \Zend\Server\Method\Callback
*/
public function setOptions(array $options)
{
foreach ($options as $key => $value) {
$method = 'set' . ucfirst($key);
if (method_exists($this, $method)) {
$this->$method($value);
}
}
return $this;
}
/**
* Set callback class
*
* @param string $class
* @return \Zend\Server\Method\Callback
*/
public function setClass($class)
{
if (is_object($class)) {
$class = get_class($class);
}
$this->class = $class;
return $this;
}
/**
* Get callback class
*
* @return string|null
*/
public function getClass()
{
return $this->class;
}
/**
* Set callback function
*
* @param string|callable $function
* @return \Zend\Server\Method\Callback
*/
public function setFunction($function)
{
$this->function = is_callable($function) ? $function : (string) $function;
$this->setType('function');
return $this;
}
/**
* Get callback function
*
* @return null|string|callable
*/
public function getFunction()
{
return $this->function;
}
/**
* Set callback class method
*
* @param string $method
* @return \Zend\Server\Method\Callback
*/
public function setMethod($method)
{
$this->method = $method;
return $this;
}
/**
* Get callback class method
*
* @return null|string
*/
public function getMethod()
{
return $this->method;
}
/**
* Set callback type
*
* @param string $type
* @return \Zend\Server\Method\Callback
* @throws Server\Exception\InvalidArgumentException
*/
public function setType($type)
{
if (! in_array($type, $this->types)) {
throw new Server\Exception\InvalidArgumentException(sprintf(
'Invalid method callback type "%s" passed to %s',
$type,
__METHOD__
));
}
$this->type = $type;
return $this;
}
/**
* Get callback type
*
* @return string
*/
public function getType()
{
return $this->type;
}
/**
* Cast callback to array
*
* @return array
*/
public function toArray()
{
$type = $this->getType();
$array = [
'type' => $type,
];
if ('function' == $type) {
$array['function'] = $this->getFunction();
} else {
$array['class'] = $this->getClass();
$array['method'] = $this->getMethod();
}
return $array;
}
}

View File

@@ -0,0 +1,276 @@
<?php
/**
* @see https://github.com/zendframework/zend-server for the canonical source repository
* @copyright Copyright (c) 2005-2018 Zend Technologies USA Inc. (https://www.zend.com)
* @license https://github.com/zendframework/zend-server/blob/master/LICENSE.md New BSD License
*/
namespace Zend\Server\Method;
use Zend\Server;
/**
* Method definition metadata
*/
class Definition
{
/**
* @var \Zend\Server\Method\Callback
*/
protected $callback;
/**
* @var array
*/
protected $invokeArguments = [];
/**
* @var string
*/
protected $methodHelp = '';
/**
* @var string
*/
protected $name;
/**
* @var null|object
*/
protected $object;
/**
* @var array Array of \Zend\Server\Method\Prototype objects
*/
protected $prototypes = [];
/**
* Constructor
*
* @param null|array $options
*/
public function __construct($options = null)
{
if ((null !== $options) && is_array($options)) {
$this->setOptions($options);
}
}
/**
* Set object state from options
*
* @param array $options
* @return \Zend\Server\Method\Definition
*/
public function setOptions(array $options)
{
foreach ($options as $key => $value) {
$method = 'set' . ucfirst($key);
if (method_exists($this, $method)) {
$this->$method($value);
}
}
return $this;
}
/**
* Set method name
*
* @param string $name
* @return \Zend\Server\Method\Definition
*/
public function setName($name)
{
$this->name = (string) $name;
return $this;
}
/**
* Get method name
*
* @return string
*/
public function getName()
{
return $this->name;
}
/**
* Set method callback
*
* @param array|\Zend\Server\Method\Callback $callback
* @throws Server\Exception\InvalidArgumentException
* @return \Zend\Server\Method\Definition
*/
public function setCallback($callback)
{
if (is_array($callback)) {
$callback = new Callback($callback);
} elseif (! $callback instanceof Callback) {
throw new Server\Exception\InvalidArgumentException('Invalid method callback provided');
}
$this->callback = $callback;
return $this;
}
/**
* Get method callback
*
* @return \Zend\Server\Method\Callback
*/
public function getCallback()
{
return $this->callback;
}
/**
* Add prototype to method definition
*
* @param array|\Zend\Server\Method\Prototype $prototype
* @throws Server\Exception\InvalidArgumentException
* @return \Zend\Server\Method\Definition
*/
public function addPrototype($prototype)
{
if (is_array($prototype)) {
$prototype = new Prototype($prototype);
} elseif (! $prototype instanceof Prototype) {
throw new Server\Exception\InvalidArgumentException('Invalid method prototype provided');
}
$this->prototypes[] = $prototype;
return $this;
}
/**
* Add multiple prototypes at once
*
* @param array $prototypes Array of \Zend\Server\Method\Prototype objects or arrays
* @return \Zend\Server\Method\Definition
*/
public function addPrototypes(array $prototypes)
{
foreach ($prototypes as $prototype) {
$this->addPrototype($prototype);
}
return $this;
}
/**
* Set all prototypes at once (overwrites)
*
* @param array $prototypes Array of \Zend\Server\Method\Prototype objects or arrays
* @return \Zend\Server\Method\Definition
*/
public function setPrototypes(array $prototypes)
{
$this->prototypes = [];
$this->addPrototypes($prototypes);
return $this;
}
/**
* Get all prototypes
*
* @return array $prototypes Array of \Zend\Server\Method\Prototype objects or arrays
*/
public function getPrototypes()
{
return $this->prototypes;
}
/**
* Set method help
*
* @param string $methodHelp
* @return \Zend\Server\Method\Definition
*/
public function setMethodHelp($methodHelp)
{
$this->methodHelp = (string) $methodHelp;
return $this;
}
/**
* Get method help
*
* @return string
*/
public function getMethodHelp()
{
return $this->methodHelp;
}
/**
* Set object to use with method calls
*
* @param object $object
* @throws Server\Exception\InvalidArgumentException
* @return \Zend\Server\Method\Definition
*/
public function setObject($object)
{
if (! is_object($object) && (null !== $object)) {
throw new Server\Exception\InvalidArgumentException(sprintf(
'Invalid object passed to %s',
__METHOD__
));
}
$this->object = $object;
return $this;
}
/**
* Get object to use with method calls
*
* @return null|object
*/
public function getObject()
{
return $this->object;
}
/**
* Set invoke arguments
*
* @param array $invokeArguments
* @return \Zend\Server\Method\Definition
*/
public function setInvokeArguments(array $invokeArguments)
{
$this->invokeArguments = $invokeArguments;
return $this;
}
/**
* Retrieve invoke arguments
*
* @return array
*/
public function getInvokeArguments()
{
return $this->invokeArguments;
}
/**
* Serialize to array
*
* @return array
*/
public function toArray()
{
$prototypes = $this->getPrototypes();
$signatures = [];
foreach ($prototypes as $prototype) {
$signatures[] = $prototype->toArray();
}
return [
'name' => $this->getName(),
'callback' => $this->getCallback()->toArray(),
'prototypes' => $signatures,
'methodHelp' => $this->getMethodHelp(),
'invokeArguments' => $this->getInvokeArguments(),
'object' => $this->getObject(),
];
}
}

View File

@@ -0,0 +1,204 @@
<?php
/**
* @see https://github.com/zendframework/zend-server for the canonical source repository
* @copyright Copyright (c) 2005-2018 Zend Technologies USA Inc. (https://www.zend.com)
* @license https://github.com/zendframework/zend-server/blob/master/LICENSE.md New BSD License
*/
namespace Zend\Server\Method;
/**
* Method parameter metadata
*/
class Parameter
{
/**
* Default parameter value
*
* @var mixed
*/
protected $defaultValue;
/**
* Parameter description
*
* @var string
*/
protected $description = '';
/**
* Parameter variable name
*
* @var string
*/
protected $name;
/**
* Is parameter optional?
*
* @var bool
*/
protected $optional = false;
/**
* Parameter type
*
* @var string
*/
protected $type = 'mixed';
/**
* Constructor
*
* @param null|array $options
*/
public function __construct($options = null)
{
if (is_array($options)) {
$this->setOptions($options);
}
}
/**
* Set object state from array of options
*
* @param array $options
* @return \Zend\Server\Method\Parameter
*/
public function setOptions(array $options)
{
foreach ($options as $key => $value) {
$method = 'set' . ucfirst($key);
if (method_exists($this, $method)) {
$this->$method($value);
}
}
return $this;
}
/**
* Set default value
*
* @param mixed $defaultValue
* @return \Zend\Server\Method\Parameter
*/
public function setDefaultValue($defaultValue)
{
$this->defaultValue = $defaultValue;
return $this;
}
/**
* Retrieve default value
*
* @return mixed
*/
public function getDefaultValue()
{
return $this->defaultValue;
}
/**
* Set description
*
* @param string $description
* @return \Zend\Server\Method\Parameter
*/
public function setDescription($description)
{
$this->description = (string) $description;
return $this;
}
/**
* Retrieve description
*
* @return string
*/
public function getDescription()
{
return $this->description;
}
/**
* Set name
*
* @param string $name
* @return \Zend\Server\Method\Parameter
*/
public function setName($name)
{
$this->name = (string) $name;
return $this;
}
/**
* Retrieve name
*
* @return string
*/
public function getName()
{
return $this->name;
}
/**
* Set optional flag
*
* @param bool $flag
* @return \Zend\Server\Method\Parameter
*/
public function setOptional($flag)
{
$this->optional = (bool) $flag;
return $this;
}
/**
* Is the parameter optional?
*
* @return bool
*/
public function isOptional()
{
return $this->optional;
}
/**
* Set parameter type
*
* @param string $type
* @return \Zend\Server\Method\Parameter
*/
public function setType($type)
{
$this->type = (string) $type;
return $this;
}
/**
* Retrieve parameter type
*
* @return string
*/
public function getType()
{
return $this->type;
}
/**
* Cast to array
*
* @return array
*/
public function toArray()
{
return [
'type' => $this->getType(),
'name' => $this->getName(),
'optional' => $this->isOptional(),
'defaultValue' => $this->getDefaultValue(),
'description' => $this->getDescription(),
];
}
}

View File

@@ -0,0 +1,187 @@
<?php
/**
* @see https://github.com/zendframework/zend-server for the canonical source repository
* @copyright Copyright (c) 2005-2018 Zend Technologies USA Inc. (https://www.zend.com)
* @license https://github.com/zendframework/zend-server/blob/master/LICENSE.md New BSD License
*/
namespace Zend\Server\Method;
/**
* Method prototype metadata
*/
class Prototype
{
/**
* @var string Return type
*/
protected $returnType = 'void';
/**
* @var array Map parameter names to parameter index
*/
protected $parameterNameMap = [];
/**
* @var array Method parameters
*/
protected $parameters = [];
/**
* Constructor
*
* @param null|array $options
*/
public function __construct($options = null)
{
if ((null !== $options) && is_array($options)) {
$this->setOptions($options);
}
}
/**
* Set return value
*
* @param string $returnType
* @return \Zend\Server\Method\Prototype
*/
public function setReturnType($returnType)
{
$this->returnType = $returnType;
return $this;
}
/**
* Retrieve return type
*
* @return string
*/
public function getReturnType()
{
return $this->returnType;
}
/**
* Add a parameter
*
* @param string $parameter
* @return \Zend\Server\Method\Prototype
*/
public function addParameter($parameter)
{
if ($parameter instanceof Parameter) {
$this->parameters[] = $parameter;
if (null !== ($name = $parameter->getName())) {
$this->parameterNameMap[$name] = count($this->parameters) - 1;
}
} else {
$parameter = new Parameter([
'type' => (string) $parameter,
]);
$this->parameters[] = $parameter;
}
return $this;
}
/**
* Add parameters
*
* @param array $parameters
* @return \Zend\Server\Method\Prototype
*/
public function addParameters(array $parameters)
{
foreach ($parameters as $parameter) {
$this->addParameter($parameter);
}
return $this;
}
/**
* Set parameters
*
* @param array $parameters
* @return \Zend\Server\Method\Prototype
*/
public function setParameters(array $parameters)
{
$this->parameters = [];
$this->parameterNameMap = [];
$this->addParameters($parameters);
return $this;
}
/**
* Retrieve parameters as list of types
*
* @return array
*/
public function getParameters()
{
$types = [];
foreach ($this->parameters as $parameter) {
$types[] = $parameter->getType();
}
return $types;
}
/**
* Get parameter objects
*
* @return array
*/
public function getParameterObjects()
{
return $this->parameters;
}
/**
* Retrieve a single parameter by name or index
*
* @param string|int $index
* @return null|\Zend\Server\Method\Parameter
*/
public function getParameter($index)
{
if (! is_string($index) && ! is_numeric($index)) {
return;
}
if (array_key_exists($index, $this->parameterNameMap)) {
$index = $this->parameterNameMap[$index];
}
if (array_key_exists($index, $this->parameters)) {
return $this->parameters[$index];
}
return;
}
/**
* Set object state from array
*
* @param array $options
* @return \Zend\Server\Method\Prototype
*/
public function setOptions(array $options)
{
foreach ($options as $key => $value) {
$method = 'set' . ucfirst($key);
if (method_exists($this, $method)) {
$this->$method($value);
}
}
return $this;
}
/**
* Serialize to array
*
* @return array
*/
public function toArray()
{
return [
'returnType' => $this->getReturnType(),
'parameters' => $this->getParameters(),
];
}
}

View File

@@ -0,0 +1,84 @@
<?php
/**
* @see https://github.com/zendframework/zend-server for the canonical source repository
* @copyright Copyright (c) 2005-2018 Zend Technologies USA Inc. (https://www.zend.com)
* @license https://github.com/zendframework/zend-server/blob/master/LICENSE.md New BSD License
*/
namespace Zend\Server;
use Zend\Server\Reflection\ReflectionClass;
use Zend\Server\Reflection\ReflectionFunction;
/**
* Reflection for determining method signatures to use with server classes
*/
class Reflection
{
/**
* Perform class reflection to create dispatch signatures
*
* Creates a {@link \Zend\Server\Reflection\ClassReflection} object for the class or
* object provided.
*
* If extra arguments should be passed to dispatchable methods, these may
* be provided as an array to $argv.
*
* @param string|object $class Class name or object
* @param bool|array $argv Optional arguments to be used during the method call
* @param string $namespace Optional namespace with which to prefix the
* method name (used for the signature key). Primarily to avoid collisions,
* also for XmlRpc namespacing
* @return \Zend\Server\Reflection\ReflectionClass
* @throws \Zend\Server\Reflection\Exception\InvalidArgumentException
*/
public static function reflectClass($class, $argv = false, $namespace = '')
{
if (is_object($class)) {
$reflection = new \ReflectionObject($class);
} elseif (is_string($class) && class_exists($class)) {
$reflection = new \ReflectionClass($class);
} else {
throw new Reflection\Exception\InvalidArgumentException('Invalid class or object passed to attachClass()');
}
if ($argv && ! is_array($argv)) {
throw new Reflection\Exception\InvalidArgumentException('Invalid argv argument passed to reflectClass');
}
return new ReflectionClass($reflection, $namespace, $argv);
}
/**
* Perform function reflection to create dispatch signatures
*
* Creates dispatch prototypes for a function. It returns a
* {@link Zend\Server\Reflection\FunctionReflection} object.
*
* If extra arguments should be passed to the dispatchable function, these
* may be provided as an array to $argv.
*
* @param string $function Function name
* @param bool|array $argv Optional arguments to be used during the method call
* @param string $namespace Optional namespace with which to prefix the
* function name (used for the signature key). Primarily to avoid
* collisions, also for XmlRpc namespacing
* @return \Zend\Server\Reflection\ReflectionFunction
* @throws \Zend\Server\Reflection\Exception\InvalidArgumentException
*/
public static function reflectFunction($function, $argv = false, $namespace = '')
{
if (! is_string($function) || ! function_exists($function)) {
throw new Reflection\Exception\InvalidArgumentException(sprintf(
'Invalid function "%s" passed to reflectFunction',
$function
));
}
if ($argv && ! is_array($argv)) {
throw new Reflection\Exception\InvalidArgumentException('Invalid argv argument passed to reflectFunction');
}
return new ReflectionFunction(new \ReflectionFunction($function), $namespace, $argv);
}
}

View File

@@ -0,0 +1,485 @@
<?php
/**
* @see https://github.com/zendframework/zend-server for the canonical source repository
* @copyright Copyright (c) 2005-2018 Zend Technologies USA Inc. (https://www.zend.com)
* @license https://github.com/zendframework/zend-server/blob/master/LICENSE.md New BSD License
*/
namespace Zend\Server\Reflection;
use ReflectionClass as PhpReflectionClass;
use ReflectionFunction as PhpReflectionFunction;
use ReflectionFunctionAbstract;
use ReflectionMethod as PhpReflectionMethod;
use Zend\Code\Reflection\DocBlockReflection;
/**
* Function/Method Reflection
*
* Decorates a ReflectionFunction. Allows setting and retrieving an alternate
* 'service' name (i.e., the name to be used when calling via a service),
* setting and retrieving the description (originally set using the docblock
* contents), retrieving the callback and callback type, retrieving additional
* method invocation arguments, and retrieving the
* method {@link \Zend\Server\Reflection\Prototype prototypes}.
*/
abstract class AbstractFunction
{
/**
* @var ReflectionFunctionAbstract
*/
protected $reflection;
/**
* Additional arguments to pass to method on invocation
* @var array
*/
protected $argv = [];
/**
* Used to store extra configuration for the method (typically done by the
* server class, e.g., to indicate whether or not to instantiate a class).
* Associative array; access is as properties via {@link __get()} and
* {@link __set()}
* @var array
*/
protected $config = [];
/**
* Declaring class (needed for when serialization occurs)
* @var string
*/
protected $class;
/**
* Function name (needed for serialization)
* @var string
*/
protected $name;
/**
* Function/method description
* @var string
*/
protected $description = '';
/**
* Namespace with which to prefix function/method name
* @var string
*/
protected $namespace;
/**
* Prototypes
* @var array
*/
protected $prototypes = [];
/**
* Phpdoc comment
* @var string
*/
protected $docComment = '';
protected $return;
protected $returnDesc;
protected $paramDesc;
protected $sigParams;
protected $sigParamsDepth;
/**
* Constructor
*
* @param ReflectionFunctionAbstract $r
* @param null|string $namespace
* @param null|array $argv
* @throws Exception\InvalidArgumentException
* @throws Exception\RuntimeException
*/
public function __construct(ReflectionFunctionAbstract $r, $namespace = null, $argv = [])
{
$this->reflection = $r;
// Determine namespace
if (null !== $namespace) {
$this->setNamespace($namespace);
}
// Determine arguments
if (is_array($argv)) {
$this->argv = $argv;
}
// If method call, need to store some info on the class
if ($r instanceof PhpReflectionMethod) {
$this->class = $r->getDeclaringClass()->getName();
}
$this->name = $r->getName();
// Perform some introspection
$this->reflect();
}
/**
* Create signature node tree
*
* Recursive method to build the signature node tree. Increments through
* each array in {@link $sigParams}, adding every value of the next level
* to the current value (unless the current value is null).
*
* @param \Zend\Server\Reflection\Node $parent
* @param int $level
* @return void
*/
protected function addTree(Node $parent, $level = 0)
{
if ($level >= $this->sigParamsDepth) {
return;
}
foreach ($this->sigParams[$level] as $value) {
$node = new Node($value, $parent);
if ((null !== $value) && ($this->sigParamsDepth > $level + 1)) {
$this->addTree($node, $level + 1);
}
}
}
/**
* Build the signature tree
*
* Builds a signature tree starting at the return values and descending
* through each method argument. Returns an array of
* {@link \Zend\Server\Reflection\Node}s.
*
* @return array
*/
protected function buildTree()
{
$returnTree = [];
foreach ($this->return as $value) {
$node = new Node($value);
$this->addTree($node);
$returnTree[] = $node;
}
return $returnTree;
}
/**
* Build method signatures
*
* Builds method signatures using the array of return types and the array of
* parameters types
*
* @param array $return Array of return types
* @param string $returnDesc Return value description
* @param array $paramTypes Array of arguments (each an array of types)
* @param array $paramDesc Array of parameter descriptions
* @return array
*/
protected function buildSignatures($return, $returnDesc, $paramTypes, $paramDesc)
{
$this->return = $return;
$this->returnDesc = $returnDesc;
$this->paramDesc = $paramDesc;
$this->sigParams = $paramTypes;
$this->sigParamsDepth = count($paramTypes);
$signatureTrees = $this->buildTree();
$signatures = [];
$endPoints = [];
foreach ($signatureTrees as $root) {
$tmp = $root->getEndPoints();
if (empty($tmp)) {
$endPoints = array_merge($endPoints, [$root]);
} else {
$endPoints = array_merge($endPoints, $tmp);
}
}
foreach ($endPoints as $node) {
if (! $node instanceof Node) {
continue;
}
$signature = [];
do {
array_unshift($signature, $node->getValue());
$node = $node->getParent();
} while ($node instanceof Node);
$signatures[] = $signature;
}
// Build prototypes
$params = $this->reflection->getParameters();
foreach ($signatures as $signature) {
$return = new ReflectionReturnValue(array_shift($signature), $this->returnDesc);
$tmp = [];
foreach ($signature as $key => $type) {
$param = new ReflectionParameter(
$params[$key],
$type,
(isset($this->paramDesc[$key]) ? $this->paramDesc[$key] : null)
);
$param->setPosition($key);
$tmp[] = $param;
}
$this->prototypes[] = new Prototype($return, $tmp);
}
}
/**
* Use code reflection to create method signatures
*
* Determines the method help/description text from the function DocBlock
* comment. Determines method signatures using a combination of
* ReflectionFunction and parsing of DocBlock @param and @return values.
*
* @throws Exception\RuntimeException
* @return array
*/
protected function reflect()
{
$function = $this->reflection;
$paramCount = $function->getNumberOfParameters();
$parameters = $function->getParameters();
if (! $this->docComment) {
$this->docComment = $function->getDocComment();
}
$scanner = new DocBlockReflection(($this->docComment) ? : '/***/');
$helpText = $scanner->getLongDescription();
/* @var \Zend\Code\Reflection\DocBlock\Tag\ParamTag[] $paramTags */
$paramTags = $scanner->getTags('param');
/* @var \Zend\Code\Reflection\DocBlock\Tag\ReturnTag $returnTag */
$returnTag = $scanner->getTag('return');
if (empty($helpText)) {
$helpText = $scanner->getShortDescription();
if (empty($helpText)) {
$helpText = $function->getName();
}
}
$this->setDescription($helpText);
if ($returnTag) {
$return = [];
$returnDesc = $returnTag->getDescription();
foreach ($returnTag->getTypes() as $type) {
$return[] = $type;
}
} else {
$return = ['void'];
$returnDesc = '';
}
$paramTypesTmp = [];
$paramDesc = [];
if (empty($paramTags)) {
foreach ($parameters as $param) {
$paramTypesTmp[] = [($param->isArray()) ? 'array' : 'mixed'];
$paramDesc[] = '';
}
} else {
$paramDesc = [];
foreach ($paramTags as $paramTag) {
$paramTypesTmp[] = $paramTag->getTypes();
$paramDesc[] = ($paramTag->getDescription()) ? : '';
}
}
// Get all param types as arrays
$nParamTypesTmp = count($paramTypesTmp);
if ($nParamTypesTmp < $paramCount) {
$start = $paramCount - $nParamTypesTmp;
for ($i = $start; $i < $paramCount; ++$i) {
$paramTypesTmp[$i] = ['mixed'];
$paramDesc[$i] = '';
}
} elseif ($nParamTypesTmp != $paramCount) {
throw new Exception\RuntimeException(
'Variable number of arguments is not supported for services (except optional parameters). '
. 'Number of function arguments must correspond to actual number of arguments described in a docblock.'
);
}
$paramTypes = [];
foreach ($paramTypesTmp as $i => $param) {
if ($parameters[$i]->isOptional()) {
array_unshift($param, null);
}
$paramTypes[] = $param;
}
$this->buildSignatures($return, $returnDesc, $paramTypes, $paramDesc);
}
/**
* Proxy reflection calls
*
* @param string $method
* @param array $args
* @throws Exception\BadMethodCallException
* @return mixed
*/
public function __call($method, $args)
{
if (method_exists($this->reflection, $method)) {
return call_user_func_array([$this->reflection, $method], $args);
}
throw new Exception\BadMethodCallException('Invalid reflection method ("' . $method . '")');
}
/**
* Retrieve configuration parameters
*
* Values are retrieved by key from {@link $config}. Returns null if no
* value found.
*
* @param string $key
* @return mixed
*/
public function __get($key)
{
if (isset($this->config[$key])) {
return $this->config[$key];
}
return;
}
/**
* Set configuration parameters
*
* Values are stored by $key in {@link $config}.
*
* @param string $key
* @param mixed $value
* @return void
*/
public function __set($key, $value)
{
$this->config[$key] = $value;
}
/**
* Set method's namespace
*
* @param string $namespace
* @throws Exception\InvalidArgumentException
* @return void
*/
public function setNamespace($namespace)
{
if (empty($namespace)) {
$this->namespace = '';
return;
}
if (! is_string($namespace) || ! preg_match('/[a-z0-9_\.]+/i', $namespace)) {
throw new Exception\InvalidArgumentException('Invalid namespace');
}
$this->namespace = $namespace;
}
/**
* Return method's namespace
*
* @return string
*/
public function getNamespace()
{
return $this->namespace;
}
/**
* Set the description
*
* @param string $string
* @throws Exception\InvalidArgumentException
* @return void
*/
public function setDescription($string)
{
if (! is_string($string)) {
throw new Exception\InvalidArgumentException('Invalid description');
}
$this->description = $string;
}
/**
* Retrieve the description
*
* @return string
*/
public function getDescription()
{
return $this->description;
}
/**
* Retrieve all prototypes as array of
* {@link \Zend\Server\Reflection\Prototype}s
*
* @return Prototype[]
*/
public function getPrototypes()
{
return $this->prototypes;
}
/**
* Retrieve additional invocation arguments
*
* @return array
*/
public function getInvokeArguments()
{
return $this->argv;
}
/**
* @return string[]
*/
public function __sleep()
{
$serializable = [];
foreach ($this as $name => $value) {
if ($value instanceof PhpReflectionFunction
|| $value instanceof PhpReflectionMethod
) {
continue;
}
$serializable[] = $name;
}
return $serializable;
}
/**
* Wakeup from serialization
*
* Reflection needs explicit instantiation to work correctly. Re-instantiate
* reflection object on wakeup.
*
* @return void
*/
public function __wakeup()
{
if ($this->reflection instanceof PhpReflectionMethod) {
$class = new PhpReflectionClass($this->class);
$this->reflection = new PhpReflectionMethod($class->newInstance(), $this->name);
} else {
$this->reflection = new PhpReflectionFunction($this->name);
}
}
}

View File

@@ -0,0 +1,14 @@
<?php
/**
* @see https://github.com/zendframework/zend-server for the canonical source repository
* @copyright Copyright (c) 2005-2018 Zend Technologies USA Inc. (https://www.zend.com)
* @license https://github.com/zendframework/zend-server/blob/master/LICENSE.md New BSD License
*/
namespace Zend\Server\Reflection\Exception;
use Zend\Server\Exception;
class BadMethodCallException extends Exception\BadMethodCallException implements ExceptionInterface
{
}

View File

@@ -0,0 +1,17 @@
<?php
/**
* @see https://github.com/zendframework/zend-server for the canonical source repository
* @copyright Copyright (c) 2005-2018 Zend Technologies USA Inc. (https://www.zend.com)
* @license https://github.com/zendframework/zend-server/blob/master/LICENSE.md New BSD License
*/
namespace Zend\Server\Reflection\Exception;
use Zend\Server\Exception\ExceptionInterface as Exception;
/**
* Zend\Server\Reflection exceptions
*/
interface ExceptionInterface extends Exception
{
}

View File

@@ -0,0 +1,14 @@
<?php
/**
* @see https://github.com/zendframework/zend-server for the canonical source repository
* @copyright Copyright (c) 2005-2018 Zend Technologies USA Inc. (https://www.zend.com)
* @license https://github.com/zendframework/zend-server/blob/master/LICENSE.md New BSD License
*/
namespace Zend\Server\Reflection\Exception;
use Zend\Server\Exception;
class InvalidArgumentException extends Exception\InvalidArgumentException implements ExceptionInterface
{
}

View File

@@ -0,0 +1,14 @@
<?php
/**
* @see https://github.com/zendframework/zend-server for the canonical source repository
* @copyright Copyright (c) 2005-2018 Zend Technologies USA Inc. (https://www.zend.com)
* @license https://github.com/zendframework/zend-server/blob/master/LICENSE.md New BSD License
*/
namespace Zend\Server\Reflection\Exception;
use Zend\Server\Exception;
class RuntimeException extends Exception\RuntimeException implements ExceptionInterface
{
}

View File

@@ -0,0 +1,181 @@
<?php
/**
* @see https://github.com/zendframework/zend-server for the canonical source repository
* @copyright Copyright (c) 2005-2018 Zend Technologies USA Inc. (https://www.zend.com)
* @license https://github.com/zendframework/zend-server/blob/master/LICENSE.md New BSD License
*/
namespace Zend\Server\Reflection;
/**
* Node Tree class for Zend\Server reflection operations
*/
class Node
{
/**
* Node value
* @var mixed
*/
protected $value = null;
/**
* Array of child nodes (if any)
* @var array
*/
protected $children = [];
/**
* Parent node (if any)
* @var \Zend\Server\Reflection\Node
*/
protected $parent = null;
/**
* Constructor
*
* @param mixed $value
* @param \Zend\Server\Reflection\Node $parent Optional
* @return \Zend\Server\Reflection\Node
*/
public function __construct($value, Node $parent = null)
{
$this->value = $value;
if (null !== $parent) {
$this->setParent($parent, true);
}
return $this;
}
/**
* Set parent node
*
* @param \Zend\Server\Reflection\Node $node
* @param bool $new Whether or not the child node is newly created
* and should always be attached
* @return void
*/
public function setParent(Node $node, $new = false)
{
$this->parent = $node;
if ($new) {
$node->attachChild($this);
return;
}
}
/**
* Create and attach a new child node
*
* @param mixed $value
* @access public
* @return \Zend\Server\Reflection\Node New child node
*/
public function createChild($value)
{
$child = new static($value, $this);
return $child;
}
/**
* Attach a child node
*
* @param \Zend\Server\Reflection\Node $node
* @return void
*/
public function attachChild(Node $node)
{
$this->children[] = $node;
if ($node->getParent() !== $this) {
$node->setParent($this);
}
}
/**
* Return an array of all child nodes
*
* @return array
*/
public function getChildren()
{
return $this->children;
}
/**
* Does this node have children?
*
* @return bool
*/
public function hasChildren()
{
return count($this->children) > 0;
}
/**
* Return the parent node
*
* @return null|\Zend\Server\Reflection\Node
*/
public function getParent()
{
return $this->parent;
}
/**
* Return the node's current value
*
* @return mixed
*/
public function getValue()
{
return $this->value;
}
/**
* Set the node value
*
* @param mixed $value
* @return void
*/
public function setValue($value)
{
$this->value = $value;
}
/**
* Retrieve the bottommost nodes of this node's tree
*
* Retrieves the bottommost nodes of the tree by recursively calling
* getEndPoints() on all children. If a child is null, it returns the parent
* as an end point.
*
* @return array
*/
public function getEndPoints()
{
$endPoints = [];
if (! $this->hasChildren()) {
return $endPoints;
}
foreach ($this->children as $child) {
$value = $child->getValue();
if (null === $value) {
$endPoints[] = $this;
} elseif ((null !== $value) && $child->hasChildren()) {
$childEndPoints = $child->getEndPoints();
if (! empty($childEndPoints)) {
$endPoints = array_merge($endPoints, $childEndPoints);
}
} elseif ((null !== $value) && ! $child->hasChildren()) {
$endPoints[] = $child;
}
}
return $endPoints;
}
}

View File

@@ -0,0 +1,69 @@
<?php
/**
* @see https://github.com/zendframework/zend-server for the canonical source repository
* @copyright Copyright (c) 2005-2018 Zend Technologies USA Inc. (https://www.zend.com)
* @license https://github.com/zendframework/zend-server/blob/master/LICENSE.md New BSD License
*/
namespace Zend\Server\Reflection;
/**
* Method/Function prototypes
*
* Contains accessors for the return value and all method arguments.
*/
class Prototype
{
/** @var ReflectionParameter[] */
protected $params;
/**
* Constructor
*
* @param ReflectionReturnValue $return
* @param ReflectionParameter[] $params
* @throws Exception\InvalidArgumentException
*/
public function __construct(ReflectionReturnValue $return, array $params = [])
{
$this->return = $return;
foreach ($params as $param) {
if (! $param instanceof ReflectionParameter) {
throw new Exception\InvalidArgumentException('One or more params are invalid');
}
}
$this->params = $params;
}
/**
* Retrieve return type
*
* @return string
*/
public function getReturnType()
{
return $this->return->getType();
}
/**
* Retrieve the return value object
*
* @return \Zend\Server\Reflection\ReflectionReturnValue
*/
public function getReturnValue()
{
return $this->return;
}
/**
* Retrieve method parameters
*
* @return ReflectionParameter[] Array of {@link \Zend\Server\Reflection\ReflectionParameter}s
*/
public function getParameters()
{
return $this->params;
}
}

View File

@@ -0,0 +1,191 @@
<?php
/**
* @see https://github.com/zendframework/zend-server for the canonical source repository
* @copyright Copyright (c) 2005-2018 Zend Technologies USA Inc. (https://www.zend.com)
* @license https://github.com/zendframework/zend-server/blob/master/LICENSE.md New BSD License
*/
namespace Zend\Server\Reflection;
use ReflectionClass as PhpReflectionClass;
/**
* Class/Object reflection
*
* Proxies calls to a ReflectionClass object, and decorates getMethods() by
* creating its own list of {@link Zend\Server\Reflection\ReflectionMethod}s.
*/
class ReflectionClass
{
/**
* Optional configuration parameters; accessible via {@link __get} and
* {@link __set()}
* @var array
*/
protected $config = [];
/**
* Array of {@link \Zend\Server\Reflection\Method}s
* @var array
*/
protected $methods = [];
/**
* Namespace
* @var string
*/
protected $namespace = null;
/**
* ReflectionClass object
* @var PhpReflectionClass
*/
protected $reflection;
/**
* Reflection class name (needed for serialization)
* @var string
*/
protected $name;
/**
* Constructor
*
* Create array of dispatchable methods, each a
* {@link Zend\Server\Reflection\ReflectionMethod}. Sets reflection object property.
*
* @param PhpReflectionClass $reflection
* @param string $namespace
* @param mixed $argv
*/
public function __construct(PhpReflectionClass $reflection, $namespace = null, $argv = false)
{
$this->reflection = $reflection;
$this->name = $reflection->getName();
$this->setNamespace($namespace);
foreach ($reflection->getMethods() as $method) {
// Don't aggregate magic methods
if ('__' == substr($method->getName(), 0, 2)) {
continue;
}
if ($method->isPublic()) {
// Get signatures and description
$this->methods[] = new ReflectionMethod($this, $method, $this->getNamespace(), $argv);
}
}
}
/**
* Proxy reflection calls
*
* @param string $method
* @param array $args
* @throws Exception\BadMethodCallException
* @return mixed
*/
public function __call($method, $args)
{
if (method_exists($this->reflection, $method)) {
return call_user_func_array([$this->reflection, $method], $args);
}
throw new Exception\BadMethodCallException('Invalid reflection method');
}
/**
* Retrieve configuration parameters
*
* Values are retrieved by key from {@link $config}. Returns null if no
* value found.
*
* @param string $key
* @return mixed
*/
public function __get($key)
{
if (isset($this->config[$key])) {
return $this->config[$key];
}
return;
}
/**
* Set configuration parameters
*
* Values are stored by $key in {@link $config}.
*
* @param string $key
* @param mixed $value
* @return void
*/
public function __set($key, $value)
{
$this->config[$key] = $value;
}
/**
* Return array of dispatchable {@link \Zend\Server\Reflection\ReflectionMethod}s.
*
* @access public
* @return array
*/
public function getMethods()
{
return $this->methods;
}
/**
* Get namespace for this class
*
* @return string
*/
public function getNamespace()
{
return $this->namespace;
}
/**
* Set namespace for this class
*
* @param string $namespace
* @throws Exception\InvalidArgumentException
* @return void
*/
public function setNamespace($namespace)
{
if (empty($namespace)) {
$this->namespace = '';
return;
}
if (! is_string($namespace) || ! preg_match('/[a-z0-9_\.]+/i', $namespace)) {
throw new Exception\InvalidArgumentException('Invalid namespace');
}
$this->namespace = $namespace;
}
/**
* Wakeup from serialization
*
* Reflection needs explicit instantiation to work correctly. Re-instantiate
* reflection object on wakeup.
*
* @return void
*/
public function __wakeup()
{
$this->reflection = new PhpReflectionClass($this->name);
}
/**
* @return string[]
*/
public function __sleep()
{
return ['config', 'methods', 'namespace', 'name'];
}
}

View File

@@ -0,0 +1,15 @@
<?php
/**
* @see https://github.com/zendframework/zend-server for the canonical source repository
* @copyright Copyright (c) 2005-2018 Zend Technologies USA Inc. (https://www.zend.com)
* @license https://github.com/zendframework/zend-server/blob/master/LICENSE.md New BSD License
*/
namespace Zend\Server\Reflection;
/**
* Function Reflection
*/
class ReflectionFunction extends AbstractFunction
{
}

View File

@@ -0,0 +1,195 @@
<?php
/**
* @see https://github.com/zendframework/zend-server for the canonical source repository
* @copyright Copyright (c) 2005-2018 Zend Technologies USA Inc. (https://www.zend.com)
* @license https://github.com/zendframework/zend-server/blob/master/LICENSE.md New BSD License
*/
namespace Zend\Server\Reflection;
/**
* Method Reflection
*/
class ReflectionMethod extends AbstractFunction
{
/**
* Doc block inherit tag for search
*/
const INHERIT_TAG = '{@inheritdoc}';
/**
* Parent class name
* @var string
*/
protected $class;
/**
* Parent class reflection
* @var ReflectionClass|\ReflectionClass
*/
protected $classReflection;
/**
* Constructor
*
* @param ReflectionClass $class
* @param \ReflectionMethod $r
* @param string $namespace
* @param array $argv
*/
public function __construct(ReflectionClass $class, \ReflectionMethod $r, $namespace = null, $argv = [])
{
$this->classReflection = $class;
$this->reflection = $r;
$classNamespace = $class->getNamespace();
// Determine namespace
if (! empty($namespace)) {
$this->setNamespace($namespace);
} elseif (! empty($classNamespace)) {
$this->setNamespace($classNamespace);
}
// Determine arguments
if (is_array($argv)) {
$this->argv = $argv;
}
// If method call, need to store some info on the class
$this->class = $class->getName();
$this->name = $r->getName();
// Perform some introspection
$this->reflect();
}
/**
* Return the reflection for the class that defines this method
*
* @return \Zend\Server\Reflection\ReflectionClass
*/
public function getDeclaringClass()
{
return $this->classReflection;
}
/**
* Wakeup from serialization
*
* Reflection needs explicit instantiation to work correctly. Re-instantiate
* reflection object on wakeup.
*
* @return void
*/
public function __wakeup()
{
$this->classReflection = new ReflectionClass(
new \ReflectionClass($this->class),
$this->getNamespace(),
$this->getInvokeArguments()
);
$this->reflection = new \ReflectionMethod($this->classReflection->getName(), $this->name);
}
/**
* {@inheritdoc}
*/
protected function reflect()
{
$docComment = $this->reflection->getDocComment();
if (strpos($docComment, self::INHERIT_TAG) !== false) {
$this->docComment = $this->fetchRecursiveDocComment();
}
parent::reflect();
}
/**
* Fetch all doc comments for inherit values
*
* @return string
*/
private function fetchRecursiveDocComment()
{
$currentMethodName = $this->reflection->getName();
$docCommentList[] = $this->reflection->getDocComment();
// fetch all doc blocks for method from parent classes
$docCommentFetched = $this->fetchRecursiveDocBlockFromParent($this->classReflection, $currentMethodName);
if ($docCommentFetched) {
$docCommentList = array_merge($docCommentList, $docCommentFetched);
}
// fetch doc blocks from interfaces
$interfaceReflectionList = $this->classReflection->getInterfaces();
foreach ($interfaceReflectionList as $interfaceReflection) {
if (! $interfaceReflection->hasMethod($currentMethodName)) {
continue;
}
$docCommentList[] = $interfaceReflection->getMethod($currentMethodName)->getDocComment();
}
$normalizedDocCommentList = array_map(
function ($docComment) {
$docComment = str_replace('/**', '', $docComment);
$docComment = str_replace('*/', '', $docComment);
return $docComment;
},
$docCommentList
);
$docComment = '/**' . implode(PHP_EOL, $normalizedDocCommentList) . '*/';
return $docComment;
}
/**
* Fetch recursive doc blocks from parent classes
*
* @param \ReflectionClass $reflectionClass
* @param string $methodName
*
* @return array|void
*/
private function fetchRecursiveDocBlockFromParent($reflectionClass, $methodName)
{
$docComment = [];
$parentReflectionClass = $reflectionClass->getParentClass();
if (! $parentReflectionClass) {
return;
}
if (! $parentReflectionClass->hasMethod($methodName)) {
return;
}
$methodReflection = $parentReflectionClass->getMethod($methodName);
$docCommentLast = $methodReflection->getDocComment();
$docComment[] = $docCommentLast;
if ($this->isInherit($docCommentLast)) {
if ($docCommentFetched = $this->fetchRecursiveDocBlockFromParent($parentReflectionClass, $methodName)) {
$docComment = array_merge($docComment, $docCommentFetched);
}
}
return $docComment;
}
/**
* Return true if doc block inherit from parent or interface
*
* @param string $docComment
*
* @return bool
*/
private function isInherit($docComment)
{
$isInherit = strpos($docComment, self::INHERIT_TAG) !== false;
return $isInherit;
}
}

View File

@@ -0,0 +1,175 @@
<?php
/**
* @see https://github.com/zendframework/zend-server for the canonical source repository
* @copyright Copyright (c) 2005-2018 Zend Technologies USA Inc. (https://www.zend.com)
* @license https://github.com/zendframework/zend-server/blob/master/LICENSE.md New BSD License
*/
namespace Zend\Server\Reflection;
/**
* Parameter Reflection
*
* Decorates a ReflectionParameter to allow setting the parameter type
*/
class ReflectionParameter
{
/**
* @var \ReflectionParameter
*/
protected $reflection;
/**
* Parameter position
* @var int
*/
protected $position;
/**
* Parameter type
* @var string
*/
protected $type;
/**
* Parameter description
* @var string
*/
protected $description;
/**
* Parameter name (needed for serialization)
* @var string
*/
protected $name;
/**
* Declaring function name (needed for serialization)
* @var string
*/
protected $functionName;
/**
* Constructor
*
* @param \ReflectionParameter $r
* @param string $type Parameter type
* @param string $description Parameter description
*/
public function __construct(\ReflectionParameter $r, $type = 'mixed', $description = '')
{
$this->reflection = $r;
// Store parameters needed for (un)serialization
$this->name = $r->getName();
$this->functionName = $r->getDeclaringClass()
? [$r->getDeclaringClass()->getName(), $r->getDeclaringFunction()->getName()]
: $r->getDeclaringFunction()->getName();
$this->setType($type);
$this->setDescription($description);
}
/**
* Proxy reflection calls
*
* @param string $method
* @param array $args
* @throws Exception\BadMethodCallException
* @return mixed
*/
public function __call($method, $args)
{
if (method_exists($this->reflection, $method)) {
return call_user_func_array([$this->reflection, $method], $args);
}
throw new Exception\BadMethodCallException('Invalid reflection method');
}
/**
* Retrieve parameter type
*
* @return string
*/
public function getType()
{
return $this->type;
}
/**
* Set parameter type
*
* @param string|null $type
* @throws Exception\InvalidArgumentException
* @return void
*/
public function setType($type)
{
if (! is_string($type) && (null !== $type)) {
throw new Exception\InvalidArgumentException('Invalid parameter type');
}
$this->type = $type;
}
/**
* Retrieve parameter description
*
* @return string
*/
public function getDescription()
{
return $this->description;
}
/**
* Set parameter description
*
* @param string|null $description
* @throws Exception\InvalidArgumentException
* @return void
*/
public function setDescription($description)
{
if (! is_string($description) && (null !== $description)) {
throw new Exception\InvalidArgumentException('Invalid parameter description');
}
$this->description = $description;
}
/**
* Set parameter position
*
* @param int $index
* @return void
*/
public function setPosition($index)
{
$this->position = (int) $index;
}
/**
* Return parameter position
*
* @return int
*/
public function getPosition()
{
return $this->position;
}
/**
* @return string[]
*/
public function __sleep()
{
return ['position', 'type', 'description', 'name', 'functionName'];
}
public function __wakeup()
{
$this->reflection = new \ReflectionParameter($this->functionName, $this->name);
}
}

View File

@@ -0,0 +1,92 @@
<?php
/**
* @see https://github.com/zendframework/zend-server for the canonical source repository
* @copyright Copyright (c) 2005-2018 Zend Technologies USA Inc. (https://www.zend.com)
* @license https://github.com/zendframework/zend-server/blob/master/LICENSE.md New BSD License
*/
namespace Zend\Server\Reflection;
/**
* Return value reflection
*
* Stores the return value type and description
*/
class ReflectionReturnValue
{
/**
* Return value type
* @var string
*/
protected $type;
/**
* Return value description
* @var string
*/
protected $description;
/**
* Constructor
*
* @param string $type Return value type
* @param string $description Return value type
*/
public function __construct($type = 'mixed', $description = '')
{
$this->setType($type);
$this->setDescription($description);
}
/**
* Retrieve parameter type
*
* @return string
*/
public function getType()
{
return $this->type;
}
/**
* Set parameter type
*
* @param string|null $type
* @throws Exception\InvalidArgumentException
* @return void
*/
public function setType($type)
{
if (! is_string($type) && (null !== $type)) {
throw new Exception\InvalidArgumentException('Invalid parameter type');
}
$this->type = $type;
}
/**
* Retrieve parameter description
*
* @return string
*/
public function getDescription()
{
return $this->description;
}
/**
* Set parameter description
*
* @param string|null $description
* @throws Exception\InvalidArgumentException
* @return void
*/
public function setDescription($description)
{
if (! is_string($description) && (null !== $description)) {
throw new Exception\InvalidArgumentException('Invalid parameter description');
}
$this->description = $description;
}
}

View File

@@ -0,0 +1,125 @@
<?php
/**
* @see https://github.com/zendframework/zend-server for the canonical source repository
* @copyright Copyright (c) 2005-2018 Zend Technologies USA Inc. (https://www.zend.com)
* @license https://github.com/zendframework/zend-server/blob/master/LICENSE.md New BSD License
*/
namespace Zend\Server;
/**
* Server Interface
*/
interface Server
{
/**
* Attach a function as a server method
*
* Namespacing is primarily for xmlrpc, but may be used with other
* implementations to prevent naming collisions.
*
* @param string $function
* @param string $namespace
* @param null|array Optional array of arguments to pass to callback at
* dispatch.
* @return void
*/
public function addFunction($function, $namespace = '');
/**
* Attach a class to a server
*
* The individual implementations should probably allow passing a variable
* number of arguments in, so that developers may define custom runtime
* arguments to pass to server methods.
*
* Namespacing is primarily for xmlrpc, but could be used for other
* implementations as well.
*
* @param mixed $class Class name or object instance to examine and attach
* to the server.
* @param string $namespace Optional namespace with which to prepend method
* names in the dispatch table.
* methods in the class will be valid callbacks.
* @param null|array Optional array of arguments to pass to callbacks at
* dispatch.
* @return void
*/
public function setClass($class, $namespace = '', $argv = null);
/**
* Generate a server fault
*
* @param mixed $fault
* @param int $code
* @return mixed
*/
public function fault($fault = null, $code = 404);
/**
* Handle a request
*
* Requests may be passed in, or the server may automatically determine the
* request based on defaults. Dispatches server request to appropriate
* method and returns a response
*
* @param mixed $request
* @return mixed
*/
public function handle($request = false);
/**
* Return a server definition array
*
* Returns a server definition array as created using
* {@link Reflection}. Can be used for server introspection,
* documentation, or persistence.
*
* @return array
*/
public function getFunctions();
/**
* Load server definition
*
* Used for persistence; loads a construct as returned by {@link getFunctions()}.
*
* @param array $definition
* @return void
*/
public function loadFunctions($definition);
/**
* Set server persistence
*
* @todo Determine how to implement this
* @param int $mode
* @return void
*/
public function setPersistence($mode);
/**
* Sets auto-response flag for the server.
*
* To unify all servers, default behavior should be to auto-emit response.
*
* @param bool $flag
* @return Server Self instance.
*/
public function setReturnResponse($flag = true);
/**
* Returns auto-response flag of the server.
*
* @return bool $flag Current status.
*/
public function getReturnResponse();
/**
* Returns last produced response.
*
* @return string|object Content of last response, or response object that
* implements __toString() methods.
*/
public function getResponse();
}