[ Index ]

PHP Cross Reference of phpBB-3.2.11-deutsch

title

Body

[close]

/vendor/ocramius/proxy-manager/tests/ProxyManagerTest/Functional/ -> AccessInterceptorScopeLocalizerFunctionalTest.php (source)

   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  }


Generated: Wed Nov 11 20:33:01 2020 Cross-referenced by PHPXref 0.7.1