Aggiornato Composer

This commit is contained in:
Paolo A
2024-05-17 12:24:19 +00:00
parent 4ac62108b5
commit ec201d75b2
2238 changed files with 38684 additions and 59785 deletions

File diff suppressed because it is too large Load Diff

View File

@@ -1,26 +1,20 @@
<?php
/**
* Mockery
* Mockery (https://docs.mockery.io/)
*
* LICENSE
*
* This source file is subject to the new BSD license that is bundled
* with this package in the file LICENSE.txt.
* It is also available through the world-wide-web at this URL:
* http://github.com/padraic/mockery/blob/master/LICENSE
* If you did not receive a copy of the license and are unable to
* obtain it through the world-wide-web, please send an email
* to padraic@php.net so we can send you a copy immediately.
*
* @category Mockery
* @package Mockery
* @copyright Copyright (c) 2010 Pádraic Brady (http://blog.astrumfutura.com)
* @license http://github.com/padraic/mockery/blob/master/LICENSE New BSD License
* @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;
use PHPUnit\Framework\Attributes\After;
use PHPUnit\Framework\Attributes\Before;
use function method_exists;
/**
* Integrates Mockery into PHPUnit. Ensures Mockery expectations are verified
@@ -32,6 +26,30 @@ trait MockeryPHPUnitIntegration
protected $mockeryOpen;
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;
}
/**
* 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.
@@ -45,41 +63,10 @@ trait MockeryPHPUnitIntegration
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
*/
#[After]
protected function purgeMockeryContainer()
{
if ($this->mockeryOpen) {
@@ -87,4 +74,13 @@ trait MockeryPHPUnitIntegration
Mockery::close();
}
}
/**
* @before
*/
#[Before]
protected function startMockery()
{
$this->mockeryOpen = true;
}
}

View File

@@ -1,21 +1,11 @@
<?php
/**
* Mockery
* Mockery (https://docs.mockery.io/)
*
* LICENSE
*
* This source file is subject to the new BSD license that is bundled
* with this package in the file LICENSE.txt.
* It is also available through the world-wide-web at this URL:
* http://github.com/padraic/mockery/blob/master/LICENSE
* If you did not receive a copy of the license and are unable to
* obtain it through the world-wide-web, please send an email
* to padraic@php.net so we can send you a copy immediately.
*
* @category Mockery
* @package Mockery
* @copyright Copyright (c) 2019 Enalean
* @license https://github.com/mockery/mockery/blob/master/LICENSE New BSD License
* @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);

View File

@@ -1,26 +1,18 @@
<?php
/**
* Mockery
* Mockery (https://docs.mockery.io/)
*
* LICENSE
*
* This source file is subject to the new BSD license that is bundled
* with this package in the file LICENSE.txt.
* It is also available through the world-wide-web at this URL:
* http://github.com/padraic/mockery/blob/master/LICENSE
* If you did not receive a copy of the license and are unable to
* obtain it through the world-wide-web, please send an email
* to padraic@php.net so we can send you a copy immediately.
*
* @category Mockery
* @package Mockery
* @copyright Copyright (c) 2010 Pádraic Brady (http://blog.astrumfutura.com)
* @license http://github.com/padraic/mockery/blob/master/LICENSE New BSD License
* @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;
abstract class MockeryTestCase extends \PHPUnit\Framework\TestCase
use PHPUnit\Framework\TestCase;
abstract class MockeryTestCase extends TestCase
{
use MockeryPHPUnitIntegration;
use MockeryTestCaseSetUp;

View File

@@ -1,21 +1,11 @@
<?php
/**
* Mockery
* Mockery (https://docs.mockery.io/)
*
* LICENSE
*
* This source file is subject to the new BSD license that is bundled
* with this package in the file LICENSE.txt.
* It is also available through the world-wide-web at this URL:
* http://github.com/padraic/mockery/blob/master/LICENSE
* If you did not receive a copy of the license and are unable to
* obtain it through the world-wide-web, please send an email
* to padraic@php.net so we can send you a copy immediately.
*
* @category Mockery
* @package Mockery
* @copyright Copyright (c) 2019 Enalean
* @license https://github.com/mockery/mockery/blob/master/LICENSE New BSD License
* @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);

View File

@@ -1,29 +1,19 @@
<?php
/**
* Mockery
* Mockery (https://docs.mockery.io/)
*
* LICENSE
*
* This source file is subject to the new BSD license that is bundled
* with this package in the file LICENSE.txt.
* It is also available through the world-wide-web at this URL:
* http://github.com/padraic/mockery/blob/master/LICENSE
* If you did not receive a copy of the license and are unable to
* obtain it through the world-wide-web, please send an email
* to padraic@php.net so we can send you a copy immediately.
*
* @category Mockery
* @package Mockery
* @copyright Copyright (c) 2010 Pádraic Brady (http://blog.astrumfutura.com)
* @license http://github.com/padraic/mockery/blob/master/LICENSE New BSD License
* @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\TestListener as PHPUnitTestListener;
use PHPUnit\Framework\TestListenerDefaultImplementation;
use PHPUnit\Framework\TestSuite;
use PHPUnit\Framework\TestListener as PHPUnitTestListener;
class TestListener implements PHPUnitTestListener
{

View File

@@ -1,30 +1,27 @@
<?php
/**
* Mockery
* Mockery (https://docs.mockery.io/)
*
* LICENSE
*
* This source file is subject to the new BSD license that is bundled
* with this package in the file LICENSE.txt.
* It is also available through the world-wide-web at this URL:
* http://github.com/padraic/mockery/blob/master/LICENSE
* If you did not receive a copy of the license and are unable to
* obtain it through the world-wide-web, please send an email
* to padraic@php.net so we can send you a copy immediately.
*
* @category Mockery
* @package Mockery
* @copyright Copyright (c) 2010 Pádraic Brady (http://blog.astrumfutura.com)
* @license http://github.com/padraic/mockery/blob/master/LICENSE New BSD License
* @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 LogicException;
use Mockery;
use PHPUnit\Framework\ExpectationFailedException;
use PHPUnit\Framework\Test;
use PHPUnit\Framework\TestCase;
use PHPUnit\Util\Blacklist;
use PHPUnit\Runner\BaseTestRunner;
use PHPUnit\Util\Blacklist;
use ReflectionClass;
use function dirname;
use function method_exists;
use function sprintf;
class TestListenerTrait
{
@@ -37,7 +34,7 @@ class TestListenerTrait
*/
public function endTest(Test $test, $time)
{
if (!$test instanceof TestCase) {
if (! $test instanceof TestCase) {
// We need the getTestResultObject and getStatus methods which are
// not part of the interface.
return;
@@ -54,13 +51,13 @@ class TestListenerTrait
try {
// The self() call is used as a sentinel. Anything that throws if
// the container is closed already will do.
\Mockery::self();
} catch (\LogicException $_) {
Mockery::self();
} catch (LogicException $logicException) {
return;
}
$e = new ExpectationFailedException(
\sprintf(
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__
@@ -78,10 +75,10 @@ class TestListenerTrait
public function startTestSuite()
{
if (method_exists(Blacklist::class, 'addDirectory')) {
(new BlackList())->getBlacklistedDirectories();
Blacklist::addDirectory(\dirname((new \ReflectionClass(\Mockery::class))->getFileName()));
(new Blacklist())->getBlacklistedDirectories();
Blacklist::addDirectory(dirname((new ReflectionClass(Mockery::class))->getFileName()));
} else {
Blacklist::$blacklistedClassNames[\Mockery::class] = 1;
Blacklist::$blacklistedClassNames[Mockery::class] = 1;
}
}
}

View File

@@ -1,27 +1,18 @@
<?php
/**
* Mockery
* Mockery (https://docs.mockery.io/)
*
* LICENSE
*
* This source file is subject to the new BSD license that is bundled
* with this package in the file LICENSE.txt.
* It is also available through the world-wide-web at this URL:
* http://github.com/padraic/mockery/blob/master/LICENSE
* If you did not receive a copy of the license and are unable to
* obtain it through the world-wide-web, please send an email
* to padraic@php.net so we can send you a copy immediately.
*
* @category Mockery
* @package Mockery
* @copyright Copyright (c) 2017 Dave Marshall https://github.com/davedevelopment
* @license http://github.com/padraic/mockery/blob/master/LICENSE New BSD License
* @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;
use Closure;
use function func_get_args;
/**
* @internal
@@ -30,13 +21,16 @@ class ClosureWrapper
{
private $closure;
public function __construct(\Closure $closure)
public function __construct(Closure $closure)
{
$this->closure = $closure;
}
/**
* @return mixed
*/
public function __invoke()
{
return call_user_func_array($this->closure, func_get_args());
return ($this->closure)(...func_get_args());
}
}

View File

@@ -1,38 +1,64 @@
<?php
/**
* Mockery
* Mockery (https://docs.mockery.io/)
*
* LICENSE
*
* This source file is subject to the new BSD license that is bundled
* with this package in the file LICENSE.txt.
* It is also available through the world-wide-web at this URL:
* http://github.com/padraic/mockery/blob/master/LICENSE
* If you did not receive a copy of the license and are unable to
* obtain it through the world-wide-web, please send an email
* to padraic@php.net so we can send you a copy immediately.
*
* @category Mockery
* @package Mockery
* @copyright Copyright (c) 2010 Pádraic Brady (http://blog.astrumfutura.com)
* @license http://github.com/padraic/mockery/blob/master/LICENSE New BSD License
* @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 function array_map;
use function current;
use function implode;
use function reset;
class CompositeExpectation implements ExpectationInterface
{
/**
* Stores an array of all expectations for this composite
*
* @var array
* @var array<ExpectationInterface>
*/
protected $_expectations = array();
protected $_expectations = [];
/**
* Intercept any expectation calls and direct against all expectations
*
* @param string $method
*
* @return self
*/
public function __call($method, array $args)
{
foreach ($this->_expectations as $expectation) {
$expectation->{$method}(...$args);
}
return $this;
}
/**
* Return the string summary of this composite expectation
*
* @return string
*/
public function __toString()
{
$parts = array_map(static function (ExpectationInterface $expectation): string {
return (string) $expectation;
}, $this->_expectations);
return '[' . implode(', ', $parts) . ']';
}
/**
* Add an expectation to the composite
*
* @param \Mockery\Expectation|\Mockery\CompositeExpectation $expectation
* @param ExpectationInterface|HigherOrderMessage $expectation
*
* @return void
*/
public function add($expectation)
@@ -52,26 +78,24 @@ class CompositeExpectation implements ExpectationInterface
* 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->andReturn(...$args);
}
/**
* Intercept any expectation calls and direct against all expectations
* Return the parent mock of the first expectation
*
* @param string $method
* @param array $args
* @return self
* @return LegacyMockInterface&MockInterface
*/
public function __call($method, array $args)
public function getMock()
{
foreach ($this->_expectations as $expectation) {
call_user_func_array(array($expectation, $method), $args);
}
return $this;
reset($this->_expectations);
$first = current($this->_expectations);
return $first->getMock();
}
/**
@@ -86,22 +110,10 @@ class CompositeExpectation implements ExpectationInterface
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
* @return LegacyMockInterface&MockInterface
*/
public function mock()
{
@@ -109,46 +121,30 @@ class CompositeExpectation implements ExpectationInterface
}
/**
* Starts a new expectation addition on the first mock which is the primary
* target outside of a demeter chain
* 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
* @return Expectation
*/
public function shouldNotReceive(...$args)
{
reset($this->_expectations);
$first = current($this->_expectations);
return call_user_func_array(array($first->getMock(), 'shouldNotReceive'), $args);
return $first->getMock()->shouldNotReceive(...$args);
}
/**
* Return the string summary of this composite expectation
* Starts a new expectation addition on the first mock which is the primary target, outside of a demeter chain
*
* @return string
* @param mixed ...$args
*
* @return Expectation
*/
public function __toString()
public function shouldReceive(...$args)
{
$return = '[';
$parts = array();
foreach ($this->_expectations as $exp) {
$parts[] = (string) $exp;
}
$return .= implode(', ', $parts) . ']';
return $return;
reset($this->_expectations);
$first = current($this->_expectations);
return $first->getMock()->shouldReceive(...$args);
}
}

View File

@@ -1,35 +1,36 @@
<?php
/**
* Mockery
* Mockery (https://docs.mockery.io/)
*
* LICENSE
*
* This source file is subject to the new BSD license that is bundled
* with this package in the file LICENSE.txt.
* It is also available through the world-wide-web at this URL:
* http://github.com/padraic/mockery/blob/master/LICENSE
* If you did not receive a copy of the license and are unable to
* obtain it through the world-wide-web, please send an email
* to padraic@php.net so we can send you a copy immediately.
*
* @category Mockery
* @package Mockery
* @copyright Copyright (c) 2010 Pádraic Brady (http://blog.astrumfutura.com)
* @license http://github.com/padraic/mockery/blob/master/LICENSE New BSD License
* @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 Hamcrest\Matcher;
use Hamcrest_Matcher;
use InvalidArgumentException;
use LogicException;
use Mockery\Matcher\MatcherInterface;
use function array_key_exists;
use function array_merge;
use function class_implements;
use function get_parent_class;
use function is_a;
use function sprintf;
use function strtolower;
use function trigger_error;
use const E_USER_DEPRECATED;
use const PHP_MAJOR_VERSION;
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()
@@ -41,18 +42,53 @@ class Configuration
protected $_allowMockingMethodsUnnecessarily = true;
/**
* @var QuickDefinitionsConfiguration
* 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 $_quickDefinitionsConfiguration;
protected $_allowMockingNonExistentMethod = true;
/**
* Constants map
*
* e.g. ['class' => ['MY_CONST' => 123, 'OTHER_CONST' => 'foo']]
*
* @var array<class-string,array<string,array<scalar>|scalar>>
*/
protected $_constantsMap = [];
/**
* Default argument matchers
*
* e.g. ['class' => 'matcher']
*
* @var array<class-string,class-string>
*/
protected $_defaultMatchers = [];
/**
* Parameter map for use with PHP internal classes.
*
* @var array
* e.g. ['class' => ['method' => ['param1', 'param2']]]
*
* @var array<class-string,array<string,list<string>>>
*/
protected $_internalClassParamMap = array();
protected $_internalClassParamMap = [];
protected $_constantsMap = array();
/**
* Custom object formatters
*
* e.g. ['class' => static fn($object) => 'formatted']
*
* @var array<class-string,Closure>
*/
protected $_objectFormatters = [];
/**
* @var QuickDefinitionsConfiguration
*/
protected $_quickDefinitionsConfiguration;
/**
* Boolean assertion is reflection caching enabled or not. It should be
@@ -67,129 +103,35 @@ class Configuration
$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
*
* @return void
*
* @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);
@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
* Set boolean to allow/prevent mocking of non-existent methods
*
* @return bool
* @param bool $flag
*
* @deprecated since 1.4.0
* @return void
*/
public function mockingMethodsUnnecessarilyAllowed()
public function allowMockingNonExistentMethods($flag = true)
{
@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;
$this->_allowMockingNonExistentMethod = (bool) $flag;
}
/**
@@ -199,6 +141,8 @@ class Configuration
* PHPUnit's --static-backup option.
*
* @see https://github.com/mockery/mockery/issues/268
*
* @return void
*/
public function disableReflectionCache()
{
@@ -212,72 +156,251 @@ class Configuration
* PHPUnit's --static-backup option.
*
* @see https://github.com/mockery/mockery/issues/268
*
* @return void
*/
public function enableReflectionCache()
{
$this->_reflectionCacheEnabled = true;
}
/**
* Get the map of constants to be used in the mock generator
*
* @return array<class-string,array<string,array<scalar>|scalar>>
*/
public function getConstantsMap()
{
return $this->_constantsMap;
}
/**
* Get the default matcher for a given class
*
* @param class-string $class
*
* @return null|class-string
*/
public function getDefaultMatcher($class)
{
$classes = [];
$parentClass = $class;
do {
$classes[] = $parentClass;
$parentClass = get_parent_class($parentClass);
} while ($parentClass !== false);
$classesAndInterfaces = array_merge($classes, class_implements($class));
foreach ($classesAndInterfaces as $type) {
if (array_key_exists($type, $this->_defaultMatchers)) {
return $this->_defaultMatchers[$type];
}
}
return null;
}
/**
* Get the parameter map of an internal PHP class method
*
* @param class-string $class
* @param string $method
*
* @return null|array
*/
public function getInternalClassMethodParamMap($class, $method)
{
$class = strtolower($class);
$method = strtolower($method);
if (! array_key_exists($class, $this->_internalClassParamMap)) {
return null;
}
if (! array_key_exists($method, $this->_internalClassParamMap[$class])) {
return null;
}
return $this->_internalClassParamMap[$class][$method];
}
/**
* Get the parameter maps of internal PHP classes
*
* @return array<class-string,array<string,list<string>>>
*/
public function getInternalClassMethodParamMaps()
{
return $this->_internalClassParamMap;
}
/**
* Get the object formatter for a class
*
* @param class-string $class
* @param Closure $defaultFormatter
*
* @return Closure
*/
public function getObjectFormatter($class, $defaultFormatter)
{
$parentClass = $class;
do {
$classes[] = $parentClass;
$parentClass = get_parent_class($parentClass);
} while ($parentClass !== false);
$classesAndInterfaces = array_merge($classes, class_implements($class));
foreach ($classesAndInterfaces as $type) {
if (array_key_exists($type, $this->_objectFormatters)) {
return $this->_objectFormatters[$type];
}
}
return $defaultFormatter;
}
/**
* Returns the quick definitions configuration
*/
public function getQuickDefinitions(): QuickDefinitionsConfiguration
{
return $this->_quickDefinitionsConfiguration;
}
/**
* 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;
}
/**
* Return flag indicating whether mocking non-existent methods allowed
*
* @return bool
*/
public function mockingNonExistentMethodsAllowed()
{
return $this->_allowMockingNonExistentMethod;
}
/**
* Is reflection cache enabled?
*
* @return bool
*/
public function reflectionCacheEnabled()
{
return $this->_reflectionCacheEnabled;
}
/**
* Remove all overridden parameter maps from internal PHP classes.
*
* @return void
*/
public function resetInternalClassMethodParamMaps()
{
$this->_internalClassParamMap = [];
}
/**
* Set a map of constants to be used in the mock generator
*
* e.g. ['MyClass' => ['MY_CONST' => 123, 'ARRAY_CONST' => ['foo', 'bar']]]
*
* @param array<class-string,array<string,array<scalar>|scalar>> $map
*
* @return void
*/
public function setConstantsMap(array $map)
{
$this->_constantsMap = $map;
}
/**
* @param class-string $class
* @param class-string $matcherClass
*
* @throws InvalidArgumentException
*
* @return void
*/
public function setDefaultMatcher($class, $matcherClass)
{
$isHamcrest = is_a($matcherClass, Matcher::class, true)
|| is_a($matcherClass, Hamcrest_Matcher::class, true);
if ($isHamcrest) {
@trigger_error('Hamcrest package has been deprecated and will be removed in 2.0', E_USER_DEPRECATED);
}
if (! $isHamcrest && ! is_a($matcherClass, MatcherInterface::class, true)) {
throw new InvalidArgumentException(sprintf(
"Matcher class must implement %s, '%s' given.",
MatcherInterface::class,
$matcherClass
));
}
$this->_defaultMatchers[$class] = $matcherClass;
}
/**
* Set a parameter map (array of param signature strings) for the method of an internal PHP class.
*
* @param class-string $class
* @param string $method
* @param list<string> $map
*
* @throws LogicException
*
* @return void
*/
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.'
);
}
$class = strtolower($class);
if (! array_key_exists($class, $this->_internalClassParamMap)) {
$this->_internalClassParamMap[$class] = [];
}
$this->_internalClassParamMap[$class][strtolower($method)] = $map;
}
/**
* Set a custom object formatter for a class
*
* @param class-string $class
* @param Closure $formatterCallback
*
* @return void
*/
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)
{
if (!is_a($matcherClass, \Mockery\Matcher\MatcherAbstract::class, true) &&
!is_a($matcherClass, \Hamcrest\Matcher::class, true) &&
!is_a($matcherClass, \Hamcrest_Matcher::class, true)
) {
throw new \InvalidArgumentException(
"Matcher class must be either Hamcrest matcher or extend \Mockery\Matcher\MatcherAbstract, " .
"'$matcherClass' given."
);
}
$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;
}
}

View File

