Вход Регистрация
Файл: vendor/mockery/mockery/library/Mockery.php
Строк: 994
<?php
/**
 * Mockery
 *
 * LICENSE
 *
 * This source file is subject to the new BSD license that is bundled
 * with this package in the file LICENSE.txt.
 * It is also available through the world-wide-web at this URL:
 * http://github.com/padraic/mockery/blob/master/LICENSE
 * If you did not receive a copy of the license and are unable to
 * obtain it through the world-wide-web, please send an email
 * to padraic@php.net so we can send you a copy immediately.
 *
 * @category   Mockery
 * @package    Mockery
 * @copyright  Copyright (c) 2010 Pádraic Brady (http://blog.astrumfutura.com)
 * @license    http://github.com/padraic/mockery/blob/master/LICENSE New BSD License
 */

use MockeryClosureWrapper;
use 
MockeryExpectationInterface;
use 
MockeryGeneratorCachingGenerator;
use 
MockeryGeneratorGenerator;
use 
MockeryGeneratorMockConfigurationBuilder;
use 
MockeryGeneratorMockNameBuilder;
use 
MockeryGeneratorStringManipulationGenerator;
use 
MockeryLoaderEvalLoader;
use 
MockeryLoaderLoader;
use 
MockeryMatcherMatcherAbstract;
use 
MockeryReflector;

