Skip to content

Commit

Permalink
Merge pull request #61 from Ocramius/hotfix/issue-#55-byref-magic-get
Browse files Browse the repository at this point in the history
Adding test cases for classes implementing by-ref magic __get
  • Loading branch information
Ocramius committed Jun 27, 2013
2 parents f785193 + 09347e2 commit 20dbacf
Show file tree
Hide file tree
Showing 27 changed files with 357 additions and 71 deletions.
45 changes: 45 additions & 0 deletions src/ProxyManager/Generator/MagicMethodGenerator.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,45 @@
<?php
/*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
* A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
* OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*
* This software consists of voluntary contributions made by many individuals
* and is licensed under the MIT license.
*/

namespace ProxyManager\Generator;

use ReflectionClass;

/**
* Method generator for magic methods
*
* @author Marco Pivetta <ocramius@gmail.com>
* @license MIT
*/
class MagicMethodGenerator extends MethodGenerator
{
public function __construct(ReflectionClass $originalClass, $name, array $parameters = array())
{
parent::__construct(
$name,
$parameters,
static::FLAG_PUBLIC,
null,
$originalClass->hasMethod($name) ? '{@inheritDoc}' : null
);

if ($originalClass->hasMethod($name)) {
$this->setReturnsReference($originalClass->getMethod($name)->returnsReference());
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,7 @@

namespace ProxyManager\ProxyGenerator\AccessInterceptor\MethodGenerator;

use ProxyManager\Generator\MagicMethodGenerator;
use ReflectionClass;
use ReflectionProperty;
use ProxyManager\Generator\MethodGenerator;
Expand All @@ -28,14 +29,14 @@
* @author Marco Pivetta <ocramius@gmail.com>
* @license MIT
*/
class MagicWakeup extends MethodGenerator
class MagicWakeup extends MagicMethodGenerator
{
/**
* Constructor
*/
public function __construct(ReflectionClass $originalClass)
{
parent::__construct('__wakeup');
parent::__construct($originalClass, '__wakeup');

/* @var $publicProperties \ReflectionProperty[] */
$publicProperties = $originalClass->getProperties(ReflectionProperty::IS_PUBLIC);
Expand All @@ -45,9 +46,6 @@ public function __construct(ReflectionClass $originalClass)
$unsetProperties[] = '$this->' . $publicProperty->getName();
}

$this->setDocblock($originalClass->hasMethod('__wakeup') ? '{@inheritDoc}' : '');
$this->setBody(
($unsetProperties ? 'unset(' . implode(', ', $unsetProperties) . ");" : '')
);
$this->setBody($unsetProperties ? 'unset(' . implode(', ', $unsetProperties) . ");" : '');
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,7 @@

namespace ProxyManager\ProxyGenerator\AccessInterceptorValueHolder\MethodGenerator;

use ProxyManager\Generator\MagicMethodGenerator;
use ReflectionClass;
use ProxyManager\Generator\MethodGenerator;
use Zend\Code\Generator\PropertyGenerator;
Expand All @@ -28,7 +29,7 @@
* @author Marco Pivetta <ocramius@gmail.com>
* @license MIT
*/
class MagicClone extends MethodGenerator
class MagicClone extends MagicMethodGenerator
{
/**
* Constructor
Expand All @@ -39,13 +40,12 @@ public function __construct(
PropertyGenerator $prefixInterceptors,
PropertyGenerator $suffixInterceptors
) {
parent::__construct('__clone');
parent::__construct($originalClass, '__clone');

$valueHolder = $valueHolderProperty->getName();
$prefix = $prefixInterceptors->getName();
$suffix = $suffixInterceptors->getName();

$this->setDocblock($originalClass->hasMethod('__wakeup') ? '{@inheritDoc}' : '');
$this->setBody(
"\$this->$valueHolder = clone \$this->$valueHolder;\n\n"
. "foreach (\$this->$prefix as \$key => \$value) {\n"
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,7 @@

namespace ProxyManager\ProxyGenerator\AccessInterceptorValueHolder\MethodGenerator;

use ProxyManager\Generator\MagicMethodGenerator;
use ProxyManager\ProxyGenerator\AccessInterceptorValueHolder\MethodGenerator\Util\InterceptorGenerator;
use ReflectionClass;
use ProxyManager\Generator\MethodGenerator;
Expand All @@ -30,7 +31,7 @@
* @author Marco Pivetta <ocramius@gmail.com>
* @license MIT
*/
class MagicGet extends MethodGenerator
class MagicGet extends MagicMethodGenerator
{
/**
* Constructor
Expand All @@ -41,11 +42,11 @@ public function __construct(
PropertyGenerator $prefixInterceptors,
PropertyGenerator $suffixInterceptors
) {
$inheritDoc = $originalClass->hasMethod('__get') ? "{@inheritDoc}\n" : '';
parent::__construct($originalClass, '__get', array(new ParameterGenerator('name')));

$inheritDoc = $originalClass->hasMethod('__get') ? "{@inheritDoc}\n" : '';

parent::__construct('__get');
$this->setDocblock($inheritDoc . '@param string $name');
$this->setParameters(array(new ParameterGenerator('name')));
$this->setBody(
InterceptorGenerator::createInterceptedMethodBody(
'$returnValue = $this->' . $valueHolder->getName() . '->$name;',
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,7 @@

namespace ProxyManager\ProxyGenerator\AccessInterceptorValueHolder\MethodGenerator;

use ProxyManager\Generator\MagicMethodGenerator;
use ProxyManager\ProxyGenerator\AccessInterceptorValueHolder\MethodGenerator\Util\InterceptorGenerator;
use ReflectionClass;
use ProxyManager\Generator\MethodGenerator;
Expand All @@ -30,7 +31,7 @@
* @author Marco Pivetta <ocramius@gmail.com>
* @license MIT
*/
class MagicIsset extends MethodGenerator
class MagicIsset extends MagicMethodGenerator
{
/**
* Constructor
Expand All @@ -41,11 +42,11 @@ public function __construct(
PropertyGenerator $prefixInterceptors,
PropertyGenerator $suffixInterceptors
) {
$inheritDoc = $originalClass->hasMethod('__isset') ? "{@inheritDoc}\n" : '';
parent::__construct($originalClass, '__isset', array(new ParameterGenerator('name')));

$inheritDoc = $originalClass->hasMethod('__isset') ? "{@inheritDoc}\n" : '';

parent::__construct('__isset');
$this->setDocblock($inheritDoc . '@param string $name');
$this->setParameters(array(new ParameterGenerator('name')));
$this->setBody(
InterceptorGenerator::createInterceptedMethodBody(
'$returnValue = isset($this->' . $valueHolder->getName() . '->$name);',
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,7 @@

namespace ProxyManager\ProxyGenerator\AccessInterceptorValueHolder\MethodGenerator;

use ProxyManager\Generator\MagicMethodGenerator;
use ProxyManager\ProxyGenerator\AccessInterceptorValueHolder\MethodGenerator\Util\InterceptorGenerator;
use ReflectionClass;
use ProxyManager\Generator\MethodGenerator;
Expand All @@ -30,7 +31,7 @@
* @author Marco Pivetta <ocramius@gmail.com>
* @license MIT
*/
class MagicSet extends MethodGenerator
class MagicSet extends MagicMethodGenerator
{
/**
* Constructor
Expand All @@ -41,11 +42,15 @@ public function __construct(
PropertyGenerator $prefixInterceptors,
PropertyGenerator $suffixInterceptors
) {
$inheritDoc = $originalClass->hasMethod('__set') ? "{@inheritDoc}\n" : '';
parent::__construct(
$originalClass,
'__set',
array(new ParameterGenerator('name'), new ParameterGenerator('value'))
);

$inheritDoc = $originalClass->hasMethod('__set') ? "{@inheritDoc}\n" : '';

parent::__construct('__set');
$this->setDocblock($inheritDoc . '@param string $name');
$this->setParameters(array(new ParameterGenerator('name'), new ParameterGenerator('value')));
$this->setBody(
InterceptorGenerator::createInterceptedMethodBody(
'$returnValue = ($this->' . $valueHolder->getName() . '->$name = $value);',
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,7 @@

namespace ProxyManager\ProxyGenerator\AccessInterceptorValueHolder\MethodGenerator;

use ProxyManager\Generator\MagicMethodGenerator;
use ProxyManager\ProxyGenerator\AccessInterceptorValueHolder\MethodGenerator\Util\InterceptorGenerator;
use ReflectionClass;
use ProxyManager\Generator\MethodGenerator;
Expand All @@ -30,7 +31,7 @@
* @author Marco Pivetta <ocramius@gmail.com>
* @license MIT
*/
class MagicUnset extends MethodGenerator
class MagicUnset extends MagicMethodGenerator
{
/**
* Constructor
Expand All @@ -41,11 +42,11 @@ public function __construct(
PropertyGenerator $prefixInterceptors,
PropertyGenerator $suffixInterceptors
) {
$inheritDoc = $originalClass->hasMethod('__isset') ? "{@inheritDoc}\n" : '';
parent::__construct($originalClass, '__unset', array(new ParameterGenerator('name')));

$inheritDoc = $originalClass->hasMethod('__isset') ? "{@inheritDoc}\n" : '';

parent::__construct('__unset');
$this->setDocblock($inheritDoc . '@param string $name');
$this->setParameters(array(new ParameterGenerator('name')));
$this->setBody(
InterceptorGenerator::createInterceptedMethodBody(
'unset($this->' . $valueHolder->getName() . '->$name);' . "\n\n" . '$returnValue = true;',
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,46 @@
<?php
/*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
* A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
* OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*
* This software consists of voluntary contributions made by many individuals
* and is licensed under the MIT license.
*/

namespace ProxyManager\ProxyGenerator\Hydrator\MethodGenerator;

use ProxyManager\Exception\DisabledMethodException;
use ProxyManager\Generator\MagicMethodGenerator;
use ProxyManager\Generator\MethodGenerator;

/**
* Method generator for forcefully disabled methods
*
* @author Marco Pivetta <ocramius@gmail.com>
* @license MIT
*/
class DisabledMagicMethod extends MagicMethodGenerator
{
/**
* {@inheritDoc}
*/
public function generate()
{
$this->setBody('throw \\' . DisabledMethodException::NAME . '::disabledMethod(__METHOD__);');
$this->setDocblock(
"{@inheritDoc}\n\n@internal disabled since this object is not a real proxy\n\n"
. "@throws \\ProxyManager\\Exception\\DisabledMethodException"
);

return parent::generate();
}
}
13 changes: 8 additions & 5 deletions src/ProxyManager/ProxyGenerator/HydratorGenerator.php
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,7 @@
namespace ProxyManager\ProxyGenerator;

use ProxyManager\Generator\MethodGenerator;
use ProxyManager\ProxyGenerator\Hydrator\MethodGenerator\DisabledMagicMethod;
use ProxyManager\ProxyGenerator\Hydrator\MethodGenerator\GetAccessorProperties;
use ProxyManager\ProxyGenerator\Hydrator\MethodGenerator\SetAccessorProperties;
use ProxyManager\ProxyGenerator\Hydrator\PropertyGenerator\PropertyAccessor;
Expand Down Expand Up @@ -90,13 +91,15 @@ function (ReflectionMethod $method) use ($excluded) {
}

foreach (array('__clone', '__sleep', '__wakeup') as $magicMethod) {
$classGenerator->addMethodFromGenerator(new DisabledMethod($magicMethod));
$classGenerator->addMethodFromGenerator(new DisabledMagicMethod($originalClass, $magicMethod));
}

$classGenerator->addMethodFromGenerator(new DisabledMethod('__get', array('name')));
$classGenerator->addMethodFromGenerator(new DisabledMethod('__set', array('name', 'value')));
$classGenerator->addMethodFromGenerator(new DisabledMethod('__isset', array('name')));
$classGenerator->addMethodFromGenerator(new DisabledMethod('__unset', array('name')));
$classGenerator->addMethodFromGenerator(new DisabledMagicMethod($originalClass, '__get', array('name')));
$classGenerator->addMethodFromGenerator(
new DisabledMagicMethod($originalClass, '__set', array('name', 'value'))
);
$classGenerator->addMethodFromGenerator(new DisabledMagicMethod($originalClass, '__isset', array('name')));
$classGenerator->addMethodFromGenerator(new DisabledMagicMethod($originalClass, '__unset', array('name')));

$accessibleFlag = ReflectionProperty::IS_PUBLIC | ReflectionProperty::IS_PROTECTED;
$accessibleProperties = $originalClass->getProperties($accessibleFlag);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,7 @@

namespace ProxyManager\ProxyGenerator\LazyLoadingGhost\MethodGenerator;

use ProxyManager\Generator\MagicMethodGenerator;
use ReflectionClass;
use ProxyManager\Generator\MethodGenerator;
use Zend\Code\Generator\PropertyGenerator;
Expand All @@ -28,23 +29,21 @@
* @author Marco Pivetta <ocramius@gmail.com>
* @license MIT
*/
class MagicClone extends MethodGenerator
class MagicClone extends MagicMethodGenerator
{
/**
* Constructor
*/
public function __construct(ReflectionClass $originalClass, PropertyGenerator $initializerProperty)
{
parent::__construct('__clone');
parent::__construct($originalClass, '__clone');

$override = $originalClass->hasMethod('__clone');
$initializer = $initializerProperty->getName();

$this->setDocblock($override ? '{@inheritDoc}' : '');
$this->setBody(
'$this->' . $initializer . ' && $this->' . $initializer
. '->__invoke($this, \'__clone\', array(), $this->' . $initializer . ');'
. ($override ? "\n\nparent::__clone();" : '')
. ($originalClass->hasMethod('__clone') ? "\n\nparent::__clone();" : '')
);
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,7 @@

namespace ProxyManager\ProxyGenerator\LazyLoadingGhost\MethodGenerator;

use ProxyManager\Generator\MagicMethodGenerator;
use ReflectionClass;
use ProxyManager\Generator\MethodGenerator;
use ProxyManager\Generator\ParameterGenerator;
Expand All @@ -30,14 +31,14 @@
* @author Marco Pivetta <ocramius@gmail.com>
* @license MIT
*/
class MagicGet extends MethodGenerator
class MagicGet extends MagicMethodGenerator
{
/**
* Constructor
*/
public function __construct(ReflectionClass $originalClass, PropertyGenerator $initializerProperty)
{
parent::__construct('__get');
parent::__construct($originalClass, '__get', array(new ParameterGenerator('name')));

$override = $originalClass->hasMethod('__get');
$initializer = $initializerProperty->getName();
Expand All @@ -49,7 +50,6 @@ function (ReflectionProperty $publicProperty) {
);

$this->setDocblock(($override ? "{@inheritDoc}\n" : '') . '@param string $name');
$this->setParameters(array(new ParameterGenerator('name')));

// @todo can be skipped when no public properties are available
$callParent = 'if (in_array($name, array(' . implode(', ', $publicProperties) . '))) {' . "\n"
Expand Down
Loading

0 comments on commit 20dbacf

Please sign in to comment.