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 * Mocker for invocations which are sent from 13 * PHPUnit_Framework_MockObject_MockObject objects. 14 * 15 * Keeps track of all expectations and stubs as well as registering 16 * identifications for builders. 17 * 18 * @since Class available since Release 1.0.0 19 */ 20class PHPUnit_Framework_MockObject_InvocationMocker implements PHPUnit_Framework_MockObject_Stub_MatcherCollection, PHPUnit_Framework_MockObject_Invokable, PHPUnit_Framework_MockObject_Builder_Namespace 21{ 22 /** 23 * @var PHPUnit_Framework_MockObject_Matcher_Invocation[] 24 */ 25 protected $matchers = []; 26 27 /** 28 * @var PHPUnit_Framework_MockObject_Builder_Match[] 29 */ 30 protected $builderMap = []; 31 32 /** 33 * @var string[] 34 */ 35 private $configurableMethods = []; 36 37 /** 38 * @param array $configurableMethods 39 */ 40 public function __construct(array $configurableMethods) 41 { 42 $this->configurableMethods = $configurableMethods; 43 } 44 45 /** 46 * @param PHPUnit_Framework_MockObject_Matcher_Invocation $matcher 47 */ 48 public function addMatcher(PHPUnit_Framework_MockObject_Matcher_Invocation $matcher) 49 { 50 $this->matchers[] = $matcher; 51 } 52 53 /** 54 * @since Method available since Release 1.1.0 55 */ 56 public function hasMatchers() 57 { 58 foreach ($this->matchers as $matcher) { 59 if ($matcher->hasMatchers()) { 60 return true; 61 } 62 } 63 64 return false; 65 } 66 67 /** 68 * @param mixed $id 69 * 70 * @return bool|null 71 */ 72 public function lookupId($id) 73 { 74 if (isset($this->builderMap[$id])) { 75 return $this->builderMap[$id]; 76 } 77 78 return; 79 } 80 81 /** 82 * @param mixed $id 83 * @param PHPUnit_Framework_MockObject_Builder_Match $builder 84 * 85 * @throws PHPUnit_Framework_MockObject_RuntimeException 86 */ 87 public function registerId($id, PHPUnit_Framework_MockObject_Builder_Match $builder) 88 { 89 if (isset($this->builderMap[$id])) { 90 throw new PHPUnit_Framework_MockObject_RuntimeException( 91 'Match builder with id <' . $id . '> is already registered.' 92 ); 93 } 94 95 $this->builderMap[$id] = $builder; 96 } 97 98 /** 99 * @param PHPUnit_Framework_MockObject_Matcher_Invocation $matcher 100 * 101 * @return PHPUnit_Framework_MockObject_Builder_InvocationMocker 102 */ 103 public function expects(PHPUnit_Framework_MockObject_Matcher_Invocation $matcher) 104 { 105 return new PHPUnit_Framework_MockObject_Builder_InvocationMocker( 106 $this, 107 $matcher, 108 $this->configurableMethods 109 ); 110 } 111 112 /** 113 * @param PHPUnit_Framework_MockObject_Invocation $invocation 114 * 115 * @return mixed 116 * 117 * @throws Exception 118 */ 119 public function invoke(PHPUnit_Framework_MockObject_Invocation $invocation) 120 { 121 $exception = null; 122 $hasReturnValue = false; 123 $returnValue = null; 124 125 foreach ($this->matchers as $match) { 126 try { 127 if ($match->matches($invocation)) { 128 $value = $match->invoked($invocation); 129 130 if (!$hasReturnValue) { 131 $returnValue = $value; 132 $hasReturnValue = true; 133 } 134 } 135 } catch (Exception $e) { 136 $exception = $e; 137 } 138 } 139 140 if ($exception !== null) { 141 throw $exception; 142 } 143 144 if ($hasReturnValue) { 145 return $returnValue; 146 } elseif (strtolower($invocation->methodName) == '__tostring') { 147 return ''; 148 } 149 150 return $invocation->generateReturnValue(); 151 } 152 153 /** 154 * @param PHPUnit_Framework_MockObject_Invocation $invocation 155 * 156 * @return bool 157 */ 158 public function matches(PHPUnit_Framework_MockObject_Invocation $invocation) 159 { 160 foreach ($this->matchers as $matcher) { 161 if (!$matcher->matches($invocation)) { 162 return false; 163 } 164 } 165 166 return true; 167 } 168 169 /** 170 * @return bool 171 */ 172 public function verify() 173 { 174 foreach ($this->matchers as $matcher) { 175 $matcher->verify(); 176 } 177 } 178} 179