<?php
/**
* Mockery
*
* LICENSE
*
* This source file is subject to the new BSD license that is bundled
* with this package in the file LICENSE.txt.
* It is also available through the world-wide-web at this URL:
* http://github.com/padraic/mockery/blob/master/LICENSE
* If you did not receive a copy of the license and are unable to
* obtain it through the world-wide-web, please send an email
* to padraic@php.net so we can send you a copy immediately.
*
* @category Mockery
* @package Mockery
* @copyright Copyright (c) 2010-2014 Pádraic Brady (http://blog.astrumfutura.com)
* @license http://github.com/padraic/mockery/blob/master/LICENSE New BSD License
*/
namespace Mockery;
class Expectation implements ExpectationInterface
{
/**
* Mock object to which this expectation belongs
*
* @var object
*/
protected $_mock = null;
/**
* Method name
*
* @var string
*/
protected $_name = null;
/**
* Arguments expected by this expectation
*
* @var array
*/
protected $_expectedArgs = array();
/**
* Count validator store
*
* @var array
*/
protected $_countValidators = array();
/**
* The count validator class to use
*
* @var string
*/
protected $_countValidatorClass = 'Mockery\CountValidator\Exact';
/**
* Actual count of calls to this expectation
*
* @var int
*/
protected $_actualCount = 0;
/**
* Value to return from this expectation
*
* @var mixed
*/
protected $_returnValue = null;
/**
* Array of return values as a queue for multiple return sequence
*
* @var array
*/
protected $_returnQueue = array();
/**
* Array of closures executed with given arguments to generate a result
* to be returned
*
* @var array
*/
protected $_closureQueue = array();
/**
* Array of values to be set when this expectation matches
*
* @var array
*/
protected $_setQueue = array();
/**
* Integer representing the call order of this expectation
*
* @var int
*/
protected $_orderNumber = null;
/**
* Integer representing the call order of this expectation on a global basis
*
* @var int
*/
protected $_globalOrderNumber = null;
/**
* Flag indicating that an exception is expected to be throw (not returned)
*
* @var bool
*/
protected $_throw = false;
/**
* Flag indicating whether the order of calling is determined locally or
* globally
*
* @var bool
*/
protected $_globally = false;
/**
* Flag indicating we expect no arguments
*
* @var bool
*/
protected $_noArgsExpectation = false;
/**
* Flag indicating if the return value should be obtained from the original
* class method instead of returning predefined values from the return queue
*
* @var bool
*/
protected $_passthru = false;
/**
* Constructor
*
* @param \Mockery\MockInterface $mock
* @param string $name
*/
public function __construct(\Mockery\MockInterface $mock, $name)
{
$this->_mock = $mock;
$this->_name = $name;
}
/**
* Return a string with the method name and arguments formatted
*
* @param string $name Name of the expected method
* @param array $args List of arguments to the method
* @return string
*/
public function __toString()
{
return \Mockery::formatArgs($this->_name, $this->_expectedArgs);
}
/**
* Verify the current call, i.e. that the given arguments match those
* of this expectation
*
* @param array $args
* @return mixed
*/
public function verifyCall(array $args)
{
$this->validateOrder();
$this->_actualCount++;
if (true === $this->_passthru) {
return $this->_mock->mockery_callSubjectMethod($this->_name, $args);
}
$return = $this->_getReturnValue($args);
if ($return instanceof \Exception && $this->_throw === true) {
throw $return;
}
$this->_setValues();
return $return;
}
/**
* Sets public properties with queued values to the mock object
*
* @param array $args
* @return mixed
*/
protected function _setValues()
{
$mockClass = get_class($this->_mock);
$container = $this->_mock->mockery_getContainer();
$mocks = $container->getMocks();
foreach ($this->_setQueue as $name => &$values) {
if (count($values) > 0) {
$value = array_shift($values);
foreach ($mocks as $mock) {
if (is_a($mock, $mockClass)) {
$mock->{$name} = $value;
}
}
}
}
}
/**
* Fetch the return value for the matching args
*
* @param array $args
* @return mixed
*/
protected function _getReturnValue(array $args)
{
if (count($this->_closureQueue) > 1) {
return call_user_func_array(array_shift($this->_closureQueue), $args);
} elseif (count($this->_closureQueue) > 0) {
return call_user_func_array(current($this->_closureQueue), $args);
} elseif (count($this->_returnQueue) > 1) {
return array_shift($this->_returnQueue);
} elseif (count($this->_returnQueue) > 0) {
return current($this->_returnQueue);
}
$rm = $this->_mock->mockery_getMethod($this->_name);
if ($rm && version_compare(PHP_VERSION, '7.0.0-dev') >= 0 && $rm->hasReturnType()) {
$type = (string) $rm->getReturnType();
switch ($type) {
case '': return;
case 'void': return;
case 'string': return '';
case 'int': return 0;
case 'float': return 0.0;
case 'bool': return false;
case 'array': return array();
case 'callable':
case 'Closure':
return function () {
};
case 'Traversable':
case 'Generator':
// Remove eval() when minimum version >=5.5
$generator = eval('return function () { yield; };');
return $generator();
default:
return \Mockery::mock($type);
}
}
}
/**
* Checks if this expectation is eligible for additional calls
*
* @return bool
*/
public function isEligible()
{
foreach ($this->_countValidators as $validator) {
if (!$validator->isEligible($this->_actualCount)) {
return false;
}
}
return true;
}
/**
* Check if there is a constraint on call count
*
* @return bool
*/
public function isCallCountConstrained()
{
return (count($this->_countValidators) > 0);
}
/**
* Verify call order
*
* @return void
*/
public function validateOrder()
{
if ($this->_orderNumber) {
$this->_mock->mockery_validateOrder((string) $this, $this->_orderNumber, $this->_mock);
}
if ($this->_globalOrderNumber) {
$this->_mock->mockery_getContainer()
->mockery_validateOrder((string) $this, $this->_globalOrderNumber, $this->_mock);
}
}
/**
* Verify this expectation
*
* @return bool
*/
public function verify()
{
foreach ($this->_countValidators as $validator) {
$validator->validate($this->_actualCount);
}
}
/**
* Check if passed arguments match an argument expectation
*
* @param array $args
* @return bool
*/
public function matchArgs(array $args)
{
if (empty($this->_expectedArgs) && !$this->_noArgsExpectation) {
return true;
}
$expected = is_array($this->_expectedArgs) ? count($this->_expectedArgs) : 0;
if (count($args) !== $expected) {
return false;
}
$argCount = count($args);
for ($i=0; $i<$argCount; $i++) {
$param =& $args[$i];
if (!$this->_matchArg($this->_expectedArgs[$i], $param)) {
return false;
}
}
return true;
}
/**
* Check if passed argument matches an argument expectation
*
* @param array $args
* @return bool
*/
protected function _matchArg($expected, &$actual)
{
if ($expected === $actual) {
return true;
}
if (!is_object($expected) && !is_object($actual) && $expected == $actual) {
return true;
}
if (is_string($expected) && !is_array($actual) && !is_object($actual)) {
# push/pop an error handler here to to make sure no error/exception thrown if $expected is not a regex
set_error_handler(function () {
});
$result = preg_match($expected, (string) $actual);
restore_error_handler();
if ($result) {
return true;
}
}
if (is_string($expected) && is_object($actual)) {
$result = $actual instanceof $expected;
if ($result) {
return true;
}
}
if ($expected instanceof \Mockery\Matcher\MatcherAbstract) {
return $expected->match($actual);
}
if (is_a($expected, '\Hamcrest\Matcher') || is_a($expected, '\Hamcrest_Matcher')) {
return $expected->matches($actual);
}
return false;
}
/**
* Expected argument setter for the expectation
*
* @param mixed ...
* @return self
*/
public function with()
{
return $this->withArgs(func_get_args());
}
/**
* Expected arguments for the expectation passed as an array
*
* @param array $args
* @return self
*/
public function withArgs(array $args)
{
if (empty($args)) {
return $this->withNoArgs();
}
$this->_expectedArgs = $args;
$this->_noArgsExpectation = false;
return $this;
}
/**
* Set with() as no arguments expected
*
* @return self
*/
public function withNoArgs()
{
$this->_noArgsExpectation = true;
$this->_expectedArgs = null;
return $this;
}
/**
* Set expectation that any arguments are acceptable
*
* @return self
*/
public function withAnyArgs()
{
$this->_expectedArgs = array();
return $this;
}
/**
* Set a return value, or sequential queue of return values
*
* @param mixed ...
* @return self
*/
public function andReturn()
{
$this->_returnQueue = func_get_args();
return $this;
}
/**
* Return this mock, like a fluent interface
*
* @return self
*/
public function andReturnSelf()
{
return $this->andReturn($this->_mock);
}
/**
* Set a sequential queue of return values with an array
*
* @param array $values
* @return self
*/
public function andReturnValues(array $values)
{
call_user_func_array(array($this, 'andReturn'), $values);
return $this;
}
/**
* Set a closure or sequence of closures with which to generate return
* values. The arguments passed to the expected method are passed to the
* closures as parameters.
*
* @param callable ...
* @return self
*/
public function andReturnUsing()
{
$this->_closureQueue = func_get_args();
return $this;
}
/**
* Return a self-returning black hole object.
*
* @return self
*/
public function andReturnUndefined()
{
$this->andReturn(new \Mockery\Undefined);
return $this;
}
/**
* Return null. This is merely a language construct for Mock describing.
*
* @return self
*/
public function andReturnNull()
{
return $this;
}
/**
* Set Exception class and arguments to that class to be thrown
*
* @param string $exception
* @param string $message
* @param int $code
* @param Exception $previous
* @return self
*/
public function andThrow($exception, $message = '', $code = 0, \Exception $previous = null)
{
$this->_throw = true;
if (is_object($exception)) {
$this->andReturn($exception);
} else {
$this->andReturn(new $exception($message, $code, $previous));
}
return $this;
}
/**
* Set Exception classes to be thrown
*
* @param array $exceptions
* @return self
*/
public function andThrowExceptions(array $exceptions)
{
$this->_throw = true;
foreach ($exceptions as $exception) {
if (!is_object($exception)) {
throw new Exception('You must pass an array of exception objects to andThrowExceptions');
}
}
return $this->andReturnValues($exceptions);
}
/**
* Register values to be set to a public property each time this expectation occurs
*
* @param string $name
* @param mixed $value
* @return self
*/
public function andSet($name, $value)
{
$values = func_get_args();
array_shift($values);
$this->_setQueue[$name] = $values;
return $this;
}
/**
* Alias to andSet(). Allows the natural English construct
* - set('foo', 'bar')->andReturn('bar')
*
* @param string $name
* @param mixed $value
* @return self
*/
public function set($name, $value)
{
return call_user_func_array(array($this, 'andSet'), func_get_args());
}
/**
* Indicates this expectation should occur zero or more times
*
* @return self
*/
public function zeroOrMoreTimes()
{
$this->atLeast()->never();
}
/**
* Indicates the number of times this expectation should occur
*
* @param int $limit
* @return self
*/
public function times($limit = null)
{
if (is_null($limit)) {
return $this;
}
$this->_countValidators[] = new $this->_countValidatorClass($this, $limit);
$this->_countValidatorClass = 'Mockery\CountValidator\Exact';
return $this;
}
/**
* Indicates that this expectation is never expected to be called
*
* @return self
*/
public function never()
{
return $this->times(0);
}
/**
* Indicates that this expectation is expected exactly once
*
* @return self
*/
public function once()
{
return $this->times(1);
}
/**
* Indicates that this expectation is expected exactly twice
*
* @return self
*/
public function twice()
{
return $this->times(2);
}
/**
* Sets next count validator to the AtLeast instance
*
* @return self
*/
public function atLeast()
{
$this->_countValidatorClass = 'Mockery\CountValidator\AtLeast';
return $this;
}
/**
* Sets next count validator to the AtMost instance
*
* @return self
*/
public function atMost()
{
$this->_countValidatorClass = 'Mockery\CountValidator\AtMost';
return $this;
}
/**
* Shorthand for setting minimum and maximum constraints on call counts
*
* @param int $minimum
* @param int $maximum
*/
public function between($minimum, $maximum)
{
return $this->atLeast()->times($minimum)->atMost()->times($maximum);
}
/**
* Indicates that this expectation must be called in a specific given order
*
* @param string $group Name of the ordered group
* @return self
*/
public function ordered($group = null)
{
if ($this->_globally) {
$this->_globalOrderNumber = $this->_defineOrdered($group, $this->_mock->mockery_getContainer());
} else {
$this->_orderNumber = $this->_defineOrdered($group, $this->_mock);
}
$this->_globally = false;
return $this;
}
/**
* Indicates call order should apply globally
*
* @return self
*/
public function globally()
{
$this->_globally = true;
return $this;
}
/**
* Setup the ordering tracking on the mock or mock container
*
* @param string $group
* @param object $ordering
* @return int
*/
protected function _defineOrdered($group, $ordering)
{
$groups = $ordering->mockery_getGroups();
if (is_null($group)) {
$result = $ordering->mockery_allocateOrder();
} elseif (isset($groups[$group])) {
$result = $groups[$group];
} else {
$result = $ordering->mockery_allocateOrder();
$ordering->mockery_setGroup($group, $result);
}
return $result;
}
/**
* Return order number
*
* @return int
*/
public function getOrderNumber()
{
return $this->_orderNumber;
}
/**
* Mark this expectation as being a default
*
* @return self
*/
public function byDefault()
{
$director = $this->_mock->mockery_getExpectationsFor($this->_name);
if (!empty($director)) {
$director->makeExpectationDefault($this);
}
return $this;
}
/**
* Return the parent mock of the expectation
*
* @return \Mockery\MockInterface
*/
public function getMock()
{
return $this->_mock;
}
/**
* Flag this expectation as calling the original class method with the
* any provided arguments instead of using a return value queue.
*
* @return self
*/
public function passthru()
{
if ($this->_mock instanceof Mock) {
throw new Exception(
'Mock Objects not created from a loaded/existing class are '
. 'incapable of passing method calls through to a parent class'
);
}
$this->_passthru = true;
return $this;
}
/**
* Cloning logic
*
*/
public function __clone()
{
$newValidators = array();
$countValidators = $this->_countValidators;
foreach ($countValidators as $validator) {
$newValidators[] = clone $validator;
}
$this->_countValidators = $newValidators;
}
public function getName()
{
return $this->_name;
}
}
Anons79 File Manager Version 1.0, Coded By Anons79
Email: [email protected]