Skip to content

Commit

Permalink
Merge 642f256 into ef07cbf
Browse files Browse the repository at this point in the history
  • Loading branch information
blanchonvincent committed Oct 2, 2013
2 parents ef07cbf + 642f256 commit e8e6c60
Show file tree
Hide file tree
Showing 16 changed files with 925 additions and 0 deletions.
51 changes: 51 additions & 0 deletions src/ProxyManager/Factory/OverloadingFactory.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,51 @@
<?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\Factory;

use ProxyManager\ProxyGenerator\OverloadingObjectGenerator;

/**
* Factory responsible of producing overloading proxy objects
*
* @author Vincent Blanchon <blanchon.vincent@gmail.com>
* @license MIT
*/
class OverloadingFactory extends AbstractBaseFactory
{
/**
* @param object $instanceOrClassName the object to be wrapped or interface to transform to overloadable object
*
* @return \ProxyManager\Proxy\NullobjectInterface
*/
public function createProxy($instanceOrClassName)
{
$className = is_object($instanceOrClassName) ? get_class($instanceOrClassName) : $instanceOrClassName;
$proxyClassName = $this->generateProxy($className);

return new $proxyClassName();
}

/**
* {@inheritDoc}
*/
protected function getGenerator()
{
return $this->generator ? $this->generator : $this->generator = new OverloadingObjectGenerator();
}
}
29 changes: 29 additions & 0 deletions src/ProxyManager/Proxy/Exception/OverloadingObjectException.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,29 @@
<?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\Proxy\Exception;

/**
* Remote object exception
*
* @author Vincent Blanchon <blanchon.vincent@gmail.com>
* @license MIT
*/
class OverloadingObjectException extends \RuntimeException
{
}
29 changes: 29 additions & 0 deletions src/ProxyManager/Proxy/OverloadingObjectInterface.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,29 @@
<?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\Proxy;

