One Hat Cyber Team
Your IP:
216.73.216.174
Server IP:
198.54.114.155
Server:
Linux server71.web-hosting.com 4.18.0-513.18.1.lve.el8.x86_64 #1 SMP Thu Feb 22 12:55:50 UTC 2024 x86_64
Server Software:
LiteSpeed
PHP Version:
5.6.40
Create File
|
Create Folder
Execute
Dir :
~
/
proc
/
self
/
root
/
home
/
fluxyjvi
/
www
/
assets
/
images
/
Edit File:
library.tar
helpers.php 0000644 00000002446 15107542733 0006734 0 ustar 00 <?php /** * Mockery (https://docs.mockery.io/) * * @copyright https://github.com/mockery/mockery/blob/HEAD/COPYRIGHT.md * @license https://github.com/mockery/mockery/blob/HEAD/LICENSE BSD 3-Clause License * @link https://github.com/mockery/mockery for the canonical source repository */ use Mockery\Matcher\AndAnyOtherArgs; use Mockery\Matcher\AnyArgs; if (!function_exists("mock")) { function mock(...$args) { return Mockery::mock(...$args); } } if (!function_exists("spy")) { function spy(...$args) { return Mockery::spy(...$args); } } if (!function_exists("namedMock")) { function namedMock(...$args) { return Mockery::namedMock(...$args); } } if (!function_exists("anyArgs")) { function anyArgs() { return new AnyArgs(); } } if (!function_exists("andAnyOtherArgs")) { function andAnyOtherArgs() { return new AndAnyOtherArgs(); } } if (!function_exists("andAnyOthers")) { function andAnyOthers() { return new AndAnyOtherArgs(); } } // //$currentDirectory = dirname(__FILE__,2); //$libraryDirectory = $currentDirectory . '/library'; //if (! file_exists($libraryDirectory)) //{ // symlink( // $currentDirectory . '/library', // $libraryDirectory // ); //} Mockery.php 0000644 00000060227 15107542733 0006704 0 ustar 00 <?php /** * Mockery (https://docs.mockery.io/) * * @copyright https://github.com/mockery/mockery/blob/HEAD/COPYRIGHT.md * @license https://github.com/mockery/mockery/blob/HEAD/LICENSE BSD 3-Clause License * @link https://github.com/mockery/mockery for the canonical source repository */ use Mockery\ClosureWrapper; use Mockery\ExpectationInterface; use Mockery\Generator\CachingGenerator; use Mockery\Generator\Generator; use Mockery\Generator\MockConfigurationBuilder; use Mockery\Generator\MockNameBuilder; use Mockery\Generator\StringManipulationGenerator; use Mockery\Loader\EvalLoader; use Mockery\Loader\Loader; use Mockery\Matcher\MatcherAbstract; use Mockery\Reflector; class Mockery { const BLOCKS = 'Mockery_Forward_Blocks'; /** * Global container to hold all mocks for the current unit test running. * * @var \Mockery\Container|null */ protected static $_container = null; /** * Global configuration handler containing configuration options. * * @var \Mockery\Configuration */ protected static $_config = null; /** * @var \Mockery\Generator\Generator */ protected static $_generator; /** * @var \Mockery\Loader\Loader */ 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($type, \Mockery::builtInTypes()); } /** * Static shortcut to \Mockery\Container::mock(). * * @param mixed ...$args * * @return \Mockery\MockInterface|\Mockery\LegacyMockInterface */ 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 \Mockery\MockInterface|\Mockery\LegacyMockInterface */ 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 \Mockery\Container::mock(). * * @param mixed ...$args * * @return \Mockery\MockInterface|\Mockery\LegacyMockInterface */ public static function instanceMock(...$args) { return call_user_func_array(array(self::getContainer(), 'mock'), $args); } /** * Static shortcut to \Mockery\Container::mock(), first argument names the mock. * * @param mixed ...$args * * @return \Mockery\MockInterface|\Mockery\LegacyMockInterface */ 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 \Mockery\Container::self(). * * @throws LogicException * * @return \Mockery\MockInterface|\Mockery\LegacyMockInterface */ 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 \Mockery\Mock */ public static function fetchMock($name) { return self::getContainer()->fetchMock($name); } /** * Lazy loader and getter for * the container property. * * @return Mockery\Container */ public static function getContainer() { if (is_null(self::$_container)) { self::$_container = new Mockery\Container(self::getGenerator(), self::getLoader()); } return self::$_container; } /** * Setter for the $_generator static property. * * @param \Mockery\Generator\Generator $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 \Mockery\Container $container * * @return \Mockery\Container */ public static function setContainer(Mockery\Container $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 \Mockery\Matcher\Any */ public static function any() { return new \Mockery\Matcher\Any(); } /** * Return instance of AndAnyOtherArgs matcher. * * An alternative name to `andAnyOtherArgs` so * the API stays closer to `any` as well. * * @return \Mockery\Matcher\AndAnyOtherArgs */ public static function andAnyOthers() { return new \Mockery\Matcher\AndAnyOtherArgs(); } /** * Return instance of AndAnyOtherArgs matcher. * * @return \Mockery\Matcher\AndAnyOtherArgs */ public static function andAnyOtherArgs() { return new \Mockery\Matcher\AndAnyOtherArgs(); } /** * Return instance of TYPE matcher. * * @param mixed $expected * * @return \Mockery\Matcher\Type */ public static function type($expected) { return new \Mockery\Matcher\Type($expected); } /** * Return instance of DUCKTYPE matcher. * * @param array ...$args * * @return \Mockery\Matcher\Ducktype */ public static function ducktype(...$args) { return new \Mockery\Matcher\Ducktype($args); } /** * Return instance of SUBSET matcher. * * @param array $part * @param bool $strict - (Optional) True for strict comparison, false for loose * * @return \Mockery\Matcher\Subset */ public static function subset(array $part, $strict = true) { return new \Mockery\Matcher\Subset($part, $strict); } /** * Return instance of CONTAINS matcher. * * @param mixed $args * * @return \Mockery\Matcher\Contains */ public static function contains(...$args) { return new \Mockery\Matcher\Contains($args); } /** * Return instance of HASKEY matcher. * * @param mixed $key * * @return \Mockery\Matcher\HasKey */ public static function hasKey($key) { return new \Mockery\Matcher\HasKey($key); } /** * Return instance of HASVALUE matcher. * * @param mixed $val * * @return \Mockery\Matcher\HasValue */ public static function hasValue($val) { return new \Mockery\Matcher\HasValue($val); } /** * Return instance of CLOSURE matcher. * * @param $reference * * @return \Mockery\Matcher\Closure */ public static function capture(&$reference) { $closure = function ($argument) use (&$reference) { $reference = $argument; return true; }; return new \Mockery\Matcher\Closure($closure); } /** * Return instance of CLOSURE matcher. * * @param mixed $closure * * @return \Mockery\Matcher\Closure */ public static function on($closure) { return new \Mockery\Matcher\Closure($closure); } /** * Return instance of MUSTBE matcher. * * @param mixed $expected * * @return \Mockery\Matcher\MustBe */ public static function mustBe($expected) { return new \Mockery\Matcher\MustBe($expected); } /** * Return instance of NOT matcher. * * @param mixed $expected * * @return \Mockery\Matcher\Not */ public static function not($expected) { return new \Mockery\Matcher\Not($expected); } /** * Return instance of ANYOF matcher. * * @param array ...$args * * @return \Mockery\Matcher\AnyOf */ public static function anyOf(...$args) { return new \Mockery\Matcher\AnyOf($args); } /** * Return instance of NOTANYOF matcher. * * @param array ...$args * * @return \Mockery\Matcher\NotAnyOf */ public static function notAnyOf(...$args) { return new \Mockery\Matcher\NotAnyOf($args); } /** * Return instance of PATTERN matcher. * * @param mixed $expected * * @return \Mockery\Matcher\Pattern */ public static function pattern($expected) { return new \Mockery\Matcher\Pattern($expected); } /** * Lazy loader and Getter for the global * configuration container. * * @return \Mockery\Configuration */ public static function getConfiguration() { if (is_null(self::$_config)) { self::$_config = new \Mockery\Configuration(); } 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($argument, 0, 1000) . '...]' : $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($parts, true) . ')'; } /** * 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 Mockery\LegacyMockInterface $mock * @param array ...$args * @param callable $add * @return \Mockery\CompositeExpectation */ public static function parseShouldReturnArgs(\Mockery\LegacyMockInterface $mock, $args, $add) { $composite = new \Mockery\CompositeExpectation(); 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 \Mockery\LegacyMockInterface $mock * @param string $arg * @param callable $add * @throws Mockery\Exception * @return \Mockery\ExpectationInterface */ protected static function buildDemeterChain(\Mockery\LegacyMockInterface $mock, $arg, $add) { /** @var Mockery\Container $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 \Mockery\Exception( '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 \Mockery\Container $container * @param string $parent * @param string $method * @param Mockery\ExpectationInterface $exp * * @return \Mockery\Mock */ private static function getNewDemeterMock( Mockery\Container $container, $parent, $method, Mockery\ExpectationInterface $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 \Mockery\Container $container * @param string $demeterMockKey * * @return mixed */ private static function getExistingDemeterMock( Mockery\Container $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; } } Mockery/HigherOrderMessage.php 0000644 00000001664 15107542733 0012413 0 ustar 00 <?php /** * Mockery (https://docs.mockery.io/) * * @copyright https://github.com/mockery/mockery/blob/HEAD/COPYRIGHT.md * @license https://github.com/mockery/mockery/blob/HEAD/LICENSE BSD 3-Clause License * @link https://github.com/mockery/mockery for the canonical source repository */ namespace Mockery; /** * @method \Mockery\Expectation withArgs(\Closure|array $args) */ class HigherOrderMessage { private $mock; private $method; public function __construct(MockInterface $mock, $method) { $this->mock = $mock; $this->method = $method; } /** * @return \Mockery\Expectation */ public function __call($method, $args) { if ($this->method === 'shouldNotHaveReceived') { return $this->mock->{$this->method}($method, $args); } $expectation = $this->mock->{$this->method}($method); return $expectation->withArgs($args); } } Mockery/ExpectationInterface.php 0000644 00000001276 15107542733 0013007 0 ustar 00 <?php /** * Mockery (https://docs.mockery.io/) * * @copyright https://github.com/mockery/mockery/blob/HEAD/COPYRIGHT.md * @license https://github.com/mockery/mockery/blob/HEAD/LICENSE BSD 3-Clause License * @link https://github.com/mockery/mockery for the canonical source repository */ namespace Mockery; interface ExpectationInterface { /** * @return int */ public function getOrderNumber(); /** * @return LegacyMockInterface|MockInterface */ public function getMock(); /** * @param mixed $args * @return self */ public function andReturn(...$args); /** * @return self */ public function andReturns(); } Mockery/LegacyMockInterface.php 0000644 00000013161 15107542733 0012536 0 ustar 00 <?php /** * Mockery (https://docs.mockery.io/) * * @copyright https://github.com/mockery/mockery/blob/HEAD/COPYRIGHT.md * @license https://github.com/mockery/mockery/blob/HEAD/LICENSE BSD 3-Clause License * @link https://github.com/mockery/mockery for the canonical source repository */ namespace Mockery; interface LegacyMockInterface { /** * Alternative setup method to constructor * * @param \Mockery\Container $container * @param object $partialObject * @return void */ public function mockery_init(\Mockery\Container $container = null, $partialObject = null); /** * Set expected method calls * * @param string|array ...$methodNames one or many methods that are expected to be called in this mock * * @return \Mockery\ExpectationInterface|\Mockery\Expectation|\Mockery\HigherOrderMessage */ public function shouldReceive(...$methodNames); /** * Shortcut method for setting an expectation that a method should not be called. * * @param string|array ...$methodNames one or many methods that are expected not to be called in this mock * @return \Mockery\ExpectationInterface|\Mockery\Expectation|\Mockery\HigherOrderMessage */ public function shouldNotReceive(...$methodNames); /** * Allows additional methods to be mocked that do not explicitly exist on mocked class * @param String $method name of the method to be mocked */ public function shouldAllowMockingMethod($method); /** * Set mock to ignore unexpected methods and return Undefined class * @param mixed $returnValue the default return value for calls to missing functions on this mock * @return static */ public function shouldIgnoreMissing($returnValue = null); /** * @return static */ public function shouldAllowMockingProtectedMethods(); /** * Set mock to defer unexpected methods to its parent if possible * * @deprecated since 1.4.0. Please use makePartial() instead. * * @return static */ public function shouldDeferMissing(); /** * Set mock to defer unexpected methods to its parent if possible * * @return static */ public function makePartial(); /** * @param null|string $method * @param null|array|Closure $args * @return mixed */ public function shouldHaveReceived($method, $args = null); /** * @return mixed */ public function shouldHaveBeenCalled(); /** * @param null|string $method * @param null|array|Closure $args * @return mixed */ public function shouldNotHaveReceived($method, $args = null); /** * @param array $args (optional) * @return mixed */ public function shouldNotHaveBeenCalled(array $args = null); /** * In the event shouldReceive() accepting an array of methods/returns * this method will switch them from normal expectations to default * expectations * * @return self */ public function byDefault(); /** * Iterate across all expectation directors and validate each * * @throws \Mockery\CountValidator\Exception * @return void */ public function mockery_verify(); /** * Tear down tasks for this mock * * @return void */ public function mockery_teardown(); /** * Fetch the next available allocation order number * * @return int */ public function mockery_allocateOrder(); /** * Set ordering for a group * * @param mixed $group * @param int $order */ public function mockery_setGroup($group, $order); /** * Fetch array of ordered groups * * @return array */ public function mockery_getGroups(); /** * Set current ordered number * * @param int $order */ public function mockery_setCurrentOrder($order); /** * Get current ordered number * * @return int */ public function mockery_getCurrentOrder(); /** * Validate the current mock's ordering * * @param string $method * @param int $order * @throws \Mockery\Exception * @return void */ public function mockery_validateOrder($method, $order); /** * Gets the count of expectations for this mock * * @return int */ public function mockery_getExpectationCount(); /** * Return the expectations director for the given method * * @var string $method * @return \Mockery\ExpectationDirector|null */ public function mockery_setExpectationsFor($method, \Mockery\ExpectationDirector $director); /** * Return the expectations director for the given method * * @var string $method * @return \Mockery\ExpectationDirector|null */ public function mockery_getExpectationsFor($method); /** * Find an expectation matching the given method and arguments * * @var string $method * @var array $args * @return \Mockery\Expectation|null */ public function mockery_findExpectation($method, array $args); /** * Return the container for this mock * * @return \Mockery\Container */ public function mockery_getContainer(); /** * Return the name for this mock * * @return string */ public function mockery_getName(); /** * @return array */ public function mockery_getMockableProperties(); /** * @return string[] */ public function mockery_getMockableMethods(); /** * @return bool */ public function mockery_isAnonymous(); } Mockery/ReceivedMethodCalls.php 0000644 00000001655 15107542733 0012552 0 ustar 00 <?php /** * Mockery (https://docs.mockery.io/) * * @copyright https://github.com/mockery/mockery/blob/HEAD/COPYRIGHT.md * @license https://github.com/mockery/mockery/blob/HEAD/LICENSE BSD 3-Clause License * @link https://github.com/mockery/mockery for the canonical source repository */ namespace Mockery; class ReceivedMethodCalls { private $methodCalls = array(); public function push(MethodCall $methodCall) { $this->methodCalls[] = $methodCall; } public function verify(Expectation $expectation) { foreach ($this->methodCalls as $methodCall) { if ($methodCall->getMethod() !== $expectation->getName()) { continue; } if (!$expectation->matchArgs($methodCall->getArgs())) { continue; } $expectation->verifyCall($methodCall->getArgs()); } $expectation->verify(); } } Mockery/Adapter/Phpunit/TestListenerTrait.php 0000644 00000005017 15107542733 0015340 0 ustar 00 <?php /** * Mockery (https://docs.mockery.io/) * * @copyright https://github.com/mockery/mockery/blob/HEAD/COPYRIGHT.md * @license https://github.com/mockery/mockery/blob/HEAD/LICENSE BSD 3-Clause License * @link https://github.com/mockery/mockery for the canonical source repository */ namespace Mockery\Adapter\Phpunit; use PHPUnit\Framework\ExpectationFailedException; use PHPUnit\Framework\Test; use PHPUnit\Framework\TestCase; use PHPUnit\Util\Blacklist; use PHPUnit\Runner\BaseTestRunner; class TestListenerTrait { /** * endTest is called after each test and checks if \Mockery::close() has * been called, and will let the test fail if it hasn't. * * @param Test $test * @param float $time */ public function endTest(Test $test, $time) { if (!$test instanceof TestCase) { // We need the getTestResultObject and getStatus methods which are // not part of the interface. return; } if ($test->getStatus() !== BaseTestRunner::STATUS_PASSED) { // If the test didn't pass there is no guarantee that // verifyMockObjects and assertPostConditions have been called. // And even if it did, the point here is to prevent false // negatives, not to make failing tests fail for more reasons. return; } try { // The self() call is used as a sentinel. Anything that throws if // the container is closed already will do. \Mockery::self(); } catch (\LogicException $_) { return; } $e = new ExpectationFailedException( \sprintf( "Mockery's expectations have not been verified. Make sure that \Mockery::close() is called at the end of the test. Consider using %s\MockeryPHPUnitIntegration or extending %s\MockeryTestCase.", __NAMESPACE__, __NAMESPACE__ ) ); /** @var \PHPUnit\Framework\TestResult $result */ $result = $test->getTestResultObject(); if ($result !== null) { $result->addFailure($test, $e, $time); } } public function startTestSuite() { if (method_exists(Blacklist::class, 'addDirectory')) { (new BlackList())->getBlacklistedDirectories(); Blacklist::addDirectory(\dirname((new \ReflectionClass(\Mockery::class))->getFileName())); } else { Blacklist::$blacklistedClassNames[\Mockery::class] = 1; } } } Mockery/Adapter/Phpunit/TestListener.php 0000644 00000001676 15107542733 0014343 0 ustar 00 <?php /** * Mockery (https://docs.mockery.io/) * * @copyright https://github.com/mockery/mockery/blob/HEAD/COPYRIGHT.md * @license https://github.com/mockery/mockery/blob/HEAD/LICENSE BSD 3-Clause License * @link https://github.com/mockery/mockery for the canonical source repository */ namespace Mockery\Adapter\Phpunit; use PHPUnit\Framework\Test; use PHPUnit\Framework\TestListenerDefaultImplementation; use PHPUnit\Framework\TestSuite; use PHPUnit\Framework\TestListener as PHPUnitTestListener; class TestListener implements PHPUnitTestListener { use TestListenerDefaultImplementation; private $trait; public function __construct() { $this->trait = new TestListenerTrait(); } public function endTest(Test $test, float $time): void { $this->trait->endTest($test, $time); } public function startTestSuite(TestSuite $suite): void { $this->trait->startTestSuite(); } } Mockery/Adapter/Phpunit/MockeryTestCase.php 0000644 00000001131 15107542733 0014745 0 ustar 00 <?php /** * Mockery (https://docs.mockery.io/) * * @copyright https://github.com/mockery/mockery/blob/HEAD/COPYRIGHT.md * @license https://github.com/mockery/mockery/blob/HEAD/LICENSE BSD 3-Clause License * @link https://github.com/mockery/mockery for the canonical source repository */ namespace Mockery\Adapter\Phpunit; use PHPUnit\Framework\TestCase; abstract class MockeryTestCase extends TestCase { use MockeryPHPUnitIntegration; use MockeryTestCaseSetUp; protected function mockeryTestSetUp() { } protected function mockeryTestTearDown() { } } Mockery/Adapter/Phpunit/MockeryPHPUnitIntegrationAssertPostConditions.php 0000644 00000001023 15107542733 0023007 0 ustar 00 <?php /** * Mockery (https://docs.mockery.io/) * * @copyright https://github.com/mockery/mockery/blob/HEAD/COPYRIGHT.md * @license https://github.com/mockery/mockery/blob/HEAD/LICENSE BSD 3-Clause License * @link https://github.com/mockery/mockery for the canonical source repository */ declare(strict_types=1); namespace Mockery\Adapter\Phpunit; trait MockeryPHPUnitIntegrationAssertPostConditions { protected function assertPostConditions(): void { $this->mockeryAssertPostConditions(); } } Mockery/Adapter/Phpunit/MockeryPHPUnitIntegration.php 0000644 00000003673 15107542733 0016742 0 ustar 00 <?php /** * Mockery (https://docs.mockery.io/) * * @copyright https://github.com/mockery/mockery/blob/HEAD/COPYRIGHT.md * @license https://github.com/mockery/mockery/blob/HEAD/LICENSE BSD 3-Clause License * @link https://github.com/mockery/mockery for the canonical source repository */ namespace Mockery\Adapter\Phpunit; use Mockery; /** * Integrates Mockery into PHPUnit. Ensures Mockery expectations are verified * for each test and are included by the assertion counter. */ trait MockeryPHPUnitIntegration { use MockeryPHPUnitIntegrationAssertPostConditions; protected $mockeryOpen; /** * Performs assertions shared by all tests of a test case. This method is * called before execution of a test ends and before the tearDown method. */ protected function mockeryAssertPostConditions() { $this->addMockeryExpectationsToAssertionCount(); $this->checkMockeryExceptions(); $this->closeMockery(); parent::assertPostConditions(); } protected function addMockeryExpectationsToAssertionCount() { $this->addToAssertionCount(Mockery::getContainer()->mockery_getExpectationCount()); } protected function checkMockeryExceptions() { if (!method_exists($this, "markAsRisky")) { return; } foreach (Mockery::getContainer()->mockery_thrownExceptions() as $e) { if (!$e->dismissed()) { $this->markAsRisky(); } } } protected function closeMockery() { Mockery::close(); $this->mockeryOpen = false; } /** * @before */ protected function startMockery() { $this->mockeryOpen = true; } /** * @after */ protected function purgeMockeryContainer() { if ($this->mockeryOpen) { // post conditions wasn't called, so test probably failed Mockery::close(); } } } Mockery/Adapter/Phpunit/MockeryTestCaseSetUp.php 0000644 00000001160 15107542733 0015730 0 ustar 00 <?php /** * Mockery (https://docs.mockery.io/) * * @copyright https://github.com/mockery/mockery/blob/HEAD/COPYRIGHT.md * @license https://github.com/mockery/mockery/blob/HEAD/LICENSE BSD 3-Clause License * @link https://github.com/mockery/mockery for the canonical source repository */ declare(strict_types=1); namespace Mockery\Adapter\Phpunit; trait MockeryTestCaseSetUp { protected function setUp(): void { parent::setUp(); $this->mockeryTestSetUp(); } protected function tearDown(): void { $this->mockeryTestTearDown(); parent::tearDown(); } } Mockery/Reflector.php 0000644 00000020327 15107542733 0010626 0 ustar 00 <?php /** * Mockery (https://docs.mockery.io/) * * @copyright https://github.com/mockery/mockery/blob/HEAD/COPYRIGHT.md * @license https://github.com/mockery/mockery/blob/HEAD/LICENSE BSD 3-Clause License * @link https://github.com/mockery/mockery for the canonical source repository */ namespace Mockery; use ReflectionType; /** * @internal */ class Reflector { private const TRAVERSABLE_ARRAY = ['\Traversable', 'array']; private const ITERABLE = ['iterable']; /** * Determine if the parameter is typed as an array. * * @param \ReflectionParameter $param * * @return bool */ public static function isArray(\ReflectionParameter $param) { $type = $param->getType(); return $type instanceof \ReflectionNamedType && $type->getName(); } /** * Compute the string representation for the paramater type. * * @param \ReflectionParameter $param * @param bool $withoutNullable * * @return string|null */ public static function getTypeHint(\ReflectionParameter $param, $withoutNullable = false) { if (!$param->hasType()) { return null; } $type = $param->getType(); $declaringClass = $param->getDeclaringClass(); $typeHint = self::getTypeFromReflectionType($type, $declaringClass); return (!$withoutNullable && $type->allowsNull()) ? self::formatNullableType($typeHint) : $typeHint; } /** * Compute the string representation for the return type. * * @param \ReflectionParameter $param * @param bool $withoutNullable * * @return string|null */ public static function getReturnType(\ReflectionMethod $method, $withoutNullable = false) { $type = $method->getReturnType(); if (!$type instanceof ReflectionType && method_exists($method, 'getTentativeReturnType')) { $type = $method->getTentativeReturnType(); } if (!$type instanceof ReflectionType) { return null; } $typeHint = self::getTypeFromReflectionType($type, $method->getDeclaringClass()); return (!$withoutNullable && $type->allowsNull()) ? self::formatNullableType($typeHint) : $typeHint; } /** * Compute the string representation for the simplest return type. * * @param \ReflectionParameter $param * * @return string|null */ public static function getSimplestReturnType(\ReflectionMethod $method) { $type = $method->getReturnType(); if (!$type instanceof ReflectionType && method_exists($method, 'getTentativeReturnType')) { $type = $method->getTentativeReturnType(); } if (!$type instanceof ReflectionType || $type->allowsNull()) { return null; } $typeInformation = self::getTypeInformation($type, $method->getDeclaringClass()); // return the first primitive type hint foreach ($typeInformation as $info) { if ($info['isPrimitive']) { return $info['typeHint']; } } // if no primitive type, return the first type foreach ($typeInformation as $info) { return $info['typeHint']; } return null; } /** * Get the string representation of the given type. * * @param \ReflectionType $type * @param \ReflectionClass $declaringClass * * @return list<array{typeHint: string, isPrimitive: bool}> */ private static function getTypeInformation(\ReflectionType $type, \ReflectionClass $declaringClass) { // PHP 8 union types and PHP 8.1 intersection types can be recursively processed if ($type instanceof \ReflectionUnionType || $type instanceof \ReflectionIntersectionType) { $types = []; foreach ($type->getTypes() as $innterType) { foreach (self::getTypeInformation($innterType, $declaringClass) as $info) { if ($info['typeHint'] === 'null' && $info['isPrimitive']) { continue; } $types[] = $info; } } return $types; } // $type must be an instance of \ReflectionNamedType $typeHint = $type->getName(); // builtins can be returned as is if ($type->isBuiltin()) { return [ [ 'typeHint' => $typeHint, 'isPrimitive' => in_array($typeHint, ['array', 'bool', 'int', 'float', 'null', 'object', 'string']), ], ]; } // 'static' can be returned as is if ($typeHint === 'static') { return [ [ 'typeHint' => $typeHint, 'isPrimitive' => false, ], ]; } // 'self' needs to be resolved to the name of the declaring class if ($typeHint === 'self') { $typeHint = $declaringClass->getName(); } // 'parent' needs to be resolved to the name of the parent class if ($typeHint === 'parent') { $typeHint = $declaringClass->getParentClass()->getName(); } // class names need prefixing with a slash return [ [ 'typeHint' => sprintf('\\%s', $typeHint), 'isPrimitive' => false, ], ]; } /** * Format the given type as a nullable type. * * @param string $typeHint * * @return string */ private static function formatNullableType($typeHint) { if ($typeHint === 'mixed') { return $typeHint; } if (strpos($typeHint, 'null') !== false) { return $typeHint; } if (\PHP_VERSION_ID < 80000) { return sprintf('?%s', $typeHint); } return sprintf('%s|null', $typeHint); } private static function getTypeFromReflectionType(\ReflectionType $type, \ReflectionClass $declaringClass): string { if ($type instanceof \ReflectionNamedType) { $typeHint = $type->getName(); if ($type->isBuiltin()) { return $typeHint; } if ($typeHint === 'static') { return $typeHint; } // 'self' needs to be resolved to the name of the declaring class if ($typeHint === 'self'){ $typeHint = $declaringClass->getName(); } // 'parent' needs to be resolved to the name of the parent class if ($typeHint === 'parent'){ $typeHint = $declaringClass->getParentClass()->getName(); } // class names need prefixing with a slash return sprintf('\\%s', $typeHint); } if ($type instanceof \ReflectionIntersectionType) { $types = array_map( static function (\ReflectionType $type) use ($declaringClass): string { return self::getTypeFromReflectionType($type, $declaringClass); }, $type->getTypes() ); return implode( '&', $types, ); } if ($type instanceof \ReflectionUnionType) { $types = array_map( static function (\ReflectionType $type) use ($declaringClass): string { return self::getTypeFromReflectionType($type, $declaringClass); }, $type->getTypes() ); $intersect = array_intersect(self::TRAVERSABLE_ARRAY, $types); if (self::TRAVERSABLE_ARRAY === $intersect) { $types = array_merge(self::ITERABLE, array_diff($types, self::TRAVERSABLE_ARRAY)); } return implode( '|', array_map( static function (string $type): string { return strpos($type, '&') === false ? $type : sprintf('(%s)', $type); }, $types ) ); } throw new \InvalidArgumentException('Unknown ReflectionType: ' . get_debug_type($type)); } } Mockery/ExpectsHigherOrderMessage.php 0000644 00000001277 15107542733 0013747 0 ustar 00 <?php /** * Mockery (https://docs.mockery.io/) * * @copyright https://github.com/mockery/mockery/blob/HEAD/COPYRIGHT.md * @license https://github.com/mockery/mockery/blob/HEAD/LICENSE BSD 3-Clause License * @link https://github.com/mockery/mockery for the canonical source repository */ namespace Mockery; class ExpectsHigherOrderMessage extends HigherOrderMessage { public function __construct(MockInterface $mock) { parent::__construct($mock, "shouldReceive"); } /** * @return \Mockery\Expectation */ public function __call($method, $args) { $expectation = parent::__call($method, $args); return $expectation->once(); } } Mockery/Loader/RequireLoader.php 0000644 00000002625 15107542733 0012653 0 ustar 00 <?php /** * Mockery (https://docs.mockery.io/) * * @copyright https://github.com/mockery/mockery/blob/HEAD/COPYRIGHT.md * @license https://github.com/mockery/mockery/blob/HEAD/LICENSE BSD 3-Clause License * @link https://github.com/mockery/mockery for the canonical source repository */ namespace Mockery\Loader; use Mockery\Generator\MockDefinition; use Mockery\Loader\Loader; class RequireLoader implements Loader { /** * @var string */ protected $path; /** * @var string */ protected $lastPath = ''; public function __construct($path = null) { $this->path = realpath($path) ?: sys_get_temp_dir(); register_shutdown_function([$this, '__destruct']); } public function __destruct() { $files = array_diff( glob($this->path . DIRECTORY_SEPARATOR . 'Mockery_*.php')?:[], [$this->lastPath] ); foreach ($files as $file) { @unlink($file); } } public function load(MockDefinition $definition) { if (class_exists($definition->getClassName(), false)) { return; } $this->lastPath = sprintf('%s%s%s.php', $this->path, DIRECTORY_SEPARATOR, uniqid('Mockery_')); file_put_contents($this->lastPath, $definition->getCode()); if (file_exists($this->lastPath)){ require $this->lastPath; } } } Mockery/Loader/Loader.php 0000644 00000000673 15107542733 0011317 0 ustar 00 <?php /** * Mockery (https://docs.mockery.io/) * * @copyright https://github.com/mockery/mockery/blob/HEAD/COPYRIGHT.md * @license https://github.com/mockery/mockery/blob/HEAD/LICENSE BSD 3-Clause License * @link https://github.com/mockery/mockery for the canonical source repository */ namespace Mockery\Loader; use Mockery\Generator\MockDefinition; interface Loader { public function load(MockDefinition $definition); } Mockery/Loader/EvalLoader.php 0000644 00000001177 15107542733 0012127 0 ustar 00 <?php /** * Mockery (https://docs.mockery.io/) * * @copyright https://github.com/mockery/mockery/blob/HEAD/COPYRIGHT.md * @license https://github.com/mockery/mockery/blob/HEAD/LICENSE BSD 3-Clause License * @link https://github.com/mockery/mockery for the canonical source repository */ namespace Mockery\Loader; use Mockery\Generator\MockDefinition; use Mockery\Loader\Loader; class EvalLoader implements Loader { public function load(MockDefinition $definition) { if (class_exists($definition->getClassName(), false)) { return; } eval("?>" . $definition->getCode()); } } Mockery/ClosureWrapper.php 0000644 00000001171 15107542733 0011652 0 ustar 00 <?php /** * Mockery (https://docs.mockery.io/) * * @copyright https://github.com/mockery/mockery/blob/HEAD/COPYRIGHT.md * @license https://github.com/mockery/mockery/blob/HEAD/LICENSE BSD 3-Clause License * @link https://github.com/mockery/mockery for the canonical source repository */ namespace Mockery; use Mockery\Matcher\Closure; /** * @internal */ class ClosureWrapper { private $closure; public function __construct(\Closure $closure) { $this->closure = $closure; } public function __invoke() { return call_user_func_array($this->closure, func_get_args()); } } Mockery/MockInterface.php 0000644 00000001556 15107542733 0011416 0 ustar 00 <?php /** * Mockery (https://docs.mockery.io/) * * @copyright https://github.com/mockery/mockery/blob/HEAD/COPYRIGHT.md * @license https://github.com/mockery/mockery/blob/HEAD/LICENSE BSD 3-Clause License * @link https://github.com/mockery/mockery for the canonical source repository */ namespace Mockery; use Mockery\LegacyMockInterface; interface MockInterface extends LegacyMockInterface { /** * @param mixed $something String method name or map of method => return * @return self|\Mockery\ExpectationInterface|\Mockery\Expectation|\Mockery\HigherOrderMessage */ public function allows($something = []); /** * @param mixed $something String method name (optional) * @return \Mockery\ExpectationInterface|\Mockery\Expectation|\Mockery\ExpectsHigherOrderMessage */ public function expects($something = null); } Mockery/CompositeExpectation.php 0000644 00000007044 15107542733 0013050 0 ustar 00 <?php /** * Mockery (https://docs.mockery.io/) * * @copyright https://github.com/mockery/mockery/blob/HEAD/COPYRIGHT.md * @license https://github.com/mockery/mockery/blob/HEAD/LICENSE BSD 3-Clause License * @link https://github.com/mockery/mockery for the canonical source repository */ namespace Mockery; class CompositeExpectation implements ExpectationInterface { /** * Stores an array of all expectations for this composite * * @var array */ protected $_expectations = array(); /** * Add an expectation to the composite * * @param \Mockery\Expectation|\Mockery\CompositeExpectation $expectation * @return void */ public function add($expectation) { $this->_expectations[] = $expectation; } /** * @param mixed ...$args */ public function andReturn(...$args) { return $this->__call(__FUNCTION__, $args); } /** * Set a return value, or sequential queue of return values * * @param mixed ...$args * @return self */ public function andReturns(...$args) { return call_user_func_array([$this, 'andReturn'], $args); } /** * Intercept any expectation calls and direct against all expectations * * @param string $method * @param array $args * @return self */ public function __call($method, array $args) { foreach ($this->_expectations as $expectation) { call_user_func_array(array($expectation, $method), $args); } return $this; } /** * Return order number of the first expectation * * @return int */ public function getOrderNumber() { reset($this->_expectations); $first = current($this->_expectations); return $first->getOrderNumber(); } /** * Return the parent mock of the first expectation * * @return \Mockery\MockInterface|\Mockery\LegacyMockInterface */ public function getMock() { reset($this->_expectations); $first = current($this->_expectations); return $first->getMock(); } /** * Mockery API alias to getMock * * @return \Mockery\LegacyMockInterface|\Mockery\MockInterface */ public function mock() { return $this->getMock(); } /** * Starts a new expectation addition on the first mock which is the primary * target outside of a demeter chain * * @param mixed ...$args * @return \Mockery\Expectation */ public function shouldReceive(...$args) { reset($this->_expectations); $first = current($this->_expectations); return call_user_func_array(array($first->getMock(), 'shouldReceive'), $args); } /** * Starts a new expectation addition on the first mock which is the primary * target outside of a demeter chain * * @param mixed ...$args * @return \Mockery\Expectation */ public function shouldNotReceive(...$args) { reset($this->_expectations); $first = current($this->_expectations); return call_user_func_array(array($first->getMock(), 'shouldNotReceive'), $args); } /** * Return the string summary of this composite expectation * * @return string */ public function __toString() { $return = '['; $parts = array(); foreach ($this->_expectations as $exp) { $parts[] = (string) $exp; } $return .= implode(', ', $parts) . ']'; return $return; } } Mockery/Expectation.php 0000644 00000055534 15107542733 0011174 0 ustar 00 <?php /** * Mockery (https://docs.mockery.io/) * * @copyright https://github.com/mockery/mockery/blob/HEAD/COPYRIGHT.md * @license https://github.com/mockery/mockery/blob/HEAD/LICENSE BSD 3-Clause License * @link https://github.com/mockery/mockery for the canonical source repository */ namespace Mockery; use Closure; use Mockery\Matcher\NoArgs; use Mockery\Matcher\AnyArgs; use Mockery\Matcher\AndAnyOtherArgs; use Mockery\Matcher\ArgumentListMatcher; use Mockery\Matcher\MultiArgumentClosure; class Expectation implements ExpectationInterface { /** * Mock object to which this expectation belongs * * @var \Mockery\LegacyMockInterface */ protected $_mock = null; /** * Method name * * @var string */ protected $_name = null; /** * Exception message * * @var string|null */ protected $_because = null; /** * Arguments expected by this expectation * * @var array */ protected $_expectedArgs = array(); /** * Count validator store * * @var array */ protected $_countValidators = array(); /** * The count validator class to use * * @var string */ protected $_countValidatorClass = 'Mockery\CountValidator\Exact'; /** * Actual count of calls to this expectation * * @var int */ protected $_actualCount = 0; /** * Value to return from this expectation * * @var mixed */ protected $_returnValue = null; /** * Array of return values as a queue for multiple return sequence * * @var array */ protected $_returnQueue = array(); /** * Array of closures executed with given arguments to generate a result * to be returned * * @var array */ protected $_closureQueue = array(); /** * Array of values to be set when this expectation matches * * @var array */ protected $_setQueue = array(); /** * Integer representing the call order of this expectation * * @var int */ protected $_orderNumber = null; /** * Integer representing the call order of this expectation on a global basis * * @var int */ protected $_globalOrderNumber = null; /** * Flag indicating that an exception is expected to be throw (not returned) * * @var bool */ protected $_throw = false; /** * Flag indicating whether the order of calling is determined locally or * globally * * @var bool */ protected $_globally = false; /** * Flag indicating if the return value should be obtained from the original * class method instead of returning predefined values from the return queue * * @var bool */ protected $_passthru = false; /** * Constructor * * @param \Mockery\LegacyMockInterface $mock * @param string $name */ public function __construct(\Mockery\LegacyMockInterface $mock, $name) { $this->_mock = $mock; $this->_name = $name; $this->withAnyArgs(); } /** * Return a string with the method name and arguments formatted * * @param string $name Name of the expected method * @param array $args List of arguments to the method * @return string */ public function __toString() { return \Mockery::formatArgs($this->_name, $this->_expectedArgs); } /** * Verify the current call, i.e. that the given arguments match those * of this expectation * * @param array $args * @return mixed */ public function verifyCall(array $args) { $this->validateOrder(); $this->_actualCount++; if (true === $this->_passthru) { return $this->_mock->mockery_callSubjectMethod($this->_name, $args); } $return = $this->_getReturnValue($args); $this->throwAsNecessary($return); $this->_setValues(); return $return; } /** * Throws an exception if the expectation has been configured to do so * * @throws \Throwable * @return void */ private function throwAsNecessary($return) { if (!$this->_throw) { return; } if ($return instanceof \Throwable) { throw $return; } return; } /** * Sets public properties with queued values to the mock object * * @param array $args * @return mixed */ protected function _setValues() { $mockClass = get_class($this->_mock); $container = $this->_mock->mockery_getContainer(); /** @var Mock[] $mocks */ $mocks = $container->getMocks(); foreach ($this->_setQueue as $name => &$values) { if (count($values) > 0) { $value = array_shift($values); $this->_mock->{$name} = $value; foreach ($mocks as $mock) { if (is_a($mock, $mockClass) && $mock->mockery_isInstance()) { $mock->{$name} = $value; } } } } } /** * Fetch the return value for the matching args * * @param array $args * @return mixed */ protected function _getReturnValue(array $args) { if (count($this->_closureQueue) > 1) { return call_user_func_array(array_shift($this->_closureQueue), $args); } elseif (count($this->_closureQueue) > 0) { return call_user_func_array(current($this->_closureQueue), $args); } elseif (count($this->_returnQueue) > 1) { return array_shift($this->_returnQueue); } elseif (count($this->_returnQueue) > 0) { return current($this->_returnQueue); } return $this->_mock->mockery_returnValueForMethod($this->_name); } /** * Checks if this expectation is eligible for additional calls * * @return bool */ public function isEligible() { foreach ($this->_countValidators as $validator) { if (!$validator->isEligible($this->_actualCount)) { return false; } } return true; } /** * Check if there is a constraint on call count * * @return bool */ public function isCallCountConstrained() { return (count($this->_countValidators) > 0); } /** * Verify call order * * @return void */ public function validateOrder() { if ($this->_orderNumber) { $this->_mock->mockery_validateOrder((string) $this, $this->_orderNumber, $this->_mock); } if ($this->_globalOrderNumber) { $this->_mock->mockery_getContainer() ->mockery_validateOrder((string) $this, $this->_globalOrderNumber, $this->_mock); } } /** * Verify this expectation * * @return void */ public function verify() { foreach ($this->_countValidators as $validator) { $validator->validate($this->_actualCount); } } /** * Check if the registered expectation is an ArgumentListMatcher * @return bool */ private function isArgumentListMatcher() { return (count($this->_expectedArgs) === 1 && ($this->_expectedArgs[0] instanceof ArgumentListMatcher)); } private function isAndAnyOtherArgumentsMatcher($expectedArg) { return $expectedArg instanceof AndAnyOtherArgs; } /** * Check if passed arguments match an argument expectation * * @param array $args * @return bool */ public function matchArgs(array $args) { if ($this->isArgumentListMatcher()) { return $this->_matchArg($this->_expectedArgs[0], $args); } $argCount = count($args); if ($argCount !== count((array) $this->_expectedArgs)) { $lastExpectedArgument = end($this->_expectedArgs); reset($this->_expectedArgs); if ($this->isAndAnyOtherArgumentsMatcher($lastExpectedArgument)) { $args = array_slice($args, 0, array_search($lastExpectedArgument, $this->_expectedArgs, true)); return $this->_matchArgs($args); } return false; } return $this->_matchArgs($args); } /** * Check if the passed arguments match the expectations, one by one. * * @param array $args * @return bool */ protected function _matchArgs($args) { $argCount = count($args); for ($i=0; $i<$argCount; $i++) { $param =& $args[$i]; if (!$this->_matchArg($this->_expectedArgs[$i], $param)) { return false; } } return true; } /** * Check if passed argument matches an argument expectation * * @param mixed $expected * @param mixed $actual * @return bool */ protected function _matchArg($expected, &$actual) { if ($expected === $actual) { return true; } if (!is_object($expected) && !is_object($actual) && $expected == $actual) { return true; } if (is_string($expected) && is_object($actual)) { $result = $actual instanceof $expected; if ($result) { return true; } } if (is_object($expected)) { $matcher = \Mockery::getConfiguration()->getDefaultMatcher(get_class($expected)); if ($matcher !== null) { $expected = new $matcher($expected); } } if ($expected instanceof \Mockery\Matcher\MatcherAbstract) { return $expected->match($actual); } if ($expected instanceof \Hamcrest\Matcher || $expected instanceof \Hamcrest_Matcher) { @trigger_error('Hamcrest package has been deprecated and will be removed in 2.0', E_USER_DEPRECATED); return $expected->matches($actual); } return false; } /** * Expected argument setter for the expectation * * @param mixed ...$args * * @return self */ public function with(...$args) { return $this->withArgs($args); } /** * Expected arguments for the expectation passed as an array * * @param array $arguments * @return self */ private function withArgsInArray(array $arguments) { if (empty($arguments)) { return $this->withNoArgs(); } $this->_expectedArgs = $arguments; return $this; } /** * Expected arguments have to be matched by the given closure. * * @param Closure $closure * @return self */ private function withArgsMatchedByClosure(Closure $closure) { $this->_expectedArgs = [new MultiArgumentClosure($closure)]; return $this; } /** * Expected arguments for the expectation passed as an array or a closure that matches each passed argument on * each function call. * * @param array|Closure $argsOrClosure * @return self */ public function withArgs($argsOrClosure) { if (is_array($argsOrClosure)) { $this->withArgsInArray($argsOrClosure); } elseif ($argsOrClosure instanceof Closure) { $this->withArgsMatchedByClosure($argsOrClosure); } else { throw new \InvalidArgumentException(sprintf('Call to %s with an invalid argument (%s), only array and ' . 'closure are allowed', __METHOD__, $argsOrClosure)); } return $this; } /** * Set with() as no arguments expected * * @return self */ public function withNoArgs() { $this->_expectedArgs = [new NoArgs()]; return $this; } /** * Set expectation that any arguments are acceptable * * @return self */ public function withAnyArgs() { $this->_expectedArgs = [new AnyArgs()]; return $this; } /** * Expected arguments should partially match the real arguments * * @param mixed ...$expectedArgs * @return self */ public function withSomeOfArgs(...$expectedArgs) { return $this->withArgs(function (...$args) use ($expectedArgs) { foreach ($expectedArgs as $expectedArg) { if (!in_array($expectedArg, $args, true)) { return false; } } return true; }); } /** * Set a return value, or sequential queue of return values * * @param mixed ...$args * @return self */ public function andReturn(...$args) { $this->_returnQueue = $args; return $this; } /** * Set a return value, or sequential queue of return values * * @param mixed ...$args * @return self */ public function andReturns(...$args) { return call_user_func_array([$this, 'andReturn'], $args); } /** * Return this mock, like a fluent interface * * @return self */ public function andReturnSelf() { return $this->andReturn($this->_mock); } /** * Set a sequential queue of return values with an array * * @param array $values * @return self */ public function andReturnValues(array $values) { call_user_func_array(array($this, 'andReturn'), $values); return $this; } /** * Set a closure or sequence of closures with which to generate return * values. The arguments passed to the expected method are passed to the * closures as parameters. * * @param callable ...$args * @return self */ public function andReturnUsing(...$args) { $this->_closureQueue = $args; return $this; } /** * Sets up a closure to return the nth argument from the expected method call * * @param int $index * @return self */ public function andReturnArg($index) { if (!is_int($index) || $index < 0) { throw new \InvalidArgumentException("Invalid argument index supplied. Index must be a non-negative integer."); } $closure = function (...$args) use ($index) { if (array_key_exists($index, $args)) { return $args[$index]; } throw new \OutOfBoundsException("Cannot return an argument value. No argument exists for the index $index"); }; $this->_closureQueue = [$closure]; return $this; } /** * Return a self-returning black hole object. * * @return self */ public function andReturnUndefined() { $this->andReturn(new \Mockery\Undefined()); return $this; } /** * Return null. This is merely a language construct for Mock describing. * * @return self */ public function andReturnNull() { return $this->andReturn(null); } public function andReturnFalse() { return $this->andReturn(false); } public function andReturnTrue() { return $this->andReturn(true); } /** * Set Exception class and arguments to that class to be thrown * * @param string|\Exception $exception * @param string $message * @param int $code * @param \Exception $previous * @return self */ public function andThrow($exception, $message = '', $code = 0, \Exception $previous = null) { $this->_throw = true; if (is_object($exception)) { $this->andReturn($exception); } else { $this->andReturn(new $exception($message, $code, $previous)); } return $this; } public function andThrows($exception, $message = '', $code = 0, \Exception $previous = null) { return $this->andThrow($exception, $message, $code, $previous); } /** * Set Exception classes to be thrown * * @param array $exceptions * @return self */ public function andThrowExceptions(array $exceptions) { $this->_throw = true; foreach ($exceptions as $exception) { if (!is_object($exception)) { throw new Exception('You must pass an array of exception objects to andThrowExceptions'); } } return $this->andReturnValues($exceptions); } /** * Register values to be set to a public property each time this expectation occurs * * @param string $name * @param array ...$values * @return self */ public function andSet($name, ...$values) { $this->_setQueue[$name] = $values; return $this; } /** * Sets up a closure that will yield each of the provided args * * @param mixed ...$args * @return self */ public function andYield(...$args) { $this->_closureQueue = [ static function () use ($args) { foreach ($args as $arg) { yield $arg; } }, ]; return $this; } /** * Alias to andSet(). Allows the natural English construct * - set('foo', 'bar')->andReturn('bar') * * @param string $name * @param mixed $value * @return self */ public function set($name, $value) { return call_user_func_array(array($this, 'andSet'), func_get_args()); } /** * Indicates this expectation should occur zero or more times * * @return self */ public function zeroOrMoreTimes() { $this->atLeast()->never(); } /** * Indicates the number of times this expectation should occur * * @param int $limit * @throws \InvalidArgumentException * @return self */ public function times($limit = null) { if (is_null($limit)) { return $this; } if (!is_int($limit)) { throw new \InvalidArgumentException('The passed Times limit should be an integer value'); } $this->_countValidators[$this->_countValidatorClass] = new $this->_countValidatorClass($this, $limit); if ('Mockery\CountValidator\Exact' !== $this->_countValidatorClass) { $this->_countValidatorClass = 'Mockery\CountValidator\Exact'; unset($this->_countValidators[$this->_countValidatorClass]); } return $this; } /** * Indicates that this expectation is never expected to be called * * @return self */ public function never() { return $this->times(0); } /** * Indicates that this expectation is expected exactly once * * @return self */ public function once() { return $this->times(1); } /** * Indicates that this expectation is expected exactly twice * * @return self */ public function twice() { return $this->times(2); } /** * Sets next count validator to the AtLeast instance * * @return self */ public function atLeast() { $this->_countValidatorClass = 'Mockery\CountValidator\AtLeast'; return $this; } /** * Sets next count validator to the AtMost instance * * @return self */ public function atMost() { $this->_countValidatorClass = 'Mockery\CountValidator\AtMost'; return $this; } /** * Shorthand for setting minimum and maximum constraints on call counts * * @param int $minimum * @param int $maximum */ public function between($minimum, $maximum) { return $this->atLeast()->times($minimum)->atMost()->times($maximum); } /** * Set the exception message * * @param string $message * @return $this */ public function because($message) { $this->_because = $message; return $this; } /** * Indicates that this expectation must be called in a specific given order * * @param string $group Name of the ordered group * @return self */ public function ordered($group = null) { if ($this->_globally) { $this->_globalOrderNumber = $this->_defineOrdered($group, $this->_mock->mockery_getContainer()); } else { $this->_orderNumber = $this->_defineOrdered($group, $this->_mock); } $this->_globally = false; return $this; } /** * Indicates call order should apply globally * * @return self */ public function globally() { $this->_globally = true; return $this; } /** * Setup the ordering tracking on the mock or mock container * * @param string $group * @param object $ordering * @return int */ protected function _defineOrdered($group, $ordering) { $groups = $ordering->mockery_getGroups(); if (is_null($group)) { $result = $ordering->mockery_allocateOrder(); } elseif (isset($groups[$group])) { $result = $groups[$group]; } else { $result = $ordering->mockery_allocateOrder(); $ordering->mockery_setGroup($group, $result); } return $result; } /** * Return order number * * @return int */ public function getOrderNumber() { return $this->_orderNumber; } /** * Mark this expectation as being a default * * @return self */ public function byDefault() { $director = $this->_mock->mockery_getExpectationsFor($this->_name); if (!empty($director)) { $director->makeExpectationDefault($this); } return $this; } /** * Return the parent mock of the expectation * * @return \Mockery\LegacyMockInterface|\Mockery\MockInterface */ public function getMock() { return $this->_mock; } /** * Flag this expectation as calling the original class method with the * any provided arguments instead of using a return value queue. * * @return self */ public function passthru() { if ($this->_mock instanceof Mock) { throw new Exception( 'Mock Objects not created from a loaded/existing class are ' . 'incapable of passing method calls through to a parent class' ); } $this->_passthru = true; return $this; } /** * Cloning logic * */ public function __clone() { $newValidators = array(); $countValidators = $this->_countValidators; foreach ($countValidators as $validator) { $newValidators[] = clone $validator; } $this->_countValidators = $newValidators; } public function getName() { return $this->_name; } public function getExceptionMessage() { return $this->_because; } } Mockery/Container.php 0000644 00000036366 15107542733 0010635 0 ustar 00 <?php /** * Mockery (https://docs.mockery.io/) * * @copyright https://github.com/mockery/mockery/blob/HEAD/COPYRIGHT.md * @license https://github.com/mockery/mockery/blob/HEAD/LICENSE BSD 3-Clause License * @link https://github.com/mockery/mockery for the canonical source repository */ namespace Mockery; use Mockery\Generator\Generator; use Mockery\Generator\MockConfigurationBuilder; use Mockery\Loader\Loader as LoaderInterface; class Container { const BLOCKS = \Mockery::BLOCKS; /** * Store of mock objects * * @var array */ protected $_mocks = array(); /** * Order number of allocation * * @var int */ protected $_allocatedOrder = 0; /** * Current ordered number * * @var int */ protected $_currentOrder = 0; /** * Ordered groups * * @var array */ protected $_groups = array(); /** * @var Generator */ protected $_generator; /** * @var LoaderInterface */ protected $_loader; /** * @var array */ protected $_namedMocks = array(); public function __construct(Generator $generator = null, LoaderInterface $loader = null) { $this->_generator = $generator ?: \Mockery::getDefaultGenerator(); $this->_loader = $loader ?: \Mockery::getDefaultLoader(); } /** * Generates a new mock object for this container * * I apologies in advance for this. A God Method just fits the API which * doesn't require differentiating between classes, interfaces, abstracts, * names or partials - just so long as it's something that can be mocked. * I'll refactor it one day so it's easier to follow. * * @param array ...$args * * @return Mock * @throws Exception\RuntimeException */ public function mock(...$args) { $expectationClosure = null; $quickdefs = array(); $constructorArgs = null; $blocks = array(); $class = null; if (count($args) > 1) { $finalArg = end($args); reset($args); if (is_callable($finalArg) && is_object($finalArg)) { $expectationClosure = array_pop($args); } } $builder = new MockConfigurationBuilder(); foreach ($args as $k => $arg) { if ($arg instanceof MockConfigurationBuilder) { $builder = $arg; unset($args[$k]); } } reset($args); $builder->setParameterOverrides(\Mockery::getConfiguration()->getInternalClassMethodParamMaps()); $builder->setConstantsMap(\Mockery::getConfiguration()->getConstantsMap()); while (count($args) > 0) { $arg = array_shift($args); // check for multiple interfaces if (is_string($arg)) { foreach (explode('|', $arg) as $type) { if ($arg === 'null') { // skip PHP 8 'null's } elseif (strpos($type, ',') && !strpos($type, ']')) { $interfaces = explode(',', str_replace(' ', '', $type)); $builder->addTargets($interfaces); } elseif (substr($type, 0, 6) == 'alias:') { $type = str_replace('alias:', '', $type); $builder->addTarget('stdClass'); $builder->setName($type); } elseif (substr($type, 0, 9) == 'overload:') { $type = str_replace('overload:', '', $type); $builder->setInstanceMock(true); $builder->addTarget('stdClass'); $builder->setName($type); } elseif (substr($type, strlen($type)-1, 1) == ']') { $parts = explode('[', $type); if (!class_exists($parts[0], true) && !interface_exists($parts[0], true)) { throw new \Mockery\Exception('Can only create a partial mock from' . ' an existing class or interface'); } $class = $parts[0]; $parts[1] = str_replace(' ', '', $parts[1]); $partialMethods = array_filter(explode(',', strtolower(rtrim($parts[1], ']')))); $builder->addTarget($class); foreach ($partialMethods as $partialMethod) { if ($partialMethod[0] === '!') { $builder->addBlackListedMethod(substr($partialMethod, 1)); continue; } $builder->addWhiteListedMethod($partialMethod); } } elseif (class_exists($type, true) || interface_exists($type, true) || trait_exists($type, true)) { $builder->addTarget($type); } elseif (!\Mockery::getConfiguration()->mockingNonExistentMethodsAllowed() && (!class_exists($type, true) && !interface_exists($type, true))) { throw new \Mockery\Exception("Mockery can't find '$type' so can't mock it"); } else { if (!$this->isValidClassName($type)) { throw new \Mockery\Exception('Class name contains invalid characters'); } $builder->addTarget($type); } break; // unions are "sum" types and not "intersections", and so we must only process the first part } } elseif (is_object($arg)) { $builder->addTarget($arg); } elseif (is_array($arg)) { if (!empty($arg) && array_keys($arg) !== range(0, count($arg) - 1)) { // if associative array if (array_key_exists(self::BLOCKS, $arg)) { $blocks = $arg[self::BLOCKS]; } unset($arg[self::BLOCKS]); $quickdefs = $arg; } else { $constructorArgs = $arg; } } else { throw new \Mockery\Exception( 'Unable to parse arguments sent to ' . get_class($this) . '::mock()' ); } } $builder->addBlackListedMethods($blocks); if (!is_null($constructorArgs)) { $builder->addBlackListedMethod("__construct"); // we need to pass through } else { $builder->setMockOriginalDestructor(true); } if (!empty($partialMethods) && $constructorArgs === null) { $constructorArgs = array(); } $config = $builder->getMockConfiguration(); $this->checkForNamedMockClashes($config); $def = $this->getGenerator()->generate($config); if (class_exists($def->getClassName(), $attemptAutoload = false)) { $rfc = new \ReflectionClass($def->getClassName()); if (!$rfc->implementsInterface("Mockery\LegacyMockInterface")) { throw new \Mockery\Exception\RuntimeException("Could not load mock {$def->getClassName()}, class already exists"); } } $this->getLoader()->load($def); $mock = $this->_getInstance($def->getClassName(), $constructorArgs); $mock->mockery_init($this, $config->getTargetObject(), $config->isInstanceMock()); if (!empty($quickdefs)) { if (\Mockery::getConfiguration()->getQuickDefinitions()->shouldBeCalledAtLeastOnce()) { $mock->shouldReceive($quickdefs)->atLeast()->once(); } else { $mock->shouldReceive($quickdefs)->byDefault(); } } if (!empty($expectationClosure)) { $expectationClosure($mock); } $this->rememberMock($mock); return $mock; } public function instanceMock() { } public function getLoader() { return $this->_loader; } public function getGenerator() { return $this->_generator; } /** * @param string $method * @param string $parent * @return string|null */ public function getKeyOfDemeterMockFor($method, $parent) { $keys = array_keys($this->_mocks); $match = preg_grep("/__demeter_" . md5($parent) . "_{$method}$/", $keys); if (count($match) == 1) { $res = array_values($match); if (count($res) > 0) { return $res[0]; } } return null; } /** * @return array */ public function getMocks() { return $this->_mocks; } /** * Tear down tasks for this container * * @throws \Exception * @return void */ public function mockery_teardown() { try { $this->mockery_verify(); } catch (\Exception $e) { $this->mockery_close(); throw $e; } } /** * Verify the container mocks * * @return void */ public function mockery_verify() { foreach ($this->_mocks as $mock) { $mock->mockery_verify(); } } /** * Retrieves all exceptions thrown by mocks * * @return array */ public function mockery_thrownExceptions() { $e = []; foreach ($this->_mocks as $mock) { $e = array_merge($e, $mock->mockery_thrownExceptions()); } return $e; } /** * Reset the container to its original state * * @return void */ public function mockery_close() { foreach ($this->_mocks as $mock) { $mock->mockery_teardown(); } $this->_mocks = array(); } /** * Fetch the next available allocation order number * * @return int */ public function mockery_allocateOrder() { $this->_allocatedOrder += 1; return $this->_allocatedOrder; } /** * Set ordering for a group * * @param mixed $group * @param int $order */ public function mockery_setGroup($group, $order) { $this->_groups[$group] = $order; } /** * Fetch array of ordered groups * * @return array */ public function mockery_getGroups() { return $this->_groups; } /** * Set current ordered number * * @param int $order * @return int The current order number that was set */ public function mockery_setCurrentOrder($order) { $this->_currentOrder = $order; return $this->_currentOrder; } /** * Get current ordered number * * @return int */ public function mockery_getCurrentOrder() { return $this->_currentOrder; } /** * Validate the current mock's ordering * * @param string $method * @param int $order * @throws \Mockery\Exception * @return void */ public function mockery_validateOrder($method, $order, \Mockery\LegacyMockInterface $mock) { if ($order < $this->_currentOrder) { $exception = new \Mockery\Exception\InvalidOrderException( 'Method ' . $method . ' called out of order: expected order ' . $order . ', was ' . $this->_currentOrder ); $exception->setMock($mock) ->setMethodName($method) ->setExpectedOrder($order) ->setActualOrder($this->_currentOrder); throw $exception; } $this->mockery_setCurrentOrder($order); } /** * Gets the count of expectations on the mocks * * @return int */ public function mockery_getExpectationCount() { $count = 0; foreach ($this->_mocks as $mock) { $count += $mock->mockery_getExpectationCount(); } return $count; } /** * Store a mock and set its container reference * * @param \Mockery\Mock $mock * @return \Mockery\LegacyMockInterface|\Mockery\MockInterface */ public function rememberMock(\Mockery\LegacyMockInterface $mock) { if (!isset($this->_mocks[get_class($mock)])) { $this->_mocks[get_class($mock)] = $mock; } else { /** * This condition triggers for an instance mock where origin mock * is already remembered */ $this->_mocks[] = $mock; } return $mock; } /** * Retrieve the last remembered mock object, which is the same as saying * retrieve the current mock being programmed where you have yet to call * mock() to change it - thus why the method name is "self" since it will be * be used during the programming of the same mock. * * @return \Mockery\Mock */ public function self() { $mocks = array_values($this->_mocks); $index = count($mocks) - 1; return $mocks[$index]; } /** * Return a specific remembered mock according to the array index it * was stored to in this container instance * * @return \Mockery\Mock */ public function fetchMock($reference) { if (isset($this->_mocks[$reference])) { return $this->_mocks[$reference]; } } protected function _getInstance($mockName, $constructorArgs = null) { if ($constructorArgs !== null) { $r = new \ReflectionClass($mockName); return $r->newInstanceArgs($constructorArgs); } try { $instantiator = new Instantiator(); $instance = $instantiator->instantiate($mockName); } catch (\Exception $ex) { $internalMockName = $mockName . '_Internal'; if (!class_exists($internalMockName)) { eval("class $internalMockName extends $mockName {" . 'public function __construct() {}' . '}'); } $instance = new $internalMockName(); } return $instance; } protected function checkForNamedMockClashes($config) { $name = $config->getName(); if (!$name) { return; } $hash = $config->getHash(); if (isset($this->_namedMocks[$name])) { if ($hash !== $this->_namedMocks[$name]) { throw new \Mockery\Exception( "The mock named '$name' has been already defined with a different mock configuration" ); } } $this->_namedMocks[$name] = $hash; } /** * see http://php.net/manual/en/language.oop5.basic.php * @param string $className * @return bool */ public function isValidClassName($className) { $pos = strpos($className, '\\'); if ($pos === 0) { $className = substr($className, 1); // remove the first backslash } // all the namespaces and class name should match the regex $invalidNames = array_filter(explode('\\', $className), function ($name) { return !preg_match('/^[a-zA-Z_\x7f-\xff][a-zA-Z0-9_\x7f-\xff]*$/', $name); }); return empty($invalidNames); } } Mockery/Undefined.php 0000644 00000001415 15107542733 0010577 0 ustar 00 <?php /** * Mockery (https://docs.mockery.io/) * * @copyright https://github.com/mockery/mockery/blob/HEAD/COPYRIGHT.md * @license https://github.com/mockery/mockery/blob/HEAD/LICENSE BSD 3-Clause License * @link https://github.com/mockery/mockery for the canonical source repository */ namespace Mockery; class Undefined { /** * Call capturing to merely return this same object. * * @param string $method * @param array $args * @return self */ public function __call($method, array $args) { return $this; } /** * Return a string, avoiding E_RECOVERABLE_ERROR * * @return string */ public function __toString() { return __CLASS__ . ":" . spl_object_hash($this); } } Mockery/Exception.php 0000644 00000000717 15107542733 0010640 0 ustar 00 <?php /** * Mockery (https://docs.mockery.io/) * * @copyright https://github.com/mockery/mockery/blob/HEAD/COPYRIGHT.md * @license https://github.com/mockery/mockery/blob/HEAD/LICENSE BSD 3-Clause License * @link https://github.com/mockery/mockery for the canonical source repository */ namespace Mockery; use Mockery\Exception\MockeryExceptionInterface; class Exception extends \UnexpectedValueException implements MockeryExceptionInterface { } Mockery/Exception/BadMethodCallException.php 0000644 00000001445 15107542733 0015141 0 ustar 00 <?php /** * Mockery (https://docs.mockery.io/) * * @copyright https://github.com/mockery/mockery/blob/HEAD/COPYRIGHT.md * @license https://github.com/mockery/mockery/blob/HEAD/LICENSE BSD 3-Clause License * @link https://github.com/mockery/mockery for the canonical source repository */ namespace Mockery\Exception; class BadMethodCallException extends \BadMethodCallException implements MockeryExceptionInterface { private $dismissed = false; public function dismiss() { $this->dismissed = true; // we sometimes stack them if ($this->getPrevious() && $this->getPrevious() instanceof BadMethodCallException) { $this->getPrevious()->dismiss(); } } public function dismissed() { return $this->dismissed; } } Mockery/Exception/InvalidOrderException.php 0000644 00000002605 15107542733 0015077 0 ustar 00 <?php /** * Mockery (https://docs.mockery.io/) * * @copyright https://github.com/mockery/mockery/blob/HEAD/COPYRIGHT.md * @license https://github.com/mockery/mockery/blob/HEAD/LICENSE BSD 3-Clause License * @link https://github.com/mockery/mockery for the canonical source repository */ namespace Mockery\Exception; use Mockery; class InvalidOrderException extends Mockery\Exception { protected $method = null; protected $expected = 0; protected $actual = null; protected $mockObject = null; public function setMock(Mockery\LegacyMockInterface $mock) { $this->mockObject = $mock; return $this; } public function setMethodName($name) { $this->method = $name; return $this; } public function setActualOrder($count) { $this->actual = $count; return $this; } public function setExpectedOrder($count) { $this->expected = $count; return $this; } public function getMock() { return $this->mockObject; } public function getMethodName() { return $this->method; } public function getActualOrder() { return $this->actual; } public function getExpectedOrder() { return $this->expected; } public function getMockName() { return $this->getMock()->mockery_getName(); } } Mockery/Exception/RuntimeException.php 0000644 00000000637 15107542733 0014143 0 ustar 00 <?php /** * Mockery (https://docs.mockery.io/) * * @copyright https://github.com/mockery/mockery/blob/HEAD/COPYRIGHT.md * @license https://github.com/mockery/mockery/blob/HEAD/LICENSE BSD 3-Clause License * @link https://github.com/mockery/mockery for the canonical source repository */ namespace Mockery\Exception; class RuntimeException extends \Exception implements MockeryExceptionInterface { } Mockery/Exception/MockeryExceptionInterface.php 0000644 00000000660 15107542733 0015746 0 ustar 00 <?php /** * Mockery (https://docs.mockery.io/) * * @copyright https://github.com/mockery/mockery/blob/HEAD/COPYRIGHT.md * @license https://github.com/mockery/mockery/blob/HEAD/LICENSE BSD 3-Clause License * @link https://github.com/mockery/mockery for the canonical source repository */ declare(strict_types=1); namespace Mockery\Exception; use Throwable; interface MockeryExceptionInterface extends Throwable { } Mockery/Exception/NoMatchingExpectationException.php 0000644 00000002265 15107542733 0016752 0 ustar 00 <?php /** * Mockery (https://docs.mockery.io/) * * @copyright https://github.com/mockery/mockery/blob/HEAD/COPYRIGHT.md * @license https://github.com/mockery/mockery/blob/HEAD/LICENSE BSD 3-Clause License * @link https://github.com/mockery/mockery for the canonical source repository */ namespace Mockery\Exception; use Mockery; class NoMatchingExpectationException extends Mockery\Exception { protected $method = null; protected $actual = array(); protected $mockObject = null; public function setMock(Mockery\LegacyMockInterface $mock) { $this->mockObject = $mock; return $this; } public function setMethodName($name) { $this->method = $name; return $this; } public function setActualArguments($count) { $this->actual = $count; return $this; } public function getMock() { return $this->mockObject; } public function getMethodName() { return $this->method; } public function getActualArguments() { return $this->actual; } public function getMockName() { return $this->getMock()->mockery_getName(); } } Mockery/Exception/InvalidArgumentException.php 0000644 00000000666 15107542733 0015613 0 ustar 00 <?php /** * Mockery (https://docs.mockery.io/) * * @copyright https://github.com/mockery/mockery/blob/HEAD/COPYRIGHT.md * @license https://github.com/mockery/mockery/blob/HEAD/LICENSE BSD 3-Clause License * @link https://github.com/mockery/mockery for the canonical source repository */ namespace Mockery\Exception; class InvalidArgumentException extends \InvalidArgumentException implements MockeryExceptionInterface { } Mockery/Exception/InvalidCountException.php 0000644 00000003650 15107542733 0015115 0 ustar 00 <?php /** * Mockery (https://docs.mockery.io/) * * @copyright https://github.com/mockery/mockery/blob/HEAD/COPYRIGHT.md * @license https://github.com/mockery/mockery/blob/HEAD/LICENSE BSD 3-Clause License * @link https://github.com/mockery/mockery for the canonical source repository */ namespace Mockery\Exception; use Mockery; use Mockery\Exception\RuntimeException; class InvalidCountException extends Mockery\CountValidator\Exception { protected $method = null; protected $expected = 0; protected $expectedComparative = '<='; protected $actual = null; protected $mockObject = null; public function setMock(Mockery\LegacyMockInterface $mock) { $this->mockObject = $mock; return $this; } public function setMethodName($name) { $this->method = $name; return $this; } public function setActualCount($count) { $this->actual = $count; return $this; } public function setExpectedCount($count) { $this->expected = $count; return $this; } public function setExpectedCountComparative($comp) { if (!in_array($comp, array('=', '>', '<', '>=', '<='))) { throw new RuntimeException( 'Illegal comparative for expected call counts set: ' . $comp ); } $this->expectedComparative = $comp; return $this; } public function getMock() { return $this->mockObject; } public function getMethodName() { return $this->method; } public function getActualCount() { return $this->actual; } public function getExpectedCount() { return $this->expected; } public function getMockName() { return $this->getMock()->mockery_getName(); } public function getExpectedCountComparative() { return $this->expectedComparative; } } Mockery/VerificationDirector.php 0000644 00000005264 15107542733 0013022 0 ustar 00 <?php /** * Mockery (https://docs.mockery.io/) * * @copyright https://github.com/mockery/mockery/blob/HEAD/COPYRIGHT.md * @license https://github.com/mockery/mockery/blob/HEAD/LICENSE BSD 3-Clause License * @link https://github.com/mockery/mockery for the canonical source repository */ namespace Mockery; class VerificationDirector { private $receivedMethodCalls; private $expectation; public function __construct(ReceivedMethodCalls $receivedMethodCalls, VerificationExpectation $expectation) { $this->receivedMethodCalls = $receivedMethodCalls; $this->expectation = $expectation; } public function verify() { return $this->receivedMethodCalls->verify($this->expectation); } public function with(...$args) { return $this->cloneApplyAndVerify("with", $args); } public function withArgs($args) { return $this->cloneApplyAndVerify("withArgs", array($args)); } public function withNoArgs() { return $this->cloneApplyAndVerify("withNoArgs", array()); } public function withAnyArgs() { return $this->cloneApplyAndVerify("withAnyArgs", array()); } public function times($limit = null) { return $this->cloneWithoutCountValidatorsApplyAndVerify("times", array($limit)); } public function once() { return $this->cloneWithoutCountValidatorsApplyAndVerify("once", array()); } public function twice() { return $this->cloneWithoutCountValidatorsApplyAndVerify("twice", array()); } public function atLeast() { return $this->cloneWithoutCountValidatorsApplyAndVerify("atLeast", array()); } public function atMost() { return $this->cloneWithoutCountValidatorsApplyAndVerify("atMost", array()); } public function between($minimum, $maximum) { return $this->cloneWithoutCountValidatorsApplyAndVerify("between", array($minimum, $maximum)); } protected function cloneWithoutCountValidatorsApplyAndVerify($method, $args) { $expectation = clone $this->expectation; $expectation->clearCountValidators(); call_user_func_array(array($expectation, $method), $args); $director = new VerificationDirector($this->receivedMethodCalls, $expectation); $director->verify(); return $director; } protected function cloneApplyAndVerify($method, $args) { $expectation = clone $this->expectation; call_user_func_array(array($expectation, $method), $args); $director = new VerificationDirector($this->receivedMethodCalls, $expectation); $director->verify(); return $director; } } Mockery/Mock.php 0000644 00000070604 15107542733 0007575 0 ustar 00 <?php /** * Mockery (https://docs.mockery.io/) * * @copyright https://github.com/mockery/mockery/blob/HEAD/COPYRIGHT.md * @license https://github.com/mockery/mockery/blob/HEAD/LICENSE BSD 3-Clause License * @link https://github.com/mockery/mockery for the canonical source repository */ namespace Mockery; use Mockery\Exception\BadMethodCallException; use Mockery\ExpectsHigherOrderMessage; use Mockery\HigherOrderMessage; use Mockery\LegacyMockInterface; use Mockery\MockInterface; use Mockery\Reflector; #[\AllowDynamicProperties] class Mock implements MockInterface { /** * Stores an array of all expectation directors for this mock * * @var array */ protected $_mockery_expectations = array(); /** * Stores an initial number of expectations that can be manipulated * while using the getter method. * * @var int */ protected $_mockery_expectations_count = 0; /** * Flag to indicate whether we can ignore method calls missing from our * expectations * * @var bool */ protected $_mockery_ignoreMissing = false; /** * Flag to indicate whether we want to set the ignoreMissing flag on * mocks generated form this calls to this one * * @var bool */ protected $_mockery_ignoreMissingRecursive = false; /** * Flag to indicate whether we can defer method calls missing from our * expectations * * @var bool */ protected $_mockery_deferMissing = false; /** * Flag to indicate whether this mock was verified * * @var bool */ protected $_mockery_verified = false; /** * Given name of the mock * * @var string */ protected $_mockery_name = null; /** * Order number of allocation * * @var int */ protected $_mockery_allocatedOrder = 0; /** * Current ordered number * * @var int */ protected $_mockery_currentOrder = 0; /** * Ordered groups * * @var array */ protected $_mockery_groups = array(); /** * Mock container containing this mock object * * @var \Mockery\Container */ protected $_mockery_container = null; /** * Instance of a core object on which methods are called in the event * it has been set, and an expectation for one of the object's methods * does not exist. This implements a simple partial mock proxy system. * * @var object */ protected $_mockery_partial = null; /** * Flag to indicate we should ignore all expectations temporarily. Used * mainly to prevent expectation matching when in the middle of a mock * object recording session. * * @var bool */ protected $_mockery_disableExpectationMatching = false; /** * Stores all stubbed public methods separate from any on-object public * properties that may exist. * * @var array */ protected $_mockery_mockableProperties = array(); /** * @var array */ protected $_mockery_mockableMethods = array(); /** * Just a local cache for this mock's target's methods * * @var \ReflectionMethod[] */ protected static $_mockery_methods; protected $_mockery_allowMockingProtectedMethods = false; protected $_mockery_receivedMethodCalls; /** * If shouldIgnoreMissing is called, this value will be returned on all calls to missing methods * @var mixed */ protected $_mockery_defaultReturnValue = null; /** * Tracks internally all the bad method call exceptions that happened during runtime * * @var array */ protected $_mockery_thrownExceptions = []; protected $_mockery_instanceMock = true; /** * We want to avoid constructors since class is copied to Generator.php * for inclusion on extending class definitions. * * @param \Mockery\Container $container * @param object $partialObject * @param bool $instanceMock * @return void */ public function mockery_init(\Mockery\Container $container = null, $partialObject = null, $instanceMock = true) { if (is_null($container)) { $container = new \Mockery\Container(); } $this->_mockery_container = $container; if (!is_null($partialObject)) { $this->_mockery_partial = $partialObject; } if (!\Mockery::getConfiguration()->mockingNonExistentMethodsAllowed()) { foreach ($this->mockery_getMethods() as $method) { if ($method->isPublic()) { $this->_mockery_mockableMethods[] = $method->getName(); } } } $this->_mockery_instanceMock = $instanceMock; } /** * Set expected method calls * * @param string ...$methodNames one or many methods that are expected to be called in this mock * * @return \Mockery\ExpectationInterface|\Mockery\Expectation|\Mockery\HigherOrderMessage */ public function shouldReceive(...$methodNames) { if (count($methodNames) === 0) { return new HigherOrderMessage($this, "shouldReceive"); } foreach ($methodNames as $method) { if ("" == $method) { throw new \InvalidArgumentException("Received empty method name"); } } $self = $this; $allowMockingProtectedMethods = $this->_mockery_allowMockingProtectedMethods; $lastExpectation = \Mockery::parseShouldReturnArgs( $this, $methodNames, function ($method) use ($self, $allowMockingProtectedMethods) { $rm = $self->mockery_getMethod($method); if ($rm) { if ($rm->isPrivate()) { throw new \InvalidArgumentException("$method() cannot be mocked as it is a private method"); } if (!$allowMockingProtectedMethods && $rm->isProtected()) { throw new \InvalidArgumentException("$method() cannot be mocked as it is a protected method and mocking protected methods is not enabled for the currently used mock object. Use shouldAllowMockingProtectedMethods() to enable mocking of protected methods."); } } $director = $self->mockery_getExpectationsFor($method); if (!$director) { $director = new \Mockery\ExpectationDirector($method, $self); $self->mockery_setExpectationsFor($method, $director); } $expectation = new \Mockery\Expectation($self, $method); $director->addExpectation($expectation); return $expectation; } ); return $lastExpectation; } // start method allows /** * @param mixed $something String method name or map of method => return * @return self|\Mockery\ExpectationInterface|\Mockery\Expectation|\Mockery\HigherOrderMessage */ public function allows($something = []) { if (is_string($something)) { return $this->shouldReceive($something); } if (empty($something)) { return $this->shouldReceive(); } foreach ($something as $method => $returnValue) { $this->shouldReceive($method)->andReturn($returnValue); } return $this; } // end method allows // start method expects /** /** * @param mixed $something String method name (optional) * @return \Mockery\ExpectationInterface|\Mockery\Expectation|ExpectsHigherOrderMessage */ public function expects($something = null) { if (is_string($something)) { return $this->shouldReceive($something)->once(); } return new ExpectsHigherOrderMessage($this); } // end method expects /** * Shortcut method for setting an expectation that a method should not be called. * * @param string ...$methodNames one or many methods that are expected not to be called in this mock * @return \Mockery\ExpectationInterface|\Mockery\Expectation|\Mockery\HigherOrderMessage */ public function shouldNotReceive(...$methodNames) { if (count($methodNames) === 0) { return new HigherOrderMessage($this, "shouldNotReceive"); } $expectation = call_user_func_array(array($this, 'shouldReceive'), $methodNames); $expectation->never(); return $expectation; } /** * Allows additional methods to be mocked that do not explicitly exist on mocked class * @param String $method name of the method to be mocked * @return Mock */ public function shouldAllowMockingMethod($method) { $this->_mockery_mockableMethods[] = $method; return $this; } /** * Set mock to ignore unexpected methods and return Undefined class * @param mixed $returnValue the default return value for calls to missing functions on this mock * @param bool $recursive Specify if returned mocks should also have shouldIgnoreMissing set * @return static */ public function shouldIgnoreMissing($returnValue = null, $recursive = false) { $this->_mockery_ignoreMissing = true; $this->_mockery_ignoreMissingRecursive = $recursive; $this->_mockery_defaultReturnValue = $returnValue; return $this; } public function asUndefined() { $this->_mockery_ignoreMissing = true; $this->_mockery_defaultReturnValue = new \Mockery\Undefined(); return $this; } /** * @return static */ public function shouldAllowMockingProtectedMethods() { if (!\Mockery::getConfiguration()->mockingNonExistentMethodsAllowed()) { foreach ($this->mockery_getMethods() as $method) { if ($method->isProtected()) { $this->_mockery_mockableMethods[] = $method->getName(); } } } $this->_mockery_allowMockingProtectedMethods = true; return $this; } /** * Set mock to defer unexpected methods to it's parent * * This is particularly useless for this class, as it doesn't have a parent, * but included for completeness * * @deprecated 2.0.0 Please use makePartial() instead * * @return static */ public function shouldDeferMissing() { return $this->makePartial(); } /** * Set mock to defer unexpected methods to it's parent * * It was an alias for shouldDeferMissing(), which will be removed * in 2.0.0. * * @return static */ public function makePartial() { $this->_mockery_deferMissing = true; return $this; } /** * In the event shouldReceive() accepting one or more methods/returns, * this method will switch them from normal expectations to default * expectations * * @return self */ public function byDefault() { foreach ($this->_mockery_expectations as $director) { $exps = $director->getExpectations(); foreach ($exps as $exp) { $exp->byDefault(); } } return $this; } /** * Capture calls to this mock */ public function __call($method, array $args) { return $this->_mockery_handleMethodCall($method, $args); } public static function __callStatic($method, array $args) { return self::_mockery_handleStaticMethodCall($method, $args); } /** * Forward calls to this magic method to the __call method */ public function __toString() { return $this->__call('__toString', array()); } /** * Iterate across all expectation directors and validate each * * @throws \Mockery\CountValidator\Exception * @return void */ public function mockery_verify() { if ($this->_mockery_verified) { return; } if (isset($this->_mockery_ignoreVerification) && $this->_mockery_ignoreVerification == true) { return; } $this->_mockery_verified = true; foreach ($this->_mockery_expectations as $director) { $director->verify(); } } /** * Gets a list of exceptions thrown by this mock * * @return array */ public function mockery_thrownExceptions() { return $this->_mockery_thrownExceptions; } /** * Tear down tasks for this mock * * @return void */ public function mockery_teardown() { } /** * Fetch the next available allocation order number * * @return int */ public function mockery_allocateOrder() { $this->_mockery_allocatedOrder += 1; return $this->_mockery_allocatedOrder; } /** * Set ordering for a group * * @param mixed $group * @param int $order */ public function mockery_setGroup($group, $order) { $this->_mockery_groups[$group] = $order; } /** * Fetch array of ordered groups * * @return array */ public function mockery_getGroups() { return $this->_mockery_groups; } /** * Set current ordered number * * @param int $order */ public function mockery_setCurrentOrder($order) { $this->_mockery_currentOrder = $order; return $this->_mockery_currentOrder; } /** * Get current ordered number * * @return int */ public function mockery_getCurrentOrder() { return $this->_mockery_currentOrder; } /** * Validate the current mock's ordering * * @param string $method * @param int $order * @throws \Mockery\Exception * @return void */ public function mockery_validateOrder($method, $order) { if ($order < $this->_mockery_currentOrder) { $exception = new \Mockery\Exception\InvalidOrderException( 'Method ' . __CLASS__ . '::' . $method . '()' . ' called out of order: expected order ' . $order . ', was ' . $this->_mockery_currentOrder ); $exception->setMock($this) ->setMethodName($method) ->setExpectedOrder($order) ->setActualOrder($this->_mockery_currentOrder); throw $exception; } $this->mockery_setCurrentOrder($order); } /** * Gets the count of expectations for this mock * * @return int */ public function mockery_getExpectationCount() { $count = $this->_mockery_expectations_count; foreach ($this->_mockery_expectations as $director) { $count += $director->getExpectationCount(); } return $count; } /** * Return the expectations director for the given method * * @var string $method * @return \Mockery\ExpectationDirector|null */ public function mockery_setExpectationsFor($method, \Mockery\ExpectationDirector $director) { $this->_mockery_expectations[$method] = $director; } /** * Return the expectations director for the given method * * @var string $method * @return \Mockery\ExpectationDirector|null */ public function mockery_getExpectationsFor($method) { if (isset($this->_mockery_expectations[$method])) { return $this->_mockery_expectations[$method]; } } /** * Find an expectation matching the given method and arguments * * @var string $method * @var array $args * @return \Mockery\Expectation|null */ public function mockery_findExpectation($method, array $args) { if (!isset($this->_mockery_expectations[$method])) { return null; } $director = $this->_mockery_expectations[$method]; return $director->findExpectation($args); } /** * Return the container for this mock * * @return \Mockery\Container */ public function mockery_getContainer() { return $this->_mockery_container; } /** * Return the name for this mock * * @return string */ public function mockery_getName() { return __CLASS__; } /** * @return array */ public function mockery_getMockableProperties() { return $this->_mockery_mockableProperties; } public function __isset($name) { if (false === stripos($name, '_mockery_') && get_parent_class($this) && method_exists(get_parent_class($this), '__isset')) { return call_user_func(get_parent_class($this) . '::__isset', $name); } return false; } public function mockery_getExpectations() { return $this->_mockery_expectations; } /** * Calls a parent class method and returns the result. Used in a passthru * expectation where a real return value is required while still taking * advantage of expectation matching and call count verification. * * @param string $name * @param array $args * @return mixed */ public function mockery_callSubjectMethod($name, array $args) { if (!method_exists($this, $name) && get_parent_class($this) && method_exists(get_parent_class($this), '__call')) { return call_user_func(get_parent_class($this) . '::__call', $name, $args); } return call_user_func_array(get_parent_class($this) . '::' . $name, $args); } /** * @return string[] */ public function mockery_getMockableMethods() { return $this->_mockery_mockableMethods; } /** * @return bool */ public function mockery_isAnonymous() { $rfc = new \ReflectionClass($this); // PHP 8 has Stringable interface $interfaces = array_filter($rfc->getInterfaces(), function ($i) { return $i->getName() !== 'Stringable'; }); return false === $rfc->getParentClass() && 2 === count($interfaces); } public function mockery_isInstance() { return $this->_mockery_instanceMock; } public function __wakeup() { /** * This does not add __wakeup method support. It's a blind method and any * expected __wakeup work will NOT be performed. It merely cuts off * annoying errors where a __wakeup exists but is not essential when * mocking */ } public function __destruct() { /** * Overrides real class destructor in case if class was created without original constructor */ } public function mockery_getMethod($name) { foreach ($this->mockery_getMethods() as $method) { if ($method->getName() == $name) { return $method; } } return null; } /** * @param string $name Method name. * * @return mixed Generated return value based on the declared return value of the named method. */ public function mockery_returnValueForMethod($name) { $rm = $this->mockery_getMethod($name); if ($rm === null) { return null; } $returnType = Reflector::getSimplestReturnType($rm); switch ($returnType) { case null: return null; case 'string': return ''; case 'int': return 0; case 'float': return 0.0; case 'bool': return false; case 'true': return true; case 'false': return false; case 'array': case 'iterable': return []; case 'callable': case '\Closure': return function () { }; case '\Traversable': case '\Generator': $generator = function () { yield; }; return $generator(); case 'void': return null; case 'static': return $this; case 'object': $mock = \Mockery::mock(); if ($this->_mockery_ignoreMissingRecursive) { $mock->shouldIgnoreMissing($this->_mockery_defaultReturnValue, true); } return $mock; default: $mock = \Mockery::mock($returnType); if ($this->_mockery_ignoreMissingRecursive) { $mock->shouldIgnoreMissing($this->_mockery_defaultReturnValue, true); } return $mock; } } public function shouldHaveReceived($method = null, $args = null) { if ($method === null) { return new HigherOrderMessage($this, "shouldHaveReceived"); } $expectation = new \Mockery\VerificationExpectation($this, $method); if (null !== $args) { $expectation->withArgs($args); } $expectation->atLeast()->once(); $director = new \Mockery\VerificationDirector($this->_mockery_getReceivedMethodCalls(), $expectation); $this->_mockery_expectations_count++; $director->verify(); return $director; } public function shouldHaveBeenCalled() { return $this->shouldHaveReceived("__invoke"); } public function shouldNotHaveReceived($method = null, $args = null) { if ($method === null) { return new HigherOrderMessage($this, "shouldNotHaveReceived"); } $expectation = new \Mockery\VerificationExpectation($this, $method); if (null !== $args) { $expectation->withArgs($args); } $expectation->never(); $director = new \Mockery\VerificationDirector($this->_mockery_getReceivedMethodCalls(), $expectation); $this->_mockery_expectations_count++; $director->verify(); return null; } public function shouldNotHaveBeenCalled(array $args = null) { return $this->shouldNotHaveReceived("__invoke", $args); } protected static function _mockery_handleStaticMethodCall($method, array $args) { $associatedRealObject = \Mockery::fetchMock(__CLASS__); try { return $associatedRealObject->__call($method, $args); } catch (BadMethodCallException $e) { throw new BadMethodCallException( 'Static method ' . $associatedRealObject->mockery_getName() . '::' . $method . '() does not exist on this mock object', 0, $e ); } } protected function _mockery_getReceivedMethodCalls() { return $this->_mockery_receivedMethodCalls ?: $this->_mockery_receivedMethodCalls = new \Mockery\ReceivedMethodCalls(); } /** * Called when an instance Mock was created and its constructor is getting called * * @see \Mockery\Generator\StringManipulation\Pass\InstanceMockPass * @param array $args */ protected function _mockery_constructorCalled(array $args) { if (!isset($this->_mockery_expectations['__construct']) /* _mockery_handleMethodCall runs the other checks */) { return; } $this->_mockery_handleMethodCall('__construct', $args); } protected function _mockery_findExpectedMethodHandler($method) { if (isset($this->_mockery_expectations[$method])) { return $this->_mockery_expectations[$method]; } $lowerCasedMockeryExpectations = array_change_key_case($this->_mockery_expectations, CASE_LOWER); $lowerCasedMethod = strtolower($method); if (isset($lowerCasedMockeryExpectations[$lowerCasedMethod])) { return $lowerCasedMockeryExpectations[$lowerCasedMethod]; } return null; } protected function _mockery_handleMethodCall($method, array $args) { $this->_mockery_getReceivedMethodCalls()->push(new \Mockery\MethodCall($method, $args)); $rm = $this->mockery_getMethod($method); if ($rm && $rm->isProtected() && !$this->_mockery_allowMockingProtectedMethods) { if ($rm->isAbstract()) { return; } try { $prototype = $rm->getPrototype(); if ($prototype->isAbstract()) { return; } } catch (\ReflectionException $re) { // noop - there is no hasPrototype method } return call_user_func_array(get_parent_class($this) . '::' . $method, $args); } $handler = $this->_mockery_findExpectedMethodHandler($method); if ($handler !== null && !$this->_mockery_disableExpectationMatching) { try { return $handler->call($args); } catch (\Mockery\Exception\NoMatchingExpectationException $e) { if (!$this->_mockery_ignoreMissing && !$this->_mockery_deferMissing) { throw $e; } } } if (!is_null($this->_mockery_partial) && (method_exists($this->_mockery_partial, $method) || method_exists($this->_mockery_partial, '__call')) ) { return call_user_func_array(array($this->_mockery_partial, $method), $args); } elseif ($this->_mockery_deferMissing && is_callable(get_parent_class($this) . '::' . $method) && (!$this->hasMethodOverloadingInParentClass() || (get_parent_class($this) && method_exists(get_parent_class($this), $method)))) { return call_user_func_array(get_parent_class($this) . '::' . $method, $args); } elseif ($this->_mockery_deferMissing && get_parent_class($this) && method_exists(get_parent_class($this), '__call')) { return call_user_func(get_parent_class($this) . '::__call', $method, $args); } elseif ($method == '__toString') { // __toString is special because we force its addition to the class API regardless of the // original implementation. Thus, we should always return a string rather than honor // _mockery_ignoreMissing and break the API with an error. return sprintf("%s#%s", __CLASS__, spl_object_hash($this)); } elseif ($this->_mockery_ignoreMissing) { if (\Mockery::getConfiguration()->mockingNonExistentMethodsAllowed() || (!is_null($this->_mockery_partial) && method_exists($this->_mockery_partial, $method)) || is_callable(get_parent_class($this) . '::' . $method)) { if ($this->_mockery_defaultReturnValue instanceof \Mockery\Undefined) { return call_user_func_array(array($this->_mockery_defaultReturnValue, $method), $args); } elseif (null === $this->_mockery_defaultReturnValue) { return $this->mockery_returnValueForMethod($method); } return $this->_mockery_defaultReturnValue; } } $message = 'Method ' . __CLASS__ . '::' . $method . '() does not exist on this mock object'; if (!is_null($rm)) { $message = 'Received ' . __CLASS__ . '::' . $method . '(), but no expectations were specified'; } $bmce = new BadMethodCallException($message); $this->_mockery_thrownExceptions[] = $bmce; throw $bmce; } /** * Uses reflection to get the list of all * methods within the current mock object * * @return array */ protected function mockery_getMethods() { if (static::$_mockery_methods && \Mockery::getConfiguration()->reflectionCacheEnabled()) { return static::$_mockery_methods; } if (isset($this->_mockery_partial)) { $reflected = new \ReflectionObject($this->_mockery_partial); } else { $reflected = new \ReflectionClass($this); } return static::$_mockery_methods = $reflected->getMethods(); } private function hasMethodOverloadingInParentClass() { // if there's __call any name would be callable return is_callable(get_parent_class($this) . '::aFunctionNameThatNoOneWouldEverUseInRealLife12345'); } /** * @return array */ private function getNonPublicMethods() { return array_map( function ($method) { return $method->getName(); }, array_filter($this->mockery_getMethods(), function ($method) { return !$method->isPublic(); }) ); } } Mockery/Configuration.php 0000644 00000017472 15107542733 0011517 0 ustar 00 <?php /** * Mockery (https://docs.mockery.io/) * * @copyright https://github.com/mockery/mockery/blob/HEAD/COPYRIGHT.md * @license https://github.com/mockery/mockery/blob/HEAD/LICENSE BSD 3-Clause License * @link https://github.com/mockery/mockery for the canonical source repository */ namespace Mockery; class Configuration { /** * Boolean assertion of whether we can mock methods which do not actually * exist for the given class or object (ignored for unreal mocks) * * @var bool */ protected $_allowMockingNonExistentMethod = true; /** * Boolean assertion of whether we ignore unnecessary mocking of methods, * i.e. when method expectations are made, set using a zeroOrMoreTimes() * constraint, and then never called. Essentially such expectations are * not required and are just taking up test space. * * @var bool */ protected $_allowMockingMethodsUnnecessarily = true; /** * @var QuickDefinitionsConfiguration */ protected $_quickDefinitionsConfiguration; /** * Parameter map for use with PHP internal classes. * * @var array */ protected $_internalClassParamMap = array(); protected $_constantsMap = array(); /** * Boolean assertion is reflection caching enabled or not. It should be * always enabled, except when using PHPUnit's --static-backup option. * * @see https://github.com/mockery/mockery/issues/268 */ protected $_reflectionCacheEnabled = true; public function __construct() { $this->_quickDefinitionsConfiguration = new QuickDefinitionsConfiguration(); } /** * Custom object formatters * * @var array */ protected $_objectFormatters = array(); /** * Default argument matchers * * @var array */ protected $_defaultMatchers = array(); /** * Set boolean to allow/prevent mocking of non-existent methods * * @param bool $flag */ public function allowMockingNonExistentMethods($flag = true) { $this->_allowMockingNonExistentMethod = (bool) $flag; } /** * Return flag indicating whether mocking non-existent methods allowed * * @return bool */ public function mockingNonExistentMethodsAllowed() { return $this->_allowMockingNonExistentMethod; } /** * Set boolean to allow/prevent unnecessary mocking of methods * * @param bool $flag * * @deprecated since 1.4.0 */ public function allowMockingMethodsUnnecessarily($flag = true) { @trigger_error(sprintf("The %s method is deprecated and will be removed in a future version of Mockery", __METHOD__), E_USER_DEPRECATED); $this->_allowMockingMethodsUnnecessarily = (bool) $flag; } /** * Return flag indicating whether mocking non-existent methods allowed * * @return bool * * @deprecated since 1.4.0 */ public function mockingMethodsUnnecessarilyAllowed() { @trigger_error(sprintf("The %s method is deprecated and will be removed in a future version of Mockery", __METHOD__), E_USER_DEPRECATED); return $this->_allowMockingMethodsUnnecessarily; } /** * Set a parameter map (array of param signature strings) for the method * of an internal PHP class. * * @param string $class * @param string $method * @param array $map */ public function setInternalClassMethodParamMap($class, $method, array $map) { if (\PHP_MAJOR_VERSION > 7) { throw new \LogicException('Internal class parameter overriding is not available in PHP 8. Incompatible signatures have been reclassified as fatal errors.'); } if (!isset($this->_internalClassParamMap[strtolower($class)])) { $this->_internalClassParamMap[strtolower($class)] = array(); } $this->_internalClassParamMap[strtolower($class)][strtolower($method)] = $map; } /** * Remove all overridden parameter maps from internal PHP classes. */ public function resetInternalClassMethodParamMaps() { $this->_internalClassParamMap = array(); } /** * Get the parameter map of an internal PHP class method * * @return array|null */ public function getInternalClassMethodParamMap($class, $method) { if (isset($this->_internalClassParamMap[strtolower($class)][strtolower($method)])) { return $this->_internalClassParamMap[strtolower($class)][strtolower($method)]; } } public function getInternalClassMethodParamMaps() { return $this->_internalClassParamMap; } public function setConstantsMap(array $map) { $this->_constantsMap = $map; } public function getConstantsMap() { return $this->_constantsMap; } /** * Returns the quick definitions configuration */ public function getQuickDefinitions(): QuickDefinitionsConfiguration { return $this->_quickDefinitionsConfiguration; } /** * Disable reflection caching * * It should be always enabled, except when using * PHPUnit's --static-backup option. * * @see https://github.com/mockery/mockery/issues/268 */ public function disableReflectionCache() { $this->_reflectionCacheEnabled = false; } /** * Enable reflection caching * * It should be always enabled, except when using * PHPUnit's --static-backup option. * * @see https://github.com/mockery/mockery/issues/268 */ public function enableReflectionCache() { $this->_reflectionCacheEnabled = true; } /** * Is reflection cache enabled? */ public function reflectionCacheEnabled() { return $this->_reflectionCacheEnabled; } public function setObjectFormatter($class, $formatterCallback) { $this->_objectFormatters[$class] = $formatterCallback; } public function getObjectFormatter($class, $defaultFormatter) { $parentClass = $class; do { $classes[] = $parentClass; $parentClass = get_parent_class($parentClass); } while ($parentClass); $classesAndInterfaces = array_merge($classes, class_implements($class)); foreach ($classesAndInterfaces as $type) { if (isset($this->_objectFormatters[$type])) { return $this->_objectFormatters[$type]; } } return $defaultFormatter; } /** * @param string $class * @param string $matcherClass */ public function setDefaultMatcher($class, $matcherClass) { $isHamcrest = is_a($matcherClass, \Hamcrest\Matcher::class, true) || is_a($matcherClass, \Hamcrest_Matcher::class, true); if ( !is_a($matcherClass, \Mockery\Matcher\MatcherAbstract::class, true) && !$isHamcrest ) { throw new \InvalidArgumentException( "Matcher class must extend \Mockery\Matcher\MatcherAbstract, " . "'$matcherClass' given." ); } if ($isHamcrest) { @trigger_error('Hamcrest package has been deprecated and will be removed in 2.0', E_USER_DEPRECATED); } $this->_defaultMatchers[$class] = $matcherClass; } public function getDefaultMatcher($class) { $parentClass = $class; do { $classes[] = $parentClass; $parentClass = get_parent_class($parentClass); } while ($parentClass); $classesAndInterfaces = array_merge($classes, class_implements($class)); foreach ($classesAndInterfaces as $type) { if (isset($this->_defaultMatchers[$type])) { return $this->_defaultMatchers[$type]; } } return null; } } Mockery/QuickDefinitionsConfiguration.php 0000644 00000003364 15107542733 0014703 0 ustar 00 <?php /** * Mockery (https://docs.mockery.io/) * * @copyright https://github.com/mockery/mockery/blob/HEAD/COPYRIGHT.md * @license https://github.com/mockery/mockery/blob/HEAD/LICENSE BSD 3-Clause License * @link https://github.com/mockery/mockery for the canonical source repository */ namespace Mockery; class QuickDefinitionsConfiguration { private const QUICK_DEFINITIONS_MODE_MOCK_AT_LEAST_ONCE = 'QUICK_DEFINITIONS_MODE_MOCK_AT_LEAST_ONCE'; private const QUICK_DEFINITIONS_MODE_DEFAULT_EXPECTATION = 'QUICK_DEFINITIONS_MODE_DEFAULT_EXPECTATION'; /** * Defines what a quick definition should produce. * Possible options are: * - self::QUICK_DEFINITIONS_MODE_DEFAULT_EXPECTATION: in this case quick * definitions define a stub. * - self::QUICK_DEFINITIONS_MODE_MOCK_AT_LEAST_ONCE: in this case quick * definitions define a mock with an 'at least once' expectation. * * @var string */ protected $_quickDefinitionsApplicationMode = self::QUICK_DEFINITIONS_MODE_DEFAULT_EXPECTATION; /** * Returns true if quick definitions should setup a stub, returns false when * quick definitions should setup a mock with 'at least once' expectation. * When parameter $newValue is specified it sets the configuration with the * given value. */ public function shouldBeCalledAtLeastOnce(?bool $newValue = null): bool { if ($newValue !== null) { $this->_quickDefinitionsApplicationMode = $newValue ? self::QUICK_DEFINITIONS_MODE_MOCK_AT_LEAST_ONCE : self::QUICK_DEFINITIONS_MODE_DEFAULT_EXPECTATION; } return $this->_quickDefinitionsApplicationMode === self::QUICK_DEFINITIONS_MODE_MOCK_AT_LEAST_ONCE; } } Mockery/Instantiator.php 0000644 00000010174 15107542733 0011357 0 ustar 00 <?php /** * Mockery (https://docs.mockery.io/) * * @copyright https://github.com/mockery/mockery/blob/HEAD/COPYRIGHT.md * @license https://github.com/mockery/mockery/blob/HEAD/LICENSE BSD 3-Clause License * @link https://github.com/mockery/mockery for the canonical source repository */ namespace Mockery; use Closure; use ReflectionClass; use UnexpectedValueException; use InvalidArgumentException; /** * This is a trimmed down version of https://github.com/doctrine/instantiator, * basically without the caching * * @author Marco Pivetta <ocramius@gmail.com> */ final class Instantiator { /** * {@inheritDoc} */ public function instantiate($className) { $factory = $this->buildFactory($className); $instance = $factory(); return $instance; } /** * Builds a {@see \Closure} capable of instantiating the given $className without * invoking its constructor. * * @param string $className * * @return Closure */ private function buildFactory($className) { $reflectionClass = $this->getReflectionClass($className); if ($this->isInstantiableViaReflection($reflectionClass)) { return function () use ($reflectionClass) { return $reflectionClass->newInstanceWithoutConstructor(); }; } $serializedString = sprintf( 'O:%d:"%s":0:{}', strlen($className), $className ); $this->attemptInstantiationViaUnSerialization($reflectionClass, $serializedString); return function () use ($serializedString) { return unserialize($serializedString); }; } /** * @param string $className * * @return ReflectionClass * * @throws InvalidArgumentException */ private function getReflectionClass($className) { if (! class_exists($className)) { throw new InvalidArgumentException("Class:$className does not exist"); } $reflection = new ReflectionClass($className); if ($reflection->isAbstract()) { throw new InvalidArgumentException("Class:$className is an abstract class"); } return $reflection; } /** * @param ReflectionClass $reflectionClass * @param string $serializedString * * @throws UnexpectedValueException * * @return void */ private function attemptInstantiationViaUnSerialization(ReflectionClass $reflectionClass, $serializedString) { set_error_handler(function ($code, $message, $file, $line) use ($reflectionClass, & $error) { $msg = sprintf( 'Could not produce an instance of "%s" via un-serialization, since an error was triggered in file "%s" at line "%d"', $reflectionClass->getName(), $file, $line ); $error = new UnexpectedValueException($msg, 0, new \Exception($message, $code)); }); try { unserialize($serializedString); } catch (\Exception $exception) { restore_error_handler(); throw new UnexpectedValueException("An exception was raised while trying to instantiate an instance of \"{$reflectionClass->getName()}\" via un-serialization", 0, $exception); } restore_error_handler(); if ($error) { throw $error; } } /** * @param ReflectionClass $reflectionClass * * @return bool */ private function isInstantiableViaReflection(ReflectionClass $reflectionClass) { return ! ($reflectionClass->isInternal() && $reflectionClass->isFinal()); } /** * Verifies whether the given class is to be considered internal * * @param ReflectionClass $reflectionClass * * @return bool */ private function hasInternalAncestors(ReflectionClass $reflectionClass) { do { if ($reflectionClass->isInternal()) { return true; } } while ($reflectionClass = $reflectionClass->getParentClass()); return false; } } Mockery/MethodCall.php 0000644 00000001214 15107542733 0010707 0 ustar 00 <?php /** * Mockery (https://docs.mockery.io/) * * @copyright https://github.com/mockery/mockery/blob/HEAD/COPYRIGHT.md * @license https://github.com/mockery/mockery/blob/HEAD/LICENSE BSD 3-Clause License * @link https://github.com/mockery/mockery for the canonical source repository */ namespace Mockery; class MethodCall { private $method; private $args; public function __construct($method, $args) { $this->method = $method; $this->args = $args; } public function getMethod() { return $this->method; } public function getArgs() { return $this->args; } } Mockery/Generator/StringManipulation/Pass/ClassPass.php 0000644 00000002005 15107542733 0017251 0 ustar 00 <?php /** * Mockery (https://docs.mockery.io/) * * @copyright https://github.com/mockery/mockery/blob/HEAD/COPYRIGHT.md * @license https://github.com/mockery/mockery/blob/HEAD/LICENSE BSD 3-Clause License * @link https://github.com/mockery/mockery for the canonical source repository */ namespace Mockery\Generator\StringManipulation\Pass; use Mockery\Generator\MockConfiguration; class ClassPass implements Pass { public function apply($code, MockConfiguration $config) { $target = $config->getTargetClass(); if (!$target) { return $code; } if ($target->isFinal()) { return $code; } $className = ltrim($target->getName(), "\\"); if (!class_exists($className)) { \Mockery::declareClass($className); } $code = str_replace( "implements MockInterface", "extends \\" . $className . " implements MockInterface", $code ); return $code; } } Mockery/Generator/StringManipulation/Pass/ClassAttributesPass.php 0000644 00000001672 15107542733 0021331 0 ustar 00 <?php /** * Mockery (https://docs.mockery.io/) * * @copyright https://github.com/mockery/mockery/blob/HEAD/COPYRIGHT.md * @license https://github.com/mockery/mockery/blob/HEAD/LICENSE BSD 3-Clause License * @link https://github.com/mockery/mockery for the canonical source repository */ namespace Mockery\Generator\StringManipulation\Pass; use Mockery\Generator\MockConfiguration; class ClassAttributesPass implements Pass { public function apply($code, MockConfiguration $config) { $class = $config->getTargetClass(); if (!$class) { return $code; } /** @var array<string> $attributes */ $attributes = $class->getAttributes(); if ($attributes !== []) { return str_replace( '#[\AllowDynamicProperties]', '#[' . implode(',', $attributes) . ']', $code ); } return $code; } } Mockery/Generator/StringManipulation/Pass/RemoveUnserializeForInternalSerializableClassesPass.php 0000644 00000003052 15107542733 0027670 0 ustar 00 <?php /** * Mockery (https://docs.mockery.io/) * * @copyright https://github.com/mockery/mockery/blob/HEAD/COPYRIGHT.md * @license https://github.com/mockery/mockery/blob/HEAD/LICENSE BSD 3-Clause License * @link https://github.com/mockery/mockery for the canonical source repository */ namespace Mockery\Generator\StringManipulation\Pass; use Mockery\Generator\MockConfiguration; /** * Internal classes can not be instantiated with the newInstanceWithoutArgs * reflection method, so need the serialization hack. If the class also * implements Serializable, we need to replace the standard unserialize method * definition with a dummy */ class RemoveUnserializeForInternalSerializableClassesPass { const DUMMY_METHOD_DEFINITION_LEGACY = 'public function unserialize($string) {} '; const DUMMY_METHOD_DEFINITION = 'public function unserialize(string $data): void {} '; public function apply($code, MockConfiguration $config) { $target = $config->getTargetClass(); if (!$target) { return $code; } if (!$target->hasInternalAncestor() || !$target->implementsInterface("Serializable")) { return $code; } $code = $this->appendToClass($code, \PHP_VERSION_ID < 80100 ? self::DUMMY_METHOD_DEFINITION_LEGACY : self::DUMMY_METHOD_DEFINITION); return $code; } protected function appendToClass($class, $code) { $lastBrace = strrpos($class, "}"); $class = substr($class, 0, $lastBrace) . $code . "\n }\n"; return $class; } } Mockery/Generator/StringManipulation/Pass/ConstantsPass.php 0000644 00000002054 15107542733 0020164 0 ustar 00 <?php /** * Mockery (https://docs.mockery.io/) * * @copyright https://github.com/mockery/mockery/blob/HEAD/COPYRIGHT.md * @license https://github.com/mockery/mockery/blob/HEAD/LICENSE BSD 3-Clause License * @link https://github.com/mockery/mockery for the canonical source repository */ namespace Mockery\Generator\StringManipulation\Pass; use Mockery\Generator\MockConfiguration; class ConstantsPass implements Pass { public function apply($code, MockConfiguration $config) { $cm = $config->getConstantsMap(); if (empty($cm)) { return $code; } if (!isset($cm[$config->getName()])) { return $code; } $cm = $cm[$config->getName()]; $constantsCode = ''; foreach ($cm as $constant => $value) { $constantsCode .= sprintf("\n const %s = %s;\n", $constant, var_export($value, true)); } $i = strrpos($code, '}'); $code = substr_replace($code, $constantsCode, $i); $code .= "}\n"; return $code; } } Mockery/Generator/StringManipulation/Pass/InterfacePass.php 0000644 00000002101 15107542733 0020101 0 ustar 00 <?php /** * Mockery (https://docs.mockery.io/) * * @copyright https://github.com/mockery/mockery/blob/HEAD/COPYRIGHT.md * @license https://github.com/mockery/mockery/blob/HEAD/LICENSE BSD 3-Clause License * @link https://github.com/mockery/mockery for the canonical source repository */ namespace Mockery\Generator\StringManipulation\Pass; use Mockery\Generator\MockConfiguration; class InterfacePass implements Pass { public function apply($code, MockConfiguration $config) { foreach ($config->getTargetInterfaces() as $i) { $name = ltrim($i->getName(), "\\"); if (!interface_exists($name)) { \Mockery::declareInterface($name); } } $interfaces = array_reduce((array) $config->getTargetInterfaces(), function ($code, $i) { return $code . ", \\" . ltrim($i->getName(), "\\"); }, ""); $code = str_replace( "implements MockInterface", "implements MockInterface" . $interfaces, $code ); return $code; } } Mockery/Generator/StringManipulation/Pass/Pass.php 0000644 00000000736 15107542733 0016274 0 ustar 00 <?php /** * Mockery (https://docs.mockery.io/) * * @copyright https://github.com/mockery/mockery/blob/HEAD/COPYRIGHT.md * @license https://github.com/mockery/mockery/blob/HEAD/LICENSE BSD 3-Clause License * @link https://github.com/mockery/mockery for the canonical source repository */ namespace Mockery\Generator\StringManipulation\Pass; use Mockery\Generator\MockConfiguration; interface Pass { public function apply($code, MockConfiguration $config); } Mockery/Generator/StringManipulation/Pass/RemoveDestructorPass.php 0000644 00000001550 15107542733 0021524 0 ustar 00 <?php /** * Mockery (https://docs.mockery.io/) * * @copyright https://github.com/mockery/mockery/blob/HEAD/COPYRIGHT.md * @license https://github.com/mockery/mockery/blob/HEAD/LICENSE BSD 3-Clause License * @link https://github.com/mockery/mockery for the canonical source repository */ namespace Mockery\Generator\StringManipulation\Pass; use Mockery\Generator\MockConfiguration; /** * Remove mock's empty destructor if we tend to use original class destructor */ class RemoveDestructorPass { public function apply($code, MockConfiguration $config) { $target = $config->getTargetClass(); if (!$target) { return $code; } if (!$config->isMockOriginalDestructor()) { $code = preg_replace('/public function __destruct\(\)\s+\{.*?\}/sm', '', $code); } return $code; } } Mockery/Generator/StringManipulation/Pass/ClassNamePass.php 0000644 00000001671 15107542733 0020062 0 ustar 00 <?php /** * Mockery (https://docs.mockery.io/) * * @copyright https://github.com/mockery/mockery/blob/HEAD/COPYRIGHT.md * @license https://github.com/mockery/mockery/blob/HEAD/LICENSE BSD 3-Clause License * @link https://github.com/mockery/mockery for the canonical source repository */ namespace Mockery\Generator\StringManipulation\Pass; use Mockery\Generator\MockConfiguration; class ClassNamePass implements Pass { public function apply($code, MockConfiguration $config) { $namespace = $config->getNamespaceName(); $namespace = ltrim($namespace, "\\"); $className = $config->getShortName(); $code = str_replace( 'namespace Mockery;', $namespace ? 'namespace ' . $namespace . ';' : '', $code ); $code = str_replace( 'class Mock', 'class ' . $className, $code ); return $code; } } Mockery/Generator/StringManipulation/Pass/RemoveBuiltinMethodsThatAreFinalPass.php 0000644 00000002475 15107542733 0024552 0 ustar 00 <?php /** * Mockery (https://docs.mockery.io/) * * @copyright https://github.com/mockery/mockery/blob/HEAD/COPYRIGHT.md * @license https://github.com/mockery/mockery/blob/HEAD/LICENSE BSD 3-Clause License * @link https://github.com/mockery/mockery for the canonical source repository */ namespace Mockery\Generator\StringManipulation\Pass; use Mockery\Generator\MockConfiguration; /** * The standard Mockery\Mock class includes some methods to ease mocking, such * as __wakeup, however if the target has a final __wakeup method, it can't be * mocked. This pass removes the builtin methods where they are final on the * target */ class RemoveBuiltinMethodsThatAreFinalPass { protected $methods = array( '__wakeup' => '/public function __wakeup\(\)\s+\{.*?\}/sm', '__toString' => '/public function __toString\(\)\s+(:\s+string)?\s*\{.*?\}/sm', ); public function apply($code, MockConfiguration $config) { $target = $config->getTargetClass(); if (!$target) { return $code; } foreach ($target->getMethods() as $method) { if ($method->isFinal() && isset($this->methods[$method->getName()])) { $code = preg_replace($this->methods[$method->getName()], '', $code); } } return $code; } } Mockery/Generator/StringManipulation/Pass/MethodDefinitionPass.php 0000644 00000013626 15107542733 0021450 0 ustar 00 <?php /** * Mockery (https://docs.mockery.io/) * * @copyright https://github.com/mockery/mockery/blob/HEAD/COPYRIGHT.md * @license https://github.com/mockery/mockery/blob/HEAD/LICENSE BSD 3-Clause License * @link https://github.com/mockery/mockery for the canonical source repository */ namespace Mockery\Generator\StringManipulation\Pass; use Mockery\Generator\Method; use Mockery\Generator\Parameter; use Mockery\Generator\MockConfiguration; class MethodDefinitionPass implements Pass { public function apply($code, MockConfiguration $config) { foreach ($config->getMethodsToMock() as $method) { if ($method->isPublic()) { $methodDef = 'public'; } elseif ($method->isProtected()) { $methodDef = 'protected'; } else { $methodDef = 'private'; } if ($method->isStatic()) { $methodDef .= ' static'; } $methodDef .= ' function '; $methodDef .= $method->returnsReference() ? ' & ' : ''; $methodDef .= $method->getName(); $methodDef .= $this->renderParams($method, $config); $methodDef .= $this->renderReturnType($method); $methodDef .= $this->renderMethodBody($method, $config); $code = $this->appendToClass($code, $methodDef); } return $code; } protected function renderParams(Method $method, $config) { $class = $method->getDeclaringClass(); if ($class->isInternal()) { $overrides = $config->getParameterOverrides(); if (isset($overrides[strtolower($class->getName())][$method->getName()])) { return '(' . implode(',', $overrides[strtolower($class->getName())][$method->getName()]) . ')'; } } $methodParams = array(); $params = $method->getParameters(); $isPhp81 = \PHP_VERSION_ID >= 80100; foreach ($params as $param) { $paramDef = $this->renderTypeHint($param); $paramDef .= $param->isPassedByReference() ? '&' : ''; $paramDef .= $param->isVariadic() ? '...' : ''; $paramDef .= '$' . $param->getName(); if (!$param->isVariadic()) { if (false !== $param->isDefaultValueAvailable()) { $defaultValue = $param->getDefaultValue(); if (is_object($defaultValue)) { $prefix = get_class($defaultValue); if ($isPhp81) { if (enum_exists($prefix)) { $prefix = var_export($defaultValue, true); } elseif ( !$param->isDefaultValueConstant() && // "Parameter #1 [ <optional> F\Q\CN $a = new \F\Q\CN(param1, param2: 2) ] preg_match( '#<optional>\s.*?\s=\snew\s(.*?)\s]$#', $param->__toString(), $matches ) === 1 ) { $prefix = 'new ' . $matches[1]; } } } else { $prefix = var_export($defaultValue, true); } $paramDef .= ' = ' . $prefix; } elseif ($param->isOptional()) { $paramDef .= ' = null'; } } $methodParams[] = $paramDef; } return '(' . implode(', ', $methodParams) . ')'; } protected function renderReturnType(Method $method) { $type = $method->getReturnType(); return $type ? sprintf(': %s', $type) : ''; } protected function appendToClass($class, $code) { $lastBrace = strrpos($class, "}"); $class = substr($class, 0, $lastBrace) . $code . "\n }\n"; return $class; } protected function renderTypeHint(Parameter $param) { $typeHint = $param->getTypeHint(); return $typeHint === null ? '' : sprintf('%s ', $typeHint); } private function renderMethodBody($method, $config) { $invoke = $method->isStatic() ? 'static::_mockery_handleStaticMethodCall' : '$this->_mockery_handleMethodCall'; $body = <<<BODY { \$argc = func_num_args(); \$argv = func_get_args(); BODY; // Fix up known parameters by reference - used func_get_args() above // in case more parameters are passed in than the function definition // says - eg varargs. $class = $method->getDeclaringClass(); $class_name = strtolower($class->getName()); $overrides = $config->getParameterOverrides(); if (isset($overrides[$class_name][$method->getName()])) { $params = array_values($overrides[$class_name][$method->getName()]); $paramCount = count($params); for ($i = 0; $i < $paramCount; ++$i) { $param = $params[$i]; if (strpos($param, '&') !== false) { $body .= <<<BODY if (\$argc > $i) { \$argv[$i] = {$param}; } BODY; } } } else { $params = array_values($method->getParameters()); $paramCount = count($params); for ($i = 0; $i < $paramCount; ++$i) { $param = $params[$i]; if (!$param->isPassedByReference()) { continue; } $body .= <<<BODY if (\$argc > $i) { \$argv[$i] =& \${$param->getName()}; } BODY; } } $body .= "\$ret = {$invoke}(__FUNCTION__, \$argv);\n"; if (! in_array($method->getReturnType(), ['never', 'void'], true)) { $body .= "return \$ret;\n"; } $body .= "}\n"; return $body; } } Mockery/Generator/StringManipulation/Pass/TraitPass.php 0000644 00000001651 15107542733 0017275 0 ustar 00 <?php /** * Mockery (https://docs.mockery.io/) * * @copyright https://github.com/mockery/mockery/blob/HEAD/COPYRIGHT.md * @license https://github.com/mockery/mockery/blob/HEAD/LICENSE BSD 3-Clause License * @link https://github.com/mockery/mockery for the canonical source repository */ namespace Mockery\Generator\StringManipulation\Pass; use Mockery\Generator\MockConfiguration; class TraitPass implements Pass { public function apply($code, MockConfiguration $config) { $traits = $config->getTargetTraits(); if (empty($traits)) { return $code; } $useStatements = array_map(function ($trait) { return "use \\\\" . ltrim($trait->getName(), "\\") . ";"; }, $traits); $code = preg_replace( '/^{$/m', "{\n " . implode("\n ", $useStatements) . "\n", $code ); return $code; } } Mockery/Generator/StringManipulation/Pass/CallTypeHintPass.php 0000644 00000002071 15107542733 0020547 0 ustar 00 <?php /** * Mockery (https://docs.mockery.io/) * * @copyright https://github.com/mockery/mockery/blob/HEAD/COPYRIGHT.md * @license https://github.com/mockery/mockery/blob/HEAD/LICENSE BSD 3-Clause License * @link https://github.com/mockery/mockery for the canonical source repository */ namespace Mockery\Generator\StringManipulation\Pass; use Mockery\Generator\MockConfiguration; class CallTypeHintPass implements Pass { public function apply($code, MockConfiguration $config) { if ($config->requiresCallTypeHintRemoval()) { $code = str_replace( 'public function __call($method, array $args)', 'public function __call($method, $args)', $code ); } if ($config->requiresCallStaticTypeHintRemoval()) { $code = str_replace( 'public static function __callStatic($method, array $args)', 'public static function __callStatic($method, $args)', $code ); } return $code; } } Mockery/Generator/StringManipulation/Pass/MagicMethodTypeHintsPass.php 0000644 00000012453 15107542733 0022245 0 ustar 00 <?php /** * Mockery (https://docs.mockery.io/) * * @copyright https://github.com/mockery/mockery/blob/HEAD/COPYRIGHT.md * @license https://github.com/mockery/mockery/blob/HEAD/LICENSE BSD 3-Clause License * @link https://github.com/mockery/mockery for the canonical source repository */ namespace Mockery\Generator\StringManipulation\Pass; use Mockery\Generator\MockConfiguration; use Mockery\Generator\TargetClassInterface; use Mockery\Generator\Method; use Mockery\Generator\Parameter; class MagicMethodTypeHintsPass implements Pass { /** * @var array $mockMagicMethods */ private $mockMagicMethods = array( '__construct', '__destruct', '__call', '__callStatic', '__get', '__set', '__isset', '__unset', '__sleep', '__wakeup', '__toString', '__invoke', '__set_state', '__clone', '__debugInfo' ); /** * Apply implementation. * * @param string $code * @param MockConfiguration $config * @return string */ public function apply($code, MockConfiguration $config) { $magicMethods = $this->getMagicMethods($config->getTargetClass()); foreach ($config->getTargetInterfaces() as $interface) { $magicMethods = array_merge($magicMethods, $this->getMagicMethods($interface)); } foreach ($magicMethods as $method) { $code = $this->applyMagicTypeHints($code, $method); } return $code; } /** * Returns the magic methods within the * passed DefinedTargetClass. * * @param TargetClassInterface $class * @return array */ public function getMagicMethods( TargetClassInterface $class = null ) { if (is_null($class)) { return array(); } return array_filter($class->getMethods(), function (Method $method) { return in_array($method->getName(), $this->mockMagicMethods); }); } /** * Applies type hints of magic methods from * class to the passed code. * * @param int $code * @param Method $method * @return string */ private function applyMagicTypeHints($code, Method $method) { if ($this->isMethodWithinCode($code, $method)) { $namedParameters = $this->getOriginalParameters( $code, $method ); $code = preg_replace( $this->getDeclarationRegex($method->getName()), $this->getMethodDeclaration($method, $namedParameters), $code ); } return $code; } /** * Checks if the method is declared within code. * * @param int $code * @param Method $method * @return boolean */ private function isMethodWithinCode($code, Method $method) { return preg_match( $this->getDeclarationRegex($method->getName()), $code ) == 1; } /** * Returns the method original parameters, as they're * described in the $code string. * * @param int $code * @param Method $method * @return array */ private function getOriginalParameters($code, Method $method) { $matches = []; $parameterMatches = []; preg_match( $this->getDeclarationRegex($method->getName()), $code, $matches ); if (count($matches) > 0) { preg_match_all( '/(?<=\$)(\w+)+/i', $matches[0], $parameterMatches ); } $groupMatches = end($parameterMatches); $parameterNames = is_array($groupMatches) ? $groupMatches : [$groupMatches]; return $parameterNames; } /** * Gets the declaration code, as a string, for the passed method. * * @param Method $method * @param array $namedParameters * @return string */ private function getMethodDeclaration( Method $method, array $namedParameters ) { $declaration = 'public'; $declaration .= $method->isStatic() ? ' static' : ''; $declaration .= ' function ' . $method->getName() . '('; foreach ($method->getParameters() as $index => $parameter) { $declaration .= $this->renderTypeHint($parameter); $name = isset($namedParameters[$index]) ? $namedParameters[$index] : $parameter->getName(); $declaration .= '$' . $name; $declaration .= ','; } $declaration = rtrim($declaration, ','); $declaration .= ') '; $returnType = $method->getReturnType(); if ($returnType !== null) { $declaration .= sprintf(': %s', $returnType); } return $declaration; } protected function renderTypeHint(Parameter $param) { $typeHint = $param->getTypeHint(); return $typeHint === null ? '' : sprintf('%s ', $typeHint); } /** * Returns a regex string used to match the * declaration of some method. * * @param string $methodName * @return string */ private function getDeclarationRegex($methodName) { return "/public\s+(?:static\s+)?function\s+$methodName\s*\(.*\)\s*(?=\{)/i"; } } Mockery/Generator/StringManipulation/Pass/InstanceMockPass.php 0000644 00000005064 15107542733 0020572 0 ustar 00 <?php /** * Mockery (https://docs.mockery.io/) * * @copyright https://github.com/mockery/mockery/blob/HEAD/COPYRIGHT.md * @license https://github.com/mockery/mockery/blob/HEAD/LICENSE BSD 3-Clause License * @link https://github.com/mockery/mockery for the canonical source repository */ namespace Mockery\Generator\StringManipulation\Pass; use Mockery\Generator\MockConfiguration; class InstanceMockPass { const INSTANCE_MOCK_CODE = <<<MOCK protected \$_mockery_ignoreVerification = true; public function __construct() { \$this->_mockery_ignoreVerification = false; \$associatedRealObject = \Mockery::fetchMock(__CLASS__); foreach (get_object_vars(\$this) as \$attr => \$val) { if (\$attr !== "_mockery_ignoreVerification" && \$attr !== "_mockery_expectations") { \$this->\$attr = \$associatedRealObject->\$attr; } } \$directors = \$associatedRealObject->mockery_getExpectations(); foreach (\$directors as \$method=>\$director) { // get the director method needed \$existingDirector = \$this->mockery_getExpectationsFor(\$method); if (!\$existingDirector) { \$existingDirector = new \Mockery\ExpectationDirector(\$method, \$this); \$this->mockery_setExpectationsFor(\$method, \$existingDirector); } \$expectations = \$director->getExpectations(); foreach (\$expectations as \$expectation) { \$clonedExpectation = clone \$expectation; \$existingDirector->addExpectation(\$clonedExpectation); } \$defaultExpectations = \$director->getDefaultExpectations(); foreach (array_reverse(\$defaultExpectations) as \$expectation) { \$clonedExpectation = clone \$expectation; \$existingDirector->addExpectation(\$clonedExpectation); \$existingDirector->makeExpectationDefault(\$clonedExpectation); } } \Mockery::getContainer()->rememberMock(\$this); \$this->_mockery_constructorCalled(func_get_args()); } MOCK; public function apply($code, MockConfiguration $config) { if ($config->isInstanceMock()) { $code = $this->appendToClass($code, static::INSTANCE_MOCK_CODE); } return $code; } protected function appendToClass($class, $code) { $lastBrace = strrpos($class, "}"); $class = substr($class, 0, $lastBrace) . $code . "\n }\n"; return $class; } } Mockery/Generator/StringManipulation/Pass/AvoidMethodClashPass.php 0000644 00000002174 15107542733 0021371 0 ustar 00 <?php /** * Mockery (https://docs.mockery.io/) * * @copyright https://github.com/mockery/mockery/blob/HEAD/COPYRIGHT.md * @license https://github.com/mockery/mockery/blob/HEAD/LICENSE BSD 3-Clause License * @link https://github.com/mockery/mockery for the canonical source repository */ namespace Mockery\Generator\StringManipulation\Pass; use Mockery\Generator\Method; use Mockery\Generator\Parameter; use Mockery\Generator\MockConfiguration; class AvoidMethodClashPass implements Pass { public function apply($code, MockConfiguration $config) { $names = array_map(function ($method) { return $method->getName(); }, $config->getMethodsToMock()); foreach (["allows", "expects"] as $method) { if (in_array($method, $names)) { $code = preg_replace( "#// start method {$method}.*// end method {$method}#ms", "", $code ); $code = str_replace(" implements MockInterface", " implements LegacyMockInterface", $code); } } return $code; } } Mockery/Generator/Method.php 0000644 00000002050 15107542733 0012040 0 ustar 00 <?php /** * Mockery (https://docs.mockery.io/) * * @copyright https://github.com/mockery/mockery/blob/HEAD/COPYRIGHT.md * @license https://github.com/mockery/mockery/blob/HEAD/LICENSE BSD 3-Clause License * @link https://github.com/mockery/mockery for the canonical source repository */ namespace Mockery\Generator; use Mockery\Reflector; class Method { /** @var \ReflectionMethod */ private $method; public function __construct(\ReflectionMethod $method) { $this->method = $method; } public function __call($method, $args) { return call_user_func_array(array($this->method, $method), $args); } /** * @return Parameter[] */ public function getParameters() { return array_map(function (\ReflectionParameter $parameter) { return new Parameter($parameter); }, $this->method->getParameters()); } /** * @return string|null */ public function getReturnType() { return Reflector::getReturnType($this->method); } } Mockery/Generator/UndefinedTargetClass.php 0000644 00000003206 15107542733 0014662 0 ustar 00 <?php /** * Mockery (https://docs.mockery.io/) * * @copyright https://github.com/mockery/mockery/blob/HEAD/COPYRIGHT.md * @license https://github.com/mockery/mockery/blob/HEAD/LICENSE BSD 3-Clause License * @link https://github.com/mockery/mockery for the canonical source repository */ namespace Mockery\Generator; use const PHP_VERSION_ID; class UndefinedTargetClass implements TargetClassInterface { private $name; public function __construct($name) { $this->name = $name; } public static function factory($name) { return new self($name); } public function getAttributes() { return []; } public function getName() { return $this->name; } public function isAbstract() { return false; } public function isFinal() { return false; } public function getMethods() { return array(); } public function getInterfaces() { return array(); } public function getNamespaceName() { $parts = explode("\\", ltrim($this->getName(), "\\")); array_pop($parts); return implode("\\", $parts); } public function inNamespace() { return $this->getNamespaceName() !== ''; } public function getShortName() { $parts = explode("\\", $this->getName()); return array_pop($parts); } public function implementsInterface($interface) { return false; } public function hasInternalAncestor() { return false; } public function __toString() { return $this->name; } } Mockery/Generator/CachingGenerator.php 0000644 00000001551 15107542733 0014030 0 ustar 00 <?php /** * Mockery (https://docs.mockery.io/) * * @copyright https://github.com/mockery/mockery/blob/HEAD/COPYRIGHT.md * @license https://github.com/mockery/mockery/blob/HEAD/LICENSE BSD 3-Clause License * @link https://github.com/mockery/mockery for the canonical source repository */ namespace Mockery\Generator; class CachingGenerator implements Generator { protected $generator; protected $cache = array(); public function __construct(Generator $generator) { $this->generator = $generator; } public function generate(MockConfiguration $config) { $hash = $config->getHash(); if (isset($this->cache[$hash])) { return $this->cache[$hash]; } $definition = $this->generator->generate($config); $this->cache[$hash] = $definition; return $definition; } } Mockery/Generator/TargetClassInterface.php 0000644 00000004101 15107542733 0014654 0 ustar 00 <?php /** * Mockery (https://docs.mockery.io/) * * @copyright https://github.com/mockery/mockery/blob/HEAD/COPYRIGHT.md * @license https://github.com/mockery/mockery/blob/HEAD/LICENSE BSD 3-Clause License * @link https://github.com/mockery/mockery for the canonical source repository */ namespace Mockery\Generator; interface TargetClassInterface { /** * Returns a new instance of the current * TargetClassInterface's * implementation. * * @param string $name * @return TargetClassInterface */ public static function factory($name); /** * Returns the targetClass's attributes. * * @return array */ public function getAttributes(); /** * Returns the targetClass's name. * * @return string */ public function getName(); /** * Returns the targetClass's methods. * * @return array */ public function getMethods(); /** * Returns the targetClass's interfaces. * * @return array */ public function getInterfaces(); /** * Returns the targetClass's namespace name. * * @return string */ public function getNamespaceName(); /** * Returns the targetClass's short name. * * @return string */ public function getShortName(); /** * Returns whether the targetClass is abstract. * * @return boolean */ public function isAbstract(); /** * Returns whether the targetClass is final. * * @return boolean */ public function isFinal(); /** * Returns whether the targetClass is in namespace. * * @return boolean */ public function inNamespace(); /** * Returns whether the targetClass is in * the passed interface. * * @param mixed $interface * @return boolean */ public function implementsInterface($interface); /** * Returns whether the targetClass has * an internal ancestor. * * @return boolean */ public function hasInternalAncestor(); } Mockery/Generator/MockDefinition.php 0000644 00000001620 15107542733 0013524 0 ustar 00 <?php /** * Mockery (https://docs.mockery.io/) * * @copyright https://github.com/mockery/mockery/blob/HEAD/COPYRIGHT.md * @license https://github.com/mockery/mockery/blob/HEAD/LICENSE BSD 3-Clause License * @link https://github.com/mockery/mockery for the canonical source repository */ namespace Mockery\Generator; class MockDefinition { protected $config; protected $code; public function __construct(MockConfiguration $config, $code) { if (!$config->getName()) { throw new \InvalidArgumentException("MockConfiguration must contain a name"); } $this->config = $config; $this->code = $code; } public function getConfig() { return $this->config; } public function getClassName() { return $this->config->getName(); } public function getCode() { return $this->code; } } Mockery/Generator/MockNameBuilder.php 0000644 00000001400 15107542733 0013617 0 ustar 00 <?php /** * Mockery (https://docs.mockery.io/) * * @copyright https://github.com/mockery/mockery/blob/HEAD/COPYRIGHT.md * @license https://github.com/mockery/mockery/blob/HEAD/LICENSE BSD 3-Clause License * @link https://github.com/mockery/mockery for the canonical source repository */ namespace Mockery\Generator; class MockNameBuilder { protected static $mockCounter = 0; protected $parts = []; public function addPart($part) { $this->parts[] = $part; return $this; } public function build() { $parts = ['Mockery', static::$mockCounter++]; foreach ($this->parts as $part) { $parts[] = str_replace("\\", "_", $part); } return implode('_', $parts); } } Mockery/Generator/StringManipulationGenerator.php 0000644 00000005406 15107542733 0016326 0 ustar 00 <?php /** * Mockery (https://docs.mockery.io/) * * @copyright https://github.com/mockery/mockery/blob/HEAD/COPYRIGHT.md * @license https://github.com/mockery/mockery/blob/HEAD/LICENSE BSD 3-Clause License * @link https://github.com/mockery/mockery for the canonical source repository */ namespace Mockery\Generator; use Mockery\Generator\StringManipulation\Pass\CallTypeHintPass; use Mockery\Generator\StringManipulation\Pass\ClassNamePass; use Mockery\Generator\StringManipulation\Pass\ClassPass; use Mockery\Generator\StringManipulation\Pass\ConstantsPass; use Mockery\Generator\StringManipulation\Pass\InstanceMockPass; use Mockery\Generator\StringManipulation\Pass\InterfacePass; use Mockery\Generator\StringManipulation\Pass\MagicMethodTypeHintsPass; use Mockery\Generator\StringManipulation\Pass\MethodDefinitionPass; use Mockery\Generator\StringManipulation\Pass\Pass; use Mockery\Generator\StringManipulation\Pass\RemoveBuiltinMethodsThatAreFinalPass; use Mockery\Generator\StringManipulation\Pass\RemoveDestructorPass; use Mockery\Generator\StringManipulation\Pass\RemoveUnserializeForInternalSerializableClassesPass; use Mockery\Generator\StringManipulation\Pass\TraitPass; use Mockery\Generator\StringManipulation\Pass\AvoidMethodClashPass; use Mockery\Generator\StringManipulation\Pass\ClassAttributesPass; class StringManipulationGenerator implements Generator { protected $passes = array(); /** * Creates a new StringManipulationGenerator with the default passes * * @return StringManipulationGenerator */ public static function withDefaultPasses() { return new static([ new CallTypeHintPass(), new MagicMethodTypeHintsPass(), new ClassPass(), new TraitPass(), new ClassNamePass(), new InstanceMockPass(), new InterfacePass(), new AvoidMethodClashPass(), new MethodDefinitionPass(), new RemoveUnserializeForInternalSerializableClassesPass(), new RemoveBuiltinMethodsThatAreFinalPass(), new RemoveDestructorPass(), new ConstantsPass(), new ClassAttributesPass(), ]); } public function __construct(array $passes) { $this->passes = $passes; } public function generate(MockConfiguration $config) { $code = file_get_contents(__DIR__ . '/../Mock.php'); $className = $config->getName() ?: $config->generateName(); $namedConfig = $config->rename($className); foreach ($this->passes as $pass) { $code = $pass->apply($code, $namedConfig); } return new MockDefinition($namedConfig, $code); } public function addPass(Pass $pass) { $this->passes[] = $pass; } } Mockery/Generator/Generator.php 0000644 00000000700 15107542733 0012546 0 ustar 00 <?php /** * Mockery (https://docs.mockery.io/) * * @copyright https://github.com/mockery/mockery/blob/HEAD/COPYRIGHT.md * @license https://github.com/mockery/mockery/blob/HEAD/LICENSE BSD 3-Clause License * @link https://github.com/mockery/mockery for the canonical source repository */ namespace Mockery\Generator; interface Generator { /** @returns MockDefinition */ public function generate(MockConfiguration $config); } Mockery/Generator/MockConfiguration.php 0000644 00000037444 15107542733 0014260 0 ustar 00 <?php /** * Mockery (https://docs.mockery.io/) * * @copyright https://github.com/mockery/mockery/blob/HEAD/COPYRIGHT.md * @license https://github.com/mockery/mockery/blob/HEAD/LICENSE BSD 3-Clause License * @link https://github.com/mockery/mockery for the canonical source repository */ namespace Mockery\Generator; /** * This class describes the configuration of mocks and hides away some of the * reflection implementation */ class MockConfiguration { /** * A class that we'd like to mock */ protected $targetClass; protected $targetClassName; /** * A number of interfaces we'd like to mock, keyed by name to attempt to * keep unique */ protected $targetInterfaces = array(); protected $targetInterfaceNames = array(); /** * A number of traits we'd like to mock, keyed by name to attempt to * keep unique */ protected $targetTraits = array(); protected $targetTraitNames = array(); /** * An object we'd like our mock to proxy to */ protected $targetObject; /** * The class name we'd like to use for a generated mock */ protected $name; /** * Methods that should specifically not be mocked * * This is currently populated with stuff we don't know how to deal with, * should really be somewhere else */ protected $blackListedMethods = array(); /** * If not empty, only these methods will be mocked */ protected $whiteListedMethods = array(); /** * An instance mock is where we override the original class before it's * autoloaded */ protected $instanceMock = false; /** * Param overrides */ protected $parameterOverrides = array(); /** * Instance cache of all methods */ protected $allMethods; /** * If true, overrides original class destructor */ protected $mockOriginalDestructor = false; protected $constantsMap = array(); public function __construct( array $targets = array(), array $blackListedMethods = array(), array $whiteListedMethods = array(), $name = null, $instanceMock = false, array $parameterOverrides = array(), $mockOriginalDestructor = false, array $constantsMap = array() ) { $this->addTargets($targets); $this->blackListedMethods = $blackListedMethods; $this->whiteListedMethods = $whiteListedMethods; $this->name = $name; $this->instanceMock = $instanceMock; $this->parameterOverrides = $parameterOverrides; $this->mockOriginalDestructor = $mockOriginalDestructor; $this->constantsMap = $constantsMap; } /** * Attempt to create a hash of the configuration, in order to allow caching * * @TODO workout if this will work * * @return string */ public function getHash() { $vars = array( 'targetClassName' => $this->targetClassName, 'targetInterfaceNames' => $this->targetInterfaceNames, 'targetTraitNames' => $this->targetTraitNames, 'name' => $this->name, 'blackListedMethods' => $this->blackListedMethods, 'whiteListedMethod' => $this->whiteListedMethods, 'instanceMock' => $this->instanceMock, 'parameterOverrides' => $this->parameterOverrides, 'mockOriginalDestructor' => $this->mockOriginalDestructor ); return md5(serialize($vars)); } /** * Gets a list of methods from the classes, interfaces and objects and * filters them appropriately. Lot's of filtering going on, perhaps we could * have filter classes to iterate through */ public function getMethodsToMock() { $methods = $this->getAllMethods(); foreach ($methods as $key => $method) { if ($method->isFinal()) { unset($methods[$key]); } } /** * Whitelist trumps everything else */ if (count($this->getWhiteListedMethods())) { $whitelist = array_map('strtolower', $this->getWhiteListedMethods()); $methods = array_filter($methods, function ($method) use ($whitelist) { return $method->isAbstract() || in_array(strtolower($method->getName()), $whitelist); }); return $methods; } /** * Remove blacklisted methods */ if (count($this->getBlackListedMethods())) { $blacklist = array_map('strtolower', $this->getBlackListedMethods()); $methods = array_filter($methods, function ($method) use ($blacklist) { return !in_array(strtolower($method->getName()), $blacklist); }); } /** * Internal objects can not be instantiated with newInstanceArgs and if * they implement Serializable, unserialize will have to be called. As * such, we can't mock it and will need a pass to add a dummy * implementation */ if ($this->getTargetClass() && $this->getTargetClass()->implementsInterface("Serializable") && $this->getTargetClass()->hasInternalAncestor()) { $methods = array_filter($methods, function ($method) { return $method->getName() !== "unserialize"; }); } return array_values($methods); } /** * We declare the __call method to handle undefined stuff, if the class * we're mocking has also defined it, we need to comply with their interface */ public function requiresCallTypeHintRemoval() { foreach ($this->getAllMethods() as $method) { if ("__call" === $method->getName()) { $params = $method->getParameters(); return !$params[1]->isArray(); } } return false; } /** * We declare the __callStatic method to handle undefined stuff, if the class * we're mocking has also defined it, we need to comply with their interface */ public function requiresCallStaticTypeHintRemoval() { foreach ($this->getAllMethods() as $method) { if ("__callStatic" === $method->getName()) { $params = $method->getParameters(); return !$params[1]->isArray(); } } return false; } public function rename($className) { $targets = array(); if ($this->targetClassName) { $targets[] = $this->targetClassName; } if ($this->targetInterfaceNames) { $targets = array_merge($targets, $this->targetInterfaceNames); } if ($this->targetTraitNames) { $targets = array_merge($targets, $this->targetTraitNames); } if ($this->targetObject) { $targets[] = $this->targetObject; } return new self( $targets, $this->blackListedMethods, $this->whiteListedMethods, $className, $this->instanceMock, $this->parameterOverrides, $this->mockOriginalDestructor, $this->constantsMap ); } protected function addTarget($target) { if (is_object($target)) { $this->setTargetObject($target); $this->setTargetClassName(get_class($target)); return $this; } if ($target[0] !== "\\") { $target = "\\" . $target; } if (class_exists($target)) { $this->setTargetClassName($target); return $this; } if (interface_exists($target)) { $this->addTargetInterfaceName($target); return $this; } if (trait_exists($target)) { $this->addTargetTraitName($target); return $this; } /** * Default is to set as class, or interface if class already set * * Don't like this condition, can't remember what the default * targetClass is for */ if ($this->getTargetClassName()) { $this->addTargetInterfaceName($target); return $this; } $this->setTargetClassName($target); } protected function addTargets($interfaces) { foreach ($interfaces as $interface) { $this->addTarget($interface); } } public function getTargetClassName() { return $this->targetClassName; } public function getTargetClass() { if ($this->targetClass) { return $this->targetClass; } if (!$this->targetClassName) { return null; } if (class_exists($this->targetClassName)) { $alias = null; if (strpos($this->targetClassName, '@') !== false) { $alias = (new MockNameBuilder()) ->addPart('anonymous_class') ->addPart(md5($this->targetClassName)) ->build(); class_alias($this->targetClassName, $alias); } $dtc = DefinedTargetClass::factory($this->targetClassName, $alias); if ($this->getTargetObject() == false && $dtc->isFinal()) { throw new \Mockery\Exception( 'The class ' . $this->targetClassName . ' is marked final and its methods' . ' cannot be replaced. Classes marked final can be passed in' . ' to \Mockery::mock() as instantiated objects to create a' . ' partial mock, but only if the mock is not subject to type' . ' hinting checks.' ); } $this->targetClass = $dtc; } else { $this->targetClass = UndefinedTargetClass::factory($this->targetClassName); } return $this->targetClass; } public function getTargetTraits() { if (!empty($this->targetTraits)) { return $this->targetTraits; } foreach ($this->targetTraitNames as $targetTrait) { $this->targetTraits[] = DefinedTargetClass::factory($targetTrait); } $this->targetTraits = array_unique($this->targetTraits); // just in case return $this->targetTraits; } public function getTargetInterfaces() { if (!empty($this->targetInterfaces)) { return $this->targetInterfaces; } foreach ($this->targetInterfaceNames as $targetInterface) { if (!interface_exists($targetInterface)) { $this->targetInterfaces[] = UndefinedTargetClass::factory($targetInterface); continue; } $dtc = DefinedTargetClass::factory($targetInterface); $extendedInterfaces = array_keys($dtc->getInterfaces()); $extendedInterfaces[] = $targetInterface; $traversableFound = false; $iteratorShiftedToFront = false; foreach ($extendedInterfaces as $interface) { if (!$traversableFound && preg_match("/^\\?Iterator(|Aggregate)$/i", $interface)) { break; } if (preg_match("/^\\\\?IteratorAggregate$/i", $interface)) { $this->targetInterfaces[] = DefinedTargetClass::factory("\\IteratorAggregate"); $iteratorShiftedToFront = true; } elseif (preg_match("/^\\\\?Iterator$/i", $interface)) { $this->targetInterfaces[] = DefinedTargetClass::factory("\\Iterator"); $iteratorShiftedToFront = true; } elseif (preg_match("/^\\\\?Traversable$/i", $interface)) { $traversableFound = true; } } if ($traversableFound && !$iteratorShiftedToFront) { $this->targetInterfaces[] = DefinedTargetClass::factory("\\IteratorAggregate"); } /** * We never straight up implement Traversable */ if (!preg_match("/^\\\\?Traversable$/i", $targetInterface)) { $this->targetInterfaces[] = $dtc; } } $this->targetInterfaces = array_unique($this->targetInterfaces); // just in case return $this->targetInterfaces; } public function getTargetObject() { return $this->targetObject; } public function getName() { return $this->name; } /** * Generate a suitable name based on the config */ public function generateName() { $nameBuilder = new MockNameBuilder(); if ($this->getTargetObject()) { $className = get_class($this->getTargetObject()); $nameBuilder->addPart(strpos($className, '@') !== false ? md5($className) : $className); } if ($this->getTargetClass()) { $className = $this->getTargetClass()->getName(); $nameBuilder->addPart(strpos($className, '@') !== false ? md5($className) : $className); } foreach ($this->getTargetInterfaces() as $targetInterface) { $nameBuilder->addPart($targetInterface->getName()); } return $nameBuilder->build(); } public function getShortName() { $parts = explode("\\", $this->getName()); return array_pop($parts); } public function getNamespaceName() { $parts = explode("\\", $this->getName()); array_pop($parts); if (count($parts)) { return implode("\\", $parts); } return ""; } public function getBlackListedMethods() { return $this->blackListedMethods; } public function getWhiteListedMethods() { return $this->whiteListedMethods; } public function isInstanceMock() { return $this->instanceMock; } public function getParameterOverrides() { return $this->parameterOverrides; } public function isMockOriginalDestructor() { return $this->mockOriginalDestructor; } protected function setTargetClassName($targetClassName) { $this->targetClassName = $targetClassName; } protected function getAllMethods() { if ($this->allMethods) { return $this->allMethods; } $classes = $this->getTargetInterfaces(); if ($this->getTargetClass()) { $classes[] = $this->getTargetClass(); } $methods = array(); foreach ($classes as $class) { $methods = array_merge($methods, $class->getMethods()); } foreach ($this->getTargetTraits() as $trait) { foreach ($trait->getMethods() as $method) { if ($method->isAbstract()) { $methods[] = $method; } } } $names = array(); $methods = array_filter($methods, function ($method) use (&$names) { if (in_array($method->getName(), $names)) { return false; } $names[] = $method->getName(); return true; }); return $this->allMethods = $methods; } /** * If we attempt to implement Traversable, we must ensure we are also * implementing either Iterator or IteratorAggregate, and that whichever one * it is comes before Traversable in the list of implements. */ protected function addTargetInterfaceName($targetInterface) { $this->targetInterfaceNames[] = $targetInterface; } protected function addTargetTraitName($targetTraitName) { $this->targetTraitNames[] = $targetTraitName; } protected function setTargetObject($object) { $this->targetObject = $object; } public function getConstantsMap() { return $this->constantsMap; } } Mockery/Generator/DefinedTargetClass.php 0000644 00000005427 15107542733 0014326 0 ustar 00 <?php /** * Mockery (https://docs.mockery.io/) * * @copyright https://github.com/mockery/mockery/blob/HEAD/COPYRIGHT.md * @license https://github.com/mockery/mockery/blob/HEAD/LICENSE BSD 3-Clause License * @link https://github.com/mockery/mockery for the canonical source repository */ namespace Mockery\Generator; use ReflectionAttribute; use ReflectionClass; use function array_map; use function array_unique; use const PHP_VERSION_ID; class DefinedTargetClass implements TargetClassInterface { private $rfc; private $name; public function __construct(ReflectionClass $rfc, $alias = null) { $this->rfc = $rfc; $this->name = $alias === null ? $rfc->getName() : $alias; } public static function factory($name, $alias = null) { return new self(new ReflectionClass($name), $alias); } public function getAttributes() { if (\PHP_VERSION_ID < 80000) { return []; } return array_unique( array_merge( ['\AllowDynamicProperties'], array_map( static function (ReflectionAttribute $attribute): string { return '\\' . $attribute->getName(); }, $this->rfc->getAttributes() ) ) ); } public function getName() { return $this->name; } public function isAbstract() { return $this->rfc->isAbstract(); } public function isFinal() { return $this->rfc->isFinal(); } public function getMethods() { return array_map(function ($method) { return new Method($method); }, $this->rfc->getMethods()); } public function getInterfaces() { $class = __CLASS__; return array_map(function ($interface) use ($class) { return new $class($interface); }, $this->rfc->getInterfaces()); } public function __toString() { return $this->getName(); } public function getNamespaceName() { return $this->rfc->getNamespaceName(); } public function inNamespace() { return $this->rfc->inNamespace(); } public function getShortName() { return $this->rfc->getShortName(); } public function implementsInterface($interface) { return $this->rfc->implementsInterface($interface); } public function hasInternalAncestor() { if ($this->rfc->isInternal()) { return true; } $child = $this->rfc; while ($parent = $child->getParentClass()) { if ($parent->isInternal()) { return true; } $child = $parent; } return false; } } Mockery/Generator/MockConfigurationBuilder.php 0000644 00000011523 15107542733 0015555 0 ustar 00 <?php /** * Mockery (https://docs.mockery.io/) * * @copyright https://github.com/mockery/mockery/blob/HEAD/COPYRIGHT.md * @license https://github.com/mockery/mockery/blob/HEAD/LICENSE BSD 3-Clause License * @link https://github.com/mockery/mockery for the canonical source repository */ namespace Mockery\Generator; class MockConfigurationBuilder { protected $name; protected $blackListedMethods = array( '__call', '__callStatic', '__clone', '__wakeup', '__set', '__get', '__toString', '__isset', '__destruct', '__debugInfo', ## mocking this makes it difficult to debug with xdebug // below are reserved words in PHP "__halt_compiler", "abstract", "and", "array", "as", "break", "callable", "case", "catch", "class", "clone", "const", "continue", "declare", "default", "die", "do", "echo", "else", "elseif", "empty", "enddeclare", "endfor", "endforeach", "endif", "endswitch", "endwhile", "eval", "exit", "extends", "final", "for", "foreach", "function", "global", "goto", "if", "implements", "include", "include_once", "instanceof", "insteadof", "interface", "isset", "list", "namespace", "new", "or", "print", "private", "protected", "public", "require", "require_once", "return", "static", "switch", "throw", "trait", "try", "unset", "use", "var", "while", "xor" ); protected $php7SemiReservedKeywords = [ "callable", "class", "trait", "extends", "implements", "static", "abstract", "final", "public", "protected", "private", "const", "enddeclare", "endfor", "endforeach", "endif", "endwhile", "and", "global", "goto", "instanceof", "insteadof", "interface", "namespace", "new", "or", "xor", "try", "use", "var", "exit", "list", "clone", "include", "include_once", "throw", "array", "print", "echo", "require", "require_once", "return", "else", "elseif", "default", "break", "continue", "switch", "yield", "function", "if", "endswitch", "finally", "for", "foreach", "declare", "case", "do", "while", "as", "catch", "die", "self", "parent", ]; protected $whiteListedMethods = array(); protected $instanceMock = false; protected $parameterOverrides = array(); protected $mockOriginalDestructor = false; protected $targets = array(); protected $constantsMap = array(); public function __construct() { $this->blackListedMethods = array_diff($this->blackListedMethods, $this->php7SemiReservedKeywords); } public function addTarget($target) { $this->targets[] = $target; return $this; } public function addTargets($targets) { foreach ($targets as $target) { $this->addTarget($target); } return $this; } public function setName($name) { $this->name = $name; return $this; } public function addBlackListedMethod($blackListedMethod) { $this->blackListedMethods[] = $blackListedMethod; return $this; } public function addBlackListedMethods(array $blackListedMethods) { foreach ($blackListedMethods as $method) { $this->addBlackListedMethod($method); } return $this; } public function setBlackListedMethods(array $blackListedMethods) { $this->blackListedMethods = $blackListedMethods; return $this; } public function addWhiteListedMethod($whiteListedMethod) { $this->whiteListedMethods[] = $whiteListedMethod; return $this; } public function addWhiteListedMethods(array $whiteListedMethods) { foreach ($whiteListedMethods as $method) { $this->addWhiteListedMethod($method); } return $this; } public function setWhiteListedMethods(array $whiteListedMethods) { $this->whiteListedMethods = $whiteListedMethods; return $this; } public function setInstanceMock($instanceMock) { $this->instanceMock = (bool) $instanceMock; } public function setParameterOverrides(array $overrides) { $this->parameterOverrides = $overrides; } public function setMockOriginalDestructor($mockDestructor) { $this->mockOriginalDestructor = $mockDestructor; return $this; } public function setConstantsMap(array $map) { $this->constantsMap = $map; } public function getMockConfiguration() { return new MockConfiguration( $this->targets, $this->blackListedMethods, $this->whiteListedMethods, $this->name, $this->instanceMock, $this->parameterOverrides, $this->mockOriginalDestructor, $this->constantsMap ); } } Mockery/Generator/Parameter.php 0000644 00000004632 15107542733 0012550 0 ustar 00 <?php /** * Mockery (https://docs.mockery.io/) * * @copyright https://github.com/mockery/mockery/blob/HEAD/COPYRIGHT.md * @license https://github.com/mockery/mockery/blob/HEAD/LICENSE BSD 3-Clause License * @link https://github.com/mockery/mockery for the canonical source repository */ namespace Mockery\Generator; use Mockery\Reflector; class Parameter { /** @var int */ private static $parameterCounter = 0; /** @var \ReflectionParameter */ private $rfp; public function __construct(\ReflectionParameter $rfp) { $this->rfp = $rfp; } public function __call($method, array $args) { return call_user_func_array(array($this->rfp, $method), $args); } /** * Get the reflection class for the parameter type, if it exists. * * This will be null if there was no type, or it was a scalar or a union. * * @return \ReflectionClass|null * * @deprecated since 1.3.3 and will be removed in 2.0. */ public function getClass() { $typeHint = Reflector::getTypeHint($this->rfp, true); return \class_exists($typeHint) ? DefinedTargetClass::factory($typeHint, false) : null; } /** * Get the string representation for the paramater type. * * @return string|null */ public function getTypeHint() { return Reflector::getTypeHint($this->rfp); } /** * Get the string representation for the paramater type. * * @return string * * @deprecated since 1.3.2 and will be removed in 2.0. Use getTypeHint() instead. */ public function getTypeHintAsString() { return (string) Reflector::getTypeHint($this->rfp, true); } /** * Get the name of the parameter. * * Some internal classes have funny looking definitions! * * @return string */ public function getName() { $name = $this->rfp->getName(); if (!$name || $name == '...') { $name = 'arg' . self::$parameterCounter++; } return $name; } /** * Determine if the parameter is an array. * * @return bool */ public function isArray() { return Reflector::isArray($this->rfp); } /** * Determine if the parameter is variadic. * * @return bool */ public function isVariadic() { return $this->rfp->isVariadic(); } } Mockery/Matcher/Contains.php 0000644 00000002465 15107542733 0012045 0 ustar 00 <?php /** * Mockery (https://docs.mockery.io/) * * @copyright https://github.com/mockery/mockery/blob/HEAD/COPYRIGHT.md * @license https://github.com/mockery/mockery/blob/HEAD/LICENSE BSD 3-Clause License * @link https://github.com/mockery/mockery for the canonical source repository */ namespace Mockery\Matcher; class Contains extends MatcherAbstract { /** * Check if the actual value matches the expected. * * @param mixed $actual * @return bool */ public function match(&$actual) { $values = array_values($actual); foreach ($this->_expected as $exp) { $match = false; foreach ($values as $val) { if ($exp === $val || $exp == $val) { $match = true; break; } } if ($match === false) { return false; } } return true; } /** * Return a string representation of this Matcher * * @return string */ public function __toString() { $return = '<Contains['; $elements = array(); foreach ($this->_expected as $v) { $elements[] = (string) $v; } $return .= implode(', ', $elements) . ']>'; return $return; } } Mockery/Matcher/Subset.php 0000644 00000004254 15107542733 0011532 0 ustar 00 <?php /** * Mockery (https://docs.mockery.io/) * * @copyright https://github.com/mockery/mockery/blob/HEAD/COPYRIGHT.md * @license https://github.com/mockery/mockery/blob/HEAD/LICENSE BSD 3-Clause License * @link https://github.com/mockery/mockery for the canonical source repository */ namespace Mockery\Matcher; class Subset extends MatcherAbstract { private $expected; private $strict = true; /** * @param array $expected Expected subset of data * @param bool $strict Whether to run a strict or loose comparison */ public function __construct(array $expected, $strict = true) { $this->expected = $expected; $this->strict = $strict; } /** * @param array $expected Expected subset of data * * @return Subset */ public static function strict(array $expected) { return new static($expected, true); } /** * @param array $expected Expected subset of data * * @return Subset */ public static function loose(array $expected) { return new static($expected, false); } /** * Check if the actual value matches the expected. * * @param mixed $actual * @return bool */ public function match(&$actual) { if (!is_array($actual)) { return false; } if ($this->strict) { return $actual === array_replace_recursive($actual, $this->expected); } return $actual == array_replace_recursive($actual, $this->expected); } /** * Return a string representation of this Matcher * * @return string */ public function __toString() { return '<Subset' . $this->formatArray($this->expected) . ">"; } /** * Recursively format an array into the string representation for this matcher * * @param array $array * @return string */ protected function formatArray(array $array) { $elements = []; foreach ($array as $k => $v) { $elements[] = $k . '=' . (is_array($v) ? $this->formatArray($v) : (string) $v); } return "[" . implode(", ", $elements) . "]"; } } Mockery/Matcher/Pattern.php 0000644 00000001433 15107542733 0011676 0 ustar 00 <?php /** * Mockery (https://docs.mockery.io/) * * @copyright https://github.com/mockery/mockery/blob/HEAD/COPYRIGHT.md * @license https://github.com/mockery/mockery/blob/HEAD/LICENSE BSD 3-Clause License * @link https://github.com/mockery/mockery for the canonical source repository */ namespace Mockery\Matcher; class Pattern extends MatcherAbstract { /** * Check if the actual value matches the expected pattern. * * @param mixed $actual * @return bool */ public function match(&$actual) { return preg_match($this->_expected, (string) $actual) >= 1; } /** * Return a string representation of this Matcher * * @return string */ public function __toString() { return '<Pattern>'; } } Mockery/Matcher/AnyArgs.php 0000644 00000001156 15107542733 0011627 0 ustar 00 <?php /** * Mockery (https://docs.mockery.io/) * * @copyright https://github.com/mockery/mockery/blob/HEAD/COPYRIGHT.md * @license https://github.com/mockery/mockery/blob/HEAD/LICENSE BSD 3-Clause License * @link https://github.com/mockery/mockery for the canonical source repository */ namespace Mockery\Matcher; class AnyArgs extends MatcherAbstract implements ArgumentListMatcher { /** * @inheritdoc */ public function match(&$actual) { return true; } /** * @inheritdoc */ public function __toString() { return '<Any Arguments>'; } } Mockery/Matcher/ArgumentListMatcher.php 0000644 00000000554 15107542733 0014206 0 ustar 00 <?php /** * Mockery (https://docs.mockery.io/) * * @copyright https://github.com/mockery/mockery/blob/HEAD/COPYRIGHT.md * @license https://github.com/mockery/mockery/blob/HEAD/LICENSE BSD 3-Clause License * @link https://github.com/mockery/mockery for the canonical source repository */ namespace Mockery\Matcher; interface ArgumentListMatcher { } Mockery/Matcher/MatcherAbstract.php 0000644 00000002126 15107542733 0013330 0 ustar 00 <?php /** * Mockery (https://docs.mockery.io/) * * @copyright https://github.com/mockery/mockery/blob/HEAD/COPYRIGHT.md * @license https://github.com/mockery/mockery/blob/HEAD/LICENSE BSD 3-Clause License * @link https://github.com/mockery/mockery for the canonical source repository */ namespace Mockery\Matcher; abstract class MatcherAbstract { /** * The expected value (or part thereof) * * @var mixed */ protected $_expected = null; /** * Set the expected value * * @param mixed $expected */ public function __construct($expected = null) { $this->_expected = $expected; } /** * Check if the actual value matches the expected. * Actual passed by reference to preserve reference trail (where applicable) * back to the original method parameter. * * @param mixed $actual * @return bool */ abstract public function match(&$actual); /** * Return a string representation of this Matcher * * @return string */ abstract public function __toString(); } Mockery/Matcher/Closure.php 0000644 00000001501 15107542733 0011671 0 ustar 00 <?php /** * Mockery (https://docs.mockery.io/) * * @copyright https://github.com/mockery/mockery/blob/HEAD/COPYRIGHT.md * @license https://github.com/mockery/mockery/blob/HEAD/LICENSE BSD 3-Clause License * @link https://github.com/mockery/mockery for the canonical source repository */ namespace Mockery\Matcher; class Closure extends MatcherAbstract { /** * Check if the actual value matches the expected. * * @param mixed $actual * @return bool */ public function match(&$actual) { $closure = $this->_expected; $result = $closure($actual); return $result === true; } /** * Return a string representation of this Matcher * * @return string */ public function __toString() { return '<Closure===true>'; } } Mockery/Matcher/MultiArgumentClosure.php 0000644 00000001764 15107542733 0014422 0 ustar 00 <?php /** * Mockery (https://docs.mockery.io/) * * @copyright https://github.com/mockery/mockery/blob/HEAD/COPYRIGHT.md * @license https://github.com/mockery/mockery/blob/HEAD/LICENSE BSD 3-Clause License * @link https://github.com/mockery/mockery for the canonical source repository */ namespace Mockery\Matcher; class MultiArgumentClosure extends MatcherAbstract implements ArgumentListMatcher { /** * Check if the actual value matches the expected. * Actual passed by reference to preserve reference trail (where applicable) * back to the original method parameter. * * @param mixed $actual * @return bool */ public function match(&$actual) { $closure = $this->_expected; return true === call_user_func_array($closure, $actual); } /** * Return a string representation of this Matcher * * @return string */ public function __toString() { return '<MultiArgumentClosure===true>'; } } Mockery/Matcher/AndAnyOtherArgs.php 0000644 00000001361 15107542733 0013252 0 ustar 00 <?php /** * Mockery (https://docs.mockery.io/) * * @copyright https://github.com/mockery/mockery/blob/HEAD/COPYRIGHT.md * @license https://github.com/mockery/mockery/blob/HEAD/LICENSE BSD 3-Clause License * @link https://github.com/mockery/mockery for the canonical source repository */ namespace Mockery\Matcher; class AndAnyOtherArgs extends MatcherAbstract { /** * Check if the actual value matches the expected. * * @param mixed $actual * @return bool */ public function match(&$actual) { return true; } /** * Return a string representation of this Matcher * * @return string */ public function __toString() { return '<AndAnyOthers>'; } } Mockery/Matcher/AnyOf.php 0000644 00000001501 15107542733 0011271 0 ustar 00 <?php /** * Mockery (https://docs.mockery.io/) * * @copyright https://github.com/mockery/mockery/blob/HEAD/COPYRIGHT.md * @license https://github.com/mockery/mockery/blob/HEAD/LICENSE BSD 3-Clause License * @link https://github.com/mockery/mockery for the canonical source repository */ namespace Mockery\Matcher; class AnyOf extends MatcherAbstract { /** * Check if the actual value does not match the expected (in this * case it's specifically NOT expected). * * @param mixed $actual * @return bool */ public function match(&$actual) { return in_array($actual, $this->_expected, true); } /** * Return a string representation of this Matcher * * @return string */ public function __toString() { return '<AnyOf>'; } } Mockery/Matcher/Any.php 0000644 00000001334 15107542733 0011010 0 ustar 00 <?php /** * Mockery (https://docs.mockery.io/) * * @copyright https://github.com/mockery/mockery/blob/HEAD/COPYRIGHT.md * @license https://github.com/mockery/mockery/blob/HEAD/LICENSE BSD 3-Clause License * @link https://github.com/mockery/mockery for the canonical source repository */ namespace Mockery\Matcher; class Any extends MatcherAbstract { /** * Check if the actual value matches the expected. * * @param mixed $actual * @return bool */ public function match(&$actual) { return true; } /** * Return a string representation of this Matcher * * @return string */ public function __toString() { return '<Any>'; } } Mockery/Matcher/NotAnyOf.php 0000644 00000001671 15107542733 0011762 0 ustar 00 <?php /** * Mockery (https://docs.mockery.io/) * * @copyright https://github.com/mockery/mockery/blob/HEAD/COPYRIGHT.md * @license https://github.com/mockery/mockery/blob/HEAD/LICENSE BSD 3-Clause License * @link https://github.com/mockery/mockery for the canonical source repository */ namespace Mockery\Matcher; class NotAnyOf extends MatcherAbstract { /** * Check if the actual value does not match the expected (in this * case it's specifically NOT expected). * * @param mixed $actual * @return bool */ public function match(&$actual) { foreach ($this->_expected as $exp) { if ($actual === $exp || $actual == $exp) { return false; } } return true; } /** * Return a string representation of this Matcher * * @return string */ public function __toString() { return '<AnyOf>'; } } Mockery/Matcher/Not.php 0000644 00000001460 15107542733 0011021 0 ustar 00 <?php /** * Mockery (https://docs.mockery.io/) * * @copyright https://github.com/mockery/mockery/blob/HEAD/COPYRIGHT.md * @license https://github.com/mockery/mockery/blob/HEAD/LICENSE BSD 3-Clause License * @link https://github.com/mockery/mockery for the canonical source repository */ namespace Mockery\Matcher; class Not extends MatcherAbstract { /** * Check if the actual value does not match the expected (in this * case it's specifically NOT expected). * * @param mixed $actual * @return bool */ public function match(&$actual) { return $actual !== $this->_expected; } /** * Return a string representation of this Matcher * * @return string */ public function __toString() { return '<Not>'; } } Mockery/Matcher/MustBe.php 0000644 00000001635 15107542733 0011464 0 ustar 00 <?php /** * Mockery (https://docs.mockery.io/) * * @copyright https://github.com/mockery/mockery/blob/HEAD/COPYRIGHT.md * @license https://github.com/mockery/mockery/blob/HEAD/LICENSE BSD 3-Clause License * @link https://github.com/mockery/mockery for the canonical source repository */ namespace Mockery\Matcher; /** * @deprecated 2.0 Due to ambiguity, use PHPUnit equivalents */ class MustBe extends MatcherAbstract { /** * Check if the actual value matches the expected. * * @param mixed $actual * @return bool */ public function match(&$actual) { if (!is_object($actual)) { return $this->_expected === $actual; } return $this->_expected == $actual; } /** * Return a string representation of this Matcher * * @return string */ public function __toString() { return '<MustBe>'; } } Mockery/Matcher/HasValue.php 0000644 00000001503 15107542733 0011767 0 ustar 00 <?php /** * Mockery (https://docs.mockery.io/) * * @copyright https://github.com/mockery/mockery/blob/HEAD/COPYRIGHT.md * @license https://github.com/mockery/mockery/blob/HEAD/LICENSE BSD 3-Clause License * @link https://github.com/mockery/mockery for the canonical source repository */ namespace Mockery\Matcher; class HasValue extends MatcherAbstract { /** * Check if the actual value matches the expected. * * @param mixed $actual * @return bool */ public function match(&$actual) { return in_array($this->_expected, $actual); } /** * Return a string representation of this Matcher * * @return string */ public function __toString() { $return = '<HasValue[' . (string) $this->_expected . ']>'; return $return; } } Mockery/Matcher/NoArgs.php 0000644 00000001173 15107542733 0011453 0 ustar 00 <?php /** * Mockery (https://docs.mockery.io/) * * @copyright https://github.com/mockery/mockery/blob/HEAD/COPYRIGHT.md * @license https://github.com/mockery/mockery/blob/HEAD/LICENSE BSD 3-Clause License * @link https://github.com/mockery/mockery for the canonical source repository */ namespace Mockery\Matcher; class NoArgs extends MatcherAbstract implements ArgumentListMatcher { /** * @inheritdoc */ public function match(&$actual) { return count($actual) == 0; } /** * @inheritdoc */ public function __toString() { return '<No Arguments>'; } } Mockery/Matcher/IsEqual.php 0000644 00000001373 15107542733 0011627 0 ustar 00 <?php /** * Mockery (https://docs.mockery.io/) * * @copyright https://github.com/mockery/mockery/blob/HEAD/COPYRIGHT.md * @license https://github.com/mockery/mockery/blob/HEAD/LICENSE BSD 3-Clause License * @link https://github.com/mockery/mockery for the canonical source repository */ namespace Mockery\Matcher; class IsEqual extends MatcherAbstract { /** * Check if the actual value matches the expected. * * @param mixed $actual * @return bool */ public function match(&$actual) { return $this->_expected == $actual; } /** * Return a string representation of this Matcher * * @return string */ public function __toString() { return '<IsEqual>'; } } Mockery/Matcher/Ducktype.php 0000644 00000001760 15107542733 0012054 0 ustar 00 <?php /** * Mockery (https://docs.mockery.io/) * * @copyright https://github.com/mockery/mockery/blob/HEAD/COPYRIGHT.md * @license https://github.com/mockery/mockery/blob/HEAD/LICENSE BSD 3-Clause License * @link https://github.com/mockery/mockery for the canonical source repository */ namespace Mockery\Matcher; class Ducktype extends MatcherAbstract { /** * Check if the actual value matches the expected. * * @param mixed $actual * @return bool */ public function match(&$actual) { if (!is_object($actual)) { return false; } foreach ($this->_expected as $method) { if (!method_exists($actual, $method)) { return false; } } return true; } /** * Return a string representation of this Matcher * * @return string */ public function __toString() { return '<Ducktype[' . implode(', ', $this->_expected) . ']>'; } } Mockery/Matcher/HasKey.php 0000644 00000001433 15107542733 0011445 0 ustar 00 <?php /** * Mockery (https://docs.mockery.io/) * * @copyright https://github.com/mockery/mockery/blob/HEAD/COPYRIGHT.md * @license https://github.com/mockery/mockery/blob/HEAD/LICENSE BSD 3-Clause License * @link https://github.com/mockery/mockery for the canonical source repository */ namespace Mockery\Matcher; class HasKey extends MatcherAbstract { /** * Check if the actual value matches the expected. * * @param mixed $actual * @return bool */ public function match(&$actual) { return array_key_exists($this->_expected, $actual); } /** * Return a string representation of this Matcher * * @return string */ public function __toString() { return "<HasKey[$this->_expected]>"; } } Mockery/Matcher/IsSame.php 0000644 00000001372 15107542733 0011444 0 ustar 00 <?php /** * Mockery (https://docs.mockery.io/) * * @copyright https://github.com/mockery/mockery/blob/HEAD/COPYRIGHT.md * @license https://github.com/mockery/mockery/blob/HEAD/LICENSE BSD 3-Clause License * @link https://github.com/mockery/mockery for the canonical source repository */ namespace Mockery\Matcher; class IsSame extends MatcherAbstract { /** * Check if the actual value matches the expected. * * @param mixed $actual * @return bool */ public function match(&$actual) { return $this->_expected === $actual; } /** * Return a string representation of this Matcher * * @return string */ public function __toString() { return '<IsSame>'; } } Mockery/Matcher/Type.php 0000644 00000002271 15107542733 0011203 0 ustar 00 <?php /** * Mockery (https://docs.mockery.io/) * * @copyright https://github.com/mockery/mockery/blob/HEAD/COPYRIGHT.md * @license https://github.com/mockery/mockery/blob/HEAD/LICENSE BSD 3-Clause License * @link https://github.com/mockery/mockery for the canonical source repository */ namespace Mockery\Matcher; class Type extends MatcherAbstract { /** * Check if the actual value matches the expected. * * @param mixed $actual * @return bool */ public function match(&$actual) { if ($this->_expected == 'real') { $function = 'is_float'; } else { $function = 'is_' . strtolower($this->_expected); } if (function_exists($function)) { return $function($actual); } elseif (is_string($this->_expected) && (class_exists($this->_expected) || interface_exists($this->_expected))) { return $actual instanceof $this->_expected; } return false; } /** * Return a string representation of this Matcher * * @return string */ public function __toString() { return '<' . ucfirst($this->_expected) . '>'; } } Mockery/CountValidator/Exception.php 0000644 00000000732 15107542733 0013573 0 ustar 00 <?php /** * Mockery (https://docs.mockery.io/) * * @copyright https://github.com/mockery/mockery/blob/HEAD/COPYRIGHT.md * @license https://github.com/mockery/mockery/blob/HEAD/LICENSE BSD 3-Clause License * @link https://github.com/mockery/mockery for the canonical source repository */ namespace Mockery\CountValidator; use Mockery\Exception\MockeryExceptionInterface; class Exception extends \OutOfBoundsException implements MockeryExceptionInterface { } Mockery/CountValidator/AtLeast.php 0000644 00000002701 15107542733 0013170 0 ustar 00 <?php /** * Mockery (https://docs.mockery.io/) * * @copyright https://github.com/mockery/mockery/blob/HEAD/COPYRIGHT.md * @license https://github.com/mockery/mockery/blob/HEAD/LICENSE BSD 3-Clause License * @link https://github.com/mockery/mockery for the canonical source repository */ namespace Mockery\CountValidator; use Mockery; class AtLeast extends CountValidatorAbstract { /** * Checks if the validator can accept an additional nth call * * @param int $n * @return bool */ public function isEligible($n) { return true; } /** * Validate the call count against this validator * * @param int $n * @return bool */ public function validate($n) { if ($this->_limit > $n) { $exception = new Mockery\Exception\InvalidCountException( 'Method ' . (string) $this->_expectation . ' from ' . $this->_expectation->getMock()->mockery_getName() . ' should be called' . PHP_EOL . ' at least ' . $this->_limit . ' times but called ' . $n . ' times.' ); $exception->setMock($this->_expectation->getMock()) ->setMethodName((string) $this->_expectation) ->setExpectedCountComparative('>=') ->setExpectedCount($this->_limit) ->setActualCount($n); throw $exception; } } } Mockery/CountValidator/Exact.php 0000644 00000002632 15107542733 0012702 0 ustar 00 <?php /** * Mockery (https://docs.mockery.io/) * * @copyright https://github.com/mockery/mockery/blob/HEAD/COPYRIGHT.md * @license https://github.com/mockery/mockery/blob/HEAD/LICENSE BSD 3-Clause License * @link https://github.com/mockery/mockery for the canonical source repository */ namespace Mockery\CountValidator; use Mockery; class Exact extends CountValidatorAbstract { /** * Validate the call count against this validator * * @param int $n * @return bool */ public function validate($n) { if ($this->_limit !== $n) { $because = $this->_expectation->getExceptionMessage(); $exception = new Mockery\Exception\InvalidCountException( 'Method ' . (string) $this->_expectation . ' from ' . $this->_expectation->getMock()->mockery_getName() . ' should be called' . PHP_EOL . ' exactly ' . $this->_limit . ' times but called ' . $n . ' times.' . ($because ? ' Because ' . $this->_expectation->getExceptionMessage() : '') ); $exception->setMock($this->_expectation->getMock()) ->setMethodName((string) $this->_expectation) ->setExpectedCountComparative('=') ->setExpectedCount($this->_limit) ->setActualCount($n); throw $exception; } } } Mockery/CountValidator/AtMost.php 0000644 00000002371 15107542733 0013045 0 ustar 00 <?php /** * Mockery (https://docs.mockery.io/) * * @copyright https://github.com/mockery/mockery/blob/HEAD/COPYRIGHT.md * @license https://github.com/mockery/mockery/blob/HEAD/LICENSE BSD 3-Clause License * @link https://github.com/mockery/mockery for the canonical source repository */ namespace Mockery\CountValidator; use Mockery; class AtMost extends CountValidatorAbstract { /** * Validate the call count against this validator * * @param int $n * @return bool */ public function validate($n) { if ($this->_limit < $n) { $exception = new Mockery\Exception\InvalidCountException( 'Method ' . (string) $this->_expectation . ' from ' . $this->_expectation->getMock()->mockery_getName() . ' should be called' . PHP_EOL . ' at most ' . $this->_limit . ' times but called ' . $n . ' times.' ); $exception->setMock($this->_expectation->getMock()) ->setMethodName((string) $this->_expectation) ->setExpectedCountComparative('<=') ->setExpectedCount($this->_limit) ->setActualCount($n); throw $exception; } } } Mockery/CountValidator/CountValidatorAbstract.php 0000644 00000002434 15107542733 0016260 0 ustar 00 <?php /** * Mockery (https://docs.mockery.io/) * * @copyright https://github.com/mockery/mockery/blob/HEAD/COPYRIGHT.md * @license https://github.com/mockery/mockery/blob/HEAD/LICENSE BSD 3-Clause License * @link https://github.com/mockery/mockery for the canonical source repository */ namespace Mockery\CountValidator; abstract class CountValidatorAbstract { /** * Expectation for which this validator is assigned * * @var \Mockery\Expectation */ protected $_expectation = null; /** * Call count limit * * @var int */ protected $_limit = null; /** * Set Expectation object and upper call limit * * @param \Mockery\Expectation $expectation * @param int $limit */ public function __construct(\Mockery\Expectation $expectation, $limit) { $this->_expectation = $expectation; $this->_limit = $limit; } /** * Checks if the validator can accept an additional nth call * * @param int $n * @return bool */ public function isEligible($n) { return ($n < $this->_limit); } /** * Validate the call count against this validator * * @param int $n * @return bool */ abstract public function validate($n); } Mockery/VerificationExpectation.php 0000644 00000001101 15107542733 0013514 0 ustar 00 <?php /** * Mockery (https://docs.mockery.io/) * * @copyright https://github.com/mockery/mockery/blob/HEAD/COPYRIGHT.md * @license https://github.com/mockery/mockery/blob/HEAD/LICENSE BSD 3-Clause License * @link https://github.com/mockery/mockery for the canonical source repository */ namespace Mockery; class VerificationExpectation extends Expectation { public function clearCountValidators() { $this->_countValidators = array(); } public function __clone() { parent::__clone(); $this->_actualCount = 0; } } Mockery/ExpectationDirector.php 0000644 00000012673 15107542733 0012665 0 ustar 00 <?php /** * Mockery (https://docs.mockery.io/) * * @copyright https://github.com/mockery/mockery/blob/HEAD/COPYRIGHT.md * @license https://github.com/mockery/mockery/blob/HEAD/LICENSE BSD 3-Clause License * @link https://github.com/mockery/mockery for the canonical source repository */ namespace Mockery; class ExpectationDirector { /** * Method name the director is directing * * @var string */ protected $_name = null; /** * Mock object the director is attached to * * @var \Mockery\MockInterface|\Mockery\LegacyMockInterface */ protected $_mock = null; /** * Stores an array of all expectations for this mock * * @var array */ protected $_expectations = array(); /** * The expected order of next call * * @var int */ protected $_expectedOrder = null; /** * Stores an array of all default expectations for this mock * * @var array */ protected $_defaults = array(); /** * Constructor * * @param string $name * @param \Mockery\LegacyMockInterface $mock */ public function __construct($name, \Mockery\LegacyMockInterface $mock) { $this->_name = $name; $this->_mock = $mock; } /** * Add a new expectation to the director * * @param \Mockery\Expectation $expectation */ public function addExpectation(\Mockery\Expectation $expectation) { $this->_expectations[] = $expectation; } /** * Handle a method call being directed by this instance * * @param array $args * @return mixed */ public function call(array $args) { $expectation = $this->findExpectation($args); if (is_null($expectation)) { $exception = new \Mockery\Exception\NoMatchingExpectationException( 'No matching handler found for ' . $this->_mock->mockery_getName() . '::' . \Mockery::formatArgs($this->_name, $args) . '. Either the method was unexpected or its arguments matched' . ' no expected argument list for this method' . PHP_EOL . PHP_EOL . \Mockery::formatObjects($args) ); $exception->setMock($this->_mock) ->setMethodName($this->_name) ->setActualArguments($args); throw $exception; } return $expectation->verifyCall($args); } /** * Verify all expectations of the director * * @throws \Mockery\CountValidator\Exception * @return void */ public function verify() { if (!empty($this->_expectations)) { foreach ($this->_expectations as $exp) { $exp->verify(); } } else { foreach ($this->_defaults as $exp) { $exp->verify(); } } } /** * Attempt to locate an expectation matching the provided args * * @param array $args * @return mixed */ public function findExpectation(array $args) { $expectation = null; if (!empty($this->_expectations)) { $expectation = $this->_findExpectationIn($this->_expectations, $args); } if ($expectation === null && !empty($this->_defaults)) { $expectation = $this->_findExpectationIn($this->_defaults, $args); } return $expectation; } /** * Make the given expectation a default for all others assuming it was * correctly created last * * @param \Mockery\Expectation $expectation */ public function makeExpectationDefault(\Mockery\Expectation $expectation) { $last = end($this->_expectations); if ($last === $expectation) { array_pop($this->_expectations); array_unshift($this->_defaults, $expectation); } else { throw new \Mockery\Exception( 'Cannot turn a previously defined expectation into a default' ); } } /** * Search current array of expectations for a match * * @param array $expectations * @param array $args * @return mixed */ protected function _findExpectationIn(array $expectations, array $args) { foreach ($expectations as $exp) { if ($exp->isEligible() && $exp->matchArgs($args)) { return $exp; } } foreach ($expectations as $exp) { if ($exp->matchArgs($args)) { return $exp; } } } /** * Return all expectations assigned to this director * * @return array */ public function getExpectations() { return $this->_expectations; } /** * Return all expectations assigned to this director * * @return array */ public function getDefaultExpectations() { return $this->_defaults; } /** * Return the number of expectations assigned to this director. * * @return int */ public function getExpectationCount() { $count = 0; /** @var Expectation $expectations */ $expectations = $this->getExpectations() ?: $this->getDefaultExpectations(); foreach ($expectations as $expectation) { if ($expectation->isCallCountConstrained()) { $count++; } } return $count; } }
Simpan