Вход Регистрация
Файл: vendor/psy/psysh/src/Readline/Hoa/Xcallable.php
Строк: 170
<?php

/**
 * Hoa
 *
 *
 * @license
 *
 * New BSD License
 *
 * Copyright © 2007-2017, Hoa community. 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 the Hoa 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 HOLDERS AND 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.
 */

namespace PsyReadlineHoa;

/**
 * Build a callable object, i.e. `function`, `class::method`, `object->method` or
 * closure. They all have the same behaviour. This callable is an extension of
 * native PHP callable (aka callback) to integrate Hoa's structures.
 */
class Xcallable
{
    
/**
     * Callback with the PHP format.
     */
    
protected $_callback null;

    
/**
     * Callable hash.
     */
    
protected $_hash null;

    
/**
     * Allocates a xcallable based on a callback.
     *
     * Accepted forms:
     *     * `'function'`,
     *     * `'class::method'`,
     *     * `'class', 'method'`,
     *     * `$object, 'method'`,
     *     * `$object, ''`,
     *     * `function (…) { … }`,
     *     * `['class', 'method']`,
     *     * `[$object, 'method']`.
     *
     * # Examples
     *
     * ```php
     * $toUpper = new HoaConsistencyXcallable('strtoupper');
     * assert('FOO' === $toUpper('foo'));
     * ```
     *
     * # Exceptions
     *
     * A `HoaConsistencyException` exception is thrown if the callback form
     * is invalid.
     *
     * ```php,must_throw(HoaConsistencyException)
     * new HoaConsistencyXcallable('Foo:');
     * ```
     */
    
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 StreamOut) {
                    
$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])) {
                    
$this->__construct($call[0]);
                    return;
                }

                
$this->__construct($call[0], $call[1]);
                return;
            } else {
                throw new 
Exception('Bad callback form.'3);
            }
        }

        
$this->_callback = [$call$able];

        return;
    }

    
/**
     * Calls the callable.
     */
    
public function __invoke(...$arguments)
    {
        
$callback $this->getValidCallback($arguments);

        return 
$callback(...$arguments);
    }

    
/**
     * Returns a valid PHP callback.
     */
    
public function getValidCallback(array &$arguments = [])
    {
        
$callback $this->_callback;
        
$head null;

        if (isset(
$arguments[0])) {
            
$head = &$arguments[0];
        }

        
// If method is undetermined, we find it (we understand event bucket and
        // stream).
        
if (null !== $head &&
            
is_array($callback) &&
            
null === $callback[1]) {
            if (
$head instanceof EventBucket) {
                
$head $head->getData();
            }

            switch (
$type gettype($head)) {
                case 
'string':
                    if (
=== 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;
    }

    
/**
     * Computes the hash of this callable.
     *
     * Will produce:
     *     * `function#…`,
     *     * `class#…::…`,
     *     * `object(…)#…::…`,
     *     * `closure(…)`.
     */
    
public function getHash(): string
    
{
        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($_).')';
    }

    
/**
     * The string representation of a callable is its hash.
     */
    
public function __toString(): string
    
{
        return 
$this->getHash();
    }

    
/**
     * Hoa's xcallable() helper.
     */
    
public static function from($call$able '')
    {
        if (
$call instanceof self) {
            return 
$call;
        }

        return new 
self($call$able);
    }
}
Онлайн: 0
Реклама