/**
* Overloading object marker
*
* @author Vincent Blanchon <blanchon.vincent@gmail.com>
* @license MIT
*/
interface OverloadingObjectInterface extends ProxyInterface
{
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,64 @@
<?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\OverloadingObject\MethodGenerator;

use ProxyManager\Generator\MethodGenerator;
use Zend\Code\Generator\PropertyGenerator;
use Zend\Code\Generator\MethodGenerator as ZendMethodGenerator;
use Zend\Code\Reflection\MethodReflection;

/**
* Implementation for overloading objects
*
* @author Vincent Blanchon <blanchon.vincent@gmail.com>
* @license MIT
*/
class Constructor extends MethodGenerator
{
/**
* Constructor
*/
public function __construct(PropertyGenerator $prototypes, array $methods)
{
parent::__construct('__construct');

$body = '';
/* @var $methods \ReflectionMethod[] */
foreach($methods as $method) {
$methodName = $method->getName();

$methodReflection = new MethodReflection(
$method->getDeclaringClass()->getName(),
$method->getName()
);
$reflection = ZendMethodGenerator::fromReflection($methodReflection);

$list = array();
foreach ($method->getParameters() as $parameter) {
$list[] = '$' . $parameter->getName();
}

$body .= '$closure = function(' . implode(',', $list) . ') {' . $reflection->getBody() . '};' . "\n";
$body .= '$prototype = $this->getPrototypeFromClosure($closure);' . "\n";
$body .= '$this->' . $prototypes->getName() . "['$methodName'][\$prototype] = \$closure;\n";
}

$this->setBody($body);
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,66 @@
<?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\OverloadingObject\MethodGenerator;

use ProxyManager\Generator\MethodGenerator;
use ProxyManager\Generator\ParameterGenerator;

/**
* Implementation for overloading objects
*
* @author Vincent Blanchon <blanchon.vincent@gmail.com>
* @license MIT
*/
class GetPrototypeFromArguments extends MethodGenerator
{
/**
* Constructor
*/
public function __construct()
{
parent::__construct('getPrototypeFromArguments');
parent::setVisibility(parent::VISIBILITY_PROTECTED);

$interceptor = new ParameterGenerator('arguments');

$interceptor->setType('array');

$this->setParameter($interceptor);
$this->setDocblock('{@inheritDoc}');

$body =
'$prototype = \'p\';' . "\n"
. '$position = 0;' . "\n"
. 'foreach($arguments as $arg => $value) {' . "\n"
. ' if (is_array($arg)) {' . "\n"
. ' $prototype .= \'array $\' . $position++;' . "\n"
. (preg_match('#^5\.4#', PHP_VERSION) ?
' } else if (is_callable($arg)) {' . "\n"
. ' $prototype .= \'callable $\' . $position++;' . "\n"
: '')
. ' } else {' . "\n"
. ' $class = is_object($value) ? get_class($value) : \'\';' . "\n"
. ' $prototype .= ($class && $class != "stdClass" ? $class : \'\') . \'$\' . $position++;' . "\n"
. ' }' . "\n"
. '}' . "\n"
. 'return $prototype;';

$this->setBody($body);
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,81 @@
<?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\OverloadingObject\MethodGenerator;

use ProxyManager\Generator\MethodGenerator;
use ProxyManager\Generator\ParameterGenerator;

/**
* Implementation for overloading objects
*
* @author Vincent Blanchon <blanchon.vincent@gmail.com>
* @license MIT
*/
class GetPrototypeFromClosure extends MethodGenerator
{
/**
* Constructor
*/
public function __construct()
{
parent::__construct('getPrototypeFromClosure');
parent::setVisibility(parent::VISIBILITY_PROTECTED);

$interceptor = new ParameterGenerator('function');

$interceptor->setType('Closure');

$this->setParameter($interceptor);
$this->setDocblock('{@inheritDoc}');

$body =
'$prototype = \'p\';' . "\n"
. '$r = new \ReflectionFunction($function);' . "\n"
. 'foreach($r->getParameters() as $arg) {' . "\n"
. ' if ($arg->isArray()) {' . "\n"
. ' $prototype .= \'array $\' . $arg->getPosition();' . "\n"
. (preg_match('#^5\.4#', PHP_VERSION) ?
' } else if ($arg->isCallable()) {' . "\n"
. ' $prototype .= \'callable $\' . $arg->getPosition();' . "\n"
: '')
. ' } else {' . "\n"
. ' $class = $arg->getClass();' . "\n"
. ' $prototype .= ($class ? $class->getName() : \'\') . \'$\' . $arg->getPosition();' . "\n"
. ' }' . "\n"
. '}' . "\n"
. 'return $prototype;';

$this->setBody($body);
}

public static function getPrototypeFromClosure(\Closure $closure)
{
$prototype = '';
$r = new \ReflectionFunction($closure);
foreach($r->getParameters() as $arg) {
if ($arg->isArray()) {
$prototype .= 'array $' . $arg->getPosition();
} else {
$class = $arg->getClass();
$prototype .= ($class ?: '') . '$' . $arg->getPosition();
}
}
return $prototype;
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,55 @@
<?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\OverloadingObject\MethodGenerator;

use ProxyManager\Generator\MagicMethodGenerator;
use ReflectionClass;
use ProxyManager\Generator\ParameterGenerator;
use Zend\Code\Generator\PropertyGenerator;

/**
* Magic `__call` for overloading objects
*
* @author Vincent Blanchon <blanchon.vincent@gmail.com>
* @license MIT
*/
class MagicCall extends MagicMethodGenerator
{
/**
* @param \ReflectionClass $originalClass
* @param \Zend\Code\Generator\PropertyGenerator $overloading
*/
public function __construct(
ReflectionClass $originalClass,
PropertyGenerator $prototypes
) {
parent::__construct($originalClass, '__call', array(new ParameterGenerator('name'), new ParameterGenerator('arguments', 'array')));

$override = $originalClass->hasMethod('__call');

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

$body =
'$prototype = $this->getPrototypeFromArguments($arguments);' . "\n"
. 'if (isset($this->' . $prototypes->getName() . '[$name][$prototype])) {' . "\n"
. ' return call_user_func_array($this->' . $prototypes->getName() . '[$name][$prototype], $arguments);' . "\n"
. '}';
$this->setBody($body);
}
}
Loading

0 comments on commit e8e6c60

Please sign in to comment.