diff --git a/src/ProxyManager/Generator/MagicMethodGenerator.php b/src/ProxyManager/Generator/MagicMethodGenerator.php index 11ca6a2e1..e0bd1f863 100644 --- a/src/ProxyManager/Generator/MagicMethodGenerator.php +++ b/src/ProxyManager/Generator/MagicMethodGenerator.php @@ -38,6 +38,8 @@ public function __construct(ReflectionClass $originalClass, $name, array $parame $originalClass->hasMethod($name) ? '{@inheritDoc}' : null ); + $this->setReturnsReference(strtolower($name) === '__get'); + if ($originalClass->hasMethod($name)) { $this->setReturnsReference($originalClass->getMethod($name)->returnsReference()); } diff --git a/src/ProxyManager/ProxyGenerator/AccessInterceptorScopeLocalizer/MethodGenerator/MagicGet.php b/src/ProxyManager/ProxyGenerator/AccessInterceptorScopeLocalizer/MethodGenerator/MagicGet.php index 099e1c9dc..b6c241fcd 100644 --- a/src/ProxyManager/ProxyGenerator/AccessInterceptorScopeLocalizer/MethodGenerator/MagicGet.php +++ b/src/ProxyManager/ProxyGenerator/AccessInterceptorScopeLocalizer/MethodGenerator/MagicGet.php @@ -48,7 +48,6 @@ public function __construct( $override = $originalClass->hasMethod('__get'); $this->setDocblock(($override ? "{@inheritDoc}\n" : '') . '@param string $name'); - $this->setReturnsReference(true); if ($override) { $callParent = '$returnValue = & parent::__get($name);'; diff --git a/src/ProxyManager/ProxyGenerator/AccessInterceptorScopeLocalizer/MethodGenerator/MagicIsset.php b/src/ProxyManager/ProxyGenerator/AccessInterceptorScopeLocalizer/MethodGenerator/MagicIsset.php index 467d1ec55..0021e22a2 100644 --- a/src/ProxyManager/ProxyGenerator/AccessInterceptorScopeLocalizer/MethodGenerator/MagicIsset.php +++ b/src/ProxyManager/ProxyGenerator/AccessInterceptorScopeLocalizer/MethodGenerator/MagicIsset.php @@ -48,7 +48,6 @@ public function __construct( $override = $originalClass->hasMethod('__isset'); $this->setDocblock(($override ? "{@inheritDoc}\n" : '') . '@param string $name'); - $this->setReturnsReference(true); if ($override) { $callParent = '$returnValue = & parent::__isset($name);'; diff --git a/src/ProxyManager/ProxyGenerator/AccessInterceptorScopeLocalizer/MethodGenerator/MagicSet.php b/src/ProxyManager/ProxyGenerator/AccessInterceptorScopeLocalizer/MethodGenerator/MagicSet.php index 5390c241e..c24780806 100644 --- a/src/ProxyManager/ProxyGenerator/AccessInterceptorScopeLocalizer/MethodGenerator/MagicSet.php +++ b/src/ProxyManager/ProxyGenerator/AccessInterceptorScopeLocalizer/MethodGenerator/MagicSet.php @@ -52,7 +52,6 @@ public function __construct( $override = $originalClass->hasMethod('__set'); $this->setDocblock(($override ? "{@inheritDoc}\n" : '') . '@param string $name'); - $this->setReturnsReference(true); if ($override) { $callParent = '$returnValue = & parent::__set($name, $value);'; diff --git a/src/ProxyManager/ProxyGenerator/AccessInterceptorScopeLocalizer/MethodGenerator/MagicUnset.php b/src/ProxyManager/ProxyGenerator/AccessInterceptorScopeLocalizer/MethodGenerator/MagicUnset.php index 811cd2d35..b2edaaf46 100644 --- a/src/ProxyManager/ProxyGenerator/AccessInterceptorScopeLocalizer/MethodGenerator/MagicUnset.php +++ b/src/ProxyManager/ProxyGenerator/AccessInterceptorScopeLocalizer/MethodGenerator/MagicUnset.php @@ -48,7 +48,6 @@ public function __construct( $override = $originalClass->hasMethod('__unset'); $this->setDocblock(($override ? "{@inheritDoc}\n" : '') . '@param string $name'); - $this->setReturnsReference(true); if ($override) { $callParent = '$returnValue = & parent::__unset($name);'; diff --git a/src/ProxyManager/ProxyGenerator/AccessInterceptorValueHolder/MethodGenerator/MagicGet.php b/src/ProxyManager/ProxyGenerator/AccessInterceptorValueHolder/MethodGenerator/MagicGet.php index 9efcfbc90..77e6c0c94 100644 --- a/src/ProxyManager/ProxyGenerator/AccessInterceptorValueHolder/MethodGenerator/MagicGet.php +++ b/src/ProxyManager/ProxyGenerator/AccessInterceptorValueHolder/MethodGenerator/MagicGet.php @@ -50,7 +50,6 @@ public function __construct( $valueHolderName = $valueHolder->getName(); $this->setDocblock(($override ? "{@inheritDoc}\n" : '') . '@param string $name'); - $this->setReturnsReference(true); $callParent = PublicScopeSimulator::getPublicAccessSimulationCode( PublicScopeSimulator::OPERATION_GET, diff --git a/src/ProxyManager/ProxyGenerator/AccessInterceptorValueHolder/MethodGenerator/MagicIsset.php b/src/ProxyManager/ProxyGenerator/AccessInterceptorValueHolder/MethodGenerator/MagicIsset.php index 8ccbbcffb..daa6b742b 100644 --- a/src/ProxyManager/ProxyGenerator/AccessInterceptorValueHolder/MethodGenerator/MagicIsset.php +++ b/src/ProxyManager/ProxyGenerator/AccessInterceptorValueHolder/MethodGenerator/MagicIsset.php @@ -50,7 +50,6 @@ public function __construct( $valueHolderName = $valueHolder->getName(); $this->setDocblock(($override ? "{@inheritDoc}\n" : '') . '@param string $name'); - $this->setReturnsReference(true); $callParent = PublicScopeSimulator::getPublicAccessSimulationCode( PublicScopeSimulator::OPERATION_ISSET, diff --git a/src/ProxyManager/ProxyGenerator/AccessInterceptorValueHolder/MethodGenerator/MagicSet.php b/src/ProxyManager/ProxyGenerator/AccessInterceptorValueHolder/MethodGenerator/MagicSet.php index ffe784648..f79747dff 100644 --- a/src/ProxyManager/ProxyGenerator/AccessInterceptorValueHolder/MethodGenerator/MagicSet.php +++ b/src/ProxyManager/ProxyGenerator/AccessInterceptorValueHolder/MethodGenerator/MagicSet.php @@ -54,7 +54,6 @@ public function __construct( $valueHolderName = $valueHolder->getName(); $this->setDocblock(($override ? "{@inheritDoc}\n" : '') . '@param string $name'); - $this->setReturnsReference(true); $callParent = PublicScopeSimulator::getPublicAccessSimulationCode( PublicScopeSimulator::OPERATION_SET, diff --git a/src/ProxyManager/ProxyGenerator/AccessInterceptorValueHolder/MethodGenerator/MagicUnset.php b/src/ProxyManager/ProxyGenerator/AccessInterceptorValueHolder/MethodGenerator/MagicUnset.php index 884b84e47..1484c14c0 100644 --- a/src/ProxyManager/ProxyGenerator/AccessInterceptorValueHolder/MethodGenerator/MagicUnset.php +++ b/src/ProxyManager/ProxyGenerator/AccessInterceptorValueHolder/MethodGenerator/MagicUnset.php @@ -50,7 +50,6 @@ public function __construct( $valueHolderName = $valueHolder->getName(); $this->setDocblock(($override ? "{@inheritDoc}\n" : '') . '@param string $name'); - $this->setReturnsReference(true); $callParent = PublicScopeSimulator::getPublicAccessSimulationCode( PublicScopeSimulator::OPERATION_UNSET, diff --git a/src/ProxyManager/ProxyGenerator/LazyLoadingGhost/MethodGenerator/MagicGet.php b/src/ProxyManager/ProxyGenerator/LazyLoadingGhost/MethodGenerator/MagicGet.php index 2e8518156..6ede4695e 100644 --- a/src/ProxyManager/ProxyGenerator/LazyLoadingGhost/MethodGenerator/MagicGet.php +++ b/src/ProxyManager/ProxyGenerator/LazyLoadingGhost/MethodGenerator/MagicGet.php @@ -52,7 +52,6 @@ public function __construct( $callParent = ''; $this->setDocblock(($override ? "{@inheritDoc}\n" : '') . '@param string $name'); - $this->setReturnsReference(true); if (! $publicProperties->isEmpty()) { $callParent = 'if (isset(self::$' . $publicProperties->getName() . "[\$name])) {\n" diff --git a/src/ProxyManager/ProxyGenerator/LazyLoadingValueHolder/MethodGenerator/MagicGet.php b/src/ProxyManager/ProxyGenerator/LazyLoadingValueHolder/MethodGenerator/MagicGet.php index 1e54f8c73..ea7fcbcf0 100644 --- a/src/ProxyManager/ProxyGenerator/LazyLoadingValueHolder/MethodGenerator/MagicGet.php +++ b/src/ProxyManager/ProxyGenerator/LazyLoadingValueHolder/MethodGenerator/MagicGet.php @@ -45,7 +45,6 @@ public function __construct( parent::__construct($originalClass, '__get', array(new ParameterGenerator('name'))); $this->setDocblock(($originalClass->hasMethod('__get') ? "{@inheritDoc}\n" : '') . '@param string $name'); - $this->setReturnsReference(true); $initializer = $initializerProperty->getName(); $valueHolder = $valueHolderProperty->getName(); diff --git a/src/ProxyManager/ProxyGenerator/RemoteObject/MethodGenerator/MagicGet.php b/src/ProxyManager/ProxyGenerator/RemoteObject/MethodGenerator/MagicGet.php index 1c0bb88c1..e321263bb 100644 --- a/src/ProxyManager/ProxyGenerator/RemoteObject/MethodGenerator/MagicGet.php +++ b/src/ProxyManager/ProxyGenerator/RemoteObject/MethodGenerator/MagicGet.php @@ -42,8 +42,8 @@ public function __construct(ReflectionClass $originalClass, PropertyGenerator $a $this->setDocblock('@param string $name'); $this->setBody( - 'return $this->' . $adapterProperty->getName() . '->call(' . var_export($originalClass->getName(), true) - . ', \'__get\', array($name));' + '$return = $this->' . $adapterProperty->getName() . '->call(' . var_export($originalClass->getName(), true) + . ', \'__get\', array($name));' . "\n\n" . 'return $return;' ); } } diff --git a/src/ProxyManager/ProxyGenerator/RemoteObject/MethodGenerator/MagicIsset.php b/src/ProxyManager/ProxyGenerator/RemoteObject/MethodGenerator/MagicIsset.php index 789f6baf2..cf24797ac 100644 --- a/src/ProxyManager/ProxyGenerator/RemoteObject/MethodGenerator/MagicIsset.php +++ b/src/ProxyManager/ProxyGenerator/RemoteObject/MethodGenerator/MagicIsset.php @@ -42,8 +42,9 @@ public function __construct(ReflectionClass $originalClass, PropertyGenerator $a $this->setDocblock('@param string $name'); $this->setBody( - 'return $this->' . $adapterProperty->getName() . '->call(' . var_export($originalClass->getName(), true) - . ', \'__isset\', array($name));' + '$return = $this->' . $adapterProperty->getName() . '->call(' . var_export($originalClass->getName(), true) + . ', \'__isset\', array($name));' . "\n\n" + . 'return $return;' ); } } diff --git a/src/ProxyManager/ProxyGenerator/RemoteObject/MethodGenerator/MagicSet.php b/src/ProxyManager/ProxyGenerator/RemoteObject/MethodGenerator/MagicSet.php index 4212ba205..6efaaf232 100644 --- a/src/ProxyManager/ProxyGenerator/RemoteObject/MethodGenerator/MagicSet.php +++ b/src/ProxyManager/ProxyGenerator/RemoteObject/MethodGenerator/MagicSet.php @@ -46,8 +46,9 @@ public function __construct(ReflectionClass $originalClass, PropertyGenerator $a $this->setDocblock('@param string \$name\n@param mixed \$value'); $this->setBody( - 'return $this->' . $adapterProperty->getName() . '->call(' . var_export($originalClass->getName(), true) - .', \'__set\', array($name, $value));' + '$return = $this->' . $adapterProperty->getName() . '->call(' . var_export($originalClass->getName(), true) + . ', \'__set\', array($name, $value));' . "\n\n" + . 'return $return;' ); } } diff --git a/src/ProxyManager/ProxyGenerator/RemoteObject/MethodGenerator/MagicUnset.php b/src/ProxyManager/ProxyGenerator/RemoteObject/MethodGenerator/MagicUnset.php index 401634d54..ffe34fbef 100644 --- a/src/ProxyManager/ProxyGenerator/RemoteObject/MethodGenerator/MagicUnset.php +++ b/src/ProxyManager/ProxyGenerator/RemoteObject/MethodGenerator/MagicUnset.php @@ -43,8 +43,9 @@ public function __construct(ReflectionClass $originalClass, PropertyGenerator $a $this->setDocblock('@param string $name'); $this->setBody( - 'return $this->' . $adapterProperty->getName() . '->call(' . var_export($originalClass->getName(), true) - . ', \'__unset\', array($name));' + '$return = $this->' . $adapterProperty->getName() . '->call(' . var_export($originalClass->getName(), true) + . ', \'__unset\', array($name));' . "\n\n" + . 'return $return;' ); } } diff --git a/src/ProxyManager/ProxyGenerator/RemoteObject/MethodGenerator/RemoteObjectMethod.php b/src/ProxyManager/ProxyGenerator/RemoteObject/MethodGenerator/RemoteObjectMethod.php index cfd1b5fcc..3d0d1de5e 100644 --- a/src/ProxyManager/ProxyGenerator/RemoteObject/MethodGenerator/RemoteObjectMethod.php +++ b/src/ProxyManager/ProxyGenerator/RemoteObject/MethodGenerator/RemoteObjectMethod.php @@ -53,8 +53,9 @@ public static function generateMethod( } $method->setBody( - 'return $this->' . $adapterProperty->getName() . '->call(' . var_export($originalClass->getName(), true) - . ', ' . var_export($originalMethod->getName(), true) . ', array('. implode(', ', $list) .'));' + '$return = $this->' . $adapterProperty->getName() . '->call(' . var_export($originalClass->getName(), true) + . ', ' . var_export($originalMethod->getName(), true) . ', array('. implode(', ', $list) .'));' . "\n\n" + . 'return $return;' ); return $method; diff --git a/src/ProxyManager/ProxyGenerator/Util/PublicScopeSimulator.php b/src/ProxyManager/ProxyGenerator/Util/PublicScopeSimulator.php index 764fb13b0..571767cff 100644 --- a/src/ProxyManager/ProxyGenerator/Util/PublicScopeSimulator.php +++ b/src/ProxyManager/ProxyGenerator/Util/PublicScopeSimulator.php @@ -36,6 +36,10 @@ class PublicScopeSimulator const OPERATION_UNSET = 'unset'; /** + * Generates code for simulating access to a property from the scope that is accessing a proxy. + * This is done by introspecting `debug_backtrace()` and then binding a closure to the scope + * of the parent caller. + * * @param string $operationType operation to execute: one of 'get', 'set', 'isset' or 'unset' * @param string $nameParameter name of the `name` parameter of the magic method * @param string|null $valueParameter name of the `value` parameter of the magic method @@ -55,15 +59,53 @@ public static function getPublicAccessSimulationCode( PropertyGenerator $valueHolder = null, $returnPropertyName = null ) { - $byRef = self::getByRefReturnValue($operationType); - $value = static::OPERATION_SET === $operationType ? ', $value' : ''; + $byRef = self::getByRefReturnValue($operationType); + $value = static::OPERATION_SET === $operationType ? ', $value' : ''; + $target = '$this'; + + if ($valueHolder) { + $target = '$this->' . $valueHolder->getName(); + } - return '$targetObject = ' . self::getTargetObject($valueHolder) . ";\n" - . ' $accessor = function ' . $byRef . '() use ($targetObject, $name' . $value . ') {' . "\n" - . ' ' . self::getOperation($operationType, $nameParameter, $valueParameter) . ';' . "\n" - . " };\n" + return '$realInstanceReflection = new \\ReflectionClass(get_parent_class($this));' . "\n\n" + . 'if (! $realInstanceReflection->hasProperty($' . $nameParameter . ')) {' . "\n" + . ' $targetObject = ' . $target . ';' . "\n\n" + . self::getUndefinedPropertyNotice($operationType, $nameParameter) + . ' ' . self::getOperation($operationType, $nameParameter, $valueParameter) . ";\n" + . " return;\n" + . '}' . "\n\n" + . '$targetObject = ' . self::getTargetObject($valueHolder) . ";\n" + . '$accessor = function ' . $byRef . '() use ($targetObject, $name' . $value . ') {' . "\n" + . ' ' . self::getOperation($operationType, $nameParameter, $valueParameter) . "\n" + . "};\n" . self::getScopeReBind() - . ' ' . ($returnPropertyName ? '$' . $returnPropertyName . ' =' : 'return') . ' $accessor();'; + . ( + $returnPropertyName + ? '$' . $returnPropertyName . ' = ' . $byRef . '$accessor();' + : '$returnValue = ' . $byRef . '$accessor();' . "\n\n" . 'return $returnValue;' + ); + } + + /** + * This will generate code that triggers a notice if access is attempted on a non-existing property + * + * @param string $operationType + * @param string $nameParameter + * + * @return string + */ + private static function getUndefinedPropertyNotice($operationType, $nameParameter) + { + if (static::OPERATION_GET !== $operationType) { + return ''; + } + + // + return ' $backtrace = debug_backtrace(false);' . "\n" + . ' trigger_error(\'Undefined property: \' . get_parent_class($this) . \'::$\' . $' + . $nameParameter + . ' . \' in \' . $backtrace[0][\'file\'] . \' on line \' . $backtrace[0][\'line\'], \E_USER_NOTICE);' + . "\n"; } /** @@ -95,7 +137,7 @@ private static function getTargetObject(PropertyGenerator $valueHolder = null) return '$this->' . $valueHolder->getName(); } - return 'unserialize(sprintf(\'O:%d:"%s":0:{}\', strlen(get_parent_class($this)), get_parent_class($this)));'; + return 'unserialize(sprintf(\'O:%d:"%s":0:{}\', strlen(get_parent_class($this)), get_parent_class($this)))'; } /** @@ -111,17 +153,17 @@ private static function getOperation($operationType, $nameParameter, $valueParam { switch ($operationType) { case static::OPERATION_GET: - return 'return $targetObject->$' . $nameParameter; + return 'return $targetObject->$' . $nameParameter . ";"; case static::OPERATION_SET: if (! $valueParameter) { throw new \InvalidArgumentException('Parameter $valueParameter not provided'); } - return 'return $targetObject->$' . $nameParameter . ' = $' . $valueParameter; + return 'return $targetObject->$' . $nameParameter . ' = $' . $valueParameter . ';'; case static::OPERATION_ISSET: - return 'return isset($targetObject->$' . $nameParameter . ')'; + return 'return isset($targetObject->$' . $nameParameter . ');'; case static::OPERATION_UNSET: - return 'unset($targetObject->$' . $nameParameter . ')'; + return 'unset($targetObject->$' . $nameParameter . ');'; } throw new \InvalidArgumentException(sprintf('Invalid operation "%s" provided', $operationType)); @@ -140,7 +182,7 @@ private static function getScopeReBind() // @codeCoverageIgnoreEnd } - return ' $backtrace = debug_backtrace(\DEBUG_BACKTRACE_PROVIDE_OBJECT);' . "\n" + return ' $backtrace = debug_backtrace(true);' . "\n" . ' $scopeObject = isset($backtrace[1][\'object\'])' . ' ? $backtrace[1][\'object\'] : new \stdClass();' . "\n" . ' $accessor = $accessor->bindTo($scopeObject, get_class($scopeObject));' . "\n"; diff --git a/tests/Bootstrap.php b/tests/Bootstrap.php index a61d6f348..9f84dcd69 100644 --- a/tests/Bootstrap.php +++ b/tests/Bootstrap.php @@ -16,7 +16,7 @@ * and is licensed under the MIT license. */ -ini_set('error_reporting', E_ALL); +ini_set('error_reporting', E_ALL | E_STRICT); $files = array(__DIR__ . '/../vendor/autoload.php', __DIR__ . '/../../../autoload.php'); diff --git a/tests/ProxyManagerTest/ProxyGenerator/AccessInterceptorScopeLocalizer/MethodGenerator/MagicGetTest.php b/tests/ProxyManagerTest/ProxyGenerator/AccessInterceptorScopeLocalizer/MethodGenerator/MagicGetTest.php index 2f7e62ccd..3d188bb5c 100644 --- a/tests/ProxyManagerTest/ProxyGenerator/AccessInterceptorScopeLocalizer/MethodGenerator/MagicGetTest.php +++ b/tests/ProxyManagerTest/ProxyGenerator/AccessInterceptorScopeLocalizer/MethodGenerator/MagicGetTest.php @@ -50,7 +50,7 @@ public function testBodyStructure() $this->assertSame('__get', $magicGet->getName()); $this->assertCount(1, $magicGet->getParameters()); - $this->assertStringMatchesFormat('%a$returnValue = $accessor();%a', $magicGet->getBody()); + $this->assertStringMatchesFormat('%a$returnValue = & $accessor();%a', $magicGet->getBody()); } /** diff --git a/tests/ProxyManagerTest/ProxyGenerator/AccessInterceptorScopeLocalizer/MethodGenerator/MagicSetTest.php b/tests/ProxyManagerTest/ProxyGenerator/AccessInterceptorScopeLocalizer/MethodGenerator/MagicSetTest.php index ecd02b781..14f6ccf43 100644 --- a/tests/ProxyManagerTest/ProxyGenerator/AccessInterceptorScopeLocalizer/MethodGenerator/MagicSetTest.php +++ b/tests/ProxyManagerTest/ProxyGenerator/AccessInterceptorScopeLocalizer/MethodGenerator/MagicSetTest.php @@ -50,7 +50,7 @@ public function testBodyStructure() $this->assertSame('__set', $magicGet->getName()); $this->assertCount(2, $magicGet->getParameters()); - $this->assertStringMatchesFormat('%a$returnValue = $accessor();%a', $magicGet->getBody()); + $this->assertStringMatchesFormat('%a$returnValue = & $accessor();%a', $magicGet->getBody()); } /** diff --git a/tests/ProxyManagerTest/ProxyGenerator/RemoteObject/MethodGenerator/MagicGetTest.php b/tests/ProxyManagerTest/ProxyGenerator/RemoteObject/MethodGenerator/MagicGetTest.php index f3e83f99e..e7dcac83b 100644 --- a/tests/ProxyManagerTest/ProxyGenerator/RemoteObject/MethodGenerator/MagicGetTest.php +++ b/tests/ProxyManagerTest/ProxyGenerator/RemoteObject/MethodGenerator/MagicGetTest.php @@ -44,7 +44,8 @@ public function testBodyStructure() $this->assertSame('__get', $magicGet->getName()); $this->assertCount(1, $magicGet->getParameters()); $this->assertStringMatchesFormat( - 'return $this->foo->call(\'ProxyManagerTestAsset\\\EmptyClass\', \'__get\', array($name));', + '$return = $this->foo->call(\'ProxyManagerTestAsset\\\EmptyClass\', \'__get\', array($name));' + . "\n\nreturn \$return;", $magicGet->getBody() ); } diff --git a/tests/ProxyManagerTest/ProxyGenerator/RemoteObject/MethodGenerator/MagicIssetTest.php b/tests/ProxyManagerTest/ProxyGenerator/RemoteObject/MethodGenerator/MagicIssetTest.php index 1e44616af..0253b8c03 100644 --- a/tests/ProxyManagerTest/ProxyGenerator/RemoteObject/MethodGenerator/MagicIssetTest.php +++ b/tests/ProxyManagerTest/ProxyGenerator/RemoteObject/MethodGenerator/MagicIssetTest.php @@ -44,7 +44,8 @@ public function testBodyStructure() $this->assertSame('__isset', $magicGet->getName()); $this->assertCount(1, $magicGet->getParameters()); $this->assertStringMatchesFormat( - 'return $this->foo->call(\'ProxyManagerTestAsset\\\EmptyClass\', \'__isset\', array($name));', + '$return = $this->foo->call(\'ProxyManagerTestAsset\\\EmptyClass\', \'__isset\', array($name));' + . "\n\nreturn \$return;", $magicGet->getBody() ); } diff --git a/tests/ProxyManagerTest/ProxyGenerator/RemoteObject/MethodGenerator/MagicSetTest.php b/tests/ProxyManagerTest/ProxyGenerator/RemoteObject/MethodGenerator/MagicSetTest.php index 0f40682b1..14b53c812 100644 --- a/tests/ProxyManagerTest/ProxyGenerator/RemoteObject/MethodGenerator/MagicSetTest.php +++ b/tests/ProxyManagerTest/ProxyGenerator/RemoteObject/MethodGenerator/MagicSetTest.php @@ -44,7 +44,8 @@ public function testBodyStructure() $this->assertSame('__set', $magicGet->getName()); $this->assertCount(2, $magicGet->getParameters()); $this->assertStringMatchesFormat( - 'return $this->foo->call(\'ProxyManagerTestAsset\\\EmptyClass\', \'__set\', array($name, $value));', + '$return = $this->foo->call(\'ProxyManagerTestAsset\\\EmptyClass\', \'__set\', array($name, $value));' + . "\n\nreturn \$return;", $magicGet->getBody() ); } diff --git a/tests/ProxyManagerTest/ProxyGenerator/RemoteObject/MethodGenerator/MagicUnsetTest.php b/tests/ProxyManagerTest/ProxyGenerator/RemoteObject/MethodGenerator/MagicUnsetTest.php index 3598512f0..c4ffb21a7 100644 --- a/tests/ProxyManagerTest/ProxyGenerator/RemoteObject/MethodGenerator/MagicUnsetTest.php +++ b/tests/ProxyManagerTest/ProxyGenerator/RemoteObject/MethodGenerator/MagicUnsetTest.php @@ -44,7 +44,8 @@ public function testBodyStructure() $this->assertSame('__unset', $magicGet->getName()); $this->assertCount(1, $magicGet->getParameters()); $this->assertStringMatchesFormat( - 'return $this->foo->call(\'ProxyManagerTestAsset\\\EmptyClass\', \'__unset\', array($name));', + '$return = $this->foo->call(\'ProxyManagerTestAsset\\\EmptyClass\', \'__unset\', array($name));' + . "\n\nreturn \$return;", $magicGet->getBody() ); } diff --git a/tests/ProxyManagerTest/ProxyGenerator/RemoteObject/MethodGenerator/RemoteObjectMethodTest.php b/tests/ProxyManagerTest/ProxyGenerator/RemoteObject/MethodGenerator/RemoteObjectMethodTest.php index 21973e914..6e72166c1 100644 --- a/tests/ProxyManagerTest/ProxyGenerator/RemoteObject/MethodGenerator/RemoteObjectMethodTest.php +++ b/tests/ProxyManagerTest/ProxyGenerator/RemoteObject/MethodGenerator/RemoteObjectMethodTest.php @@ -53,8 +53,9 @@ public function testBodyStructureWithParameters() $this->assertSame('publicByReferenceParameterMethod', $method->getName()); $this->assertCount(2, $method->getParameters()); $this->assertSame( - 'return $this->adapter->call(\'Zend\\\Code\\\Generator\\\PropertyGenerator\', ' - . '\'publicByReferenceParameterMethod\', array($param, $byRefParam));', + '$return = $this->adapter->call(\'Zend\\\Code\\\Generator\\\PropertyGenerator\', ' + . '\'publicByReferenceParameterMethod\', array($param, $byRefParam));' + . "\n\nreturn \$return;", $method->getBody() ); } @@ -78,8 +79,9 @@ public function testBodyStructureWithArrayParameter() $this->assertSame('publicArrayHintedMethod', $method->getName()); $this->assertCount(1, $method->getParameters()); $this->assertSame( - 'return $this->adapter->call(\'Zend\\\Code\\\Generator\\\PropertyGenerator\', ' - . '\'publicArrayHintedMethod\', array($param));', + '$return = $this->adapter->call(\'Zend\\\Code\\\Generator\\\PropertyGenerator\', ' + . '\'publicArrayHintedMethod\', array($param));' + . "\n\nreturn \$return;", $method->getBody() ); } @@ -103,8 +105,9 @@ public function testBodyStructureWithoutParameters() $this->assertSame('testBodyStructureWithoutParameters', $method->getName()); $this->assertCount(0, $method->getParameters()); $this->assertSame( - 'return $this->adapter->call(\'Zend\\\Code\\\Generator\\\PropertyGenerator\', ' - . '\'testBodyStructureWithoutParameters\', array());', + '$return = $this->adapter->call(\'Zend\\\Code\\\Generator\\\PropertyGenerator\', ' + . '\'testBodyStructureWithoutParameters\', array());' + . "\n\nreturn \$return;", $method->getBody() ); } diff --git a/tests/language-feature-scripts/lazy-loading-ghost-allows-inexisting-magic-property-read.phpt b/tests/language-feature-scripts/lazy-loading-ghost-allows-inexisting-magic-property-read.phpt new file mode 100644 index 000000000..2f318c745 --- /dev/null +++ b/tests/language-feature-scripts/lazy-loading-ghost-allows-inexisting-magic-property-read.phpt @@ -0,0 +1,25 @@ +--TEST-- +Verifies that generated lazy loading ghost objects disallow reading non-existing properties via direct read +--FILE-- +createProxy('Kitchen', function () {}); + +echo $proxy->nonExisting; +?> +--EXPECTF-- +nonExisting \ No newline at end of file diff --git a/tests/language-feature-scripts/lazy-loading-ghost-allows-inexisting-property-write.phpt b/tests/language-feature-scripts/lazy-loading-ghost-allows-inexisting-property-write.phpt new file mode 100644 index 000000000..e815d0f2c --- /dev/null +++ b/tests/language-feature-scripts/lazy-loading-ghost-allows-inexisting-property-write.phpt @@ -0,0 +1,21 @@ +--TEST-- +Verifies that generated lazy loading ghost objects disallow reading non-existing properties via direct read +--FILE-- +createProxy('Kitchen', function () {}); + +$proxy->nonExisting = 'I do not exist'; +echo $proxy->nonExisting; +?> +--EXPECTF-- +I do not exist \ No newline at end of file diff --git a/tests/language-feature-scripts/lazy-loading-ghost-denies-inexisting-property-read.phpt b/tests/language-feature-scripts/lazy-loading-ghost-denies-inexisting-property-read.phpt new file mode 100644 index 000000000..73042abe0 --- /dev/null +++ b/tests/language-feature-scripts/lazy-loading-ghost-denies-inexisting-property-read.phpt @@ -0,0 +1,20 @@ +--TEST-- +Verifies that generated lazy loading ghost objects disallow reading non-existing properties via direct read +--FILE-- +createProxy('Kitchen', function () {}); + +$proxy->nonExisting; +?> +--EXPECTF-- +Notice: Undefined property: Kitchen::$nonExisting in %s on line %d \ No newline at end of file