123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317 |
- <?php
- namespace Hoa\Consistency;
- use Hoa\Event;
- use Hoa\Stream;
- class Xcallable
- {
-
- protected $_callback = null;
-
- protected $_hash = null;
-
- public function __construct($call, $able = '')
- {
- if ($call instanceof \Closure) {
- $this->_callback = $call;
- return;
- }
- if (!is_string($able)) {
- throw new Exception(
- 'Bad callback form; the able part must be a string.',
- 0
- );
- }
- if ('' === $able) {
- if (is_string($call)) {
- if (false === strpos($call, '::')) {
- if (!function_exists($call)) {
- throw new Exception(
- 'Bad callback form; function %s does not exist.',
- 1,
- $call
- );
- }
- $this->_callback = $call;
- return;
- }
- list($call, $able) = explode('::', $call);
- } elseif (is_object($call)) {
- if ($call instanceof Stream\IStream\Out) {
- $able = null;
- } elseif (method_exists($call, '__invoke')) {
- $able = '__invoke';
- } else {
- throw new Exception(
- 'Bad callback form; an object but without a known ' .
- 'method.',
- 2
- );
- }
- } elseif (is_array($call) && isset($call[0])) {
- if (!isset($call[1])) {
- return $this->__construct($call[0]);
- }
- return $this->__construct($call[0], $call[1]);
- } else {
- throw new Exception(
- 'Bad callback form.',
- 3
- );
- }
- }
- $this->_callback = [$call, $able];
- return;
- }
-
- public function __invoke()
- {
- $arguments = func_get_args();
- $valid = $this->getValidCallback($arguments);
- return call_user_func_array($valid, $arguments);
- }
-
- public function distributeArguments(array $arguments)
- {
- return call_user_func_array([$this, '__invoke'], $arguments);
- }
-
- public function getValidCallback(array &$arguments = [])
- {
- $callback = $this->_callback;
- $head = null;
- if (isset($arguments[0])) {
- $head = &$arguments[0];
- }
-
-
- if (null !== $head &&
- is_array($callback) &&
- null === $callback[1]) {
- if ($head instanceof Event\Bucket) {
- $head = $head->getData();
- }
- switch ($type = gettype($head)) {
- case 'string':
- if (1 === strlen($head)) {
- $method = 'writeCharacter';
- } else {
- $method = 'writeString';
- }
- break;
- case 'boolean':
- case 'integer':
- case 'array':
- $method = 'write' . ucfirst($type);
- break;
- case 'double':
- $method = 'writeFloat';
- break;
- default:
- $method = 'writeAll';
- $head = $head . "\n";
- }
- $callback[1] = $method;
- }
- return $callback;
- }
-
- public function getHash()
- {
- if (null !== $this->_hash) {
- return $this->_hash;
- }
- $_ = &$this->_callback;
- if (is_string($_)) {
- return $this->_hash = 'function#' . $_;
- }
- if (is_array($_)) {
- return
- $this->_hash =
- (is_object($_[0])
- ? 'object(' . spl_object_hash($_[0]) . ')' .
- '#' . get_class($_[0])
- : 'class#' . $_[0]) .
- '::' .
- (null !== $_[1]
- ? $_[1]
- : '???');
- }
- return $this->_hash = 'closure(' . spl_object_hash($_) . ')';
- }
-
- public function getReflection()
- {
- $arguments = func_get_args();
- $valid = $this->getValidCallback($arguments);
- if (is_string($valid)) {
- return new \ReflectionFunction($valid);
- }
- if ($valid instanceof \Closure) {
- return new \ReflectionFunction($valid);
- }
- if (is_array($valid)) {
- if (is_string($valid[0])) {
- if (false === method_exists($valid[0], $valid[1])) {
- return new \ReflectionClass($valid[0]);
- }
- return new \ReflectionMethod($valid[0], $valid[1]);
- }
- $object = new \ReflectionObject($valid[0]);
- if (null === $valid[1]) {
- return $object;
- }
- return $object->getMethod($valid[1]);
- }
- }
-
- public function __toString()
- {
- return $this->getHash();
- }
- }
|