class 
Mockery
{
    const 
BLOCKS 'Mockery_Forward_Blocks';

    
/**
     * Global container to hold all mocks for the current unit test running.
     *
     * @var MockeryContainer|null
     */
    
protected static $_container null;

    
/**
     * Global configuration handler containing configuration options.
     *
     * @var MockeryConfiguration
     */
    
protected static $_config null;

    
/**
     * @var MockeryGeneratorGenerator
     */
    
protected static $_generator;

    
/**
     * @var MockeryLoaderLoader
     */
    
protected static $_loader;

    
/**
     * @var array
     */
    
private static $_filesToCleanUp = [];

    
/**
     * Defines the global helper functions
     *
     * @return void
     */
    
public static function globalHelpers()
    {
        require_once 
__DIR__ '/helpers.php';
    }

    
/**
     * @return array
     *
     * @deprecated since 1.3.2 and will be removed in 2.0.
     */
    
public static function builtInTypes()
    {
        return array(
            
'array',
            
'bool',
            
'callable',
            
'float',
            
'int',
            
'iterable',
            
'object',
            
'self',
            
'string',
            
'void',
        );
    }

    
/**
     * @param string $type
     * @return bool
     *
     * @deprecated since 1.3.2 and will be removed in 2.0.
     */
    
public static function isBuiltInType($type)
    {
        return 
in_array($typeMockery::builtInTypes());
    }

    
/**
     * Static shortcut to MockeryContainer::mock().
     *
     * @param mixed ...$args
     *
     * @return MockeryMockInterface|MockeryLegacyMockInterface
     */
    
public static function mock(...$args)
    {
        return 
call_user_func_array(array(self::getContainer(), 'mock'), $args);
    }

    
/**
     * Static and semantic shortcut for getting a mock from the container
     * and applying the spy's expected behavior into it.
     *
     * @param mixed ...$args
     *
     * @return MockeryMockInterface|MockeryLegacyMockInterface
     */
    
public static function spy(...$args)
    {
        if (
count($args) && $args[0] instanceof Closure) {
            
$args[0] = new ClosureWrapper($args[0]);
        }

        return 
call_user_func_array(array(self::getContainer(), 'mock'), $args)->shouldIgnoreMissing();
    }

    
/**
     * Static and Semantic shortcut to MockeryContainer::mock().
     *
     * @param mixed ...$args
     *
     * @return MockeryMockInterface|MockeryLegacyMockInterface
     */
    
public static function instanceMock(...$args)
    {
        return 
call_user_func_array(array(self::getContainer(), 'mock'), $args);
    }

    
/**
     * Static shortcut to MockeryContainer::mock(), first argument names the mock.
     *
     * @param mixed ...$args
     *
     * @return MockeryMockInterface|MockeryLegacyMockInterface
     */
    
public static function namedMock(...$args)
    {
        
$name array_shift($args);

        
$builder = new MockConfigurationBuilder();
        
$builder->setName($name);

        
array_unshift($args$builder);

        return 
call_user_func_array(array(self::getContainer(), 'mock'), $args);
    }

    
/**
     * Static shortcut to MockeryContainer::self().
     *
     * @throws LogicException
     *
     * @return MockeryMockInterface|MockeryLegacyMockInterface
     */
    
public static function self()
    {
        if (
is_null(self::$_container)) {
            throw new 
LogicException('You have not declared any mocks yet');
        }

        return 
self::$_container->self();
    }

    
/**
     * Static shortcut to closing up and verifying all mocks in the global
     * container, and resetting the container static variable to null.
     *
     * @return void
     */
    
public static function close()
    {
        foreach (
self::$_filesToCleanUp as $fileName) {
            @
unlink($fileName);
        }
        
self::$_filesToCleanUp = [];

        if (
is_null(self::$_container)) {
            return;
        }

        
$container self::$_container;
        
self::$_container null;

        
$container->mockery_teardown();
        
$container->mockery_close();
    }

    
/**
     * Static fetching of a mock associated with a name or explicit class poser.
     *
     * @param string $name
     *
     * @return MockeryMock
     */
    
public static function fetchMock($name)
    {
        return 
self::getContainer()->fetchMock($name);
    }

    
/**
     * Lazy loader and getter for
     * the container property.
     *
     * @return MockeryContainer
     */
    
public static function getContainer()
    {
        if (
is_null(self::$_container)) {
            
self::$_container = new MockeryContainer(self::getGenerator(), self::getLoader());
        }

        return 
self::$_container;
    }

    
/**
     * Setter for the $_generator static property.
     *
     * @param MockeryGeneratorGenerator $generator
     */
    
public static function setGenerator(Generator $generator)
    {
        
self::$_generator $generator;
    }

    
/**
     * Lazy loader method and getter for
     * the generator property.
     *
     * @return Generator
     */
    
public static function getGenerator()
    {
        if (
is_null(self::$_generator)) {
            
self::$_generator self::getDefaultGenerator();
        }

        return 
self::$_generator;
    }

    
/**
     * Creates and returns a default generator
     * used inside this class.
     *
     * @return CachingGenerator
     */
    
public static function getDefaultGenerator()
    {
        return new 
CachingGenerator(StringManipulationGenerator::withDefaultPasses());
    }

    
/**
     * Setter for the $_loader static property.
     *
     * @param Loader $loader
     */
    
public static function setLoader(Loader $loader)
    {
        
self::$_loader $loader;
    }

    
/**
     * Lazy loader method and getter for
     * the $_loader property.
     *
     * @return Loader
     */
    
public static function getLoader()
    {
        if (
is_null(self::$_loader)) {
            
self::$_loader self::getDefaultLoader();
        }

        return 
self::$_loader;
    }

    
/**
     * Gets an EvalLoader to be used as default.
     *
     * @return EvalLoader
     */
    
public static function getDefaultLoader()
    {
        return new 
EvalLoader();
    }

    
/**
     * Set the container.
     *
     * @param MockeryContainer $container
     *
     * @return MockeryContainer
     */
    
public static function setContainer(MockeryContainer $container)
    {
        return 
self::$_container $container;
    }

    
/**
     * Reset the container to null.
     *
     * @return void
     */
    
public static function resetContainer()
    {
        
self::$_container null;
    }

    
/**
     * Return instance of ANY matcher.
     *
     * @return MockeryMatcherAny
     */
    
public static function any()
    {
        return new 
MockeryMatcherAny();
    }

    
/**
     * Return instance of AndAnyOtherArgs matcher.
     *
     * An alternative name to `andAnyOtherArgs` so
     * the API stays closer to `any` as well.
     *
     * @return MockeryMatcherAndAnyOtherArgs
     */
    
public static function andAnyOthers()
    {
        return new 
MockeryMatcherAndAnyOtherArgs();
    }

    
/**
     * Return instance of AndAnyOtherArgs matcher.
     *
     * @return MockeryMatcherAndAnyOtherArgs
     */
    
public static function andAnyOtherArgs()
    {
        return new 
MockeryMatcherAndAnyOtherArgs();
    }

    
/**
     * Return instance of TYPE matcher.
     *
     * @param mixed $expected
     *
     * @return MockeryMatcherType
     */
    
public static function type($expected)
    {
        return new 
MockeryMatcherType($expected);
    }

    
/**
     * Return instance of DUCKTYPE matcher.
     *
     * @param array ...$args
     *
     * @return MockeryMatcherDucktype
     */
    
public static function ducktype(...$args)
    {
        return new 
MockeryMatcherDucktype($args);
    }

    
/**
     * Return instance of SUBSET matcher.
     *
     * @param array $part
     * @param bool $strict - (Optional) True for strict comparison, false for loose
     *
     * @return MockeryMatcherSubset
     */
    
public static function subset(array $part$strict true)
    {
        return new 
MockeryMatcherSubset($part$strict);
    }

    
/**
     * Return instance of CONTAINS matcher.
     *
     * @param mixed $args
     *
     * @return MockeryMatcherContains
     */
    
public static function contains(...$args)
    {
        return new 
MockeryMatcherContains($args);
    }

    
/**
     * Return instance of HASKEY matcher.
     *
     * @param mixed $key
     *
     * @return MockeryMatcherHasKey
     */
    
public static function hasKey($key)
    {
        return new 
MockeryMatcherHasKey($key);
    }

    
/**
     * Return instance of HASVALUE matcher.
     *
     * @param mixed $val
     *
     * @return MockeryMatcherHasValue
     */
    
public static function hasValue($val)
    {
        return new 
MockeryMatcherHasValue($val);
    }

    
/**
     * Return instance of CLOSURE matcher.
     *
     * @param $reference
     *
     * @return MockeryMatcherClosure
     */
    
public static function capture(&$reference)
    {
        
$closure = function ($argument) use (&$reference) {
            
$reference $argument;
            return 
true;
        };

        return new 
MockeryMatcherClosure($closure);
    }

    
/**
     * Return instance of CLOSURE matcher.
     *
     * @param mixed $closure
     *
     * @return MockeryMatcherClosure
     */
    
public static function on($closure)
    {
        return new 
MockeryMatcherClosure($closure);
    }

    
/**
     * Return instance of MUSTBE matcher.
     *
     * @param mixed $expected
     *
     * @return MockeryMatcherMustBe
     */
    
public static function mustBe($expected)
    {
        return new 
MockeryMatcherMustBe($expected);
    }

    
/**
     * Return instance of NOT matcher.
     *
     * @param mixed $expected
     *
     * @return MockeryMatcherNot
     */
    
public static function not($expected)
    {
        return new 
MockeryMatcherNot($expected);
    }

    
/**
     * Return instance of ANYOF matcher.
     *
     * @param array ...$args
     *
     * @return MockeryMatcherAnyOf
     */
    
public static function anyOf(...$args)
    {
        return new 
MockeryMatcherAnyOf($args);
    }

    
/**
     * Return instance of NOTANYOF matcher.
     *
     * @param array ...$args
     *
     * @return MockeryMatcherNotAnyOf
     */
    
public static function notAnyOf(...$args)
    {
        return new 
MockeryMatcherNotAnyOf($args);
    }

    
/**
     * Return instance of PATTERN matcher.
     *
     * @param mixed $expected
     *
     * @return MockeryMatcherPattern
     */
    
public static function pattern($expected)
    {
        return new 
MockeryMatcherPattern($expected);
    }

    
/**
     * Lazy loader and Getter for the global
     * configuration container.
     *
     * @return MockeryConfiguration
     */
    
public static function getConfiguration()
    {
        if (
is_null(self::$_config)) {
            
self::$_config = new MockeryConfiguration();
        }

        return 
self::$_config;
    }

    
/**
     * Utility method to format method name and arguments into a string.
     *
     * @param string $method
     * @param array $arguments
     *
     * @return string
     */
    
public static function formatArgs($method, array $arguments null)
    {
        if (
is_null($arguments)) {
            return 
$method '()';
        }

        
$formattedArguments = array();
        foreach (
$arguments as $argument) {
            
$formattedArguments[] = self::formatArgument($argument);
        }

        return 
$method '(' implode(', '$formattedArguments) . ')';
    }

    
/**
     * Gets the string representation
     * of any passed argument.
     *
     * @param mixed $argument
     * @param int $depth
     *
     * @return mixed
     */
    
private static function formatArgument($argument$depth 0)
    {
        if (
$argument instanceof MatcherAbstract) {
            return (string) 
$argument;
        }

        if (
is_object($argument)) {
            return 
'object(' get_class($argument) . ')';
        }

        if (
is_int($argument) || is_float($argument)) {
            return 
$argument;
        }

        if (
is_array($argument)) {
            if (
$depth === 1) {
                
$argument '[...]';
            } else {
                
$sample = array();
                foreach (
$argument as $key => $value) {
                    
$key is_int($key) ? $key "'$key'";
                    
$value self::formatArgument($value$depth 1);
                    
$sample[] = "$key => $value";
                }

                
$argument "[" implode(", "$sample) . "]";
            }

            return ((
strlen($argument) > 1000) ? substr($argument01000) . '...]' $argument);
        }

        if (
is_bool($argument)) {
            return 
$argument 'true' 'false';
        }

        if (
is_resource($argument)) {
            return 
'resource(...)';
        }

        if (
is_null($argument)) {
            return 
'NULL';
        }

        return 
"'" . (string) $argument "'";
    }

    
/**
     * Utility function to format objects to printable arrays.
     *
     * @param array $objects
     *
     * @return string
     */
    
public static function formatObjects(array $objects null)
    {
        static 
$formatting;

        if (
$formatting) {
            return 
'[Recursion]';
        }

        if (
is_null($objects)) {
            return 
'';
        }

        
$objects array_filter($objects'is_object');
        if (empty(
$objects)) {
            return 
'';
        }

        
$formatting true;
        
$parts = array();

        foreach (
$objects as $object) {
            
$parts[get_class($object)] = self::objectToArray($object);
        }

        
$formatting false;

        return 
'Objects: ( ' var_export($partstrue) . ')';
    }

    
/**
     * Utility function to turn public properties and public get* and is* method values into an array.
     *
     * @param object $object
     * @param int $nesting
     *
     * @return array
     */
    
private static function objectToArray($object$nesting 3)
    {
        if (
$nesting == 0) {
            return array(
'...');
        }

        
$defaultFormatter = function ($object$nesting) {
            return array(
'properties' => self::extractInstancePublicProperties($object$nesting));
        };

        
$class get_class($object);

        
$formatter self::getConfiguration()->getObjectFormatter($class$defaultFormatter);

        
$array = array(
          
'class' => $class,
          
'identity' => '#' md5(spl_object_hash($object))
        );

        
$array array_merge($array$formatter($object$nesting));

        return 
$array;
    }

    
/**
     * Returns all public instance properties.
     *
     * @param mixed $object
     * @param int $nesting
     *
     * @return array
     */
    
private static function extractInstancePublicProperties($object$nesting)
    {
        
$reflection = new ReflectionClass(get_class($object));
        
$properties $reflection->getProperties(ReflectionProperty::IS_PUBLIC);
        
$cleanedProperties = array();

        foreach (
$properties as $publicProperty) {
            if (!
$publicProperty->isStatic()) {
                
$name $publicProperty->getName();
                try {
                    
$cleanedProperties[$name] = self::cleanupNesting($object->$name$nesting);
                } catch (
Exception $exception) {
                    
$cleanedProperties[$name] = $exception->getMessage();
                }
            }
        }

        return 
$cleanedProperties;
    }

    
/**
     * Utility method used for recursively generating
     * an object or array representation.
     *
     * @param mixed $argument
     * @param int $nesting
     *
     * @return mixed
     */
    
private static function cleanupNesting($argument$nesting)
    {
        if (
is_object($argument)) {
            
$object self::objectToArray($argument$nesting 1);
            
$object['class'] = get_class($argument);

            return 
$object;
        }

        if (
is_array($argument)) {
            return 
self::cleanupArray($argument$nesting 1);
        }

        return 
$argument;
    }

    
/**
     * Utility method for recursively
     * gerating a representation
     * of the given array.
     *
     * @param array $argument
     * @param int $nesting
     *
     * @return mixed
     */
    
private static function cleanupArray($argument$nesting 3)
    {
        if (
$nesting == 0) {
            return 
'...';
        }

        foreach (
$argument as $key => $value) {
            if (
is_array($value)) {
                
$argument[$key] = self::cleanupArray($value$nesting 1);
            } elseif (
is_object($value)) {
                
$argument[$key] = self::objectToArray($value$nesting 1);
            }
        }

        return 
$argument;
    }

    
/**
     * Utility function to parse shouldReceive() arguments and generate
     * expectations from such as needed.
     *
     * @param MockeryLegacyMockInterface $mock
     * @param array ...$args
     * @param callable $add
     * @return MockeryCompositeExpectation
     */
    
public static function parseShouldReturnArgs(MockeryLegacyMockInterface $mock$args$add)
    {
        
$composite = new MockeryCompositeExpectation();

        foreach (
$args as $arg) {
            if (
is_array($arg)) {
                foreach (
$arg as $k => $v) {
                    
$expectation self::buildDemeterChain($mock$k$add)->andReturn($v);
                    
$composite->add($expectation);
                }
            } elseif (
is_string($arg)) {
                
$expectation self::buildDemeterChain($mock$arg$add);
                
$composite->add($expectation);
            }
        }

        return 
$composite;
    }

    
/**
     * Sets up expectations on the members of the CompositeExpectation and
     * builds up any demeter chain that was passed to shouldReceive.
     *
     * @param MockeryLegacyMockInterface $mock
     * @param string $arg
     * @param callable $add
     * @throws MockeryException
     * @return MockeryExpectationInterface
     */
    
protected static function buildDemeterChain(MockeryLegacyMockInterface $mock$arg$add)
    {
        
/** @var MockeryContainer $container */
        
$container $mock->mockery_getContainer();
        
$methodNames explode('->'$arg);
        
reset($methodNames);

        if (!
Mockery::getConfiguration()->mockingNonExistentMethodsAllowed()
            && !
$mock->mockery_isAnonymous()
            && !
in_array(current($methodNames), $mock->mockery_getMockableMethods())
        ) {
            throw new 
MockeryException(
                
'Mockery's configuration currently forbids mocking the method '
                . current($methodNames) . ' 
as it does not exist on the class or object '
                . '
being mocked'
            );
        }

        /** @var ExpectationInterface|null $expectations */
        $expectations = null;

        /** @var Callable $nextExp */
        $nextExp = function ($method) use ($add) {
            return $add($method);
        };

        $parent = get_class($mock);

        while (true) {
            $method = array_shift($methodNames);
            $expectations = $mock->mockery_getExpectationsFor($method);

            if (is_null($expectations) || self::noMoreElementsInChain($methodNames)) {
                $expectations = $nextExp($method);
                if (self::noMoreElementsInChain($methodNames)) {
                    break;
                }

                $mock = self::getNewDemeterMock($container, $parent, $method, $expectations);
            } else {
                $demeterMockKey = $container->getKeyOfDemeterMockFor($method, $parent);
                if ($demeterMockKey) {
                    $mock = self::getExistingDemeterMock($container, $demeterMockKey);
                }
            }

            $parent .= '
->' . $method;

            $nextExp = function ($n) use ($mock) {
                return $mock->shouldReceive($n);
            };
        }

        return $expectations;
    }

    /**
     * Gets a new demeter configured
     * mock from the container.
     *
     * @param MockeryContainer $container
     * @param string $parent
     * @param string $method
     * @param MockeryExpectationInterface $exp
     *
     * @return MockeryMock
     */
    private static function getNewDemeterMock(
        MockeryContainer $container,
        $parent,
        $method,
        MockeryExpectationInterface $exp
    ) {
        $newMockName = '
demeter_' . md5($parent) . '_' . $method;

        $parRef = null;
        $parRefMethod = null;
        $parRefMethodRetType = null;

        $parentMock = $exp->getMock();
        if ($parentMock !== null) {
            $parRef = new ReflectionObject($parentMock);
        }

        if ($parRef !== null && $parRef->hasMethod($method)) {
            $parRefMethod = $parRef->getMethod($method);
            $parRefMethodRetType = Reflector::getReturnType($parRefMethod, true);

            if ($parRefMethodRetType !== null && $parRefMethodRetType !== '
mixed') {
                $nameBuilder = new MockNameBuilder();
                $nameBuilder->addPart('
\' . $newMockName);
                $mock = self::namedMock($nameBuilder->build(), $parRefMethodRetType);
                $exp->andReturn($mock);

                return $mock;
            }
        }

        $mock = $container->mock($newMockName);
        $exp->andReturn($mock);

        return $mock;
    }

    /**
     * Gets an specific demeter mock from
     * the ones kept by the container.
     *
     * @param MockeryContainer $container
     * @param string $demeterMockKey
     *
     * @return mixed
     */
    private static function getExistingDemeterMock(
        MockeryContainer $container,
        $demeterMockKey
    ) {
        $mocks = $container->getMocks();
        $mock = $mocks[$demeterMockKey];

        return $mock;
    }

    /**
     * Checks if the passed array representing a demeter
     * chain with the method names is empty.
     *
     * @param array $methodNames
     *
     * @return bool
     */
    private static function noMoreElementsInChain(array $methodNames)
    {
        return empty($methodNames);
    }

    public static function declareClass($fqn)
    {
        return static::declareType($fqn, "class");
    }

    public static function declareInterface($fqn)
    {
        return static::declareType($fqn, "interface");
    }

    private static function declareType($fqn, $type)
    {
        $targetCode = "<?php ";
        $shortName = $fqn;

        if (strpos($fqn, "\")) {
            $parts = explode("\", $fqn);

            $shortName = trim(array_pop($parts));
            $namespace = implode("\", $parts);

            $targetCode.= "namespace $namespace;n";
        }

        $targetCode.= "$type $shortName {} ";

        /*
         * We could eval here, but it doesn'
t play well with the way
         
PHPUnit tries to backup global state and the require definition
         
loader
         
*/
        
$tmpfname tempnam(sys_get_temp_dir(), "Mockery");
        
file_put_contents($tmpfname$targetCode);
        require 
$tmpfname;
        
Mockery::registerFileForCleanUp($tmpfname);
    }

    
/**
     * Register a file to be deleted on tearDown.
     *
     * @param string $fileName
     */
    
public static function registerFileForCleanUp($fileName)
    {
        
self::$_filesToCleanUp[] = $fileName;
    }
}
Онлайн: 0
Реклама