[ Index ] |
PHP Cross Reference of phpBB-3.2.11-deutsch |
[Summary view] [Print] [Text view]
1 <?php 2 /* 3 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 4 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 5 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR 6 * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT 7 * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 8 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT 9 * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 10 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 11 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 12 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 13 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 14 * 15 * This software consists of voluntary contributions made by many individuals 16 * and is licensed under the MIT license. 17 */ 18 19 namespace ProxyManagerTest\Functional; 20 21 use PHPUnit_Framework_SkippedTestError; 22 use PHPUnit_Framework_TestCase; 23 use ProxyManager\Exception\UnsupportedProxiedClassException; 24 use ProxyManager\GeneratorStrategy\EvaluatingGeneratorStrategy; 25 use ProxyManager\Proxy\AccessInterceptorInterface; 26 use ProxyManager\ProxyGenerator\AccessInterceptorScopeLocalizerGenerator; 27 use ProxyManagerTestAsset\BaseClass; 28 use ProxyManagerTestAsset\ClassWithPublicArrayProperty; 29 use ProxyManagerTestAsset\ClassWithPublicProperties; 30 use ProxyManagerTestAsset\ClassWithSelfHint; 31 use ReflectionClass; 32 use ProxyManager\Generator\ClassGenerator; 33 use ProxyManager\Generator\Util\UniqueIdentifierGenerator; 34 35 /** 36 * Tests for {@see \ProxyManager\ProxyGenerator\AccessInterceptorScopeLocalizerGenerator} produced objects 37 * 38 * @author Marco Pivetta <ocramius@gmail.com> 39 * @license MIT 40 * 41 * @group Functional 42 * @coversNothing 43 */ 44 class AccessInterceptorScopeLocalizerFunctionalTest extends PHPUnit_Framework_TestCase 45 { 46 /** 47 * {@inheritDoc} 48 */ 49 public static function setUpBeforeClass() 50 { 51 if (! method_exists('Closure', 'bind')) { 52 throw new PHPUnit_Framework_SkippedTestError( 53 'PHP 5.3 doesn\'t support scope localization of private properties' 54 ); 55 } 56 } 57 58 /** 59 * @dataProvider getProxyMethods 60 */ 61 public function testMethodCalls($className, $instance, $method, $params, $expectedValue) 62 { 63 $proxyName = $this->generateProxy($className); 64 65 /* @var $proxy \ProxyManager\Proxy\AccessInterceptorInterface */ 66 $proxy = new $proxyName($instance); 67 68 $this->assertProxySynchronized($instance, $proxy); 69 $this->assertSame($expectedValue, call_user_func_array(array($proxy, $method), $params)); 70 71 $listener = $this->getMock('stdClass', array('__invoke')); 72 $listener 73 ->expects($this->once()) 74 ->method('__invoke') 75 ->with($proxy, $proxy, $method, $params, false); 76 77 $proxy->setMethodPrefixInterceptor( 78 $method, 79 function ($proxy, $instance, $method, $params, & $returnEarly) use ($listener) { 80 $listener->__invoke($proxy, $instance, $method, $params, $returnEarly); 81 } 82 ); 83 84 $this->assertSame($expectedValue, call_user_func_array(array($proxy, $method), $params)); 85 86 $random = uniqid(); 87 88 $proxy->setMethodPrefixInterceptor( 89 $method, 90 function ($proxy, $instance, $method, $params, & $returnEarly) use ($random) { 91 $returnEarly = true; 92 93 return $random; 94 } 95 ); 96 97 $this->assertSame($random, call_user_func_array(array($proxy, $method), $params)); 98 $this->assertProxySynchronized($instance, $proxy); 99 } 100 101 /** 102 * @dataProvider getProxyMethods 103 */ 104 public function testMethodCallsWithSuffixListener($className, $instance, $method, $params, $expectedValue) 105 { 106 $proxyName = $this->generateProxy($className); 107 108 /* @var $proxy \ProxyManager\Proxy\AccessInterceptorInterface */ 109 $proxy = new $proxyName($instance); 110 $listener = $this->getMock('stdClass', array('__invoke')); 111 $listener 112 ->expects($this->once()) 113 ->method('__invoke') 114 ->with($proxy, $proxy, $method, $params, $expectedValue, false); 115 116 $proxy->setMethodSuffixInterceptor( 117 $method, 118 function ($proxy, $instance, $method, $params, $returnValue, & $returnEarly) use ($listener) { 119 $listener->__invoke($proxy, $instance, $method, $params, $returnValue, $returnEarly); 120 } 121 ); 122 123 $this->assertSame($expectedValue, call_user_func_array(array($proxy, $method), $params)); 124 125 $random = uniqid(); 126 127 $proxy->setMethodSuffixInterceptor( 128 $method, 129 function ($proxy, $instance, $method, $params, $returnValue, & $returnEarly) use ($random) { 130 $returnEarly = true; 131 132 return $random; 133 } 134 ); 135 136 $this->assertSame($random, call_user_func_array(array($proxy, $method), $params)); 137 $this->assertProxySynchronized($instance, $proxy); 138 } 139 140 /** 141 * @dataProvider getProxyMethods 142 */ 143 public function testMethodCallsAfterUnSerialization($className, $instance, $method, $params, $expectedValue) 144 { 145 $proxyName = $this->generateProxy($className); 146 /* @var $proxy \ProxyManager\Proxy\AccessInterceptorInterface */ 147 $proxy = unserialize(serialize(new $proxyName($instance))); 148 149 $this->assertSame($expectedValue, call_user_func_array(array($proxy, $method), $params)); 150 $this->assertProxySynchronized($instance, $proxy); 151 } 152 153 /** 154 * @dataProvider getProxyMethods 155 */ 156 public function testMethodCallsAfterCloning($className, $instance, $method, $params, $expectedValue) 157 { 158 $proxyName = $this->generateProxy($className); 159 160 /* @var $proxy \ProxyManager\Proxy\AccessInterceptorInterface */ 161 $proxy = new $proxyName($instance); 162 $cloned = clone $proxy; 163 164 $this->assertProxySynchronized($instance, $proxy); 165 $this->assertSame($expectedValue, call_user_func_array(array($cloned, $method), $params)); 166 $this->assertProxySynchronized($instance, $proxy); 167 } 168 169 /** 170 * @dataProvider getPropertyAccessProxies 171 */ 172 public function testPropertyReadAccess($instance, $proxy, $publicProperty, $propertyValue) 173 { 174 /* @var $proxy \ProxyManager\Proxy\AccessInterceptorInterface */ 175 $this->assertSame($propertyValue, $proxy->$publicProperty); 176 $this->assertProxySynchronized($instance, $proxy); 177 } 178 179 /** 180 * @dataProvider getPropertyAccessProxies 181 */ 182 public function testPropertyWriteAccess($instance, $proxy, $publicProperty) 183 { 184 /* @var $proxy \ProxyManager\Proxy\AccessInterceptorInterface */ 185 $newValue = uniqid(); 186 $proxy->$publicProperty = $newValue; 187 188 $this->assertSame($newValue, $proxy->$publicProperty); 189 $this->assertProxySynchronized($instance, $proxy); 190 } 191 192 /** 193 * @dataProvider getPropertyAccessProxies 194 */ 195 public function testPropertyExistence($instance, $proxy, $publicProperty) 196 { 197 /* @var $proxy \ProxyManager\Proxy\AccessInterceptorInterface */ 198 $this->assertSame(isset($instance->$publicProperty), isset($proxy->$publicProperty)); 199 $this->assertProxySynchronized($instance, $proxy); 200 201 $instance->$publicProperty = null; 202 $this->assertFalse(isset($proxy->$publicProperty)); 203 $this->assertProxySynchronized($instance, $proxy); 204 } 205 206 /** 207 * @dataProvider getPropertyAccessProxies 208 */ 209 public function testPropertyUnset($instance, $proxy, $publicProperty) 210 { 211 $this->markTestSkipped('It is currently not possible to synchronize properties un-setting'); 212 /* @var $proxy \ProxyManager\Proxy\AccessInterceptorInterface */ 213 unset($proxy->$publicProperty); 214 215 $this->assertFalse(isset($instance->$publicProperty)); 216 $this->assertFalse(isset($proxy->$publicProperty)); 217 $this->assertProxySynchronized($instance, $proxy); 218 } 219 220 /** 221 * Verifies that accessing a public property containing an array behaves like in a normal context 222 */ 223 public function testCanWriteToArrayKeysInPublicProperty() 224 { 225 $instance = new ClassWithPublicArrayProperty(); 226 $className = get_class($instance); 227 $proxyName = $this->generateProxy($className); 228 /* @var $proxy ClassWithPublicArrayProperty */ 229 $proxy = new $proxyName($instance); 230 231 $proxy->arrayProperty['foo'] = 'bar'; 232 233 $this->assertSame('bar', $proxy->arrayProperty['foo']); 234 235 $proxy->arrayProperty = array('tab' => 'taz'); 236 237 $this->assertSame(array('tab' => 'taz'), $proxy->arrayProperty); 238 $this->assertProxySynchronized($instance, $proxy); 239 } 240 241 /** 242 * Verifies that public properties retrieved via `__get` don't get modified in the object state 243 */ 244 public function testWillNotModifyRetrievedPublicProperties() 245 { 246 $instance = new ClassWithPublicProperties(); 247 $className = get_class($instance); 248 $proxyName = $this->generateProxy($className); 249 /* @var $proxy ClassWithPublicProperties */ 250 $proxy = new $proxyName($instance); 251 $variable = $proxy->property0; 252 253 $this->assertSame('property0', $variable); 254 255 $variable = 'foo'; 256 257 $this->assertSame('property0', $proxy->property0); 258 $this->assertProxySynchronized($instance, $proxy); 259 } 260 261 /** 262 * Verifies that public properties references retrieved via `__get` modify in the object state 263 */ 264 public function testWillModifyByRefRetrievedPublicProperties() 265 { 266 $instance = new ClassWithPublicProperties(); 267 $className = get_class($instance); 268 $proxyName = $this->generateProxy($className); 269 /* @var $proxy ClassWithPublicProperties */ 270 $proxy = new $proxyName($instance); 271 $variable = & $proxy->property0; 272 273 $this->assertSame('property0', $variable); 274 275 $variable = 'foo'; 276 277 $this->assertSame('foo', $proxy->property0); 278 $this->assertProxySynchronized($instance, $proxy); 279 } 280 281 /** 282 * Generates a proxy for the given class name, and retrieves its class name 283 * 284 * @param string $parentClassName 285 * 286 * @return string 287 * 288 * @throws UnsupportedProxiedClassException 289 */ 290 private function generateProxy($parentClassName) 291 { 292 $generatedClassName = __NAMESPACE__ . '\\' . UniqueIdentifierGenerator::getIdentifier('Foo'); 293 $generator = new AccessInterceptorScopeLocalizerGenerator(); 294 $generatedClass = new ClassGenerator($generatedClassName); 295 $strategy = new EvaluatingGeneratorStrategy(); 296 297 $generator->generate(new ReflectionClass($parentClassName), $generatedClass); 298 $strategy->generate($generatedClass); 299 300 return $generatedClassName; 301 } 302 303 /** 304 * Generates a list of object | invoked method | parameters | expected result 305 * 306 * @return array 307 */ 308 public function getProxyMethods() 309 { 310 $selfHintParam = new ClassWithSelfHint(); 311 312 $data = array( 313 array( 314 'ProxyManagerTestAsset\\BaseClass', 315 new BaseClass(), 316 'publicMethod', 317 array(), 318 'publicMethodDefault' 319 ), 320 array( 321 'ProxyManagerTestAsset\\BaseClass', 322 new BaseClass(), 323 'publicTypeHintedMethod', 324 array('param' => new \stdClass()), 325 'publicTypeHintedMethodDefault' 326 ), 327 array( 328 'ProxyManagerTestAsset\\BaseClass', 329 new BaseClass(), 330 'publicByReferenceMethod', 331 array(), 332 'publicByReferenceMethodDefault' 333 ), 334 ); 335 336 if (PHP_VERSION_ID >= 50401) { 337 // PHP < 5.4.1 misbehaves, throwing strict standards, see https://bugs.php.net/bug.php?id=60573 338 $data[] = array( 339 'ProxyManagerTestAsset\\ClassWithSelfHint', 340 new ClassWithSelfHint(), 341 'selfHintMethod', 342 array('parameter' => $selfHintParam), 343 $selfHintParam 344 ); 345 } 346 347 return $data; 348 } 349 350 /** 351 * Generates proxies and instances with a public property to feed to the property accessor methods 352 * 353 * @return array 354 */ 355 public function getPropertyAccessProxies() 356 { 357 $instance1 = new BaseClass(); 358 $proxyName1 = $this->generateProxy(get_class($instance1)); 359 360 return array( 361 array( 362 $instance1, 363 new $proxyName1($instance1), 364 'publicProperty', 365 'publicPropertyDefault', 366 ), 367 ); 368 } 369 370 /** 371 * @param object $instance 372 * @param AccessInterceptorInterface $proxy 373 */ 374 private function assertProxySynchronized($instance, AccessInterceptorInterface $proxy) 375 { 376 $reflectionClass = new ReflectionClass($instance); 377 378 foreach ($reflectionClass->getProperties() as $property) { 379 $property->setAccessible(true); 380 381 $this->assertSame( 382 $property->getValue($instance), 383 $property->getValue($proxy), 384 'Property "' . $property->getName() . '" is synchronized between instance and proxy' 385 ); 386 } 387 } 388 }
title
Description
Body
title
Description
Body
title
Description
Body
title
Body
Generated: Wed Nov 11 20:33:01 2020 | Cross-referenced by PHPXref 0.7.1 |