@@ -1,39 +1,63 @@
<?php
/**
* Mockery
* Mockery (https://docs.mockery.io/)
*
* LICENSE
*
* This source file is subject to the new BSD license that is bundled
* with this package in the file LICENSE.txt.
* It is also available through the world-wide-web at this URL:
* http://github.com/padraic/mockery/blob/master/LICENSE
* If you did not receive a copy of the license and are unable to
* obtain it through the world-wide-web, please send an email
* to padraic@php.net so we can send you a copy immediately.
*
* @category Mockery
* @package Mockery
* @copyright Copyright (c) 2010 Pádraic Brady (http://blog.astrumfutura.com)
* @license http://github.com/padraic/mockery/blob/master/LICENSE New BSD License
* @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 Exception as PHPException;
use Mockery;
use Mockery\Exception\InvalidOrderException;
use Mockery\Exception\RuntimeException;
use Mockery\Generator\Generator;
use Mockery\Generator\MockConfigurationBuilder;
use Mockery\Loader\Loader as LoaderInterface;
use ReflectionClass;
use ReflectionException;
use Throwable;
use function array_filter;
use function array_key_exists;
use function array_keys;
use function array_pop;
use function array_shift;
use function array_values;
use function class_exists;
use function count;
use function explode;
use function get_class;
use function interface_exists;
use function is_callable;
use function is_object;
use function is_string;
use function md5;
use function preg_grep;
use function preg_match;
use function range;
use function reset;
use function rtrim;
use function sprintf;
use function str_replace;
use function strlen;
use function strpos;
use function strtolower;
use function substr;
use function trait_exists;
/**
* Container for mock objects
*
* @template TMockObject of object
*/
class Container
{
const BLOCKS = \Mockery::BLOCKS;
/**
* Store of mock objects
*
* @var array
*/
protected $_mocks = array();
public const BLOCKS = Mockery::BLOCKS;
/**
* Order number of allocation
@@ -49,32 +73,136 @@ class Container
*/
protected $_currentOrder = 0;
/**
* Ordered groups
*
* @var array
*/
protected $_groups = array();
/**
* @var Generator
*/
protected $_generator;
/**
* Ordered groups
*
* @var array<string,int>
*/
protected $_groups = [];
/**
* @var LoaderInterface
*/
protected $_loader;
/**
* @var array
* Store of mock objects
*
* @var array<class-string<LegacyMockInterface&MockInterface&TMockObject>|array-key,LegacyMockInterface&MockInterface&TMockObject>
*/
protected $_namedMocks = array();
protected $_mocks = [];
public function __construct(Generator $generator = null, LoaderInterface $loader = null)
/**
* @var array<string,string>
*/
protected $_namedMocks = [];
/**
* @var Instantiator
*/
protected $instantiator;
public function __construct(?Generator $generator = null, ?LoaderInterface $loader = null, ?Instantiator $instantiator = null)
{
$this->_generator = $generator ?: \Mockery::getDefaultGenerator();
$this->_loader = $loader ?: \Mockery::getDefaultLoader();
$this->_generator = $generator instanceof Generator ? $generator : Mockery::getDefaultGenerator();
$this->_loader = $loader instanceof LoaderInterface ? $loader : Mockery::getDefaultLoader();
$this->instantiator = $instantiator instanceof Instantiator ? $instantiator : new Instantiator();
}
/**
* Return a specific remembered mock according to the array index it
* was stored to in this container instance
*
* @template TMock of object
*
* @param class-string<TMock> $reference
*
* @return null|(LegacyMockInterface&MockInterface&TMock)
*/
public function fetchMock($reference)
{
return $this->_mocks[$reference] ?? null;
}
/**
* @return Generator
*/
public function getGenerator()
{
return $this->_generator;
}
/**
* @param string $method
* @param string $parent
*
* @return null|string
*/
public function getKeyOfDemeterMockFor($method, $parent)
{
$keys = array_keys($this->_mocks);
$match = preg_grep('/__demeter_' . md5($parent) . sprintf('_%s$/', $method), $keys);
if ($match === false) {
return null;
}
if ($match === []) {
return null;
}
return array_values($match)[0];
}
/**
* @return LoaderInterface
*/
public function getLoader()
{
return $this->_loader;
}
/**
* @template TMock of object
* @return array<class-string<LegacyMockInterface&MockInterface&TMockObject>|array-key,LegacyMockInterface&MockInterface&TMockObject>
*/
public function getMocks()
{
return $this->_mocks;
}
/**
* @return void
*/
public function instanceMock()
{
}
/**
* see http://php.net/manual/en/language.oop5.basic.php
*
* @param string $className
*
* @return bool
*/
public function isValidClassName($className)
{
if ($className[0] === '\\') {
$className = substr($className, 1); // remove the first backslash
}
// all the namespaces and class name should match the regex
return array_filter(
explode('\\', $className),
static function ($name): bool {
return ! preg_match('/^[a-zA-Z_\x7f-\xff][a-zA-Z0-9_\x7f-\xff]*$/', $name);
}
) === [];
}
/**
@@ -85,119 +213,179 @@ class Container
* 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
* @template TMock of object
*
* @return Mock
* @throws Exception\RuntimeException
* @param array<class-string<TMock>|TMock|Closure(LegacyMockInterface&MockInterface&TMock):LegacyMockInterface&MockInterface&TMock|array<TMock>> $args
*
* @throws ReflectionException|RuntimeException
*
* @return LegacyMockInterface&MockInterface&TMock
*/
public function mock(...$args)
{
/** @var null|MockConfigurationBuilder $builder */
$builder = null;
/** @var null|callable $expectationClosure */
$expectationClosure = null;
$quickdefs = array();
$partialMethods = null;
$quickDefinitions = [];
$constructorArgs = null;
$blocks = array();
$class = null;
$blocks = [];
if (count($args) > 1) {
$finalArg = end($args);
reset($args);
$finalArg = array_pop($args);
if (is_callable($finalArg) && is_object($finalArg)) {
$expectationClosure = array_pop($args);
$expectationClosure = $finalArg;
} else {
$args[] = $finalArg;
}
}
$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());
$builder = $builder ?? new MockConfigurationBuilder();
$mockeryConfiguration = Mockery::getConfiguration();
$builder->setParameterOverrides($mockeryConfiguration->getInternalClassMethodParamMaps());
$builder->setConstantsMap($mockeryConfiguration->getConstantsMap());
while (count($args) > 0) {
while ($args !== []) {
$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, ']')) {
continue;
}
if (strpos($type, ',') && !strpos($type, ']')) {
$interfaces = explode(',', str_replace(' ', '', $type));
$builder->addTargets($interfaces);
} elseif (substr($type, 0, 6) == 'alias:') {
continue;
}
if (strpos($type, 'alias:') === 0) {
$type = str_replace('alias:', '', $type);
$builder->addTarget('stdClass');
$builder->setName($type);
} elseif (substr($type, 0, 9) == 'overload:') {
continue;
}
if (strpos($type, 'overload:') === 0) {
$type = str_replace('overload:', '', $type);
$builder->setInstanceMock(true);
$builder->addTarget('stdClass');
$builder->setName($type);
} elseif (substr($type, strlen($type)-1, 1) == ']') {
continue;
}
if ($type[strlen($type) - 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], ']'))));
if (! class_exists($class, true) && ! interface_exists($class, true)) {
throw new Exception('Can only create a partial mock from an existing class or interface');
}
$builder->addTarget($class);
$partialMethods = array_filter(
explode(',', strtolower(rtrim(str_replace(' ', '', $parts[1]), ']')))
);
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);
continue;
}
break; // unions are "sum" types and not "intersections", and so we must only process the first part
if (class_exists($type, true) || interface_exists($type, true) || trait_exists($type, true)) {
$builder->addTarget($type);
continue;
}
if (! $mockeryConfiguration->mockingNonExistentMethodsAllowed()) {
throw new Exception(sprintf("Mockery can't find '%s' so can't mock it", $type));
}
if (! $this->isValidClassName($type)) {
throw new Exception('Class name contains invalid characters');
}
$builder->addTarget($type);
// unions are "sum" types and not "intersections", and so we must only process the first part
break;
}
} elseif (is_object($arg)) {
continue;
}
if (is_object($arg)) {
$builder->addTarget($arg);
} elseif (is_array($arg)) {
if (!empty($arg) && array_keys($arg) !== range(0, count($arg) - 1)) {
continue;
}
if (is_array($arg)) {
if ([] !== $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;
$quickDefinitions = $arg;
continue;
}
} else {
throw new \Mockery\Exception(
'Unable to parse arguments sent to '
. get_class($this) . '::mock()'
);
$constructorArgs = $arg;
continue;
}
throw new Exception(sprintf(
'Unable to parse arguments sent to %s::mock()', get_class($this)
));
}
$builder->addBlackListedMethods($blocks);
if (!is_null($constructorArgs)) {
$builder->addBlackListedMethod("__construct"); // we need to pass through
if ($constructorArgs !== null) {
$builder->addBlackListedMethod('__construct'); // we need to pass through
} else {
$builder->setMockOriginalDestructor(true);
}
if (!empty($partialMethods) && $constructorArgs === null) {
$constructorArgs = array();
if ($partialMethods !== null && $constructorArgs === null) {
$constructorArgs = [];
}
$config = $builder->getMockConfiguration();
@@ -206,114 +394,44 @@ class Container
$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");
$className = $def->getClassName();
if (class_exists($className, $attemptAutoload = false)) {
$rfc = new ReflectionClass($className);
if (! $rfc->implementsInterface(LegacyMockInterface::class)) {
throw new RuntimeException(sprintf('Could not load mock %s, class already exists', $className));
}
}
$this->getLoader()->load($def);
$mock = $this->_getInstance($def->getClassName(), $constructorArgs);
$mock = $this->_getInstance($className, $constructorArgs);
$mock->mockery_init($this, $config->getTargetObject(), $config->isInstanceMock());
if (!empty($quickdefs)) {
if (\Mockery::getConfiguration()->getQuickDefinitions()->shouldBeCalledAtLeastOnce()) {
$mock->shouldReceive($quickdefs)->atLeast()->once();
if ($quickDefinitions !== []) {
if ($mockeryConfiguration->getQuickDefinitions()->shouldBeCalledAtLeastOnce()) {
$mock->shouldReceive($quickDefinitions)->atLeast()->once();
} else {
$mock->shouldReceive($quickdefs)->byDefault();
$mock->shouldReceive($quickDefinitions)->byDefault();
}
}
if (!empty($expectationClosure)) {
// if the last parameter passed to mock() is a closure,
if ($expectationClosure instanceof Closure) {
// call the closure with the mock object
$expectationClosure($mock);
}
$this->rememberMock($mock);
return $mock;
}
public function instanceMock()
{
}
public function getLoader()
{
return $this->_loader;
}
public function getGenerator()
{
return $this->_generator;
return $this->rememberMock($mock);
}
/**
* @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
* Fetch the next available allocation order number
*
* @throws \Exception
* @return void
* @return int
*/
public function mockery_teardown()
public function mockery_allocateOrder()
{
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;
return ++$this->_allocatedOrder;
}
/**
@@ -326,51 +444,8 @@ class Container
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;
$this->_mocks = [];
}
/**
@@ -383,30 +458,6 @@ class Container
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
*
@@ -418,36 +469,151 @@ class Container
foreach ($this->_mocks as $mock) {
$count += $mock->mockery_getExpectationCount();
}
return $count;
}
/**
* Fetch array of ordered groups
*
* @return array<string,int>
*/
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)
{
return $this->_currentOrder = $order;
}
/**
* Set ordering for a group
*
* @param string $group
* @param int $order
*
* @return void
*/
public function mockery_setGroup($group, $order)
{
$this->_groups[$group] = $order;
}
/**
* Tear down tasks for this container
*
* @throws PHPException
*/
public function mockery_teardown()
{
try {
$this->mockery_verify();
} catch (PHPException $phpException) {
$this->mockery_close();
throw $phpException;
}
}
/**
* Retrieves all exceptions thrown by mocks
*
* @return array<Throwable>
*/
public function mockery_thrownExceptions()
{
/** @var array<Throwable> $exceptions */
$exceptions = [];
foreach ($this->_mocks as $mock) {
foreach ($mock->mockery_thrownExceptions() as $exception) {
$exceptions[] = $exception;
}
}
return $exceptions;
}
/**
* Validate the current mock's ordering
*
* @param string $method
* @param int $order
*
* @throws Exception
*/
public function mockery_validateOrder($method, $order, LegacyMockInterface $mock)
{
if ($order < $this->_currentOrder) {
$exception = new InvalidOrderException(
sprintf(
'Method %s called out of order: expected order %d, was %d',
$method,
$order,
$this->_currentOrder
)
);
$exception->setMock($mock)
->setMethodName($method)
->setExpectedOrder($order)
->setActualOrder($this->_currentOrder);
throw $exception;
}
$this->mockery_setCurrentOrder($order);
}
/**
* Verify the container mocks
*/
public function mockery_verify()
{
foreach ($this->_mocks as $mock) {
$mock->mockery_verify();
}
}
/**
* Store a mock and set its container reference
*
* @param \Mockery\Mock $mock
* @return \Mockery\LegacyMockInterface|\Mockery\MockInterface
* @template TRememberMock of object
*
* @param LegacyMockInterface&MockInterface&TRememberMock $mock
*
* @return LegacyMockInterface&MockInterface&TRememberMock
*/
public function rememberMock(\Mockery\LegacyMockInterface $mock)
public function rememberMock(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;
$class = get_class($mock);
if (! array_key_exists($class, $this->_mocks)) {
return $this->_mocks[$class] = $mock;
}
return $mock;
/**
* This condition triggers for an instance mock where origin mock
* is already remembered
*/
return $this->_mocks[] = $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.
* 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 used during the programming of the same mock.
*
* @return \Mockery\Mock
* @return LegacyMockInterface|MockInterface
*/
public function self()
{
@@ -457,35 +623,32 @@ class Container
}
/**
* Return a specific remembered mock according to the array index it
* was stored to in this container instance
* @template TMock of object
* @template TMixed
*
* @return \Mockery\Mock
* @param class-string<TMock> $mockName
* @param null|array<TMixed> $constructorArgs
*
* @return TMock
*/
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);
return (new ReflectionClass($mockName))->newInstanceArgs($constructorArgs);
}
try {
$instantiator = new Instantiator();
$instance = $instantiator->instantiate($mockName);
} catch (\Exception $ex) {
$instance = $this->instantiator->instantiate($mockName);
} catch (PHPException $phpException) {
/** @var class-string<TMock> $internalMockName */
$internalMockName = $mockName . '_Internal';
if (!class_exists($internalMockName)) {
eval("class $internalMockName extends $mockName {" .
'public function __construct() {}' .
'}');
if (! class_exists($internalMockName)) {
eval(sprintf(
'class %s extends %s { public function __construct() {} }',
$internalMockName,
$mockName
));
}
$instance = new $internalMockName();
@@ -498,38 +661,18 @@ class Container
{
$name = $config->getName();
if (!$name) {
if ($name === null) {
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"
);
}
if (array_key_exists($name, $this->_namedMocks) && $hash !== $this->_namedMocks[$name]) {
throw new Exception(
sprintf("The mock named '%s' has been already defined with a different mock configuration", $name)
);
}
$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);
}
}

View File

@@ -1,26 +1,18 @@
<?php
/**
* Mockery
* Mockery (https://docs.mockery.io/)
*
* LICENSE
*
* This source file is subject to the new BSD license that is bundled
* with this package in the file LICENSE.txt.
* It is also available through the world-wide-web at this URL:
* http://github.com/padraic/mockery/blob/master/LICENSE
* If you did not receive a copy of the license and are unable to
* obtain it through the world-wide-web, please send an email
* to padraic@php.net so we can send you a copy immediately.
*
* @category Mockery
* @package Mockery
* @copyright Copyright (c) 2010 Pádraic Brady (http://blog.astrumfutura.com)
* @license http://github.com/padraic/mockery/blob/master/LICENSE New BSD License
* @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;
use Mockery\Exception\InvalidCountException;
use const PHP_EOL;
class AtLeast extends CountValidatorAbstract
{
@@ -28,6 +20,7 @@ class AtLeast extends CountValidatorAbstract
* Checks if the validator can accept an additional nth call
*
* @param int $n
*
* @return bool
*/
public function isEligible($n)
@@ -39,18 +32,21 @@ class AtLeast extends CountValidatorAbstract
* Validate the call count against this validator
*
* @param int $n
*
* @throws InvalidCountException
* @return bool
*/
public function validate($n)
{
if ($this->_limit > $n) {
$exception = new Mockery\Exception\InvalidCountException(
$exception = new 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('>=')

View File

@@ -1,26 +1,18 @@
<?php
/**
* Mockery
* Mockery (https://docs.mockery.io/)
*
* LICENSE
*
* This source file is subject to the new BSD license that is bundled
* with this package in the file LICENSE.txt.
* It is also available through the world-wide-web at this URL:
* http://github.com/padraic/mockery/blob/master/LICENSE
* If you did not receive a copy of the license and are unable to
* obtain it through the world-wide-web, please send an email
* to padraic@php.net so we can send you a copy immediately.
*
* @category Mockery
* @package Mockery
* @copyright Copyright (c) 2010 Pádraic Brady (http://blog.astrumfutura.com)
* @license http://github.com/padraic/mockery/blob/master/LICENSE New BSD License
* @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;
use Mockery\Exception\InvalidCountException;
use const PHP_EOL;
class AtMost extends CountValidatorAbstract
{
@@ -28,12 +20,14 @@ class AtMost extends CountValidatorAbstract
* Validate the call count against this validator
*
* @param int $n
*
* @throws InvalidCountException
* @return bool
*/
public function validate($n)
{
if ($this->_limit < $n) {
$exception = new Mockery\Exception\InvalidCountException(
$exception = new InvalidCountException(
'Method ' . (string) $this->_expectation
. ' from ' . $this->_expectation->getMock()->mockery_getName()
. ' should be called' . PHP_EOL

View File

@@ -1,31 +1,23 @@
<?php
/**
* Mockery
* Mockery (https://docs.mockery.io/)
*
* LICENSE
*
* This source file is subject to the new BSD license that is bundled
* with this package in the file LICENSE.txt.
* It is also available through the world-wide-web at this URL:
* http://github.com/padraic/mockery/blob/master/LICENSE
* If you did not receive a copy of the license and are unable to
* obtain it through the world-wide-web, please send an email
* to padraic@php.net so we can send you a copy immediately.
*
* @category Mockery
* @package Mockery
* @copyright Copyright (c) 2010 Pádraic Brady (http://blog.astrumfutura.com)
* @license http://github.com/padraic/mockery/blob/master/LICENSE New BSD License
* @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
use Mockery\Expectation;
abstract class CountValidatorAbstract implements CountValidatorInterface
{
/**
* Expectation for which this validator is assigned
*
* @var \Mockery\Expectation
* @var Expectation
*/
protected $_expectation = null;
@@ -39,10 +31,9 @@ abstract class CountValidatorAbstract
/**
* Set Expectation object and upper call limit
*
* @param \Mockery\Expectation $expectation
* @param int $limit
*/
public function __construct(\Mockery\Expectation $expectation, $limit)
public function __construct(Expectation $expectation, $limit)
{
$this->_expectation = $expectation;
$this->_limit = $limit;
@@ -52,17 +43,19 @@ abstract class CountValidatorAbstract
* Checks if the validator can accept an additional nth call
*
* @param int $n
*
* @return bool
*/
public function isEligible($n)
{
return ($n < $this->_limit);
return $n < $this->_limit;
}
/**
* Validate the call count against this validator
*
* @param int $n
*
* @return bool
*/
abstract public function validate($n);

View File

@@ -1,26 +1,18 @@
<?php
/**
* Mockery
* Mockery (https://docs.mockery.io/)
*
* LICENSE
*
* This source file is subject to the new BSD license that is bundled
* with this package in the file LICENSE.txt.
* It is also available through the world-wide-web at this URL:
* http://github.com/padraic/mockery/blob/master/LICENSE
* If you did not receive a copy of the license and are unable to
* obtain it through the world-wide-web, please send an email
* to padraic@php.net so we can send you a copy immediately.
*
* @category Mockery
* @package Mockery
* @copyright Copyright (c) 2010 Pádraic Brady (http://blog.astrumfutura.com)
* @license http://github.com/padraic/mockery/blob/master/LICENSE New BSD License
* @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;
use Mockery\Exception\InvalidCountException;
use const PHP_EOL;
class Exact extends CountValidatorAbstract
{
@@ -28,6 +20,8 @@ class Exact extends CountValidatorAbstract
* Validate the call count against this validator
*
* @param int $n
*
* @throws InvalidCountException
* @return bool
*/
public function validate($n)
@@ -35,7 +29,7 @@ class Exact extends CountValidatorAbstract
if ($this->_limit !== $n) {
$because = $this->_expectation->getExceptionMessage();
$exception = new Mockery\Exception\InvalidCountException(
$exception = new InvalidCountException(
'Method ' . (string) $this->_expectation
. ' from ' . $this->_expectation->getMock()->mockery_getName()
. ' should be called' . PHP_EOL

View File

@@ -1,25 +1,18 @@
<?php
/**
* Mockery
* Mockery (https://docs.mockery.io/)
*
* LICENSE
*
* This source file is subject to the new BSD license that is bundled
* with this package in the file LICENSE.txt.
* It is also available through the world-wide-web at this URL:
* http://github.com/padraic/mockery/blob/master/LICENSE
* If you did not receive a copy of the license and are unable to
* obtain it through the world-wide-web, please send an email
* to padraic@php.net so we can send you a copy immediately.
*
* @category Mockery
* @package Mockery
* @copyright Copyright (c) 2010 Pádraic Brady (http://blog.astrumfutura.com)
* @license http://github.com/padraic/mockery/blob/master/LICENSE New BSD License
* @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;
class Exception extends \OutOfBoundsException
use Mockery\Exception\MockeryExceptionInterface;
use OutOfBoundsException;
class Exception extends OutOfBoundsException implements MockeryExceptionInterface
{
}

View File

@@ -1,25 +1,18 @@
<?php
/**
* Mockery
* Mockery (https://docs.mockery.io/)
*
* LICENSE
*
* This source file is subject to the new BSD license that is bundled
* with this package in the file LICENSE.txt.
* It is also available through the world-wide-web at this URL:
* http://github.com/padraic/mockery/blob/master/LICENSE
* If you did not receive a copy of the license and are unable to
* obtain it through the world-wide-web, please send an email
* to padraic@php.net so we can send you a copy immediately.
*
* @category Mockery
* @package Mockery
* @copyright Copyright (c) 2010 Pádraic Brady (http://blog.astrumfutura.com)
* @license http://github.com/padraic/mockery/blob/master/LICENSE New BSD License
* @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 Exception extends \UnexpectedValueException
use Mockery\Exception\MockeryExceptionInterface;
use UnexpectedValueException;
class Exception extends UnexpectedValueException implements MockeryExceptionInterface
{
}

View File

@@ -1,21 +1,37 @@
<?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
class BadMethodCallException extends \BadMethodCallException implements MockeryExceptionInterface
{
/**
* @var bool
*/
private $dismissed = false;
public function dismiss()
{
$this->dismissed = true;
// we sometimes stack them
if ($this->getPrevious() && $this->getPrevious() instanceof BadMethodCallException) {
$this->getPrevious()->dismiss();
$previous = $this->getPrevious();
if (! $previous instanceof self) {
return;
}
$previous->dismiss();
}
/**
* @return bool
*/
public function dismissed()
{
return $this->dismissed;

View File

@@ -1,25 +1,15 @@
<?php
/**
* Mockery
* Mockery (https://docs.mockery.io/)
*
* LICENSE
*
* This source file is subject to the new BSD license that is bundled
* with this package in the file LICENSE.txt.
* It is also available through the world-wide-web at this URL:
* http://github.com/padraic/mockery/blob/master/LICENSE
* If you did not receive a copy of the license and are unable to
* obtain it through the world-wide-web, please send an email
* to padraic@php.net so we can send you a copy immediately.
*
* @category Mockery
* @package Mockery
* @copyright Copyright (c) 2010 Pádraic Brady (http://blog.astrumfutura.com)
* @license http://github.com/padraic/mockery/blob/master/LICENSE New BSD License
* @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
class InvalidArgumentException extends \InvalidArgumentException implements MockeryExceptionInterface
{
}

View File

@@ -1,102 +1,152 @@
<?php
/**
* Mockery
* Mockery (https://docs.mockery.io/)
*
* LICENSE
*
* This source file is subject to the new BSD license that is bundled
* with this package in the file LICENSE.txt.
* It is also available through the world-wide-web at this URL:
* http://github.com/padraic/mockery/blob/master/LICENSE
* If you did not receive a copy of the license and are unable to
* obtain it through the world-wide-web, please send an email
* to padraic@php.net so we can send you a copy immediately.
*
* @category Mockery
* @package Mockery
* @copyright Copyright (c) 2010 Pádraic Brady (http://blog.astrumfutura.com)
* @license http://github.com/padraic/mockery/blob/master/LICENSE New BSD License
* @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;
use Mockery\CountValidator\Exception;
use Mockery\LegacyMockInterface;
class InvalidCountException extends Mockery\CountValidator\Exception
use function in_array;
class InvalidCountException extends Exception
{
protected $method = null;
protected $expected = 0;
protected $expectedComparative = '<=';
/**
* @var int|null
*/
protected $actual = null;
/**
* @var int
*/
protected $expected = 0;
/**
* @var string
*/
protected $expectedComparative = '<=';
/**
* @var string|null
*/
protected $method = null;
/**
* @var LegacyMockInterface|null
*/
protected $mockObject = null;
public function setMock(Mockery\LegacyMockInterface $mock)
/**
* @return int|null
*/
public function getActualCount()
{
$this->mockObject = $mock;
return $this;
return $this->actual;
}
public function setMethodName($name)
/**
* @return int
*/
public function getExpectedCount()
{
$this->method = $name;
return $this;
return $this->expected;
}
/**
* @return string
*/
public function getExpectedCountComparative()
{
return $this->expectedComparative;
}
/**
* @return string|null
*/
public function getMethodName()
{
return $this->method;
}
/**
* @return LegacyMockInterface|null
*/
public function getMock()
{
return $this->mockObject;
}
/**
* @throws RuntimeException
* @return string|null
*/
public function getMockName()
{
$mock = $this->getMock();
if ($mock === null) {
return '';
}
return $mock->mockery_getName();
}
/**
* @param int $count
* @return self
*/
public function setActualCount($count)
{
$this->actual = $count;
return $this;
}
/**
* @param int $count
* @return self
*/
public function setExpectedCount($count)
{
$this->expected = $count;
return $this;
}
/**
* @param string $comp
* @return self
*/
public function setExpectedCountComparative($comp)
{
if (!in_array($comp, array('=', '>', '<', '>=', '<='))) {
throw new RuntimeException(
'Illegal comparative for expected call counts set: ' . $comp
);
if (! in_array($comp, ['=', '>', '<', '>=', '<='], true)) {
throw new RuntimeException('Illegal comparative for expected call counts set: ' . $comp);
}
$this->expectedComparative = $comp;
return $this;
}
public function getMock()
/**
* @param string $name
* @return self
*/
public function setMethodName($name)
{
return $this->mockObject;
$this->method = $name;
return $this;
}
public function getMethodName()
/**
* @return self
*/
public function setMock(LegacyMockInterface $mock)
{
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;
$this->mockObject = $mock;
return $this;
}
}

View File

@@ -1,83 +1,125 @@
<?php
/**
* Mockery
* Mockery (https://docs.mockery.io/)
*
* LICENSE
*
* This source file is subject to the new BSD license that is bundled
* with this package in the file LICENSE.txt.
* It is also available through the world-wide-web at this URL:
* http://github.com/padraic/mockery/blob/master/LICENSE
* If you did not receive a copy of the license and are unable to
* obtain it through the world-wide-web, please send an email
* to padraic@php.net so we can send you a copy immediately.
*
* @category Mockery
* @package Mockery
* @copyright Copyright (c) 2010 Pádraic Brady (http://blog.astrumfutura.com)
* @license http://github.com/padraic/mockery/blob/master/LICENSE New BSD License
* @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;
use Mockery\LegacyMockInterface;
class InvalidOrderException extends Mockery\Exception
class InvalidOrderException extends Exception
{
protected $method = null;
protected $expected = 0;
/**
* @var int|null
*/
protected $actual = null;
/**
* @var int
*/
protected $expected = 0;
/**
* @var string|null
*/
protected $method = null;
/**
* @var LegacyMockInterface|null
*/
protected $mockObject = null;
public function setMock(Mockery\LegacyMockInterface $mock)
/**
* @return int|null
*/
public function getActualOrder()
{
$this->mockObject = $mock;
return $this;
return $this->actual;
}
public function setMethodName($name)
/**
* @return int
*/
public function getExpectedOrder()
{
$this->method = $name;
return $this;
return $this->expected;
}
/**
* @return string|null
*/
public function getMethodName()
{
return $this->method;
}
/**
* @return LegacyMockInterface|null
*/
public function getMock()
{
return $this->mockObject;
}
/**
* @return string|null
*/
public function getMockName()
{
$mock = $this->getMock();
if ($mock === null) {
return $mock;
}
return $mock->mockery_getName();
}
/**
* @param int $count
*
* @return self
*/
public function setActualOrder($count)
{
$this->actual = $count;
return $this;
}
/**
* @param int $count
*
* @return self
*/
public function setExpectedOrder($count)
{
$this->expected = $count;
return $this;
}
public function getMock()
/**
* @param string $name
*
* @return self
*/
public function setMethodName($name)
{
return $this->mockObject;
$this->method = $name;
return $this;
}
public function getMethodName()
/**
* @return self
*/
public function setMock(LegacyMockInterface $mock)
{
return $this->method;
}
public function getActualOrder()
{
return $this->actual;
}
public function getExpectedOrder()
{
return $this->expected;
}
public function getMockName()
{
return $this->getMock()->mockery_getName();
$this->mockObject = $mock;
return $this;
}
}

View File

@@ -1,70 +1,102 @@
<?php
/**
* Mockery
* Mockery (https://docs.mockery.io/)
*
* LICENSE
*
* This source file is subject to the new BSD license that is bundled
* with this package in the file LICENSE.txt.
* It is also available through the world-wide-web at this URL:
* http://github.com/padraic/mockery/blob/master/LICENSE
* If you did not receive a copy of the license and are unable to
* obtain it through the world-wide-web, please send an email
* to padraic@php.net so we can send you a copy immediately.
*
* @category Mockery
* @package Mockery
* @copyright Copyright (c) 2010 Pádraic Brady (http://blog.astrumfutura.com)
* @license http://github.com/padraic/mockery/blob/master/LICENSE New BSD License
* @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;
use Mockery\LegacyMockInterface;
class NoMatchingExpectationException extends Mockery\Exception
class NoMatchingExpectationException extends Exception
{
/**
* @var array<mixed>
*/
protected $actual = [];
/**
* @var string|null
*/
protected $method = null;
protected $actual = array();
/**
* @var LegacyMockInterface|null
*/
protected $mockObject = null;
public function setMock(Mockery\LegacyMockInterface $mock)
/**
* @return array<mixed>
*/
public function getActualArguments()
{
$this->mockObject = $mock;
return $this;
return $this->actual;
}
public function setMethodName($name)
/**
* @return string|null
*/
public function getMethodName()
{
$this->method = $name;
return $this;
return $this->method;
}
/**
* @return LegacyMockInterface|null
*/
public function getMock()
{
return $this->mockObject;
}
/**
* @return string|null
*/
public function getMockName()
{
$mock = $this->getMock();
if ($mock === null) {
return $mock;
}
return $mock->mockery_getName();
}
/**
* @todo Rename param `count` to `args`
* @template TMixed
*
* @param array<TMixed> $count
* @return self
*/
public function setActualArguments($count)
{
$this->actual = $count;
return $this;
}
public function getMock()
/**
* @param string $name
* @return self
*/
public function setMethodName($name)
{
return $this->mockObject;
$this->method = $name;
return $this;
}
public function getMethodName()
/**
* @return self
*/
public function setMock(LegacyMockInterface $mock)
{
return $this->method;
}
public function getActualArguments()
{
return $this->actual;
}
public function getMockName()
{
return $this->getMock()->mockery_getName();
$this->mockObject = $mock;
return $this;
}
}

View File

@@ -1,25 +1,17 @@
<?php
/**
* Mockery
* Mockery (https://docs.mockery.io/)
*
* LICENSE
*
* This source file is subject to the new BSD license that is bundled
* with this package in the file LICENSE.txt.
* It is also available through the world-wide-web at this URL:
* http://github.com/padraic/mockery/blob/master/LICENSE
* If you did not receive a copy of the license and are unable to
* obtain it through the world-wide-web, please send an email
* to padraic@php.net so we can send you a copy immediately.
*
* @category Mockery
* @package Mockery
* @copyright Copyright (c) 2010 Pádraic Brady (http://blog.astrumfutura.com)
* @license http://github.com/padraic/mockery/blob/master/LICENSE New BSD License
* @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
use Exception;
class RuntimeException extends Exception implements MockeryExceptionInterface
{
}

File diff suppressed because it is too large Load Diff

View File

@@ -1,47 +1,39 @@
<?php
/**
* Mockery
* Mockery (https://docs.mockery.io/)
*
* LICENSE
*
* This source file is subject to the new BSD license that is bundled
* with this package in the file LICENSE.txt.
* It is also available through the world-wide-web at this URL:
* http://github.com/padraic/mockery/blob/master/LICENSE
* If you did not receive a copy of the license and are unable to
* obtain it through the world-wide-web, please send an email
* to padraic@php.net so we can send you a copy immediately.
*
* @category Mockery
* @package Mockery
* @copyright Copyright (c) 2010 Pádraic Brady (http://blog.astrumfutura.com)
* @license http://github.com/padraic/mockery/blob/master/LICENSE New BSD License
* @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;
use Mockery\Exception\NoMatchingExpectationException;
use function array_pop;
use function array_unshift;
use function end;
use const PHP_EOL;
class ExpectationDirector
{
/**
* Method name the director is directing
* Stores an array of all default expectations for this mock
*
* @var string
* @var list<ExpectationInterface>
*/
protected $_name = null;
/**
* Mock object the director is attached to
*
* @var \Mockery\MockInterface|\Mockery\LegacyMockInterface
*/
protected $_mock = null;
protected $_defaults = [];
/**
* Stores an array of all expectations for this mock
*
* @var array
* @var list<ExpectationInterface>
*/
protected $_expectations = array();
protected $_expectations = [];
/**
* The expected order of next call
@@ -51,19 +43,25 @@ class ExpectationDirector
protected $_expectedOrder = null;
/**
* Stores an array of all default expectations for this mock
* Mock object the director is attached to
*
* @var array
* @var LegacyMockInterface|MockInterface
*/
protected $_defaults = array();
protected $_mock = null;
/**
* Method name the director is directing
*
* @var string
*/
protected $_name = null;
/**
* Constructor
*
* @param string $name
* @param \Mockery\LegacyMockInterface $mock
*/
public function __construct($name, \Mockery\LegacyMockInterface $mock)
public function __construct($name, LegacyMockInterface $mock)
{
$this->_name = $name;
$this->_mock = $mock;
@@ -71,10 +69,8 @@ class ExpectationDirector
/**
* Add a new expectation to the director
*
* @param \Mockery\Expectation $expectation
*/
public function addExpectation(\Mockery\Expectation $expectation)
public function addExpectation(Expectation $expectation)
{
$this->_expectations[] = $expectation;
}
@@ -82,124 +78,56 @@ class ExpectationDirector
/**
* 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;
if ($expectation !== null) {
return $expectation->verifyCall($args);
}
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();
}
}
$exception = new 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;
}
/**
* 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)) {
if ($this->_expectations !== []) {
$expectation = $this->_findExpectationIn($this->_expectations, $args);
}
if ($expectation === null && !empty($this->_defaults)) {
$expectation = $this->_findExpectationIn($this->_defaults, $args);
if ($expectation === null && $this->_defaults !== []) {
return $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
* @return array<ExpectationInterface>
*/
public function getDefaultExpectations()
{
@@ -213,6 +141,102 @@ class ExpectationDirector
*/
public function getExpectationCount()
{
return count($this->getExpectations()) ?: count($this->getDefaultExpectations());
$count = 0;
$expectations = $this->getExpectations();
if ($expectations === []) {
$expectations = $this->getDefaultExpectations();
}
foreach ($expectations as $expectation) {
if ($expectation->isCallCountConstrained()) {
++$count;
}
}
return $count;
}
/**
* Return all expectations assigned to this director
*
* @return array<ExpectationInterface>
*/
public function getExpectations()
{
return $this->_expectations;
}
/**
* Make the given expectation a default for all others assuming it was correctly created last
*
* @throws Exception
*
* @return void
*/
public function makeExpectationDefault(Expectation $expectation)
{
if (end($this->_expectations) === $expectation) {
array_pop($this->_expectations);
array_unshift($this->_defaults, $expectation);
return;
}
throw new Exception('Cannot turn a previously defined expectation into a default');
}
/**
* Verify all expectations of the director
*
* @throws Exception
*
* @return void
*/
public function verify()
{
if ($this->_expectations !== []) {
foreach ($this->_expectations as $expectation) {
$expectation->verify();
}
return;
}
foreach ($this->_defaults as $expectation) {
$expectation->verify();
}
}
/**
* Search current array of expectations for a match
*
* @param array<ExpectationInterface> $expectations
*
* @return null|ExpectationInterface
*/
protected function _findExpectationIn(array $expectations, array $args)
{
foreach ($expectations as $expectation) {
if (! $expectation->isEligible()) {
continue;
}
if (! $expectation->matchArgs($args)) {
continue;
}
return $expectation;
}
foreach ($expectations as $expectation) {
if ($expectation->matchArgs($args)) {
return $expectation;
}
}
return null;
}
}

View File

@@ -1,22 +1,11 @@
<?php
/**
* Mockery
* Mockery (https://docs.mockery.io/)
*
* LICENSE
*
* This source file is subject to the new BSD license that is bundled
* with this package in the file LICENSE.txt.
* It is also available through the world-wide-web at this URL:
* http://github.com/padraic/mockery/blob/master/LICENSE
* If you did not receive a copy of the license and are unable to
* obtain it through the world-wide-web, please send an email
* to padraic@php.net so we can send you a copy immediately.
*
* @category Mockery
* @package Mockery
* @copyright Copyright (c) 2010 Pádraic Brady (http://blog.astrumfutura.com)
* @license http://github.com/padraic/mockery/blob/master/LICENSE New BSD License
* @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;
@@ -24,17 +13,10 @@ namespace Mockery;
interface ExpectationInterface
{
/**
* @return int
*/
public function getOrderNumber();
/**
* @return LegacyMockInterface|MockInterface
*/
public function getMock();
/**
* @param mixed $args
* @template TArgs
*
* @param TArgs ...$args
*
* @return self
*/
public function andReturn(...$args);
@@ -43,4 +25,14 @@ interface ExpectationInterface
* @return self
*/
public function andReturns();
/**
* @return LegacyMockInterface|MockInterface
*/
public function getMock();
/**
* @return int
*/
public function getOrderNumber();
}

View File

@@ -1,21 +1,11 @@
<?php
/**
* Mockery
* Mockery (https://docs.mockery.io/)
*
* LICENSE
*
* This source file is subject to the new BSD license that is bundled
* with this package in the file LICENSE.txt.
* It is also available through the world-wide-web at this URL:
* http://github.com/padraic/mockery/blob/master/LICENSE
* If you did not receive a copy of the license and are unable to
* obtain it through the world-wide-web, please send an email
* to padraic@php.net so we can send you a copy immediately.
*
* @category Mockery
* @package Mockery
* @copyright Copyright (c) 2010 Pádraic Brady (http://blog.astrumfutura.com)
* @license http://github.com/padraic/mockery/blob/master/LICENSE New BSD License
* @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;
@@ -24,10 +14,14 @@ class ExpectsHigherOrderMessage extends HigherOrderMessage
{
public function __construct(MockInterface $mock)
{
parent::__construct($mock, "shouldReceive");
parent::__construct($mock, 'shouldReceive');
}
/**
* @return \Mockery\Expectation
* @param string $method
* @param array $args
*
* @return Expectation|ExpectationInterface|HigherOrderMessage
*/
public function __call($method, $args)
{

View File

@@ -1,45 +1,43 @@
<?php
/**
* Mockery
* Mockery (https://docs.mockery.io/)
*
* LICENSE
*
* This source file is subject to the new BSD license that is bundled
* with this package in the file LICENSE.txt.
* It is also available through the world-wide-web at this URL:
* http://github.com/padraic/mockery/blob/master/LICENSE
* If you did not receive a copy of the license and are unable to
* obtain it through the world-wide-web, please send an email
* to padraic@php.net so we can send you a copy immediately.
*
* @category Mockery
* @package Mockery
* @copyright Copyright (c) 2010 Pádraic Brady (http://blog.astrumfutura.com)
* @license http://github.com/padraic/mockery/blob/master/LICENSE New BSD License
* @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
{
/**
* @var array<string,string>
*/
protected $cache = [];
/**
* @var Generator
*/
protected $generator;
protected $cache = array();
public function __construct(Generator $generator)
{
$this->generator = $generator;
}
/**
* @return string
*/
public function generate(MockConfiguration $config)
{
$hash = $config->getHash();
if (isset($this->cache[$hash])) {
if (array_key_exists($hash, $this->cache)) {
return $this->cache[$hash];
}
$definition = $this->generator->generate($config);
$this->cache[$hash] = $definition;
return $definition;
return $this->cache[$hash] = $this->generator->generate($config);
}
}

View File

@@ -1,96 +1,140 @@
<?php
/**
* Mockery
* Mockery (https://docs.mockery.io/)
*
* LICENSE
*
* This source file is subject to the new BSD license that is bundled
* with this package in the file LICENSE.txt.
* It is also available through the world-wide-web at this URL:
* http://github.com/padraic/mockery/blob/master/LICENSE
* If you did not receive a copy of the license and are unable to
* obtain it through the world-wide-web, please send an email
* to padraic@php.net so we can send you a copy immediately.
*
* @category Mockery
* @package Mockery
* @copyright Copyright (c) 2010 Pádraic Brady (http://blog.astrumfutura.com)
* @license http://github.com/padraic/mockery/blob/master/LICENSE New BSD License
* @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 ReflectionMethod;
use function array_map;
use function array_merge;
use function array_unique;
use const PHP_VERSION_ID;
class DefinedTargetClass implements TargetClassInterface
{
private $rfc;
/**
* @var class-string
*/
private $name;
public function __construct(\ReflectionClass $rfc, $alias = null)
/**
* @var ReflectionClass
*/
private $rfc;
/**
* @param ReflectionClass $rfc
* @param class-string|null $alias
*/
public function __construct(ReflectionClass $rfc, $alias = null)
{
$this->rfc = $rfc;
$this->name = $alias === null ? $rfc->getName() : $alias;
$this->name = $alias ?? $rfc->getName();
}
/**
* @return class-string
*/
public function __toString()
{
return $this->name;
}
/**
* @param class-string $name
* @param class-string|null $alias
* @return self
*/
public static function factory($name, $alias = null)
{
return new self(new \ReflectionClass($name), $alias);
return new self(new ReflectionClass($name), $alias);
}
/**
* @return list<class-string>
*/
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()
)
)
);
}
/**
* @return array<class-string,self>
*/
public function getInterfaces()
{
return array_map(
static function (ReflectionClass $interface): self {
return new self($interface);
},
$this->rfc->getInterfaces()
);
}
/**
* @return list<Method>
*/
public function getMethods()
{
return array_map(
static function (ReflectionMethod $method): Method {
return new Method($method);
},
$this->rfc->getMethods()
);
}
/**
* @return class-string
*/
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();
}
/**
* @return string
*/
public function getNamespaceName()
{
return $this->rfc->getNamespaceName();
}
public function inNamespace()
{
return $this->rfc->inNamespace();
}
/**
* @return string
*/
public function getShortName()
{
return $this->rfc->getShortName();
}
public function implementsInterface($interface)
{
return $this->rfc->implementsInterface($interface);
}
/**
* @return bool
*/
public function hasInternalAncestor()
{
if ($this->rfc->isInternal()) {
@@ -102,9 +146,43 @@ class DefinedTargetClass implements TargetClassInterface
if ($parent->isInternal()) {
return true;
}
$child = $parent;
}
return false;
}
/**
* @param class-string $interface
* @return bool
*/
public function implementsInterface($interface)
{
return $this->rfc->implementsInterface($interface);
}
/**
* @return bool
*/
public function inNamespace()
{
return $this->rfc->inNamespace();
}
/**
* @return bool
*/
public function isAbstract()
{
return $this->rfc->isAbstract();
}
/**
* @return bool
*/
public function isFinal()
{
return $this->rfc->isFinal();
}
}

View File

@@ -1,27 +1,19 @@
<?php
/**
* Mockery
* Mockery (https://docs.mockery.io/)
*
* LICENSE
*
* This source file is subject to the new BSD license that is bundled
* with this package in the file LICENSE.txt.
* It is also available through the world-wide-web at this URL:
* http://github.com/padraic/mockery/blob/master/LICENSE
* If you did not receive a copy of the license and are unable to
* obtain it through the world-wide-web, please send an email
* to padraic@php.net so we can send you a copy immediately.
*
* @category Mockery
* @package Mockery
* @copyright Copyright (c) 2010 Pádraic Brady (http://blog.astrumfutura.com)
* @license http://github.com/padraic/mockery/blob/master/LICENSE New BSD License
* @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 */
/**
* @returns MockDefinition
*/
public function generate(MockConfiguration $config);
}

View File

@@ -1,54 +1,63 @@
<?php
/**
* Mockery
* Mockery (https://docs.mockery.io/)
*
* LICENSE
*
* This source file is subject to the new BSD license that is bundled
* with this package in the file LICENSE.txt.
* It is also available through the world-wide-web at this URL:
* http://github.com/padraic/mockery/blob/master/LICENSE
* If you did not receive a copy of the license and are unable to
* obtain it through the world-wide-web, please send an email
* to padraic@php.net so we can send you a copy immediately.
*
* @category Mockery
* @package Mockery
* @copyright Copyright (c) 2010 Pádraic Brady (http://blog.astrumfutura.com)
* @license http://github.com/padraic/mockery/blob/master/LICENSE New BSD License
* @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;
use ReflectionMethod;
use ReflectionParameter;
use function array_map;
/**
* @mixin ReflectionMethod
*/
class Method
{
/** @var \ReflectionMethod */
/**
* @var ReflectionMethod
*/
private $method;
public function __construct(\ReflectionMethod $method)
public function __construct(ReflectionMethod $method)
{
$this->method = $method;
}
/**
* @template TArgs
* @template TMixed
*
* @param string $method
* @param array<TArgs> $args
*
* @return TMixed
*/
public function __call($method, $args)
{
return call_user_func_array(array($this->method, $method), $args);
/** @var TMixed */
return $this->method->{$method}(...$args);
}
/**
* @return Parameter[]
* @return list<Parameter>
*/
public function getParameters()
{
return array_map(function (\ReflectionParameter $parameter) {
return array_map(static function (ReflectionParameter $parameter) {
return new Parameter($parameter);
}, $this->method->getParameters());
}
/**
* @return string|null
* @return null|string
*/
public function getReturnType()
{

View File

@@ -1,25 +1,39 @@
<?php
/**
* Mockery
* Mockery (https://docs.mockery.io/)
*
* LICENSE
*
* This source file is subject to the new BSD license that is bundled
* with this package in the file LICENSE.txt.
* It is also available through the world-wide-web at this URL:
* http://github.com/padraic/mockery/blob/master/LICENSE
* If you did not receive a copy of the license and are unable to
* obtain it through the world-wide-web, please send an email
* to padraic@php.net so we can send you a copy immediately.
*
* @category Mockery
* @package Mockery
* @copyright Copyright (c) 2010 Pádraic Brady (http://blog.astrumfutura.com)
* @license http://github.com/padraic/mockery/blob/master/LICENSE New BSD License
* @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\Exception;
use Serializable;
use function array_filter;
use function array_keys;
use function array_map;
use function array_merge;
use function array_pop;
use function array_unique;
use function array_values;
use function class_alias;
use function class_exists;
use function explode;
use function get_class;
use function implode;
use function in_array;
use function interface_exists;
use function is_object;
use function md5;
use function preg_match;
use function serialize;
use function strpos;
use function strtolower;
use function trait_exists;
/**
* This class describes the configuration of mocks and hides away some of the
* reflection implementation
@@ -27,80 +41,117 @@ namespace Mockery\Generator;
class MockConfiguration
{
/**
* A class that we'd like to mock
* Instance cache of all methods
*
* @var list<Method>
*/
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;
protected $allMethods = [];
/**
* 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
* This is currently populated with stuff we don't know how to deal with, should really be somewhere else
*/
protected $blackListedMethods = array();
protected $blackListedMethods = [];
protected $constantsMap = [];
/**
* 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
* An instance mock is where we override the original class before it's autoloaded
*
* @var bool
*/
protected $instanceMock = false;
/**
* Param overrides
*/
protected $parameterOverrides = array();
/**
* Instance cache of all methods
*/
protected $allMethods;
/**
* If true, overrides original class destructor
*
* @var bool
*/
protected $mockOriginalDestructor = false;
protected $constantsMap = array();
/**
* The class name we'd like to use for a generated mock
*
* @var string|null
*/
protected $name;
/**
* Param overrides
*
* @var array<string,mixed>
*/
protected $parameterOverrides = [];
/**
* A class that we'd like to mock
* @var TargetClassInterface|null
*/
protected $targetClass;
/**
* @var class-string|null
*/
protected $targetClassName;
/**
* @var array<class-string>
*/
protected $targetInterfaceNames = [];
/**
* A number of interfaces we'd like to mock, keyed by name to attempt to keep unique
*
* @var array<TargetClassInterface>
*/
protected $targetInterfaces = [];
/**
* An object we'd like our mock to proxy to
*
* @var object|null
*/
protected $targetObject;
/**
* @var array<string>
*/
protected $targetTraitNames = [];
/**
* A number of traits we'd like to mock, keyed by name to attempt to keep unique
*
* @var array<string,DefinedTargetClass>
*/
protected $targetTraits = [];
/**
* If not empty, only these methods will be mocked
*
* @var array<string>
*/
protected $whiteListedMethods = [];
/**
* @param array<class-string|object> $targets
* @param array<string> $blackListedMethods
* @param array<string> $whiteListedMethods
* @param string|null $name
* @param bool $instanceMock
* @param array<string,mixed> $parameterOverrides
* @param bool $mockOriginalDestructor
* @param array<string,array<scalar>|scalar> $constantsMap
*/
public function __construct(
array $targets = array(),
array $blackListedMethods = array(),
array $whiteListedMethods = array(),
array $targets = [],
array $blackListedMethods = [],
array $whiteListedMethods = [],
$name = null,
$instanceMock = false,
array $parameterOverrides = array(),
array $parameterOverrides = [],
$mockOriginalDestructor = false,
array $constantsMap = array()
array $constantsMap = []
) {
$this->addTargets($targets);
$this->blackListedMethods = $blackListedMethods;
@@ -112,6 +163,52 @@ class MockConfiguration
$this->constantsMap = $constantsMap;
}
/**
* Generate a suitable name based on the config
*
* @return string
*/
public function generateName()
{
$nameBuilder = new MockNameBuilder();
$targetObject = $this->getTargetObject();
if ($targetObject !== null) {
$className = get_class($targetObject);
$nameBuilder->addPart(strpos($className, '@') !== false ? md5($className) : $className);
}
$targetClass = $this->getTargetClass();
if ($targetClass instanceof TargetClassInterface) {
$className = $targetClass->getName();
$nameBuilder->addPart(strpos($className, '@') !== false ? md5($className) : $className);
}
foreach ($this->getTargetInterfaces() as $targetInterface) {
$nameBuilder->addPart($targetInterface->getName());
}
return $nameBuilder->build();
}
/**
* @return array<string>
*/
public function getBlackListedMethods()
{
return $this->blackListedMethods;
}
/**
* @return array<string,scalar|array<scalar>>
*/
public function getConstantsMap()
{
return $this->constantsMap;
}
/**
* Attempt to create a hash of the configuration, in order to allow caching
*
@@ -121,25 +218,26 @@ class MockConfiguration
*/
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
);
$vars = [
'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
* 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
*
* @return list<Method>
*/
public function getMethodsToMock()
{
@@ -154,22 +252,28 @@ class MockConfiguration
/**
* 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);
});
$whiteListedMethods = $this->getWhiteListedMethods();
if ($whiteListedMethods !== []) {
$whitelist = array_map('strtolower', $whiteListedMethods);
return $methods;
return array_filter($methods, static function ($method) use ($whitelist) {
if ($method->isAbstract()) {
return true;
}
return in_array(strtolower($method->getName()), $whitelist, true);
});
}
/**
* 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);
$blackListedMethods = $this->getBlackListedMethods();
if ($blackListedMethods !== []) {
$blacklist = array_map('strtolower', $blackListedMethods);
$methods = array_filter($methods, static function ($method) use ($blacklist) {
return ! in_array(strtolower($method->getName()), $blacklist, true);
});
}
@@ -179,11 +283,15 @@ class MockConfiguration
* 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";
$targetClass = $this->getTargetClass();
if (
$targetClass !== null
&& $targetClass->implementsInterface(Serializable::class)
&& $targetClass->hasInternalAncestor()
) {
$methods = array_filter($methods, static function ($method) {
return $method->getName() !== 'unserialize';
});
}
@@ -191,40 +299,213 @@ class MockConfiguration
}
/**
* 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
* @return string|null
*/
public function requiresCallTypeHintRemoval()
public function getName()
{
foreach ($this->getAllMethods() as $method) {
if ("__call" === $method->getName()) {
$params = $method->getParameters();
return !$params[1]->isArray();
}
}
return false;
return $this->name;
}
/**
* 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
* @return string
*/
public function requiresCallStaticTypeHintRemoval()
public function getNamespaceName()
{
foreach ($this->getAllMethods() as $method) {
if ("__callStatic" === $method->getName()) {
$params = $method->getParameters();
return !$params[1]->isArray();
$parts = explode('\\', $this->getName());
array_pop($parts);
if ($parts !== []) {
return implode('\\', $parts);
}
return '';
}
/**
* @return array<string,mixed>
*/
public function getParameterOverrides()
{
return $this->parameterOverrides;
}
/**
* @return string
*/
public function getShortName()
{
$parts = explode('\\', $this->getName());
return array_pop($parts);
}
/**
* @return null|TargetClassInterface
*/
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() === null && $dtc->isFinal()) {
throw new 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;
}
/**
* @return class-string|null
*/
public function getTargetClassName()
{
return $this->targetClassName;
}
/**
* @return list<TargetClassInterface>
*/
public function getTargetInterfaces()
{
if ($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;
continue;
}
if (preg_match('/^\\\\?Iterator$/i', $interface)) {
$this->targetInterfaces[] = DefinedTargetClass::factory('\\Iterator');
$iteratorShiftedToFront = true;
continue;
}
if (preg_match('/^\\\\?Traversable$/i', $interface)) {
$traversableFound = true;
}
}
if ($traversableFound && ! $iteratorShiftedToFront) {
$this->targetInterfaces[] = DefinedTargetClass::factory('\\IteratorAggregate');
}
/**
* We never straight up implement Traversable
*/
$isTraversable = preg_match('/^\\\\?Traversable$/i', $targetInterface);
if ($isTraversable === 0 || $isTraversable === false) {
$this->targetInterfaces[] = $dtc;
}
}
return false;
return $this->targetInterfaces = array_unique($this->targetInterfaces);
}
/**
* @return object|null
*/
public function getTargetObject()
{
return $this->targetObject;
}
/**
* @return list<TargetClassInterface>
*/
public function getTargetTraits()
{
if ($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;
}
/**
* @return array<string>
*/
public function getWhiteListedMethods()
{
return $this->whiteListedMethods;
}
/**
* @return bool
*/
public function isInstanceMock()
{
return $this->instanceMock;
}
/**
* @return bool
*/
public function isMockOriginalDestructor()
{
return $this->mockOriginalDestructor;
}
/**
* @param class-string $className
* @return self
*/
public function rename($className)
{
$targets = array();
$targets = [];
if ($this->targetClassName) {
$targets[] = $this->targetClassName;
@@ -254,31 +535,75 @@ class MockConfiguration
);
}
/**
* 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
*
* @return bool
*/
public function requiresCallStaticTypeHintRemoval()
{
foreach ($this->getAllMethods() as $method) {
if ($method->getName() === '__callStatic') {
$params = $method->getParameters();
if (! array_key_exists(1, $params)) {
return false;
}
return ! $params[1]->isArray();
}
}
return false;
}
/**
* 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
*
* @return bool
*/
public function requiresCallTypeHintRemoval()
{
foreach ($this->getAllMethods() as $method) {
if ($method->getName() === '__call') {
$params = $method->getParameters();
return ! $params[1]->isArray();
}
}
return false;
}
/**
* @param class-string|object $target
*/
protected function addTarget($target)
{
if (is_object($target)) {
$this->setTargetObject($target);
$this->setTargetClassName(get_class($target));
return $this;
return;
}
if ($target[0] !== "\\") {
$target = "\\" . $target;
if ($target[0] !== '\\') {
$target = '\\' . $target;
}
if (class_exists($target)) {
$this->setTargetClassName($target);
return $this;
return;
}
if (interface_exists($target)) {
$this->addTargetInterfaceName($target);
return $this;
return;
}
if (trait_exists($target)) {
$this->addTargetTraitName($target);
return $this;
return;
}
/**
@@ -289,12 +614,27 @@ class MockConfiguration
*/
if ($this->getTargetClassName()) {
$this->addTargetInterfaceName($target);
return $this;
return;
}
$this->setTargetClassName($target);
}
/**
* 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.
*
* @param class-string $targetInterface
*/
protected function addTargetInterfaceName($targetInterface)
{
$this->targetInterfaceNames[] = $targetInterface;
}
/**
* @param array<class-string> $interfaces
*/
protected function addTargets($interfaces)
{
foreach ($interfaces as $interface) {
@@ -302,195 +642,17 @@ class MockConfiguration
}
}
public function getTargetClassName()
/**
* @param class-string $targetTraitName
*/
protected function addTargetTraitName($targetTraitName)
{
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;
$this->targetTraitNames[] = $targetTraitName;
}
/**
* Generate a suitable name based on the config
* @return list<Method>
*/
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) {
@@ -503,7 +665,7 @@ class MockConfiguration
$classes[] = $this->getTargetClass();
}
$methods = array();
$methods = [];
foreach ($classes as $class) {
$methods = array_merge($methods, $class->getMethods());
}
@@ -516,9 +678,9 @@ class MockConfiguration
}
}
$names = array();
$methods = array_filter($methods, function ($method) use (&$names) {
if (in_array($method->getName(), $names)) {
$names = [];
$methods = array_filter($methods, static function ($method) use (&$names) {
if (in_array($method->getName(), $names, true)) {
return false;
}
@@ -530,27 +692,18 @@ class MockConfiguration
}
/**
* 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.
* @param class-string $targetClassName
*/
protected function addTargetInterfaceName($targetInterface)
protected function setTargetClassName($targetClassName)
{
$this->targetInterfaceNames[] = $targetInterface;
}
protected function addTargetTraitName($targetTraitName)
{
$this->targetTraitNames[] = $targetTraitName;
$this->targetClassName = $targetClassName;
}
/**
* @param object $object
*/
protected function setTargetObject($object)
{
$this->targetObject = $object;
}
public function getConstantsMap()
{
return $this->constantsMap;
}
}

View File

@@ -1,29 +1,23 @@
<?php
/**
* Mockery
* Mockery (https://docs.mockery.io/)
*
* LICENSE
*
* This source file is subject to the new BSD license that is bundled
* with this package in the file LICENSE.txt.
* It is also available through the world-wide-web at this URL:
* http://github.com/padraic/mockery/blob/master/LICENSE
* If you did not receive a copy of the license and are unable to
* obtain it through the world-wide-web, please send an email
* to padraic@php.net so we can send you a copy immediately.
*
* @category Mockery
* @package Mockery
* @copyright Copyright (c) 2010 Pádraic Brady (http://blog.astrumfutura.com)
* @license http://github.com/padraic/mockery/blob/master/LICENSE New BSD License
* @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 function array_diff;
class MockConfigurationBuilder
{
protected $name;
protected $blackListedMethods = array(
/**
* @var list<string>
*/
protected $blackListedMethods = [
'__call',
'__callStatic',
'__clone',
@@ -36,45 +30,101 @@ class MockConfigurationBuilder
'__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",
'__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 $whiteListedMethods = array();
/**
* @var array
*/
protected $constantsMap = [];
/**
* @var bool
*/
protected $instanceMock = false;
protected $parameterOverrides = array();
/**
* @var bool
*/
protected $mockOriginalDestructor = false;
protected $targets = array();
protected $constantsMap = array();
/**
* @var string
*/
protected $name;
/**
* @var array
*/
protected $parameterOverrides = [];
/**
* @var list<string>
*/
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',
];
/**
* @var array
*/
protected $targets = [];
/**
* @var array
*/
protected $whiteListedMethods = [];
public function __construct()
{
$this->blackListedMethods = array_diff($this->blackListedMethods, $this->php7SemiReservedKeywords);
}
/**
* @param string $blackListedMethod
* @return self
*/
public function addBlackListedMethod($blackListedMethod)
{
$this->blackListedMethods[] = $blackListedMethod;
return $this;
}
/**
* @param list<string> $blackListedMethods
* @return self
*/
public function addBlackListedMethods(array $blackListedMethods)
{
foreach ($blackListedMethods as $method) {
$this->addBlackListedMethod($method);
}
return $this;
}
/**
* @param class-string $target
* @return self
*/
public function addTarget($target)
{
$this->targets[] = $target;
@@ -82,6 +132,10 @@ class MockConfigurationBuilder
return $this;
}
/**
* @param list<class-string> $targets
* @return self
*/
public function addTargets($targets)
{
foreach ($targets as $target) {
@@ -91,73 +145,30 @@ class MockConfigurationBuilder
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;
}
/**
* @return self
*/
public function addWhiteListedMethod($whiteListedMethod)
{
$this->whiteListedMethods[] = $whiteListedMethod;
return $this;
}
/**
* @return self
*/
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;
}
/**
* @return MockConfiguration
*/
public function getMockConfiguration()
{
return new MockConfiguration(
@@ -171,4 +182,71 @@ class MockConfigurationBuilder
$this->constantsMap
);
}
/**
* @param list<string> $blackListedMethods
* @return self
*/
public function setBlackListedMethods(array $blackListedMethods)
{
$this->blackListedMethods = $blackListedMethods;
return $this;
}
/**
* @return self
*/
public function setConstantsMap(array $map)
{
$this->constantsMap = $map;
return $this;
}
/**
* @param bool $instanceMock
*/
public function setInstanceMock($instanceMock)
{
$this->instanceMock = (bool) $instanceMock;
return $this;
}
/**
* @param bool $mockDestructor
*/
public function setMockOriginalDestructor($mockDestructor)
{
$this->mockOriginalDestructor = (bool) $mockDestructor;
return $this;
}
/**
* @param string $name
*/
public function setName($name)
{
$this->name = $name;
return $this;
}
/**
* @return self
*/
public function setParameterOverrides(array $overrides)
{
$this->parameterOverrides = $overrides;
return $this;
}
/**
* @param list<string> $whiteListedMethods
* @return self
*/
public function setWhiteListedMethods(array $whiteListedMethods)
{
$this->whiteListedMethods = $whiteListedMethods;
return $this;
}
}

View File

@@ -1,51 +1,64 @@
<?php
/**
* Mockery
* Mockery (https://docs.mockery.io/)
*
* LICENSE
*
* This source file is subject to the new BSD license that is bundled
* with this package in the file LICENSE.txt.
* It is also available through the world-wide-web at this URL:
* http://github.com/padraic/mockery/blob/master/LICENSE
* If you did not receive a copy of the license and are unable to
* obtain it through the world-wide-web, please send an email
* to padraic@php.net so we can send you a copy immediately.
*
* @category Mockery
* @package Mockery
* @copyright Copyright (c) 2010 Pádraic Brady (http://blog.astrumfutura.com)
* @license http://github.com/padraic/mockery/blob/master/LICENSE New BSD License
* @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 InvalidArgumentException;
class MockDefinition
{
protected $config;
/**
* @var string
*/
protected $code;
/**
* @var MockConfiguration
*/
protected $config;
/**
* @param string $code
* @throws InvalidArgumentException
*/
public function __construct(MockConfiguration $config, $code)
{
if (!$config->getName()) {
throw new \InvalidArgumentException("MockConfiguration must contain a name");
if (! $config->getName()) {
throw new InvalidArgumentException('MockConfiguration must contain a name');
}
$this->config = $config;
$this->code = $code;
}
public function getConfig()
{
return $this->config;
}
/**
* @return string
*/
public function getClassName()
{
return $this->config->getName();
}
/**
* @return string
*/
public function getCode()
{
return $this->code;
}
/**
* @return MockConfiguration
*/
public function getConfig()
{
return $this->config;
}
}

View File

@@ -1,31 +1,33 @@
<?php
/**
* Mockery
* Mockery (https://docs.mockery.io/)
*
* LICENSE
*
* This source file is subject to the new BSD license that is bundled
* with this package in the file LICENSE.txt.
* It is also available through the world-wide-web at this URL:
* http://github.com/padraic/mockery/blob/master/LICENSE
* If you did not receive a copy of the license and are unable to
* obtain it through the world-wide-web, please send an email
* to padraic@php.net so we can send you a copy immediately.
*
* @category Mockery
* @package Mockery
* @copyright Copyright (c) 2010 Pádraic Brady (http://blog.astrumfutura.com)
* @license http://github.com/padraic/mockery/blob/master/LICENSE New BSD License
* @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 function implode;
use function str_replace;
class MockNameBuilder
{
/**
* @var int
*/
protected static $mockCounter = 0;
/**
* @var list<string>
*/
protected $parts = [];
/**
* @param string $part
*/
public function addPart($part)
{
$this->parts[] = $part;
@@ -33,12 +35,15 @@ class MockNameBuilder
return $this;
}
/**
* @return string
*/
public function build()
{
$parts = ['Mockery', static::$mockCounter++];
foreach ($this->parts as $part) {
$parts[] = str_replace("\\", "_", $part);
$parts[] = str_replace('\\', '_', $part);
}
return implode('_', $parts);

View File

@@ -1,43 +1,55 @@
<?php
/**
* Mockery
* Mockery (https://docs.mockery.io/)
*
* LICENSE
*
* This source file is subject to the new BSD license that is bundled
* with this package in the file LICENSE.txt.
* It is also available through the world-wide-web at this URL:
* http://github.com/padraic/mockery/blob/master/LICENSE
* If you did not receive a copy of the license and are unable to
* obtain it through the world-wide-web, please send an email
* to padraic@php.net so we can send you a copy immediately.
*
* @category Mockery
* @package Mockery
* @copyright Copyright (c) 2010 Pádraic Brady (http://blog.astrumfutura.com)
* @license http://github.com/padraic/mockery/blob/master/LICENSE New BSD License
* @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;
use ReflectionClass;
use ReflectionParameter;
use function class_exists;
/**
* @mixin ReflectionParameter
*/
class Parameter
{
/** @var int */
/**
* @var int
*/
private static $parameterCounter = 0;
/** @var \ReflectionParameter */
/**
* @var ReflectionParameter
*/
private $rfp;
public function __construct(\ReflectionParameter $rfp)
public function __construct(ReflectionParameter $rfp)
{
$this->rfp = $rfp;
}
/**
* Proxy all method calls to the reflection parameter.
*
* @template TMixed
* @template TResult
*
* @param string $method
* @param array<TMixed> $args
*
* @return TResult
*/
public function __call($method, array $args)
{
return call_user_func_array(array($this->rfp, $method), $args);
/** @var TResult */
return $this->rfp->{$method}(...$args);
}
/**
@@ -45,7 +57,7 @@ class Parameter
*
* This will be null if there was no type, or it was a scalar or a union.
*
* @return \ReflectionClass|null
* @return null|ReflectionClass
*
* @deprecated since 1.3.3 and will be removed in 2.0.
*/
@@ -53,13 +65,31 @@ class Parameter
{
$typeHint = Reflector::getTypeHint($this->rfp, true);
return \class_exists($typeHint) ? DefinedTargetClass::factory($typeHint, false) : null;
return class_exists($typeHint) ? DefinedTargetClass::factory($typeHint, false) : null;
}
/**
* 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 === '...') {
return 'arg' . self::$parameterCounter++;
}
return $name;
}
/**
* Get the string representation for the paramater type.
*
* @return string|null
* @return null|string
*/
public function getTypeHint()
{
@@ -78,23 +108,6 @@ class Parameter
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.
*

View File

@@ -1,46 +1,39 @@
<?php
/**
* Mockery
* Mockery (https://docs.mockery.io/)
*
* LICENSE
*
* This source file is subject to the new BSD license that is bundled
* with this package in the file LICENSE.txt.
* It is also available through the world-wide-web at this URL:
* http://github.com/padraic/mockery/blob/master/LICENSE
* If you did not receive a copy of the license and are unable to
* obtain it through the world-wide-web, please send an email
* to padraic@php.net so we can send you a copy immediately.
*
* @category Mockery
* @package Mockery
* @copyright Copyright (c) 2010 Pádraic Brady (http://blog.astrumfutura.com)
* @license http://github.com/padraic/mockery/blob/master/LICENSE New BSD License
* @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;
use function array_map;
use function in_array;
use function preg_replace;
use function sprintf;
use function str_replace;
class AvoidMethodClashPass implements Pass
{
/**
* @param string $code
* @return string
*/
public function apply($code, MockConfiguration $config)
{
$names = array_map(function ($method) {
$names = array_map(static 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
);
foreach (['allows', 'expects'] as $method) {
if (in_array($method, $names, true)) {
$code = preg_replace(sprintf('#// start method %s.*// end method %s#ms', $method, $method), '', $code);
$code = str_replace(" implements MockInterface", " implements LegacyMockInterface", $code);
$code = str_replace(' implements MockInterface', ' implements LegacyMockInterface', $code);
}
}

View File

@@ -1,29 +1,24 @@
<?php
/**
* Mockery
* Mockery (https://docs.mockery.io/)
*
* LICENSE
*
* This source file is subject to the new BSD license that is bundled
* with this package in the file LICENSE.txt.
* It is also available through the world-wide-web at this URL:
* http://github.com/padraic/mockery/blob/master/LICENSE
* If you did not receive a copy of the license and are unable to
* obtain it through the world-wide-web, please send an email
* to padraic@php.net so we can send you a copy immediately.
*
* @category Mockery
* @package Mockery
* @copyright Copyright (c) 2010 Pádraic Brady (http://blog.astrumfutura.com)
* @license http://github.com/padraic/mockery/blob/master/LICENSE New BSD License
* @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 function str_replace;
class CallTypeHintPass implements Pass
{
/**
* @param string $code
* @return string
*/
public function apply($code, MockConfiguration $config)
{
if ($config->requiresCallTypeHintRemoval()) {
@@ -35,7 +30,7 @@ class CallTypeHintPass implements Pass
}
if ($config->requiresCallStaticTypeHintRemoval()) {
$code = str_replace(
return str_replace(
'public static function __callStatic($method, array $args)',
'public static function __callStatic($method, $args)',
$code

View File

@@ -1,49 +1,35 @@
<?php
/**
* Mockery
* Mockery (https://docs.mockery.io/)
*
* LICENSE
*
* This source file is subject to the new BSD license that is bundled
* with this package in the file LICENSE.txt.
* It is also available through the world-wide-web at this URL:
* http://github.com/padraic/mockery/blob/master/LICENSE
* If you did not receive a copy of the license and are unable to
* obtain it through the world-wide-web, please send an email
* to padraic@php.net so we can send you a copy immediately.
*
* @category Mockery
* @package Mockery
* @copyright Copyright (c) 2010 Pádraic Brady (http://blog.astrumfutura.com)
* @license http://github.com/padraic/mockery/blob/master/LICENSE New BSD License
* @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 function ltrim;
use function str_replace;
class ClassNamePass implements Pass
{
/**
* @param string $code
* @return string
*/
public function apply($code, MockConfiguration $config)
{
$namespace = $config->getNamespaceName();
$namespace = ltrim($namespace, "\\");
$namespace = ltrim($namespace, '\\');
$className = $config->getShortName();
$code = str_replace(
'namespace Mockery;',
$namespace ? 'namespace ' . $namespace . ';' : '',
$code
);
$code = str_replace('namespace Mockery;', $namespace !== '' ? 'namespace ' . $namespace . ';' : '', $code);
$code = str_replace(
'class Mock',
'class ' . $className,
$code
);
return $code;
return str_replace('class Mock', 'class ' . $className, $code);
}
}

View File

@@ -1,34 +1,32 @@
<?php
/**
* Mockery
* Mockery (https://docs.mockery.io/)
*
* LICENSE
*
* This source file is subject to the new BSD license that is bundled
* with this package in the file LICENSE.txt.
* It is also available through the world-wide-web at this URL:
* http://github.com/padraic/mockery/blob/master/LICENSE
* If you did not receive a copy of the license and are unable to
* obtain it through the world-wide-web, please send an email
* to padraic@php.net so we can send you a copy immediately.
*
* @category Mockery
* @package Mockery
* @copyright Copyright (c) 2010 Pádraic Brady (http://blog.astrumfutura.com)
* @license http://github.com/padraic/mockery/blob/master/LICENSE New BSD License
* @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;
use Mockery\Generator\MockConfiguration;
use function class_exists;
use function ltrim;
use function str_replace;
class ClassPass implements Pass
{
/**
* @param string $code
* @return string
*/
public function apply($code, MockConfiguration $config)
{
$target = $config->getTargetClass();
if (!$target) {
if (! $target) {
return $code;
}
@@ -36,18 +34,16 @@ class ClassPass implements Pass
return $code;
}
$className = ltrim($target->getName(), "\\");
$className = ltrim($target->getName(), '\\');
if (!class_exists($className)) {
\Mockery::declareClass($className);
if (! class_exists($className)) {
Mockery::declareClass($className);
}
$code = str_replace(
"implements MockInterface",
"extends \\" . $className . " implements MockInterface",
return str_replace(
'implements MockInterface',
'extends \\' . $className . ' implements MockInterface',
$code
);
return $code;
}
}

View File

@@ -1,33 +1,51 @@
<?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 function array_key_exists;
use function sprintf;
use function strrpos;
use function substr_replace;
use function var_export;
use const PHP_EOL;
class ConstantsPass implements Pass
{
/**
* @param string $code
* @return string
*/
public function apply($code, MockConfiguration $config)
{
$cm = $config->getConstantsMap();
if (empty($cm)) {
if ($cm === []) {
return $code;
}
if (!isset($cm[$config->getName()])) {
$name = $config->getName();
if (! array_key_exists($name, $cm)) {
return $code;
}
$cm = $cm[$config->getName()];
$constantsCode = '';
foreach ($cm as $constant => $value) {
foreach ($cm[$name] 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";
$offset = strrpos($code, '}');
if ($offset === false) {
return $code;
}
return $code;
return substr_replace($code, $constantsCode, $offset) . '}' . PHP_EOL;
}
}

View File

@@ -1,30 +1,22 @@
<?php
/**
* Mockery
* Mockery (https://docs.mockery.io/)
*
* LICENSE
*
* This source file is subject to the new BSD license that is bundled
* with this package in the file LICENSE.txt.
* It is also available through the world-wide-web at this URL:
* http://github.com/padraic/mockery/blob/master/LICENSE
* If you did not receive a copy of the license and are unable to
* obtain it through the world-wide-web, please send an email
* to padraic@php.net so we can send you a copy immediately.
*
* @category Mockery
* @package Mockery
* @copyright Copyright (c) 2010 Pádraic Brady (http://blog.astrumfutura.com)
* @license http://github.com/padraic/mockery/blob/master/LICENSE New BSD License
* @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 function strrpos;
use function substr;
class InstanceMockPass
class InstanceMockPass implements Pass
{
const INSTANCE_MOCK_CODE = <<<MOCK
public const INSTANCE_MOCK_CODE = <<<MOCK
protected \$_mockery_ignoreVerification = true;
@@ -60,15 +52,19 @@ class InstanceMockPass
}
}
\Mockery::getContainer()->rememberMock(\$this);
\$this->_mockery_constructorCalled(func_get_args());
}
MOCK;
/**
* @param string $code
* @return string
*/
public function apply($code, MockConfiguration $config)
{
if ($config->isInstanceMock()) {
$code = $this->appendToClass($code, static::INSTANCE_MOCK_CODE);
return $this->appendToClass($code, static::INSTANCE_MOCK_CODE);
}
return $code;
@@ -76,8 +72,7 @@ MOCK;
protected function appendToClass($class, $code)
{
$lastBrace = strrpos($class, "}");
$class = substr($class, 0, $lastBrace) . $code . "\n }\n";
return $class;
$lastBrace = strrpos($class, '}');
return substr($class, 0, $lastBrace) . $code . "\n }\n";
}
}

View File

@@ -1,48 +1,41 @@
<?php
/**
* Mockery
* Mockery (https://docs.mockery.io/)
*
* LICENSE
*
* This source file is subject to the new BSD license that is bundled
* with this package in the file LICENSE.txt.
* It is also available through the world-wide-web at this URL:
* http://github.com/padraic/mockery/blob/master/LICENSE
* If you did not receive a copy of the license and are unable to
* obtain it through the world-wide-web, please send an email
* to padraic@php.net so we can send you a copy immediately.
*
* @category Mockery
* @package Mockery
* @copyright Copyright (c) 2010 Pádraic Brady (http://blog.astrumfutura.com)
* @license http://github.com/padraic/mockery/blob/master/LICENSE New BSD License
* @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;
use Mockery\Generator\MockConfiguration;
use function array_reduce;
use function interface_exists;
use function ltrim;
use function str_replace;
class InterfacePass implements Pass
{
/**
* @param string $code
* @return string
*/
public function apply($code, MockConfiguration $config)
{
foreach ($config->getTargetInterfaces() as $i) {
$name = ltrim($i->getName(), "\\");
if (!interface_exists($name)) {
\Mockery::declareInterface($name);
$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(), "\\");
}, "");
$interfaces = array_reduce($config->getTargetInterfaces(), static function ($code, $i) {
return $code . ', \\' . ltrim($i->getName(), '\\');
}, '');
$code = str_replace(
"implements MockInterface",
"implements MockInterface" . $interfaces,
$code
);
return $code;
return str_replace('implements MockInterface', 'implements MockInterface' . $interfaces, $code);
}
}

View File

@@ -1,36 +1,36 @@
<?php
/**
* Mockery
* Mockery (https://docs.mockery.io/)
*
* LICENSE
*
* This source file is subject to the new BSD license that is bundled
* with this package in the file LICENSE.txt.
* It is also available through the world-wide-web at this URL:
* http://github.com/padraic/mockery/blob/master/LICENSE
* If you did not receive a copy of the license and are unable to
* obtain it through the world-wide-web, please send an email
* to padraic@php.net so we can send you a copy immediately.
*
* @category Mockery
* @package Mockery
* @copyright Copyright (c) 2010 Pádraic Brady (http://blog.astrumfutura.com)
* @license http://github.com/padraic/mockery/blob/master/LICENSE New BSD License
* @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\MockConfiguration;
use Mockery\Generator\Parameter;
use Mockery\Generator\TargetClassInterface;
use function array_filter;
use function array_merge;
use function end;
use function in_array;
use function is_array;
use function preg_match;
use function preg_match_all;
use function preg_replace;
use function rtrim;
use function sprintf;
class MagicMethodTypeHintsPass implements Pass
{
/**
* @var array $mockMagicMethods
* @var array
*/
private $mockMagicMethods = array(
private $mockMagicMethods = [
'__construct',
'__destruct',
'__call',
@@ -45,14 +45,14 @@ class MagicMethodTypeHintsPass implements Pass
'__invoke',
'__set_state',
'__clone',
'__debugInfo'
);
'__debugInfo',
];
/**
* Apply implementation.
*
* @param string $code
* @param MockConfiguration $config
*
* @return string
*/
public function apply($code, MockConfiguration $config)
@@ -73,113 +73,81 @@ class MagicMethodTypeHintsPass implements Pass
* 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();
public function getMagicMethods(?TargetClassInterface $class = null)
{
if (! $class instanceof TargetClassInterface) {
return [];
}
return array_filter($class->getMethods(), function (Method $method) {
return in_array($method->getName(), $this->mockMagicMethods);
return in_array($method->getName(), $this->mockMagicMethods, true);
});
}
protected function renderTypeHint(Parameter $param)
{
$typeHint = $param->getTypeHint();
return $typeHint === null ? '' : sprintf('%s ', $typeHint);
}
/**
* 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
);
$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.
* Returns a regex string used to match the
* declaration of some method.
*
* @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 string $methodName
*
* @param int $code
* @param Method $method
* @return array
* @return string
*/
private function getOriginalParameters($code, Method $method)
private function getDeclarationRegex($methodName)
{
$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;
return sprintf('/public\s+(?:static\s+)?function\s+%s\s*\(.*\)\s*(?=\{)/i', $methodName);
}
/**
* Gets the declaration code, as a string, for the passed method.
*
* @param Method $method
* @param array $namedParameters
* @param array $namedParameters
*
* @return string
*/
private function getMethodDeclaration(
Method $method,
array $namedParameters
) {
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();
$name = $namedParameters[$index] ?? $parameter->getName();
$declaration .= '$' . $name;
$declaration .= ',';
}
$declaration = rtrim($declaration, ',');
$declaration .= ') ';
@@ -191,22 +159,39 @@ class MagicMethodTypeHintsPass implements Pass
return $declaration;
}
protected function renderTypeHint(Parameter $param)
/**
* Returns the method original parameters, as they're
* described in the $code string.
*
* @param int $code
*
* @return array
*/
private function getOriginalParameters($code, Method $method)
{
$typeHint = $param->getTypeHint();
$matches = [];
$parameterMatches = [];
return $typeHint === null ? '' : sprintf('%s ', $typeHint);
preg_match($this->getDeclarationRegex($method->getName()), $code, $matches);
if ($matches !== []) {
preg_match_all('/(?<=\$)(\w+)+/i', $matches[0], $parameterMatches);
}
$groupMatches = end($parameterMatches);
return is_array($groupMatches) ? $groupMatches : [$groupMatches];
}
/**
* Returns a regex string used to match the
* declaration of some method.
* Checks if the method is declared within code.
*
* @param string $methodName
* @return string
* @param int $code
*
* @return bool
*/
private function getDeclarationRegex($methodName)
private function isMethodWithinCode($code, Method $method)
{
return "/public\s+(?:static\s+)?function\s+$methodName\s*\(.*\)\s*(?=\{)/i";
return preg_match($this->getDeclarationRegex($method->getName()), $code) === 1;
}
}

View File

@@ -1,31 +1,40 @@
<?php
/**
* Mockery
* Mockery (https://docs.mockery.io/)
*
* LICENSE
*
* This source file is subject to the new BSD license that is bundled
* with this package in the file LICENSE.txt.
* It is also available through the world-wide-web at this URL:
* http://github.com/padraic/mockery/blob/master/LICENSE
* If you did not receive a copy of the license and are unable to
* obtain it through the world-wide-web, please send an email
* to padraic@php.net so we can send you a copy immediately.
*
* @category Mockery
* @package Mockery
* @copyright Copyright (c) 2010 Pádraic Brady (http://blog.astrumfutura.com)
* @license http://github.com/padraic/mockery/blob/master/LICENSE New BSD License
* @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;
use Mockery\Generator\Parameter;
use function array_values;
use function count;
use function enum_exists;
use function get_class;
use function implode;
use function in_array;
use function is_object;
use function preg_match;
use function sprintf;
use function strpos;
use function strrpos;
use function strtolower;
use function substr;
use function var_export;
use const PHP_VERSION_ID;
class MethodDefinitionPass implements Pass
{
/**
* @param string $code
* @return string
*/
public function apply($code, MockConfiguration $config)
{
foreach ($config->getMethodsToMock() as $method) {
@@ -54,6 +63,12 @@ class MethodDefinitionPass implements Pass
return $code;
}
protected function appendToClass($class, $code)
{
$lastBrace = strrpos($class, '}');
return substr($class, 0, $lastBrace) . $code . "\n }\n";
}
protected function renderParams(Method $method, $config)
{
$class = $method->getDeclaringClass();
@@ -65,18 +80,41 @@ class MethodDefinitionPass implements Pass
}
}
$methodParams = array();
$methodParams = [];
$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()) {
if (! $param->isVariadic()) {
if ($param->isDefaultValueAvailable() !== false) {
$defaultValue = $param->getDefaultValue();
$paramDef .= ' = ' . (is_object($defaultValue) ? get_class($defaultValue) : var_export($defaultValue, true));
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';
}
@@ -84,6 +122,7 @@ class MethodDefinitionPass implements Pass
$methodParams[] = $paramDef;
}
return '(' . implode(', ', $methodParams) . ')';
}
@@ -94,13 +133,6 @@ class MethodDefinitionPass implements Pass
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();
@@ -131,8 +163,8 @@ BODY;
$param = $params[$i];
if (strpos($param, '&') !== false) {
$body .= <<<BODY
if (\$argc > $i) {
\$argv[$i] = {$param};
if (\$argc > {$i}) {
\$argv[{$i}] = {$param};
}
BODY;
@@ -143,12 +175,13 @@ BODY;
$paramCount = count($params);
for ($i = 0; $i < $paramCount; ++$i) {
$param = $params[$i];
if (!$param->isPassedByReference()) {
if (! $param->isPassedByReference()) {
continue;
}
$body .= <<<BODY
if (\$argc > $i) {
\$argv[$i] =& \${$param->getName()};
if (\$argc > {$i}) {
\$argv[{$i}] =& \${$param->getName()};
}
BODY;
@@ -157,11 +190,10 @@ BODY;
$body .= "\$ret = {$invoke}(__FUNCTION__, \$argv);\n";
if ($method->getReturnType() !== "void") {
if (! in_array($method->getReturnType(), ['never', 'void'], true)) {
$body .= "return \$ret;\n";
}
$body .= "}\n";
return $body;
return $body . "}\n";
}
}

View File

@@ -1,21 +1,11 @@
<?php
/**
* Mockery
* Mockery (https://docs.mockery.io/)
*
* LICENSE
*
* This source file is subject to the new BSD license that is bundled
* with this package in the file LICENSE.txt.
* It is also available through the world-wide-web at this URL:
* http://github.com/padraic/mockery/blob/master/LICENSE
* If you did not receive a copy of the license and are unable to
* obtain it through the world-wide-web, please send an email
* to padraic@php.net so we can send you a copy immediately.
*
* @category Mockery
* @package Mockery
* @copyright Copyright (c) 2010 Pádraic Brady (http://blog.astrumfutura.com)
* @license http://github.com/padraic/mockery/blob/master/LICENSE New BSD License
* @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;
@@ -24,5 +14,9 @@ use Mockery\Generator\MockConfiguration;
interface Pass
{
/**
* @param string $code
* @return string
*/
public function apply($code, MockConfiguration $config);
}

View File

@@ -1,26 +1,18 @@
<?php
/**
* Mockery
* Mockery (https://docs.mockery.io/)
*
* LICENSE
*
* This source file is subject to the new BSD license that is bundled
* with this package in the file LICENSE.txt.
* It is also available through the world-wide-web at this URL:
* http://github.com/padraic/mockery/blob/master/LICENSE
* If you did not receive a copy of the license and are unable to
* obtain it through the world-wide-web, please send an email
* to padraic@php.net so we can send you a copy immediately.
*
* @category Mockery
* @package Mockery
* @copyright Copyright (c) 2010 Pádraic Brady (http://blog.astrumfutura.com)
* @license http://github.com/padraic/mockery/blob/master/LICENSE New BSD License
* @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 function preg_replace;
/**
* The standard Mockery\Mock class includes some methods to ease mocking, such
@@ -28,24 +20,35 @@ use Mockery\Generator\MockConfiguration;
* mocked. This pass removes the builtin methods where they are final on the
* target
*/
class RemoveBuiltinMethodsThatAreFinalPass
class RemoveBuiltinMethodsThatAreFinalPass implements Pass
{
protected $methods = array(
protected $methods = [
'__wakeup' => '/public function __wakeup\(\)\s+\{.*?\}/sm',
);
'__toString' => '/public function __toString\(\)\s+(:\s+string)?\s*\{.*?\}/sm',
];
/**
* @param string $code
* @return string
*/
public function apply($code, MockConfiguration $config)
{
$target = $config->getTargetClass();
if (!$target) {
if (! $target instanceof TargetClassInterface) {
return $code;
}
foreach ($target->getMethods() as $method) {
if ($method->isFinal() && isset($this->methods[$method->getName()])) {
$code = preg_replace($this->methods[$method->getName()], '', $code);
if (! $method->isFinal()) {
continue;
}
if (! isset($this->methods[$method->getName()])) {
continue;
}
$code = preg_replace($this->methods[$method->getName()], '', $code);
}
return $code;

View File

@@ -1,43 +1,37 @@
<?php
/**
* Mockery
* Mockery (https://docs.mockery.io/)
*
* LICENSE
*
* This source file is subject to the new BSD license that is bundled
* with this package in the file LICENSE.txt.
* It is also available through the world-wide-web at this URL:
* http://github.com/padraic/mockery/blob/master/LICENSE
* If you did not receive a copy of the license and are unable to
* obtain it through the world-wide-web, please send an email
* to padraic@php.net so we can send you a copy immediately.
*
* @category Mockery
* @package Mockery
* @copyright Copyright (c) 2010 Pádraic Brady (http://blog.astrumfutura.com)
* @license http://github.com/padraic/mockery/blob/master/LICENSE New BSD License
* @author Boris Avdeev <elephant@lislon.ru>
* @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 function preg_replace;
/**
* Remove mock's empty destructor if we tend to use original class destructor
*/
class RemoveDestructorPass
class RemoveDestructorPass implements Pass
{
/**
* @param string $code
* @return string
*/
public function apply($code, MockConfiguration $config)
{
$target = $config->getTargetClass();
if (!$target) {
if (! $target) {
return $code;
}
if (!$config->isMockOriginalDestructor()) {
$code = preg_replace('/public function __destruct\(\)\s+\{.*?\}/sm', '', $code);
if (! $config->isMockOriginalDestructor()) {
return preg_replace('/public function __destruct\(\)\s+\{.*?\}/sm', '', $code);
}
return $code;

View File

@@ -1,26 +1,19 @@
<?php
/**
* Mockery
* Mockery (https://docs.mockery.io/)
*
* LICENSE
*
* This source file is subject to the new BSD license that is bundled
* with this package in the file LICENSE.txt.
* It is also available through the world-wide-web at this URL:
* http://github.com/padraic/mockery/blob/master/LICENSE
* If you did not receive a copy of the license and are unable to
* obtain it through the world-wide-web, please send an email
* to padraic@php.net so we can send you a copy immediately.
*
* @category Mockery
* @package Mockery
* @copyright Copyright (c) 2010 Pádraic Brady (http://blog.astrumfutura.com)
* @license http://github.com/padraic/mockery/blob/master/LICENSE New BSD License
* @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 function strrpos;
use function substr;
use const PHP_VERSION_ID;
/**
* Internal classes can not be instantiated with the newInstanceWithoutArgs
@@ -28,32 +21,37 @@ use Mockery\Generator\MockConfiguration;
* implements Serializable, we need to replace the standard unserialize method
* definition with a dummy
*/
class RemoveUnserializeForInternalSerializableClassesPass
class RemoveUnserializeForInternalSerializableClassesPass implements Pass
{
const DUMMY_METHOD_DEFINITION_LEGACY = 'public function unserialize($string) {} ';
const DUMMY_METHOD_DEFINITION = 'public function unserialize(string $data): void {} ';
public const DUMMY_METHOD_DEFINITION = 'public function unserialize(string $data): void {} ';
public const DUMMY_METHOD_DEFINITION_LEGACY = 'public function unserialize($string) {} ';
/**
* @param string $code
* @return string
*/
public function apply($code, MockConfiguration $config)
{
$target = $config->getTargetClass();
if (!$target) {
if (! $target) {
return $code;
}
if (!$target->hasInternalAncestor() || !$target->implementsInterface("Serializable")) {
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;
return $this->appendToClass(
$code,
PHP_VERSION_ID < 80100 ? self::DUMMY_METHOD_DEFINITION_LEGACY : self::DUMMY_METHOD_DEFINITION
);
}
protected function appendToClass($class, $code)
{
$lastBrace = strrpos($class, "}");
$class = substr($class, 0, $lastBrace) . $code . "\n }\n";
return $class;
$lastBrace = strrpos($class, '}');
return substr($class, 0, $lastBrace) . $code . "\n }\n";
}
}

View File

@@ -1,47 +1,39 @@
<?php
/**
* Mockery
* Mockery (https://docs.mockery.io/)
*
* LICENSE
*
* This source file is subject to the new BSD license that is bundled
* with this package in the file LICENSE.txt.
* It is also available through the world-wide-web at this URL:
* http://github.com/padraic/mockery/blob/master/LICENSE
* If you did not receive a copy of the license and are unable to
* obtain it through the world-wide-web, please send an email
* to padraic@php.net so we can send you a copy immediately.
*
* @category Mockery
* @package Mockery
* @copyright Copyright (c) 2010 Pádraic Brady (http://blog.astrumfutura.com)
* @license http://github.com/padraic/mockery/blob/master/LICENSE New BSD License
* @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 function array_map;
use function implode;
use function ltrim;
use function preg_replace;
class TraitPass implements Pass
{
/**
* @param string $code
* @return string
*/
public function apply($code, MockConfiguration $config)
{
$traits = $config->getTargetTraits();
if (empty($traits)) {
if ($traits === []) {
return $code;
}
$useStatements = array_map(function ($trait) {
return "use \\\\" . ltrim($trait->getName(), "\\") . ";";
$useStatements = array_map(static function ($trait) {
return 'use \\\\' . ltrim($trait->getName(), '\\') . ';';
}, $traits);
$code = preg_replace(
'/^{$/m',
"{\n " . implode("\n ", $useStatements) . "\n",
$code
);
return $code;
return preg_replace('/^{$/m', "{\n " . implode("\n ", $useStatements) . "\n", $code);
}
}

View File

@@ -1,26 +1,18 @@
<?php
/**
* Mockery
* Mockery (https://docs.mockery.io/)
*
* LICENSE
*
* This source file is subject to the new BSD license that is bundled
* with this package in the file LICENSE.txt.
* It is also available through the world-wide-web at this URL:
* http://github.com/padraic/mockery/blob/master/LICENSE
* If you did not receive a copy of the license and are unable to
* obtain it through the world-wide-web, please send an email
* to padraic@php.net so we can send you a copy immediately.
*
* @category Mockery
* @package Mockery
* @copyright Copyright (c) 2010 Pádraic Brady (http://blog.astrumfutura.com)
* @license http://github.com/padraic/mockery/blob/master/LICENSE New BSD License
* @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\AvoidMethodClashPass;
use Mockery\Generator\StringManipulation\Pass\CallTypeHintPass;
use Mockery\Generator\StringManipulation\Pass\ClassAttributesPass;
use Mockery\Generator\StringManipulation\Pass\ClassNamePass;
use Mockery\Generator\StringManipulation\Pass\ClassPass;
use Mockery\Generator\StringManipulation\Pass\ConstantsPass;
@@ -33,11 +25,55 @@ use Mockery\Generator\StringManipulation\Pass\RemoveBuiltinMethodsThatAreFinalPa
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 function file_get_contents;
class StringManipulationGenerator implements Generator
{
protected $passes = array();
/**
* @var list<Pass>
*/
protected $passes = [];
/**
* @var string
*/
private $code;
/**
* @param list<Pass> $passes
*/
public function __construct(array $passes)
{
$this->passes = $passes;
$this->code = file_get_contents(__DIR__ . '/../Mock.php');
}
/**
* @param Pass $pass
* @return void
*/
public function addPass(Pass $pass)
{
$this->passes[] = $pass;
}
/**
* @return MockDefinition
*/
public function generate(MockConfiguration $config)
{
$className = $config->getName() ?: $config->generateName();
$namedConfig = $config->rename($className);
$code = $this->code;
foreach ($this->passes as $pass) {
$code = $pass->apply($code, $namedConfig);
}
return new MockDefinition($namedConfig, $code);
}
/**
* Creates a new StringManipulationGenerator with the default passes
@@ -60,30 +96,7 @@ class StringManipulationGenerator implements Generator
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;
}
}

View File

@@ -1,21 +1,11 @@
<?php
/**
* Mockery
* Mockery (https://docs.mockery.io/)
*
* LICENSE
*
* This source file is subject to the new BSD license that is bundled
* with this package in the file LICENSE.txt.
* It is also available through the world-wide-web at this URL:
* http://github.com/padraic/mockery/blob/master/LICENSE
* If you did not receive a copy of the license and are unable to
* obtain it through the world-wide-web, please send an email
* to padraic@php.net so we can send you a copy immediately.
*
* @category Mockery
* @package Mockery
* @copyright Copyright (c) 2010 Pádraic Brady (http://blog.astrumfutura.com)
* @license http://github.com/padraic/mockery/blob/master/LICENSE New BSD License
* @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;
@@ -23,36 +13,42 @@ namespace Mockery\Generator;
interface TargetClassInterface
{
/**
* Returns a new instance of the current
* TargetClassInterface's
* implementation.
* Returns a new instance of the current TargetClassInterface's implementation.
*
* @param class-string $name
*
* @param string $name
* @return TargetClassInterface
*/
public static function factory($name);
/**
* Returns the targetClass's name.
* Returns the targetClass's attributes.
*
* @return string
* @return array<class-string>
*/
public function getName();
/**
* Returns the targetClass's methods.
*
* @return array
*/
public function getMethods();
public function getAttributes();
/**
* Returns the targetClass's interfaces.
*
* @return array
* @return array<TargetClassInterface>
*/
public function getInterfaces();
/**
* Returns the targetClass's methods.
*
* @return array<Method>
*/
public function getMethods();
/**
* Returns the targetClass's name.
*
* @return class-string
*/
public function getName();
/**
* Returns the targetClass's namespace name.
*
@@ -67,41 +63,42 @@ interface TargetClassInterface
*/
public function getShortName();
/**
* Returns whether the targetClass has
* an internal ancestor.
*
* @return bool
*/
public function hasInternalAncestor();
/**
* Returns whether the targetClass is in
* the passed interface.
*
* @param class-string|string $interface
*
* @return bool
*/
public function implementsInterface($interface);
/**
* Returns whether the targetClass is in namespace.
*
* @return bool
*/
public function inNamespace();
/**
* Returns whether the targetClass is abstract.
*
* @return boolean
* @return bool
*/
public function isAbstract();
/**
* Returns whether the targetClass is final.
*
* @return boolean
* @return bool
*/
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();
}

View File

@@ -1,94 +1,141 @@
<?php
/**
* Mockery
* Mockery (https://docs.mockery.io/)
*
* LICENSE
*
* This source file is subject to the new BSD license that is bundled
* with this package in the file LICENSE.txt.
* It is also available through the world-wide-web at this URL:
* http://github.com/padraic/mockery/blob/master/LICENSE
* If you did not receive a copy of the license and are unable to
* obtain it through the world-wide-web, please send an email
* to padraic@php.net so we can send you a copy immediately.
*
* @category Mockery
* @package Mockery
* @copyright Copyright (c) 2010 Pádraic Brady (http://blog.astrumfutura.com)
* @license http://github.com/padraic/mockery/blob/master/LICENSE New BSD License
* @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 function array_pop;
use function explode;
use function implode;
use function ltrim;
class UndefinedTargetClass implements TargetClassInterface
{
/**
* @var class-string
*/
private $name;
/**
* @param class-string $name
*/
public function __construct($name)
{
$this->name = $name;
}
/**
* @return class-string
*/
public function __toString()
{
return $this->name;
}
/**
* @param class-string $name
* @return self
*/
public static function factory($name)
{
return new self($name);
}
/**
* @return list<class-string>
*/
public function getAttributes()
{
return [];
}
/**
* @return list<self>
*/
public function getInterfaces()
{
return [];
}
/**
* @return list<Method>
*/
public function getMethods()
{
return [];
}
/**
* @return class-string
*/
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();
}
/**
* @return string
*/
public function getNamespaceName()
{
$parts = explode("\\", ltrim($this->getName(), "\\"));
$parts = explode('\\', ltrim($this->getName(), '\\'));
array_pop($parts);
return implode("\\", $parts);
}
public function inNamespace()
{
return $this->getNamespaceName() !== '';
return implode('\\', $parts);
}
/**
* @return string
*/
public function getShortName()
{
$parts = explode("\\", $this->getName());
$parts = explode('\\', $this->getName());
return array_pop($parts);
}
public function implementsInterface($interface)
{
return false;
}
/**
* @return bool
*/
public function hasInternalAncestor()
{
return false;
}
public function __toString()
/**
* @param class-string $interface
* @return bool
*/
public function implementsInterface($interface)
{
return $this->name;
return false;
}
/**
* @return bool
*/
public function inNamespace()
{
return $this->getNamespaceName() !== '';
}
/**
* @return bool
*/
public function isAbstract()
{
return false;
}
/**
* @return bool
*/
public function isFinal()
{
return false;
}
}

View File

@@ -1,33 +1,32 @@
<?php
/**
* Mockery
* Mockery (https://docs.mockery.io/)
*
* LICENSE
*
* This source file is subject to the new BSD license that is bundled
* with this package in the file LICENSE.txt.
* It is also available through the world-wide-web at this URL:
* http://github.com/padraic/mockery/blob/master/LICENSE
* If you did not receive a copy of the license and are unable to
* obtain it through the world-wide-web, please send an email
* to padraic@php.net so we can send you a copy immediately.
*
* @category Mockery
* @package Mockery
* @copyright Copyright (c) 2010 Pádraic Brady (http://blog.astrumfutura.com)
* @license http://github.com/padraic/mockery/blob/master/LICENSE New BSD License
* @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;
/**
* @method \Mockery\Expectation withArgs(\Closure|array $args)
* @method Expectation withArgs(array|Closure $args)
*/
class HigherOrderMessage
{
private $mock;
/**
* @var string
*/
private $method;
/**
* @var LegacyMockInterface|MockInterface
*/
private $mock;
public function __construct(MockInterface $mock, $method)
{
$this->mock = $mock;
@@ -35,7 +34,10 @@ class HigherOrderMessage
}
/**
* @return \Mockery\Expectation
* @param string $method
* @param array $args
*
* @return Expectation|ExpectationInterface|HigherOrderMessage
*/
public function __call($method, $args)
{
@@ -44,6 +46,7 @@ class HigherOrderMessage
}
$expectation = $this->mock->{$this->method}($method);
return $expectation->withArgs($args);
}
}

View File

@@ -1,112 +1,56 @@
<?php
/*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
* A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
* OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
/**
* Mockery (https://docs.mockery.io/)
*
* This software consists of voluntary contributions made by many individuals
* and is licensed under the MIT license. For more information, see
* <http://www.doctrine-project.org>.
* @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 Exception;
use InvalidArgumentException;
use ReflectionClass;
use UnexpectedValueException;
use InvalidArgumentException;
use function class_exists;
use function restore_error_handler;
use function set_error_handler;
use function sprintf;
use function strlen;
use function unserialize;
/**
* This is a trimmed down version of https://github.com/doctrine/instantiator,
* basically without the caching
*
* @author Marco Pivetta <ocramius@gmail.com>
* This is a trimmed down version of https://github.com/doctrine/instantiator, without the caching mechanism.
*/
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.
* @template TClass of object
*
* @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
* @param class-string<TClass> $className
*
* @throws InvalidArgumentException
* @throws UnexpectedValueException
*
* @return TClass
*/
private function getReflectionClass($className)
public function instantiate($className): object
{
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;
return $this->buildFactory($className)();
}
/**
* @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) {
private function attemptInstantiationViaUnSerialization(
ReflectionClass $reflectionClass,
string $serializedString
): void {
set_error_handler(static function ($code, $message, $file, $line) use ($reflectionClass, &$error): void {
$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(),
@@ -114,42 +58,75 @@ final class Instantiator
$line
);
$error = new UnexpectedValueException($msg, 0, new \Exception($message, $code));
$error = new UnexpectedValueException($msg, 0, new Exception($message, $code));
});
try {
unserialize($serializedString);
} catch (\Exception $exception) {
} 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);
throw new UnexpectedValueException(
sprintf(
'An exception was raised while trying to instantiate an instance of "%s" via un-serialization',
$reflectionClass->getName()
),
0,
$exception
);
}
restore_error_handler();
if ($error) {
if ($error instanceof UnexpectedValueException) {
throw $error;
}
}
/**
* @param ReflectionClass $reflectionClass
*
* @return bool
* Builds a {@see Closure} capable of instantiating the given $className without invoking its constructor.
*/
private function isInstantiableViaReflection(ReflectionClass $reflectionClass)
private function buildFactory(string $className): Closure
{
return ! ($reflectionClass->isInternal() && $reflectionClass->isFinal());
$reflectionClass = $this->getReflectionClass($className);
if ($this->isInstantiableViaReflection($reflectionClass)) {
return static function () use ($reflectionClass) {
return $reflectionClass->newInstanceWithoutConstructor();
};
}
$serializedString = sprintf('O:%d:"%s":0:{}', strlen($className), $className);
$this->attemptInstantiationViaUnSerialization($reflectionClass, $serializedString);
return static function () use ($serializedString) {
return unserialize($serializedString);
};
}
/**
* @throws InvalidArgumentException
*/
private function getReflectionClass(string $className): ReflectionClass
{
if (! class_exists($className)) {
throw new InvalidArgumentException(sprintf('Class:%s does not exist', $className));
}
$reflection = new ReflectionClass($className);
if ($reflection->isAbstract()) {
throw new InvalidArgumentException(sprintf('Class:%s is an abstract class', $className));
}
return $reflection;
}
/**
* Verifies whether the given class is to be considered internal
*
* @param ReflectionClass $reflectionClass
*
* @return bool
*/
private function hasInternalAncestors(ReflectionClass $reflectionClass)
private function hasInternalAncestors(ReflectionClass $reflectionClass): bool
{
do {
if ($reflectionClass->isInternal()) {
@@ -159,4 +136,12 @@ final class Instantiator
return false;
}
/**
* Verifies if the class is instantiable via reflection
*/
private function isInstantiableViaReflection(ReflectionClass $reflectionClass): bool
{
return ! ($reflectionClass->isInternal() && $reflectionClass->isFinal());
}
}

View File

@@ -1,112 +1,20 @@
<?php
/**
* Mockery
* Mockery (https://docs.mockery.io/)
*
* LICENSE
*
* This source file is subject to the new BSD license that is bundled
* with this package in the file LICENSE.txt.
* It is also available through the world-wide-web at this URL:
* http://github.com/padraic/mockery/blob/master/LICENSE
* If you did not receive a copy of the license and are unable to
* obtain it through the world-wide-web, please send an email
* to padraic@php.net so we can send you a copy immediately.
*
* @category Mockery
* @package Mockery
* @copyright Copyright (c) 2010 Pádraic Brady (http://blog.astrumfutura.com)
* @license http://github.com/padraic/mockery/blob/master/LICENSE New BSD License
* @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 Throwable;
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 Mock
*/
public function shouldIgnoreMissing($returnValue = null);
/**
* @return Mock
*/
public function shouldAllowMockingProtectedMethods();
/**
* Set mock to defer unexpected methods to its parent if possible
*
* @deprecated since 1.4.0. Please use makePartial() instead.
*
* @return Mock
*/
public function shouldDeferMissing();
/**
* Set mock to defer unexpected methods to its parent if possible
*
* @return Mock
*/
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
@@ -117,19 +25,11 @@ interface LegacyMockInterface
public function byDefault();
/**
* Iterate across all expectation directors and validate each
* Set mock to defer unexpected methods to its parent if possible
*
* @throws \Mockery\CountValidator\Exception
* @return void
* @return self
*/
public function mockery_verify();
/**
* Tear down tasks for this mock
*
* @return void
*/
public function mockery_teardown();
public function makePartial();
/**
* Fetch the next available allocation order number
@@ -139,26 +39,23 @@ interface LegacyMockInterface
public function mockery_allocateOrder();
/**
* Set ordering for a group
* Find an expectation matching the given method and arguments
*
* @param mixed $group
* @param int $order
* @template TMixed
*
* @param string $method
* @param array<TMixed> $args
*
* @return null|Expectation
*/
public function mockery_setGroup($group, $order);
public function mockery_findExpectation($method, array $args);
/**
* Fetch array of ordered groups
* Return the container for this mock
*
* @return array
* @return Container
*/
public function mockery_getGroups();
/**
* Set current ordered number
*
* @param int $order
*/
public function mockery_setCurrentOrder($order);
public function mockery_getContainer();
/**
* Get current ordered number
@@ -167,16 +64,6 @@ interface LegacyMockInterface
*/
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
*
@@ -187,34 +74,28 @@ interface LegacyMockInterface
/**
* 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
* @param string $method
*
* @var string $method
* @return \Mockery\ExpectationDirector|null
* @return null|ExpectationDirector
*/
public function mockery_getExpectationsFor($method);
/**
* Find an expectation matching the given method and arguments
* Fetch array of ordered groups
*
* @var string $method
* @var array $args
* @return \Mockery\Expectation|null
* @return array<string,int>
*/
public function mockery_findExpectation($method, array $args);
public function mockery_getGroups();
/**
* Return the container for this mock
*
* @return \Mockery\Container
* @return string[]
*/
public function mockery_getContainer();
public function mockery_getMockableMethods();
/**
* @return array
*/
public function mockery_getMockableProperties();
/**
* Return the name for this mock
@@ -224,17 +105,154 @@ interface LegacyMockInterface
public function mockery_getName();
/**
* @return array
* Alternative setup method to constructor
*
* @param object $partialObject
*
* @return void
*/
public function mockery_getMockableProperties();
/**
* @return string[]
*/
public function mockery_getMockableMethods();
public function mockery_init(?Container $container = null, $partialObject = null);
/**
* @return bool
*/
public function mockery_isAnonymous();
/**
* Set current ordered number
*
* @param int $order
*
* @return int
*/
public function mockery_setCurrentOrder($order);
/**
* Return the expectations director for the given method
*
* @param string $method
*
* @return null|ExpectationDirector
*/
public function mockery_setExpectationsFor($method, ExpectationDirector $director);
/**
* Set ordering for a group
*
* @param string $group
* @param int $order
*
* @return void
*/
public function mockery_setGroup($group, $order);
/**
* Tear down tasks for this mock
*
* @return void
*/
public function mockery_teardown();
/**
* Validate the current mock's ordering
*
* @param string $method
* @param int $order
*
* @throws Exception
*
* @return void
*/
public function mockery_validateOrder($method, $order);
/**
* Iterate across all expectation directors and validate each
*
* @throws Throwable
*
* @return void
*/
public function mockery_verify();
/**
* Allows additional methods to be mocked that do not explicitly exist on mocked class
*
* @param string $method the method name to be mocked
* @return self
*/
public function shouldAllowMockingMethod($method);
/**
* @return self
*/
public function shouldAllowMockingProtectedMethods();
/**
* Set mock to defer unexpected methods to its parent if possible
*
* @deprecated since 1.4.0. Please use makePartial() instead.
*
* @return self
*/
public function shouldDeferMissing();
/**
* @return self
*/
public function shouldHaveBeenCalled();
/**
* @template TMixed
* @param string $method
* @param null|array<TMixed>|Closure $args
*
* @return self
*/
public function shouldHaveReceived($method, $args = null);
/**
* Set mock to ignore unexpected methods and return Undefined class
*
* @template TReturnValue
*
* @param null|TReturnValue $returnValue the default return value for calls to missing functions on this mock
*
* @return self
*/
public function shouldIgnoreMissing($returnValue = null);
/**
* @template TMixed
* @param null|array<TMixed> $args (optional)
*
* @return self
*/
public function shouldNotHaveBeenCalled(?array $args = null);
/**
* @template TMixed
* @param string $method
* @param null|array<TMixed>|Closure $args
*
* @return self
*/
public function shouldNotHaveReceived($method, $args = null);
/**
* 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 Expectation|ExpectationInterface|HigherOrderMessage
*/
public function shouldNotReceive(...$methodNames);
/**
* Set expected method calls
*
* @param string ...$methodNames one or many methods that are expected to be called in this mock
*
* @return Expectation|ExpectationInterface|HigherOrderMessage
*/
public function shouldReceive(...$methodNames);
}

View File

@@ -1,36 +1,32 @@
<?php
/**
* Mockery
* Mockery (https://docs.mockery.io/)
*
* LICENSE
*
* This source file is subject to the new BSD license that is bundled
* with this package in the file LICENSE.txt.
* It is also available through the world-wide-web at this URL:
* http://github.com/padraic/mockery/blob/master/LICENSE
* If you did not receive a copy of the license and are unable to
* obtain it through the world-wide-web, please send an email
* to padraic@php.net so we can send you a copy immediately.
*
* @category Mockery
* @package Mockery
* @copyright Copyright (c) 2010 Pádraic Brady (http://blog.astrumfutura.com)
* @license http://github.com/padraic/mockery/blob/master/LICENSE New BSD License
* @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;
use function class_exists;
class EvalLoader implements Loader
{
/**
* Load the given mock definition
*
* @return void
*/
public function load(MockDefinition $definition)
{
if (class_exists($definition->getClassName(), false)) {
return;
}
eval("?>" . $definition->getCode());
eval('?>' . $definition->getCode());
}
}

View File

@@ -1,21 +1,11 @@
<?php
/**
* Mockery
* Mockery (https://docs.mockery.io/)
*
* LICENSE
*
* This source file is subject to the new BSD license that is bundled
* with this package in the file LICENSE.txt.
* It is also available through the world-wide-web at this URL:
* http://github.com/padraic/mockery/blob/master/LICENSE
* If you did not receive a copy of the license and are unable to
* obtain it through the world-wide-web, please send an email
* to padraic@php.net so we can send you a copy immediately.
*
* @category Mockery
* @package Mockery
* @copyright Copyright (c) 2010 Pádraic Brady (http://blog.astrumfutura.com)
* @license http://github.com/padraic/mockery/blob/master/LICENSE New BSD License
* @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;
@@ -24,5 +14,10 @@ use Mockery\Generator\MockDefinition;
interface Loader
{
/**
* Load the given mock definition
*
* @return void
*/
public function load(MockDefinition $definition);
}

View File

@@ -1,46 +1,80 @@
<?php
/**
* Mockery
* Mockery (https://docs.mockery.io/)
*
* LICENSE
*
* This source file is subject to the new BSD license that is bundled
* with this package in the file LICENSE.txt.
* It is also available through the world-wide-web at this URL:
* http://github.com/padraic/mockery/blob/master/LICENSE
* If you did not receive a copy of the license and are unable to
* obtain it through the world-wide-web, please send an email
* to padraic@php.net so we can send you a copy immediately.
*
* @category Mockery
* @package Mockery
* @copyright Copyright (c) 2010 Pádraic Brady (http://blog.astrumfutura.com)
* @license http://github.com/padraic/mockery/blob/master/LICENSE New BSD License
* @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;
use function array_diff;
use function class_exists;
use function file_exists;
use function file_put_contents;
use function glob;
use function realpath;
use function sprintf;
use function sys_get_temp_dir;
use function uniqid;
use function unlink;
use const DIRECTORY_SEPARATOR;
class RequireLoader implements Loader
{
/**
* @var string
*/
protected $lastPath = '';
/**
* @var string
*/
protected $path;
/**
* @param string|null $path
*/
public function __construct($path = null)
{
$this->path = realpath($path) ?: sys_get_temp_dir();
if ($path === null) {
$path = sys_get_temp_dir();
}
$this->path = realpath($path);
}
public function __destruct()
{
$files = array_diff(glob($this->path . DIRECTORY_SEPARATOR . 'Mockery_*.php') ?: [], [$this->lastPath]);
foreach ($files as $file) {
@unlink($file);
}
}
/**
* Load the given mock definition
*
* @return void
*/
public function load(MockDefinition $definition)
{
if (class_exists($definition->getClassName(), false)) {
return;
}
$tmpfname = $this->path . DIRECTORY_SEPARATOR . "Mockery_" . uniqid() . ".php";
file_put_contents($tmpfname, $definition->getCode());
$this->lastPath = sprintf('%s%s%s.php', $this->path, DIRECTORY_SEPARATOR, uniqid('Mockery_', false));
require $tmpfname;
file_put_contents($this->lastPath, $definition->getCode());
if (file_exists($this->lastPath)) {
require $this->lastPath;
}
}
}

View File

@@ -1,38 +1,17 @@
<?php
/**
* Mockery
* Mockery (https://docs.mockery.io/)
*
* LICENSE
*
* This source file is subject to the new BSD license that is bundled
* with this package in the file LICENSE.txt.
* It is also available through the world-wide-web at this URL:
* http://github.com/padraic/mockery/blob/master/LICENSE
* If you did not receive a copy of the license and are unable to
* obtain it through the world-wide-web, please send an email
* to padraic@php.net so we can send you a copy immediately.
*
* @category Mockery
* @package Mockery
* @copyright Copyright (c) 2010 Pádraic Brady (http://blog.astrumfutura.com)
* @license http://github.com/padraic/mockery/blob/master/LICENSE New BSD License
* @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
*
@@ -42,4 +21,18 @@ class AndAnyOtherArgs extends MatcherAbstract
{
return '<AndAnyOthers>';
}
/**
* Check if the actual value matches the expected.
*
* @template TMixed
*
* @param TMixed $actual
*
* @return bool
*/
public function match(&$actual)
{
return true;
}
}

View File

@@ -1,38 +1,17 @@
<?php
/**
* Mockery
* Mockery (https://docs.mockery.io/)
*
* LICENSE
*
* This source file is subject to the new BSD license that is bundled
* with this package in the file LICENSE.txt.
* It is also available through the world-wide-web at this URL:
* http://github.com/padraic/mockery/blob/master/LICENSE
* If you did not receive a copy of the license and are unable to
* obtain it through the world-wide-web, please send an email
* to padraic@php.net so we can send you a copy immediately.
*
* @category Mockery
* @package Mockery
* @copyright Copyright (c) 2010 Pádraic Brady (http://blog.astrumfutura.com)
* @license http://github.com/padraic/mockery/blob/master/LICENSE New BSD License
* @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
*
@@ -42,4 +21,18 @@ class Any extends MatcherAbstract
{
return '<Any>';
}
/**
* Check if the actual value matches the expected.
*
* @template TMixed
*
* @param TMixed $actual
*
* @return bool
*/
public function match(&$actual)
{
return true;
}
}

View File

@@ -1,40 +1,31 @@
<?php
/**
* Mockery
* Mockery (https://docs.mockery.io/)
*
* LICENSE
*
* This source file is subject to the new BSD license that is bundled
* with this package in the file LICENSE.txt.
* It is also available through the world-wide-web at this URL:
* http://github.com/padraic/mockery/blob/master/LICENSE
* If you did not receive a copy of the license and are unable to
* obtain it through the world-wide-web, please send an email
* to padraic@php.net so we can send you a copy immediately.
*
* @category Mockery
* @package Mockery
* @copyright Copyright (c) 2017 Dave Marshall
* @license http://github.com/padraic/mockery/blob/master/LICENSE New BSD License
* @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
{
public function __toString()
{
return '<Any Arguments>';
}
/**
* @inheritdoc
* @template TMixed
*
* @param TMixed $actual
*
* @return bool
*/
public function match(&$actual)
{
return true;
}
/**
* @inheritdoc
*/
public function __toString()
{
return '<Any Arguments>';
}
}

View File

@@ -1,39 +1,19 @@
<?php
/**
* Mockery
* Mockery (https://docs.mockery.io/)
*
* LICENSE
*
* This source file is subject to the new BSD license that is bundled
* with this package in the file LICENSE.txt.
* It is also available through the world-wide-web at this URL:
* http://github.com/padraic/mockery/blob/master/LICENSE
* If you did not receive a copy of the license and are unable to
* obtain it through the world-wide-web, please send an email
* to padraic@php.net so we can send you a copy immediately.
*
* @category Mockery
* @package Mockery
* @copyright Copyright (c) 2010 Pádraic Brady (http://blog.astrumfutura.com)
* @license http://github.com/padraic/mockery/blob/master/LICENSE New BSD License
* @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;
use function in_array;
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
*
@@ -43,4 +23,19 @@ class AnyOf extends MatcherAbstract
{
return '<AnyOf>';
}
/**
* Check if the actual value does not match the expected (in this
* case it's specifically NOT expected).
*
* @template TMixed
*
* @param TMixed $actual
*
* @return bool
*/
public function match(&$actual)
{
return in_array($actual, $this->_expected, true);
}
}

View File

@@ -1,21 +1,11 @@
<?php
/**
* Mockery
* Mockery (https://docs.mockery.io/)
*
* LICENSE
*
* This source file is subject to the new BSD license that is bundled
* with this package in the file LICENSE.txt.
* It is also available through the world-wide-web at this URL:
* http://github.com/padraic/mockery/blob/master/LICENSE
* If you did not receive a copy of the license and are unable to
* obtain it through the world-wide-web, please send an email
* to padraic@php.net so we can send you a copy immediately.
*
* @category Mockery
* @package Mockery
* @copyright Copyright (c) 2017 Dave Marshall
* @license http://github.com/padraic/mockery/blob/master/LICENSE New BSD License
* @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;

View File

@@ -1,40 +1,17 @@
<?php
/**
* Mockery
* Mockery (https://docs.mockery.io/)
*
* LICENSE
*
* This source file is subject to the new BSD license that is bundled
* with this package in the file LICENSE.txt.
* It is also available through the world-wide-web at this URL:
* http://github.com/padraic/mockery/blob/master/LICENSE
* If you did not receive a copy of the license and are unable to
* obtain it through the world-wide-web, please send an email
* to padraic@php.net so we can send you a copy immediately.
*
* @category Mockery
* @package Mockery
* @copyright Copyright (c) 2010 Pádraic Brady (http://blog.astrumfutura.com)
* @license http://github.com/padraic/mockery/blob/master/LICENSE New BSD License
* @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
*
@@ -44,4 +21,18 @@ class Closure extends MatcherAbstract
{
return '<Closure===true>';
}
/**
* Check if the actual value matches the expected.
*
* @template TMixed
*
* @param TMixed $actual
*
* @return bool
*/
public function match(&$actual)
{
return ($this->_expected)($actual) === true;
}
}

View File

@@ -1,31 +1,42 @@
<?php
/**
* Mockery
* Mockery (https://docs.mockery.io/)
*
* LICENSE
*
* This source file is subject to the new BSD license that is bundled
* with this package in the file LICENSE.txt.
* It is also available through the world-wide-web at this URL:
* http://github.com/padraic/mockery/blob/master/LICENSE
* If you did not receive a copy of the license and are unable to
* obtain it through the world-wide-web, please send an email
* to padraic@php.net so we can send you a copy immediately.
*
* @category Mockery
* @package Mockery
* @copyright Copyright (c) 2010 Pádraic Brady (http://blog.astrumfutura.com)
* @license http://github.com/padraic/mockery/blob/master/LICENSE New BSD License
* @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;
use function array_values;
use function implode;
class Contains extends MatcherAbstract
{
/**
* Return a string representation of this Matcher
*
* @return string
*/
public function __toString()
{
$elements = [];
foreach ($this->_expected as $v) {
$elements[] = (string) $v;
}
return '<Contains[' . implode(', ', $elements) . ']>';
}
/**
* Check if the actual value matches the expected.
*
* @param mixed $actual
* @template TMixed
*
* @param TMixed $actual
*
* @return bool
*/
public function match(&$actual)
@@ -39,26 +50,12 @@ class Contains extends MatcherAbstract
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;
}
}

View File

@@ -1,46 +1,21 @@
<?php
/**
* Mockery
* Mockery (https://docs.mockery.io/)
*
* LICENSE
*
* This source file is subject to the new BSD license that is bundled
* with this package in the file LICENSE.txt.
* It is also available through the world-wide-web at this URL:
* http://github.com/padraic/mockery/blob/master/LICENSE
* If you did not receive a copy of the license and are unable to
* obtain it through the world-wide-web, please send an email
* to padraic@php.net so we can send you a copy immediately.
*
* @category Mockery
* @package Mockery
* @copyright Copyright (c) 2010 Pádraic Brady (http://blog.astrumfutura.com)
* @license http://github.com/padraic/mockery/blob/master/LICENSE New BSD License
* @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;
use function implode;
use function is_object;
use function method_exists;
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
*
@@ -50,4 +25,28 @@ class Ducktype extends MatcherAbstract
{
return '<Ducktype[' . implode(', ', $this->_expected) . ']>';
}
/**
* Check if the actual value matches the expected.
*
* @template TMixed
*
* @param TMixed $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;
}
}

View File

@@ -1,38 +1,23 @@
<?php
/**
* Mockery
* Mockery (https://docs.mockery.io/)
*
* LICENSE
*
* This source file is subject to the new BSD license that is bundled
* with this package in the file LICENSE.txt.
* It is also available through the world-wide-web at this URL:
* http://github.com/padraic/mockery/blob/master/LICENSE
* If you did not receive a copy of the license and are unable to
* obtain it through the world-wide-web, please send an email
* to padraic@php.net so we can send you a copy immediately.
*
* @category Mockery
* @package Mockery
* @copyright Copyright (c) 2010 Pádraic Brady (http://blog.astrumfutura.com)
* @license http://github.com/padraic/mockery/blob/master/LICENSE New BSD License
* @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;
use ArrayAccess;
use function array_key_exists;
use function is_array;
use function sprintf;
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
*
@@ -40,6 +25,24 @@ class HasKey extends MatcherAbstract
*/
public function __toString()
{
return "<HasKey[$this->_expected]>";
return sprintf('<HasKey[%s]>', $this->_expected);
}
/**
* Check if the actual value matches the expected.
*
* @template TMixed
*
* @param TMixed $actual
*
* @return bool
*/
public function match(&$actual)
{
if (! is_array($actual) && ! $actual instanceof ArrayAccess) {
return false;
}
return array_key_exists($this->_expected, (array) $actual);
}
}

View File

@@ -1,38 +1,22 @@
<?php
/**
* Mockery
* Mockery (https://docs.mockery.io/)
*
* LICENSE
*
* This source file is subject to the new BSD license that is bundled
* with this package in the file LICENSE.txt.
* It is also available through the world-wide-web at this URL:
* http://github.com/padraic/mockery/blob/master/LICENSE
* If you did not receive a copy of the license and are unable to
* obtain it through the world-wide-web, please send an email
* to padraic@php.net so we can send you a copy immediately.
*
* @category Mockery
* @package Mockery
* @copyright Copyright (c) 2010 Pádraic Brady (http://blog.astrumfutura.com)
* @license http://github.com/padraic/mockery/blob/master/LICENSE New BSD License
* @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;
use ArrayAccess;
use function in_array;
use function is_array;
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
*
@@ -40,7 +24,24 @@ class HasValue extends MatcherAbstract
*/
public function __toString()
{
$return = '<HasValue[' . (string) $this->_expected . ']>';
return $return;
return '<HasValue[' . (string) $this->_expected . ']>';
}
/**
* Check if the actual value matches the expected.
*
* @template TMixed
*
* @param TMixed $actual
*
* @return bool
*/
public function match(&$actual)
{
if (! is_array($actual) && ! $actual instanceof ArrayAccess) {
return false;
}
return in_array($this->_expected, (array) $actual, true);
}
}

View File

@@ -1,58 +1,39 @@
<?php
/**
* Mockery
* Mockery (https://docs.mockery.io/)
*
* LICENSE
*
* This source file is subject to the new BSD license that is bundled
* with this package in the file LICENSE.txt.
* It is also available through the world-wide-web at this URL:
* http://github.com/padraic/mockery/blob/master/LICENSE
* If you did not receive a copy of the license and are unable to
* obtain it through the world-wide-web, please send an email
* to padraic@php.net so we can send you a copy immediately.
*
* @category Mockery
* @package Mockery
* @copyright Copyright (c) 2010 Pádraic Brady (http://blog.astrumfutura.com)
* @license http://github.com/padraic/mockery/blob/master/LICENSE New BSD License
* @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
/**
* @deprecated Implement \Mockery\Matcher\MatcherInterface instead of extending this class
* @see https://github.com/mockery/mockery/pull/1338
*/
abstract class MatcherAbstract implements MatcherInterface
{
/**
* The expected value (or part thereof)
*
* @var mixed
* @template TExpected
*
* @var TExpected
*/
protected $_expected = null;
/**
* Set the expected value
*
* @param mixed $expected
* @template TExpected
*
* @param TExpected $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();
}

View File

@@ -1,41 +1,17 @@
<?php
/**
* Mockery
* Mockery (https://docs.mockery.io/)
*
* LICENSE
*
* This source file is subject to the new BSD license that is bundled
* with this package in the file LICENSE.txt.
* It is also available through the world-wide-web at this URL:
* http://github.com/padraic/mockery/blob/master/LICENSE
* If you did not receive a copy of the license and are unable to
* obtain it through the world-wide-web, please send an email
* to padraic@php.net so we can send you a copy immediately.
*
* @category Mockery
* @package Mockery
* @copyright Copyright (c) 2010 Pádraic Brady (http://blog.astrumfutura.com)
* @license http://github.com/padraic/mockery/blob/master/LICENSE New BSD License
* @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
*
@@ -45,4 +21,20 @@ class MultiArgumentClosure extends MatcherAbstract implements ArgumentListMatche
{
return '<MultiArgumentClosure===true>';
}
/**
* Check if the actual value matches the expected.
* Actual passed by reference to preserve reference trail (where applicable)
* back to the original method parameter.
*
* @template TMixed
*
* @param TMixed $actual
*
* @return bool
*/
public function match(&$actual)
{
return ($this->_expected)(...$actual) === true;
}
}

View File

@@ -1,45 +1,22 @@
<?php
/**
* Mockery
* Mockery (https://docs.mockery.io/)
*
* LICENSE
*
* This source file is subject to the new BSD license that is bundled
* with this package in the file LICENSE.txt.
* It is also available through the world-wide-web at this URL:
* http://github.com/padraic/mockery/blob/master/LICENSE
* If you did not receive a copy of the license and are unable to
* obtain it through the world-wide-web, please send an email
* to padraic@php.net so we can send you a copy immediately.
*
* @category Mockery
* @package Mockery
* @copyright Copyright (c) 2010 Pádraic Brady (http://blog.astrumfutura.com)
* @license http://github.com/padraic/mockery/blob/master/LICENSE New BSD License
* @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;
use function is_object;
/**
* @deprecated 2.0 Due to ambiguity, use Hamcrest or PHPUnit equivalents
* @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
*
@@ -49,4 +26,22 @@ class MustBe extends MatcherAbstract
{
return '<MustBe>';
}
/**
* Check if the actual value matches the expected.
*
* @template TMixed
*
* @param TMixed $actual
*
* @return bool
*/
public function match(&$actual)
{
if (! is_object($actual)) {
return $this->_expected === $actual;
}
return $this->_expected == $actual;
}
}

View File

@@ -1,40 +1,33 @@
<?php
/**
* Mockery
* Mockery (https://docs.mockery.io/)
*
* LICENSE
*
* This source file is subject to the new BSD license that is bundled
* with this package in the file LICENSE.txt.
* It is also available through the world-wide-web at this URL:
* http://github.com/padraic/mockery/blob/master/LICENSE
* If you did not receive a copy of the license and are unable to
* obtain it through the world-wide-web, please send an email
* to padraic@php.net so we can send you a copy immediately.
*
* @category Mockery
* @package Mockery
* @copyright Copyright (c) 2017 Dave Marshall
* @license http://github.com/padraic/mockery/blob/master/LICENSE New BSD License
* @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;
use function count;
class NoArgs extends MatcherAbstract implements ArgumentListMatcher
{
/**
* @inheritdoc
*/
public function match(&$actual)
{
return count($actual) == 0;
}
/**
* @inheritdoc
*/
public function __toString()
{
return '<No Arguments>';
}
/**
* @template TMixed
*
* @param TMixed $actual
*
* @return bool
*/
public function match(&$actual)
{
return count($actual) === 0;
}
}

View File

@@ -1,39 +1,17 @@
<?php
/**
* Mockery
* Mockery (https://docs.mockery.io/)
*
* LICENSE
*
* This source file is subject to the new BSD license that is bundled
* with this package in the file LICENSE.txt.
* It is also available through the world-wide-web at this URL:
* http://github.com/padraic/mockery/blob/master/LICENSE
* If you did not receive a copy of the license and are unable to
* obtain it through the world-wide-web, please send an email
* to padraic@php.net so we can send you a copy immediately.
*
* @category Mockery
* @package Mockery
* @copyright Copyright (c) 2010 Pádraic Brady (http://blog.astrumfutura.com)
* @license http://github.com/padraic/mockery/blob/master/LICENSE New BSD License
* @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
*
@@ -43,4 +21,19 @@ class Not extends MatcherAbstract
{
return '<Not>';
}
/**
* Check if the actual value does not match the expected (in this
* case it's specifically NOT expected).
*
* @template TMixed
*
* @param TMixed $actual
*
* @return bool
*/
public function match(&$actual)
{
return $actual !== $this->_expected;
}
}

View File

@@ -1,44 +1,17 @@
<?php
/**
* Mockery
* Mockery (https://docs.mockery.io/)
*
* LICENSE
*
* This source file is subject to the new BSD license that is bundled
* with this package in the file LICENSE.txt.
* It is also available through the world-wide-web at this URL:
* http://github.com/padraic/mockery/blob/master/LICENSE
* If you did not receive a copy of the license and are unable to
* obtain it through the world-wide-web, please send an email
* to padraic@php.net so we can send you a copy immediately.
*
* @category Mockery
* @package Mockery
* @copyright Copyright (c) 2010 Pádraic Brady (http://blog.astrumfutura.com)
* @license http://github.com/padraic/mockery/blob/master/LICENSE New BSD License
* @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
*
@@ -48,4 +21,25 @@ class NotAnyOf extends MatcherAbstract
{
return '<AnyOf>';
}
/**
* Check if the actual value does not match the expected (in this
* case it's specifically NOT expected).
*
* @template TMixed
*
* @param TMixed $actual
*
* @return bool
*/
public function match(&$actual)
{
foreach ($this->_expected as $exp) {
if ($actual === $exp || $actual == $exp) {
return false;
}
}
return true;
}
}

View File

@@ -1,38 +1,19 @@
<?php
/**
* Mockery
* Mockery (https://docs.mockery.io/)
*
* LICENSE
*
* This source file is subject to the new BSD license that is bundled
* with this package in the file LICENSE.txt.
* It is also available through the world-wide-web at this URL:
* http://github.com/padraic/mockery/blob/master/LICENSE
* If you did not receive a copy of the license and are unable to
* obtain it through the world-wide-web, please send an email
* to padraic@php.net so we can send you a copy immediately.
*
* @category Mockery
* @package Mockery
* @copyright Copyright (c) 2010 Pádraic Brady (http://blog.astrumfutura.com)
* @license http://github.com/padraic/mockery/blob/master/LICENSE New BSD License
* @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;
use function preg_match;
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
*
@@ -42,4 +23,18 @@ class Pattern extends MatcherAbstract
{
return '<Pattern>';
}
/**
* Check if the actual value matches the expected pattern.
*
* @template TMixed
*
* @param TMixed $actual
*
* @return bool
*/
public function match(&$actual)
{
return preg_match($this->_expected, (string) $actual) >= 1;
}
}

View File

@@ -1,33 +1,28 @@
<?php
/**
* Mockery
* Mockery (https://docs.mockery.io/)
*
* LICENSE
*
* This source file is subject to the new BSD license that is bundled
* with this package in the file LICENSE.txt.
* It is also available through the world-wide-web at this URL:
* http://github.com/padraic/mockery/blob/master/LICENSE
* If you did not receive a copy of the license and are unable to
* obtain it through the world-wide-web, please send an email
* to padraic@php.net so we can send you a copy immediately.
*
* @category Mockery
* @package Mockery
* @copyright Copyright (c) 2010 Pádraic Brady (http://blog.astrumfutura.com)
* @license http://github.com/padraic/mockery/blob/master/LICENSE New BSD License
* @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;
use function array_replace_recursive;
use function implode;
use function is_array;
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
* @param bool $strict Whether to run a strict or loose comparison
*/
public function __construct(array $expected, $strict = true)
{
@@ -36,13 +31,13 @@ class Subset extends MatcherAbstract
}
/**
* @param array $expected Expected subset of data
* Return a string representation of this Matcher
*
* @return Subset
* @return string
*/
public static function strict(array $expected)
public function __toString()
{
return new static($expected, true);
return '<Subset' . $this->formatArray($this->expected) . '>';
}
/**
@@ -58,12 +53,15 @@ class Subset extends MatcherAbstract
/**
* Check if the actual value matches the expected.
*
* @param mixed $actual
* @template TMixed
*
* @param TMixed $actual
*
* @return bool
*/
public function match(&$actual)
{
if (!is_array($actual)) {
if (! is_array($actual)) {
return false;
}
@@ -75,18 +73,27 @@ class Subset extends MatcherAbstract
}
/**
* Return a string representation of this Matcher
* @param array $expected Expected subset of data
*
* @return Subset
*/
public static function strict(array $expected)
{
return new static($expected, true);
}
/**
* Recursively format an array into the string representation for this matcher
*
* @return string
*/
public function __toString()
protected function formatArray(array $array)
{
$return = '<Subset[';
$elements = array();
foreach ($this->expected as $k=>$v) {
$elements[] = $k . '=' . (string) $v;
$elements = [];
foreach ($array as $k => $v) {
$elements[] = $k . '=' . (is_array($v) ? $this->formatArray($v) : (string) $v);
}
$return .= implode(', ', $elements) . ']>';
return $return;
return '[' . implode(', ', $elements) . ']';
}
}

View File

@@ -1,49 +1,24 @@
<?php
/**
* Mockery
* Mockery (https://docs.mockery.io/)
*
* LICENSE
*
* This source file is subject to the new BSD license that is bundled
* with this package in the file LICENSE.txt.
* It is also available through the world-wide-web at this URL:
* http://github.com/padraic/mockery/blob/master/LICENSE
* If you did not receive a copy of the license and are unable to
* obtain it through the world-wide-web, please send an email
* to padraic@php.net so we can send you a copy immediately.
*
* @category Mockery
* @package Mockery
* @copyright Copyright (c) 2010 Pádraic Brady (http://blog.astrumfutura.com)
* @license http://github.com/padraic/mockery/blob/master/LICENSE New BSD License
* @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;
use function class_exists;
use function function_exists;
use function interface_exists;
use function is_string;
use function strtolower;
use function ucfirst;
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
*
@@ -53,4 +28,32 @@ class Type extends MatcherAbstract
{
return '<' . ucfirst($this->_expected) . '>';
}
/**
* Check if the actual value matches the expected.
*
* @template TMixed
*
* @param TMixed $actual
*
* @return bool
*/
public function match(&$actual)
{
$function = $this->_expected === 'real' ? 'is_float' : 'is_' . strtolower($this->_expected);
if (function_exists($function)) {
return $function($actual);
}
if (! is_string($this->_expected)) {
return false;
}
if (class_exists($this->_expected) || interface_exists($this->_expected)) {
return $actual instanceof $this->_expected;
}
return false;
}
}

View File

@@ -1,43 +1,50 @@
<?php
/**
* Mockery
* Mockery (https://docs.mockery.io/)
*
* LICENSE
*
* This source file is subject to the new BSD license that is bundled
* with this package in the file LICENSE.txt.
* It is also available through the world-wide-web at this URL:
* http://github.com/padraic/mockery/blob/master/LICENSE
* If you did not receive a copy of the license and are unable to
* obtain it through the world-wide-web, please send an email
* to padraic@php.net so we can send you a copy immediately.
*
* @category Mockery
* @package Mockery
* @copyright Copyright (c) 2010 Pádraic Brady (http://blog.astrumfutura.com)
* @license http://github.com/padraic/mockery/blob/master/LICENSE New BSD License
* @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;
/**
* @var array
*/
private $args;
/**
* @var string
*/
private $method;
/**
* @param string $method
* @param array $args
*/
public function __construct($method, $args)
{
$this->method = $method;
$this->args = $args;
}
public function getMethod()
{
return $this->method;
}
/**
* @return array
*/
public function getArgs()
{
return $this->args;
}
/**
* @return string
*/
public function getMethod()
{
return $this->method;
}
}

View File

@@ -1,32 +1,34 @@
<?php
/**
* Mockery
* Mockery (https://docs.mockery.io/)
*
* LICENSE
*
* This source file is subject to the new BSD license that is bundled
* with this package in the file LICENSE.txt.
* It is also available through the world-wide-web at this URL:
* http://github.com/padraic/mockery/blob/master/LICENSE
* If you did not receive a copy of the license and are unable to
* obtain it through the world-wide-web, please send an email
* to padraic@php.net so we can send you a copy immediately.
*
* @category Mockery
* @package Mockery
* @copyright Copyright (c) 2010 Pádraic Brady (http://blog.astrumfutura.com)
* @license http://github.com/padraic/mockery/blob/master/LICENSE New BSD License
* @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\Container;
use Mockery\CountValidator\Exception;
use Mockery\Exception\BadMethodCallException;
use Mockery\Exception\InvalidOrderException;
use Mockery\Exception\NoMatchingExpectationException;
use Mockery\Expectation;
use Mockery\ExpectationDirector;
use Mockery\ExpectsHigherOrderMessage;
use Mockery\HigherOrderMessage;
use Mockery\LegacyMockInterface;
use Mockery\MethodCall;
use Mockery\MockInterface;
use Mockery\ReceivedMethodCalls;
use Mockery\Reflector;
use Mockery\Undefined;
use Mockery\VerificationDirector;
use Mockery\VerificationExpectation;
#[\AllowDynamicProperties]
class Mock implements MockInterface
{
/**
@@ -34,7 +36,7 @@ class Mock implements MockInterface
*
* @var array
*/
protected $_mockery_expectations = array();
protected $_mockery_expectations = [];
/**
* Stores an initial number of expectations that can be manipulated
@@ -101,12 +103,12 @@ class Mock implements MockInterface
*
* @var array
*/
protected $_mockery_groups = array();
protected $_mockery_groups = [];
/**
* Mock container containing this mock object
*
* @var \Mockery\Container
* @var Container
*/
protected $_mockery_container = null;
@@ -134,12 +136,12 @@ class Mock implements MockInterface
*
* @var array
*/
protected $_mockery_mockableProperties = array();
protected $_mockery_mockableProperties = [];
/**
* @var array
*/
protected $_mockery_mockableMethods = array();
protected $_mockery_mockableMethods = [];
/**
* Just a local cache for this mock's target's methods
@@ -167,20 +169,24 @@ class Mock implements MockInterface
protected $_mockery_instanceMock = true;
/** @var null|string $parentClass */
private $_mockery_parentClass = null;
/**
* We want to avoid constructors since class is copied to Generator.php
* for inclusion on extending class definitions.
*
* @param \Mockery\Container $container
* @param Container $container
* @param object $partialObject
* @param bool $instanceMock
* @return void
*/
public function mockery_init(\Mockery\Container $container = null, $partialObject = null, $instanceMock = true)
public function mockery_init(?Container $container = null, $partialObject = null, $instanceMock = true)
{
if (is_null($container)) {
$container = new \Mockery\Container();
if (null === $container) {
$container = new Container();
}
$this->_mockery_container = $container;
if (!is_null($partialObject)) {
$this->_mockery_partial = $partialObject;
@@ -195,6 +201,8 @@ class Mock implements MockInterface
}
$this->_mockery_instanceMock = $instanceMock;
$this->_mockery_parentClass = get_parent_class($this);
}
/**
@@ -202,54 +210,54 @@ class Mock implements MockInterface
*
* @param string ...$methodNames one or many methods that are expected to be called in this mock
*
* @return \Mockery\ExpectationInterface|\Mockery\Expectation|\Mockery\HigherOrderMessage
* @return ExpectationInterface|Expectation|HigherOrderMessage
*/
public function shouldReceive(...$methodNames)
{
if (count($methodNames) === 0) {
return new HigherOrderMessage($this, "shouldReceive");
if ($methodNames === []) {
return new HigherOrderMessage($this, 'shouldReceive');
}
foreach ($methodNames as $method) {
if ("" == $method) {
throw new \InvalidArgumentException("Received empty method name");
if ('' === $method) {
throw new \InvalidArgumentException('Received empty method name');
}
}
$self = $this;
$allowMockingProtectedMethods = $this->_mockery_allowMockingProtectedMethods;
$lastExpectation = \Mockery::parseShouldReturnArgs(
return \Mockery::parseShouldReturnArgs(
$this,
$methodNames,
function ($method) use ($self, $allowMockingProtectedMethods) {
static 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");
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.");
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);
$director = new ExpectationDirector($method, $self);
$self->mockery_setExpectationsFor($method, $director);
}
$expectation = new \Mockery\Expectation($self, $method);
$expectation = new 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
* @return self|ExpectationInterface|Expectation|HigherOrderMessage
*/
public function allows($something = [])
{
@@ -267,14 +275,14 @@ class Mock implements MockInterface
return $this;
}
// end method allows
// end method allows
// start method expects
/**
/**
* @param mixed $something String method name (optional)
* @return \Mockery\ExpectationInterface|\Mockery\Expectation|ExpectsHigherOrderMessage
*/
/**
* @param mixed $something String method name (optional)
* @return ExpectationInterface|Expectation|ExpectsHigherOrderMessage
*/
public function expects($something = null)
{
if (is_string($something)) {
@@ -283,29 +291,32 @@ class Mock implements MockInterface
return new ExpectsHigherOrderMessage($this);
}
// end method expects
// 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
* @return ExpectationInterface|Expectation|HigherOrderMessage
*/
public function shouldNotReceive(...$methodNames)
{
if (count($methodNames) === 0) {
return new HigherOrderMessage($this, "shouldNotReceive");
if ($methodNames === []) {
return new HigherOrderMessage($this, 'shouldNotReceive');
}
$expectation = call_user_func_array(array($this, 'shouldReceive'), $methodNames);
$expectation = call_user_func_array(function (string $methodNames) {
return $this->shouldReceive($methodNames);
}, $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
*
* @param string $method name of the method to be mocked
* @return Mock|MockInterface|LegacyMockInterface
*/
public function shouldAllowMockingMethod($method)
{
@@ -317,7 +328,7 @@ class Mock implements MockInterface
* 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 Mock
* @return static
*/
public function shouldIgnoreMissing($returnValue = null, $recursive = false)
{
@@ -330,12 +341,12 @@ class Mock implements MockInterface
public function asUndefined()
{
$this->_mockery_ignoreMissing = true;
$this->_mockery_defaultReturnValue = new \Mockery\Undefined();
$this->_mockery_defaultReturnValue = new Undefined();
return $this;
}
/**
* @return Mock
* @return static
*/
public function shouldAllowMockingProtectedMethods()
{
@@ -360,7 +371,7 @@ class Mock implements MockInterface
*
* @deprecated 2.0.0 Please use makePartial() instead
*
* @return Mock
* @return static
*/
public function shouldDeferMissing()
{
@@ -373,7 +384,7 @@ class Mock implements MockInterface
* It was an alias for shouldDeferMissing(), which will be removed
* in 2.0.0.
*
* @return Mock
* @return static
*/
public function makePartial()
{
@@ -396,6 +407,7 @@ class Mock implements MockInterface
$exp->byDefault();
}
}
return $this;
}
@@ -415,15 +427,16 @@ class Mock implements MockInterface
/**
* Forward calls to this magic method to the __call method
*/
#[\ReturnTypeWillChange]
public function __toString()
{
return $this->__call('__toString', array());
return $this->__call('__toString', []);
}
/**
* Iterate across all expectation directors and validate each
*
* @throws \Mockery\CountValidator\Exception
* @throws Exception
* @return void
*/
public function mockery_verify()
@@ -431,10 +444,12 @@ class Mock implements MockInterface
if ($this->_mockery_verified) {
return;
}
if (isset($this->_mockery_ignoreVerification)
if (property_exists($this, '_mockery_ignoreVerification') && $this->_mockery_ignoreVerification !== null
&& $this->_mockery_ignoreVerification == true) {
return;
}
$this->_mockery_verified = true;
foreach ($this->_mockery_expectations as $director) {
$director->verify();
@@ -467,7 +482,7 @@ class Mock implements MockInterface
*/
public function mockery_allocateOrder()
{
$this->_mockery_allocatedOrder += 1;
++$this->_mockery_allocatedOrder;
return $this->_mockery_allocatedOrder;
}
@@ -524,8 +539,8 @@ class Mock implements MockInterface
public function mockery_validateOrder($method, $order)
{
if ($order < $this->_mockery_currentOrder) {
$exception = new \Mockery\Exception\InvalidOrderException(
'Method ' . __CLASS__ . '::' . $method . '()'
$exception = new InvalidOrderException(
'Method ' . self::class . '::' . $method . '()'
. ' called out of order: expected order '
. $order . ', was ' . $this->_mockery_currentOrder
);
@@ -535,6 +550,7 @@ class Mock implements MockInterface
->setActualOrder($this->_mockery_currentOrder);
throw $exception;
}
$this->mockery_setCurrentOrder($order);
}
@@ -549,6 +565,7 @@ class Mock implements MockInterface
foreach ($this->_mockery_expectations as $director) {
$count += $director->getExpectationCount();
}
return $count;
}
@@ -556,9 +573,9 @@ class Mock implements MockInterface
* Return the expectations director for the given method
*
* @var string $method
* @return \Mockery\ExpectationDirector|null
* @return ExpectationDirector|null
*/
public function mockery_setExpectationsFor($method, \Mockery\ExpectationDirector $director)
public function mockery_setExpectationsFor($method, ExpectationDirector $director)
{
$this->_mockery_expectations[$method] = $director;
}
@@ -567,7 +584,7 @@ class Mock implements MockInterface
* Return the expectations director for the given method
*
* @var string $method
* @return \Mockery\ExpectationDirector|null
* @return ExpectationDirector|null
*/
public function mockery_getExpectationsFor($method)
{
@@ -581,13 +598,14 @@ class Mock implements MockInterface
*
* @var string $method
* @var array $args
* @return \Mockery\Expectation|null
* @return 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);
@@ -596,7 +614,7 @@ class Mock implements MockInterface
/**
* Return the container for this mock
*
* @return \Mockery\Container
* @return Container
*/
public function mockery_getContainer()
{
@@ -610,7 +628,7 @@ class Mock implements MockInterface
*/
public function mockery_getName()
{
return __CLASS__;
return self::class;
}
/**
@@ -623,11 +641,19 @@ class Mock implements MockInterface
public function __isset($name)
{
if (false === stripos($name, '_mockery_') && get_parent_class($this) && method_exists(get_parent_class($this), '__isset')) {
return call_user_func('parent::__isset', $name);
if (false !== stripos($name, '_mockery_')) {
return false;
}
return false;
if (!$this->_mockery_parentClass) {
return false;
}
if (!method_exists($this->_mockery_parentClass, '__isset')) {
return false;
}
return call_user_func($this->_mockery_parentClass . '::__isset', $name);
}
public function mockery_getExpectations()
@@ -646,10 +672,11 @@ class Mock implements MockInterface
*/
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('parent::__call', $name, $args);
if (!method_exists($this, $name) && $this->_mockery_parentClass && method_exists($this->_mockery_parentClass, '__call')) {
return call_user_func($this->_mockery_parentClass . '::__call', $name, $args);
}
return call_user_func_array('parent::' . $name, $args);
return call_user_func_array($this->_mockery_parentClass . '::' . $name, $args);
}
/**
@@ -668,7 +695,7 @@ class Mock implements MockInterface
$rfc = new \ReflectionClass($this);
// PHP 8 has Stringable interface
$interfaces = array_filter($rfc->getInterfaces(), function ($i) {
$interfaces = array_filter($rfc->getInterfaces(), static function ($i) {
return $i->getName() !== 'Stringable';
});
@@ -729,6 +756,8 @@ class Mock implements MockInterface
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':
@@ -736,12 +765,14 @@ class Mock implements MockInterface
case 'callable':
case '\Closure':
return function () {
return static function () : void {
};
case '\Traversable':
case '\Generator':
$generator = function () { yield; };
$generator = static function () {
yield;
};
return $generator();
case 'void':
@@ -755,6 +786,7 @@ class Mock implements MockInterface
if ($this->_mockery_ignoreMissingRecursive) {
$mock->shouldIgnoreMissing($this->_mockery_defaultReturnValue, true);
}
return $mock;
default:
@@ -762,6 +794,7 @@ class Mock implements MockInterface
if ($this->_mockery_ignoreMissingRecursive) {
$mock->shouldIgnoreMissing($this->_mockery_defaultReturnValue, true);
}
return $mock;
}
}
@@ -769,65 +802,67 @@ class Mock implements MockInterface
public function shouldHaveReceived($method = null, $args = null)
{
if ($method === null) {
return new HigherOrderMessage($this, "shouldHaveReceived");
return new HigherOrderMessage($this, 'shouldHaveReceived');
}
$expectation = new \Mockery\VerificationExpectation($this, $method);
$expectation = new 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 = new VerificationDirector($this->_mockery_getReceivedMethodCalls(), $expectation);
++$this->_mockery_expectations_count;
$director->verify();
return $director;
}
public function shouldHaveBeenCalled()
{
return $this->shouldHaveReceived("__invoke");
return $this->shouldHaveReceived('__invoke');
}
public function shouldNotHaveReceived($method = null, $args = null)
{
if ($method === null) {
return new HigherOrderMessage($this, "shouldNotHaveReceived");
return new HigherOrderMessage($this, 'shouldNotHaveReceived');
}
$expectation = new \Mockery\VerificationExpectation($this, $method);
$expectation = new VerificationExpectation($this, $method);
if (null !== $args) {
$expectation->withArgs($args);
}
$expectation->never();
$director = new \Mockery\VerificationDirector($this->_mockery_getReceivedMethodCalls(), $expectation);
$this->_mockery_expectations_count++;
$director = new VerificationDirector($this->_mockery_getReceivedMethodCalls(), $expectation);
++$this->_mockery_expectations_count;
$director->verify();
return null;
}
public function shouldNotHaveBeenCalled(array $args = null)
public function shouldNotHaveBeenCalled(?array $args = null)
{
return $this->shouldNotHaveReceived("__invoke", $args);
return $this->shouldNotHaveReceived('__invoke', $args);
}
protected static function _mockery_handleStaticMethodCall($method, array $args)
{
$associatedRealObject = \Mockery::fetchMock(__CLASS__);
$associatedRealObject = \Mockery::fetchMock(self::class);
try {
return $associatedRealObject->__call($method, $args);
} catch (BadMethodCallException $e) {
} catch (BadMethodCallException $badMethodCallException) {
throw new BadMethodCallException(
'Static method ' . $associatedRealObject->mockery_getName() . '::' . $method
. '() does not exist on this mock object',
0,
$e
$badMethodCallException
);
}
}
protected function _mockery_getReceivedMethodCalls()
{
return $this->_mockery_receivedMethodCalls ?: $this->_mockery_receivedMethodCalls = new \Mockery\ReceivedMethodCalls();
return $this->_mockery_receivedMethodCalls ?: $this->_mockery_receivedMethodCalls = new ReceivedMethodCalls();
}
/**
@@ -841,6 +876,7 @@ class Mock implements MockInterface
if (!isset($this->_mockery_expectations['__construct']) /* _mockery_handleMethodCall runs the other checks */) {
return;
}
$this->_mockery_handleMethodCall('__construct', $args);
}
@@ -853,16 +889,12 @@ class Mock implements MockInterface
$lowerCasedMockeryExpectations = array_change_key_case($this->_mockery_expectations, CASE_LOWER);
$lowerCasedMethod = strtolower($method);
if (isset($lowerCasedMockeryExpectations[$lowerCasedMethod])) {
return $lowerCasedMockeryExpectations[$lowerCasedMethod];
}
return null;
return $lowerCasedMockeryExpectations[$lowerCasedMethod] ?? null;
}
protected function _mockery_handleMethodCall($method, array $args)
{
$this->_mockery_getReceivedMethodCalls()->push(new \Mockery\MethodCall($method, $args));
$this->_mockery_getReceivedMethodCalls()->push(new MethodCall($method, $args));
$rm = $this->mockery_getMethod($method);
if ($rm && $rm->isProtected() && !$this->_mockery_allowMockingProtectedMethods) {
@@ -879,7 +911,11 @@ class Mock implements MockInterface
// noop - there is no hasPrototype method
}
return call_user_func_array("parent::$method", $args);
if (null === $this->_mockery_parentClass) {
$this->_mockery_parentClass = get_parent_class($this);
}
return call_user_func_array($this->_mockery_parentClass . '::' . $method, $args);
}
$handler = $this->_mockery_findExpectedMethodHandler($method);
@@ -887,7 +923,7 @@ class Mock implements MockInterface
if ($handler !== null && !$this->_mockery_disableExpectationMatching) {
try {
return $handler->call($args);
} catch (\Mockery\Exception\NoMatchingExpectationException $e) {
} catch (NoMatchingExpectationException $e) {
if (!$this->_mockery_ignoreMissing && !$this->_mockery_deferMissing) {
throw $e;
}
@@ -895,36 +931,43 @@ class Mock implements MockInterface
}
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("parent::$method")
&& (!$this->hasMethodOverloadingInParentClass() || (get_parent_class($this) && method_exists(get_parent_class($this), $method)))) {
return call_user_func_array("parent::$method", $args);
} elseif ($this->_mockery_deferMissing && get_parent_class($this) && method_exists(get_parent_class($this), '__call')) {
return call_user_func('parent::__call', $method, $args);
} elseif ($method == '__toString') {
(method_exists($this->_mockery_partial, $method) || method_exists($this->_mockery_partial, '__call'))) {
return $this->_mockery_partial->{$method}(...$args);
}
if ($this->_mockery_deferMissing && is_callable($this->_mockery_parentClass . '::' . $method)
&& (!$this->hasMethodOverloadingInParentClass() || ($this->_mockery_parentClass && method_exists($this->_mockery_parentClass, $method)))) {
return call_user_func_array($this->_mockery_parentClass . '::' . $method, $args);
}
if ($this->_mockery_deferMissing && $this->_mockery_parentClass && method_exists($this->_mockery_parentClass, '__call')) {
return call_user_func($this->_mockery_parentClass . '::__call', $method, $args);
}
if ($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("parent::$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;
}
return sprintf('%s#%s', self::class, spl_object_hash($this));
}
$message = 'Method ' . __CLASS__ . '::' . $method .
if ($this->_mockery_ignoreMissing && (\Mockery::getConfiguration()->mockingNonExistentMethodsAllowed() || (!is_null($this->_mockery_partial) && method_exists($this->_mockery_partial, $method)) || is_callable($this->_mockery_parentClass . '::' . $method))) {
if ($this->_mockery_defaultReturnValue instanceof Undefined) {
return $this->_mockery_defaultReturnValue->{$method}(...$args);
}
if (null === $this->_mockery_defaultReturnValue) {
return $this->mockery_returnValueForMethod($method);
}
return $this->_mockery_defaultReturnValue;
}
$message = 'Method ' . self::class . '::' . $method .
'() does not exist on this mock object';
if (!is_null($rm)) {
$message = 'Received ' . __CLASS__ .
$message = 'Received ' . self::class .
'::' . $method . '(), but no expectations were specified';
}
@@ -945,7 +988,7 @@ class Mock implements MockInterface
return static::$_mockery_methods;
}
if (isset($this->_mockery_partial)) {
if ($this->_mockery_partial !== null) {
$reflected = new \ReflectionObject($this->_mockery_partial);
} else {
$reflected = new \ReflectionClass($this);
@@ -957,7 +1000,7 @@ class Mock implements MockInterface
private function hasMethodOverloadingInParentClass()
{
// if there's __call any name would be callable
return is_callable('parent::aFunctionNameThatNoOneWouldEverUseInRealLife12345');
return is_callable($this->_mockery_parentClass . '::aFunctionNameThatNoOneWouldEverUseInRealLife12345');
}
/**
@@ -966,10 +1009,10 @@ class Mock implements MockInterface
private function getNonPublicMethods()
{
return array_map(
function ($method) {
static function ($method) {
return $method->getName();
},
array_filter($this->mockery_getMethods(), function ($method) {
array_filter($this->mockery_getMethods(), static function ($method) {
return !$method->isPublic();
})
);

View File

@@ -1,38 +1,28 @@
<?php
/**
* Mockery
* Mockery (https://docs.mockery.io/)
*
* LICENSE
*
* This source file is subject to the new BSD license that is bundled
* with this package in the file LICENSE.txt.
* It is also available through the world-wide-web at this URL:
* http://github.com/padraic/mockery/blob/master/LICENSE
* If you did not receive a copy of the license and are unable to
* obtain it through the world-wide-web, please send an email
* to padraic@php.net so we can send you a copy immediately.
*
* @category Mockery
* @package Mockery
* @copyright Copyright (c) 2010 Pádraic Brady (http://blog.astrumfutura.com)
* @license http://github.com/padraic/mockery/blob/master/LICENSE New BSD License
* @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
* @param mixed $something String method name or map of method => return
*
* @return Expectation|ExpectationInterface|HigherOrderMessage|self
*/
public function allows($something = []);
/**
* @param mixed $something String method name (optional)
* @return \Mockery\ExpectationInterface|\Mockery\Expectation|\Mockery\ExpectsHigherOrderMessage
* @param mixed $something String method name (optional)
*
* @return Expectation|ExpectationInterface|ExpectsHigherOrderMessage
*/
public function expects($something = null);
}

View File

@@ -1,30 +1,21 @@
<?php
/**
* Mockery
* Mockery (https://docs.mockery.io/)
*
* LICENSE
*
* This source file is subject to the new BSD license that is bundled
* with this package in the file LICENSE.txt.
* It is also available through the world-wide-web at this URL:
* http://github.com/padraic/mockery/blob/master/LICENSE
* If you did not receive a copy of the license and are unable to
* obtain it through the world-wide-web, please send an email
* to padraic@php.net so we can send you a copy immediately.
*
* @category Mockery
* @package Mockery
* @copyright Copyright (c) 2010 Pádraic Brady (http://blog.astrumfutura.com)
* @license http://github.com/padraic/mockery/blob/master/LICENSE New BSD License
* @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';
private const QUICK_DEFINITIONS_MODE_MOCK_AT_LEAST_ONCE = 'QUICK_DEFINITIONS_MODE_MOCK_AT_LEAST_ONCE';
/**
* Defines what a quick definition should produce.
* Possible options are:

View File

@@ -1,28 +1,18 @@
<?php
/**
* Mockery
* Mockery (https://docs.mockery.io/)
*
* LICENSE
*
* This source file is subject to the new BSD license that is bundled
* with this package in the file LICENSE.txt.
* It is also available through the world-wide-web at this URL:
* http://github.com/padraic/mockery/blob/master/LICENSE
* If you did not receive a copy of the license and are unable to
* obtain it through the world-wide-web, please send an email
* to padraic@php.net so we can send you a copy immediately.
*
* @category Mockery
* @package Mockery
* @copyright Copyright (c) 2010 Pádraic Brady (http://blog.astrumfutura.com)
* @license http://github.com/padraic/mockery/blob/master/LICENSE New BSD License
* @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();
private $methodCalls = [];
public function push(MethodCall $methodCall)
{
@@ -36,7 +26,7 @@ class ReceivedMethodCalls
continue;
}
if (!$expectation->matchArgs($methodCall->getArgs())) {
if (! $expectation->matchArgs($methodCall->getArgs())) {
continue;
}

View File

@@ -1,107 +1,108 @@
<?php
/**
* Mockery
* Mockery (https://docs.mockery.io/)
*
* LICENSE
*
* This source file is subject to the new BSD license that is bundled
* with this package in the file LICENSE.txt.
* It is also available through the world-wide-web at this URL:
* http://github.com/padraic/mockery/blob/master/LICENSE
* If you did not receive a copy of the license and are unable to
* obtain it through the world-wide-web, please send an email
* to padraic@php.net so we can send you a copy immediately.
*
* @category Mockery
* @package Mockery
* @copyright Copyright (c) 2017 Dave Marshall https://github.com/davedevelopment
* @license http://github.com/padraic/mockery/blob/master/LICENSE New BSD License
* @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 InvalidArgumentException;
use ReflectionClass;
use ReflectionIntersectionType;
use ReflectionMethod;
use ReflectionNamedType;
use ReflectionParameter;
use ReflectionType;
use ReflectionUnionType;
use function array_diff;
use function array_intersect;
use function array_map;
use function array_merge;
use function get_debug_type;
use function implode;
use function in_array;
use function method_exists;
use function sprintf;
use function strpos;
use const PHP_VERSION_ID;
/**
* @internal
*/
class Reflector
{
/**
* Determine if the parameter is typed as an array.
* List of built-in types.
*
* @param \ReflectionParameter $param
*
* @return bool
* @var list<string>
*/
public static function isArray(\ReflectionParameter $param)
{
$type = $param->getType();
return $type instanceof \ReflectionNamedType && $type->getName();
}
public const BUILTIN_TYPES = ['array', 'bool', 'int', 'float', 'null', 'object', 'string'];
/**
* Compute the string representation for the paramater type.
* List of reserved words.
*
* @param \ReflectionParameter $param
* @param bool $withoutNullable
*
* @return string|null
* @var list<string>
*/
public static function getTypeHint(\ReflectionParameter $param, $withoutNullable = false)
{
if (!$param->hasType()) {
return null;
}
public const RESERVED_WORDS = ['bool', 'true', 'false', 'float', 'int', 'iterable', 'mixed', 'never', 'null', 'object', 'string', 'void'];
$type = $param->getType();
$declaringClass = $param->getDeclaringClass();
$typeHint = self::typeToString($type, $declaringClass);
/**
* Iterable.
*
* @var list<string>
*/
private const ITERABLE = ['iterable'];
return (!$withoutNullable && $type->allowsNull()) ? self::formatNullableType($typeHint) : $typeHint;
}
/**
* Traversable array.
*
* @var list<string>
*/
private const TRAVERSABLE_ARRAY = ['\Traversable', 'array'];
/**
* Compute the string representation for the return type.
*
* @param \ReflectionParameter $param
* @param bool $withoutNullable
*
* @return string|null
* @return null|string
*/
public static function getReturnType(\ReflectionMethod $method, $withoutNullable = false)
public static function getReturnType(ReflectionMethod $method, $withoutNullable = false)
{
$type = $method->getReturnType();
if (is_null($type) && method_exists($method, 'getTentativeReturnType')) {
if (! $type instanceof ReflectionType && method_exists($method, 'getTentativeReturnType')) {
$type = $method->getTentativeReturnType();
}
if (is_null($type)) {
if (! $type instanceof ReflectionType) {
return null;
}
$typeHint = self::typeToString($type, $method->getDeclaringClass());
$typeHint = self::getTypeFromReflectionType($type, $method->getDeclaringClass());
return (!$withoutNullable && $type->allowsNull()) ? self::formatNullableType($typeHint) : $typeHint;
return (! $withoutNullable && $type->allowsNull()) ? self::formatNullableType($typeHint) : $typeHint;
}
/**
* Compute the string representation for the simplest return type.
*
* @param \ReflectionParameter $param
*
* @return string|null
* @return null|string
*/
public static function getSimplestReturnType(\ReflectionMethod $method)
public static function getSimplestReturnType(ReflectionMethod $method)
{
$type = $method->getReturnType();
if (is_null($type) && method_exists($method, 'getTentativeReturnType')) {
if (! $type instanceof ReflectionType && method_exists($method, 'getTentativeReturnType')) {
$type = $method->getTentativeReturnType();
}
if (is_null($type) || $type->allowsNull()) {
if (! $type instanceof ReflectionType || $type->allowsNull()) {
return null;
}
@@ -123,32 +124,139 @@ class Reflector
}
/**
* Get the string representation of the given type.
* Compute the string representation for the paramater type.
*
* @param \ReflectionType $type
* @param string $declaringClass
* @param bool $withoutNullable
*
* @return string|null
* @return null|string
*/
private static function typeToString(\ReflectionType $type, \ReflectionClass $declaringClass)
public static function getTypeHint(ReflectionParameter $param, $withoutNullable = false)
{
return \implode('|', \array_map(function (array $typeInformation) {
return $typeInformation['typeHint'];
}, self::getTypeInformation($type, $declaringClass)));
if (! $param->hasType()) {
return null;
}
$type = $param->getType();
$declaringClass = $param->getDeclaringClass();
$typeHint = self::getTypeFromReflectionType($type, $declaringClass);
return (! $withoutNullable && $type->allowsNull()) ? self::formatNullableType($typeHint) : $typeHint;
}
/**
* Determine if the parameter is typed as an array.
*
* @return bool
*/
public static function isArray(ReflectionParameter $param)
{
$type = $param->getType();
return $type instanceof ReflectionNamedType && $type->getName();
}
/**
* Determine if the given type is a reserved word.
*/
public static function isReservedWord(string $type): bool
{
return in_array(strtolower($type), self::RESERVED_WORDS, true);
}
/**
* Format the given type as a nullable type.
*/
private static function formatNullableType(string $typeHint): string
{
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 ($intersect === self::TRAVERSABLE_ARRAY) {
$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));
}
/**
* Get the string representation of the given type.
*
* @param \ReflectionType $type
* @param \ReflectionClass $declaringClass
*
* @return list<array{typeHint: string, isPrimitive: bool}>
* @return list<array{typeHint:string,isPrimitive:bool}>
*/
private static function getTypeInformation(\ReflectionType $type, \ReflectionClass $declaringClass)
private static function getTypeInformation(ReflectionType $type, ReflectionClass $declaringClass): array
{
// PHP 8 union types can be recursively processed
if ($type instanceof \ReflectionUnionType) {
// 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) {
@@ -172,7 +280,7 @@ class Reflector
return [
[
'typeHint' => $typeHint,
'isPrimitive' => in_array($typeHint, ['array', 'bool', 'int', 'float', 'null', 'object', 'string']),
'isPrimitive' => in_array($typeHint, self::BUILTIN_TYPES, true),
],
];
}
@@ -205,20 +313,4 @@ class Reflector
],
];
}
/**
* Format the given type as a nullable type.
*
* @param string $typeHint
*
* @return string
*/
private static function formatNullableType($typeHint)
{
if (\PHP_VERSION_ID < 80000) {
return sprintf('?%s', $typeHint);
}
return $typeHint === 'mixed' ? 'mixed' : sprintf('%s|null', $typeHint);
}
}

View File

@@ -1,32 +1,25 @@
<?php
/**
* Mockery
* Mockery (https://docs.mockery.io/)
*
* LICENSE
*
* This source file is subject to the new BSD license that is bundled
* with this package in the file LICENSE.txt.
* It is also available through the world-wide-web at this URL:
* http://github.com/padraic/mockery/blob/master/LICENSE
* If you did not receive a copy of the license and are unable to
* obtain it through the world-wide-web, please send an email
* to padraic@php.net so we can send you a copy immediately.
*
* @category Mockery
* @package Mockery
* @copyright Copyright (c) 2010 Pádraic Brady (http://blog.astrumfutura.com)
* @license http://github.com/padraic/mockery/blob/master/LICENSE New BSD License
* @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 function spl_object_hash;
class Undefined
{
/**
* Call capturing to merely return this same object.
*
* @param string $method
* @param array $args
* @param array $args
*
* @return self
*/
public function __call($method, array $args)
@@ -35,12 +28,12 @@ class Undefined
}
/**
* Return a string, avoiding E_RECOVERABLE_ERROR
* Return a string, avoiding E_RECOVERABLE_ERROR.
*
* @return string
*/
public function __toString()
{
return __CLASS__ . ":" . spl_object_hash($this);
return self::class . ':' . spl_object_hash($this);
}
}

View File

@@ -1,107 +1,168 @@
<?php
/**
* Mockery
* Mockery (https://docs.mockery.io/)
*
* LICENSE
*
* This source file is subject to the new BSD license that is bundled
* with this package in the file LICENSE.txt.
* It is also available through the world-wide-web at this URL:
* http://github.com/padraic/mockery/blob/master/LICENSE
* If you did not receive a copy of the license and are unable to
* obtain it through the world-wide-web, please send an email
* to padraic@php.net so we can send you a copy immediately.
*
* @category Mockery
* @package Mockery
* @copyright Copyright (c) 2010 Pádraic Brady (http://blog.astrumfutura.com)
* @license http://github.com/padraic/mockery/blob/master/LICENSE New BSD License
* @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;
/**
* @var VerificationExpectation
*/
private $expectation;
/**
* @var ReceivedMethodCalls
*/
private $receivedMethodCalls;
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());
}
/**
* @return self
*/
public function atLeast()
{
return $this->cloneWithoutCountValidatorsApplyAndVerify("atLeast", array());
return $this->cloneWithoutCountValidatorsApplyAndVerify('atLeast', []);
}
/**
* @return self
*/
public function atMost()
{
return $this->cloneWithoutCountValidatorsApplyAndVerify("atMost", array());
return $this->cloneWithoutCountValidatorsApplyAndVerify('atMost', []);
}
/**
* @param int $minimum
* @param int $maximum
*
* @return self
*/
public function between($minimum, $maximum)
{
return $this->cloneWithoutCountValidatorsApplyAndVerify("between", array($minimum, $maximum));
return $this->cloneWithoutCountValidatorsApplyAndVerify('between', [$minimum, $maximum]);
}
protected function cloneWithoutCountValidatorsApplyAndVerify($method, $args)
/**
* @return self
*/
public function once()
{
$expectation = clone $this->expectation;
$expectation->clearCountValidators();
call_user_func_array(array($expectation, $method), $args);
$director = new VerificationDirector($this->receivedMethodCalls, $expectation);
$director->verify();
return $director;
return $this->cloneWithoutCountValidatorsApplyAndVerify('once', []);
}
/**
* @param int $limit
*
* @return self
*/
public function times($limit = null)
{
return $this->cloneWithoutCountValidatorsApplyAndVerify('times', [$limit]);
}
/**
* @return self
*/
public function twice()
{
return $this->cloneWithoutCountValidatorsApplyAndVerify('twice', []);
}
public function verify()
{
$this->receivedMethodCalls->verify($this->expectation);
}
/**
* @template TArgs
*
* @param TArgs $args
*
* @return self
*/
public function with(...$args)
{
return $this->cloneApplyAndVerify('with', $args);
}
/**
* @return self
*/
public function withAnyArgs()
{
return $this->cloneApplyAndVerify('withAnyArgs', []);
}
/**
* @template TArgs
*
* @param TArgs $args
*
* @return self
*/
public function withArgs($args)
{
return $this->cloneApplyAndVerify('withArgs', [$args]);
}
/**
* @return self
*/
public function withNoArgs()
{
return $this->cloneApplyAndVerify('withNoArgs', []);
}
/**
* @param string $method
* @param array $args
*
* @return self
*/
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;
$verificationExpectation = clone $this->expectation;
$verificationExpectation->{$method}(...$args);
$verificationDirector = new self($this->receivedMethodCalls, $verificationExpectation);
$verificationDirector->verify();
return $verificationDirector;
}
/**
* @param string $method
* @param array $args
*
* @return self
*/
protected function cloneWithoutCountValidatorsApplyAndVerify($method, $args)
{
$verificationExpectation = clone $this->expectation;
$verificationExpectation->clearCountValidators();
$verificationExpectation->{$method}(...$args);
$verificationDirector = new self($this->receivedMethodCalls, $verificationExpectation);
$verificationDirector->verify();
return $verificationDirector;
}
}

View File

@@ -1,35 +1,29 @@
<?php
/**
* Mockery
* Mockery (https://docs.mockery.io/)
*
* LICENSE
*
* This source file is subject to the new BSD license that is bundled
* with this package in the file LICENSE.txt.
* It is also available through the world-wide-web at this URL:
* http://github.com/padraic/mockery/blob/master/LICENSE
* If you did not receive a copy of the license and are unable to
* obtain it through the world-wide-web, please send an email
* to padraic@php.net so we can send you a copy immediately.
*
* @category Mockery
* @package Mockery
* @copyright Copyright (c) 2010 Pádraic Brady (http://blog.astrumfutura.com)
* @license http://github.com/padraic/mockery/blob/master/LICENSE New BSD License
* @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;
}
/**
* @return void
*/
public function clearCountValidators()
{
$this->_countValidators = [];
}
}

View File

@@ -1,64 +1,76 @@
<?php
use Mockery\Matcher\AndAnyOtherArgs;
use Mockery\Matcher\AnyArgs;
/**
* Mockery
* Mockery (https://docs.mockery.io/)
*
* LICENSE
*
* This source file is subject to the new BSD license that is bundled
* with this package in the file LICENSE.txt.
* It is also available through the world-wide-web at this URL:
* http://github.com/padraic/mockery/blob/master/LICENSE
* If you did not receive a copy of the license and are unable to
* obtain it through the world-wide-web, please send an email
* to padraic@php.net so we can send you a copy immediately.
*
* @category Mockery
* @package Mockery
* @copyright Copyright (c) 2016 Dave Marshall
* @license http://github.com/padraic/mockery/blob/master/LICENSE New BSD License
* @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
*/
if (!function_exists("mock")) {
use Mockery\LegacyMockInterface;
use Mockery\Matcher\AndAnyOtherArgs;
use Mockery\Matcher\AnyArgs;
use Mockery\MockInterface;
if (! \function_exists('mock')) {
/**
* @template TMock of object
*
* @param array<class-string<TMock>|TMock|Closure(LegacyMockInterface&MockInterface&TMock):LegacyMockInterface&MockInterface&TMock|array<TMock>> $args
*
* @return LegacyMockInterface&MockInterface&TMock
*/
function mock(...$args)
{
return Mockery::mock(...$args);
}
}
if (!function_exists("spy")) {
if (! \function_exists('spy')) {
/**
* @template TSpy of object
*
* @param array<class-string<TSpy>|TSpy|Closure(LegacyMockInterface&MockInterface&TSpy):LegacyMockInterface&MockInterface&TSpy|array<TSpy>> $args
*
* @return LegacyMockInterface&MockInterface&TSpy
*/
function spy(...$args)
{
return Mockery::spy(...$args);
}
}
if (!function_exists("namedMock")) {
if (! \function_exists('namedMock')) {
/**
* @template TNamedMock of object
*
* @param array<class-string<TNamedMock>|TNamedMock|array<TNamedMock>> $args
*
* @return LegacyMockInterface&MockInterface&TNamedMock
*/
function namedMock(...$args)
{
return Mockery::namedMock(...$args);
}
}
if (!function_exists("anyArgs")) {
function anyArgs()
if (! \function_exists('anyArgs')) {
function anyArgs(): AnyArgs
{
return new AnyArgs();
}
}
if (!function_exists("andAnyOtherArgs")) {
function andAnyOtherArgs()
if (! \function_exists('andAnyOtherArgs')) {
function andAnyOtherArgs(): AndAnyOtherArgs
{
return new AndAnyOtherArgs();
}
}
if (!function_exists("andAnyOthers")) {
function andAnyOthers()
if (! \function_exists('andAnyOthers')) {
function andAnyOthers(): AndAnyOtherArgs
{
return new AndAnyOtherArgs();
}