1<?php 2/* 3 * This file is part of the PHPUnit_MockObject package. 4 * 5 * (c) Sebastian Bergmann <sebastian@phpunit.de> 6 * 7 * For the full copyright and license information, please view the LICENSE 8 * file that was distributed with this source code. 9 */ 10 11/** 12 * Invocation matcher which looks for specific parameters in the invocations. 13 * 14 * Checks the parameters of all incoming invocations, the parameter list is 15 * checked against the defined constraints in $parameters. If the constraint 16 * is met it will return true in matches(). 17 * 18 * @since Class available since Release 1.0.0 19 */ 20class PHPUnit_Framework_MockObject_Matcher_Parameters extends PHPUnit_Framework_MockObject_Matcher_StatelessInvocation 21{ 22 /** 23 * @var PHPUnit_Framework_Constraint[] 24 */ 25 protected $parameters = []; 26 27 /** 28 * @var PHPUnit_Framework_MockObject_Invocation 29 */ 30 protected $invocation; 31 32 /** 33 * @var PHPUnit_Framework_ExpectationFailedException 34 */ 35 private $parameterVerificationResult; 36 37 /** 38 * @param array $parameters 39 */ 40 public function __construct(array $parameters) 41 { 42 foreach ($parameters as $parameter) { 43 if (!($parameter instanceof PHPUnit_Framework_Constraint)) { 44 $parameter = new PHPUnit_Framework_Constraint_IsEqual( 45 $parameter 46 ); 47 } 48 49 $this->parameters[] = $parameter; 50 } 51 } 52 53 /** 54 * @return string 55 */ 56 public function toString() 57 { 58 $text = 'with parameter'; 59 60 foreach ($this->parameters as $index => $parameter) { 61 if ($index > 0) { 62 $text .= ' and'; 63 } 64 65 $text .= ' ' . $index . ' ' . $parameter->toString(); 66 } 67 68 return $text; 69 } 70 71 /** 72 * @param PHPUnit_Framework_MockObject_Invocation $invocation 73 * 74 * @return bool 75 */ 76 public function matches(PHPUnit_Framework_MockObject_Invocation $invocation) 77 { 78 $this->invocation = $invocation; 79 $this->parameterVerificationResult = null; 80 81 try { 82 $this->parameterVerificationResult = $this->verify(); 83 84 return $this->parameterVerificationResult; 85 } catch (PHPUnit_Framework_ExpectationFailedException $e) { 86 $this->parameterVerificationResult = $e; 87 88 throw $this->parameterVerificationResult; 89 } 90 } 91 92 /** 93 * Checks if the invocation $invocation matches the current rules. If it 94 * does the matcher will get the invoked() method called which should check 95 * if an expectation is met. 96 * 97 * @return bool 98 * 99 * @throws PHPUnit_Framework_ExpectationFailedException 100 */ 101 public function verify() 102 { 103 if (isset($this->parameterVerificationResult)) { 104 return $this->guardAgainstDuplicateEvaluationOfParameterConstraints(); 105 } 106 107 if ($this->invocation === null) { 108 throw new PHPUnit_Framework_ExpectationFailedException( 109 'Mocked method does not exist.' 110 ); 111 } 112 113 if (count($this->invocation->parameters) < count($this->parameters)) { 114 $message = 'Parameter count for invocation %s is too low.'; 115 116 // The user called `->with($this->anything())`, but may have meant 117 // `->withAnyParameters()`. 118 // 119 // @see https://github.com/sebastianbergmann/phpunit-mock-objects/issues/199 120 if (count($this->parameters) === 1 && 121 get_class($this->parameters[0]) === 'PHPUnit_Framework_Constraint_IsAnything') { 122 $message .= "\nTo allow 0 or more parameters with any value, omit ->with() or use ->withAnyParameters() instead."; 123 } 124 125 throw new PHPUnit_Framework_ExpectationFailedException( 126 sprintf($message, $this->invocation->toString()) 127 ); 128 } 129 130 foreach ($this->parameters as $i => $parameter) { 131 $parameter->evaluate( 132 $this->invocation->parameters[$i], 133 sprintf( 134 'Parameter %s for invocation %s does not match expected ' . 135 'value.', 136 $i, 137 $this->invocation->toString() 138 ) 139 ); 140 } 141 142 return true; 143 } 144 145 /** 146 * @return bool 147 * 148 * @throws PHPUnit_Framework_ExpectationFailedException 149 */ 150 private function guardAgainstDuplicateEvaluationOfParameterConstraints() 151 { 152 if ($this->parameterVerificationResult instanceof Exception) { 153 throw $this->parameterVerificationResult; 154 } 155 156 return (bool) $this->parameterVerificationResult; 157 } 158} 159