Skip to content

Commit

Permalink
Add real subject
Browse files Browse the repository at this point in the history
  • Loading branch information
romain.kuzniak committed Nov 2, 2015
1 parent 1446d16 commit 98005c6
Show file tree
Hide file tree
Showing 10 changed files with 73 additions and 68 deletions.
6 changes: 4 additions & 2 deletions src/Annotations/Cache.php
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,9 @@
*/
class Cache
{
const MEMCACHE_KEY_MAX_LENGTH = 244;
const MEMCACHE_KEY_MAX_LENGTH = 240;

const QUOTES_LENGTH = 4;

/**
* @var string
Expand All @@ -32,7 +34,7 @@ class Cache
*/
public function getId()
{
if (null !== $this->id && self::MEMCACHE_KEY_MAX_LENGTH < mb_strlen($this->id)) {
if (null !== $this->id && self::MEMCACHE_KEY_MAX_LENGTH + self::QUOTES_LENGTH < mb_strlen($this->id)) {
throw new InvalidCacheIdException('id is too long, MUST be inferior to 240');
}

Expand Down
11 changes: 7 additions & 4 deletions src/Proxy/Factory/ProxyFactory.php
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@
namespace OpenClassrooms\ServiceProxy\Proxy\Factory;

use OpenClassrooms\ServiceProxy\Proxy\ProxyGenerator\ServiceProxyGenerator;
use OpenClassrooms\ServiceProxy\ServiceProxyInterface;
use ProxyManager\Configuration;
use ProxyManager\Factory\AbstractBaseFactory;
use Symfony\Component\Filesystem\Filesystem;
Expand Down Expand Up @@ -35,12 +36,14 @@ public function __construct($cacheDir = null)
/**
* {@inheritdoc}
*/
public function createProxy($instanceOrClassName)
public function createProxy($instance)
{
$className = is_object($instanceOrClassName) ? get_class($instanceOrClassName) : $instanceOrClassName;
$proxyClassName = $this->generateProxy($className);
$proxyClassName = $this->generateProxy(get_class($instance));
/** @var ServiceProxyInterface $proxy */
$proxy = new $proxyClassName();
$proxy->setProxy_RealSubject($instance);

return new $proxyClassName();
return $proxy;
}

/**
Expand Down
2 changes: 1 addition & 1 deletion src/Proxy/Factory/ProxyFactoryInterface.php
Original file line number Diff line number Diff line change
Expand Up @@ -12,5 +12,5 @@ interface ProxyFactoryInterface
/**
* @return ServiceProxyInterface|object
*/
public function createProxy($instanceOrClassName);
public function createProxy($instance);
}
105 changes: 46 additions & 59 deletions src/Proxy/ProxyGenerator/ServiceProxyGenerator.php
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@
use ReflectionClass;
use Zend\Code\Generator\ClassGenerator;
use Zend\Code\Generator\MethodGenerator;
use Zend\Code\Generator\PropertyGenerator;
use Zend\Code\Reflection\MethodReflection;

/**
Expand Down Expand Up @@ -40,72 +41,55 @@ public function generate(ReflectionClass $originalClass, ClassGenerator $classGe
{
CanProxyAssertion::assertClassCanBeProxied($originalClass);
$classGenerator->setExtendedClass($originalClass->getName());
$additionalInterfaces = ['OpenClassrooms\\ServiceProxy\\ServiceProxyInterface'];
$additionalProperties['proxy_realSubject'] = new PropertyGenerator(
'proxy_realSubject',
null,
PropertyGenerator::FLAG_PRIVATE
);
$additionalMethods['setProxy_realSubject'] = new MethodGenerator(
'setProxy_realSubject',
[['name' => 'realSubject']],
MethodGenerator::FLAG_PUBLIC,
'$this->proxy_realSubject = $realSubject;'
);

$methodsAnnotations = $this->getMethodsAnnotations($originalClass);

$interfacesToAdd = ['OpenClassrooms\\ServiceProxy\\ServiceProxyInterface'];
$propertiesToAdd = [];
$methodsToAdd = [];

foreach ($methodsAnnotations as $methodAnnotation) {
$methods = $originalClass->getMethods(\ReflectionMethod::IS_PUBLIC);
foreach ($methods as $method) {
$preSource = '';
$postSource = '';
$exceptionSource = '';
/** @var \ReflectionMethod $method */
$method = $methodAnnotation['method'];
foreach ($methodAnnotation['annotations'] as $annotation) {
if ($annotation instanceof Cache) {
$interfacesToAdd['cache'] = 'OpenClassrooms\\ServiceProxy\\ServiceProxyCacheInterface';
$methodAnnotations = $this->annotationReader->getMethodAnnotations($method);
foreach ($methodAnnotations as $methodAnnotation) {
if ($methodAnnotation instanceof Cache) {
$additionalInterfaces['cache'] = 'OpenClassrooms\\ServiceProxy\\ServiceProxyCacheInterface';
$response = $this->cacheStrategy->execute(
$this->serviceProxyStrategyRequestBuilder
->create()
->withAnnotation($annotation)
->withAnnotation($methodAnnotation)
->withClass($originalClass)
->withMethod($method)
->build()
);
foreach ($response->getMethods() as $methodToAdd) {
$additionalMethods[$methodToAdd->getName()] = $methodToAdd;
}
foreach ($response->getProperties() as $propertyToAdd) {
$additionalProperties[$propertyToAdd->getName()] = $propertyToAdd;
}
$preSource .= $response->getPreSource();
$postSource .= $response->getPostSource();
$exceptionSource .= $response->getExceptionSource();
}

foreach ($response->getMethods() as $methodToAdd) {
$methodsToAdd[$methodToAdd->getName()] = $methodToAdd;
}
foreach ($response->getProperties() as $propertyToAdd) {
$propertiesToAdd[$propertyToAdd->getName()] = $propertyToAdd;
}
$preSource .= $response->getPreSource();
$postSource .= $response->getPostSource();
$exceptionSource .= $response->getExceptionSource();
}
$classGenerator->addMethodFromGenerator(
$this->generateProxyMethod($method, $preSource, $postSource, $exceptionSource)
);
}
$classGenerator->setImplementedInterfaces($interfacesToAdd);
$classGenerator->addProperties($propertiesToAdd);
$classGenerator->addMethods($methodsToAdd);
}

/**
* @return [][]
*/
private function getMethodsAnnotations(ReflectionClass $originalClass)
{
$methodsAnnotations = [];

$methods = $originalClass->getMethods(\ReflectionMethod::IS_PUBLIC);
foreach ($methods as $method) {
$methodAnnotations = $this->annotationReader->getMethodAnnotations($method);
if (!empty($methodAnnotations)) {
$methodsAnnotations[$method->getName()] = ['method' => $method, 'annotations' => []];
foreach ($methodAnnotations as $annotation) {
if ($annotation instanceof Cache) {
$methodsAnnotations[$method->getName()]['annotations'][] = $annotation;
}
}
}
}

return $methodsAnnotations;
$classGenerator->setImplementedInterfaces($additionalInterfaces);
$classGenerator->addProperties($additionalProperties);
$classGenerator->addMethods($additionalMethods);
}

/**
Expand All @@ -122,17 +106,20 @@ private function generateProxyMethod(\ReflectionMethod $method, $preSource, $pos
$parametersString .= '$'.$parameter->getName().(--$i > 0 ? ',' : '');
}
$parametersString .= ')';
$methodGenerator->setBody(
"try {\n"
.$preSource."\n"
.'$data = parent::'.$method->getName().$parametersString.";\n"
.$postSource."\n"
."return \$data;\n"
."} catch(\\Exception \$e){\n"
.$exceptionSource."\n"
."throw \$e;\n"
.'};'
);
if ('' === $preSource && '' === $postSource && '' === $exceptionSource) {
$body = 'return $this->proxy_realSubject->'.$method->getName().$parametersString.";\n";
} else {
$body = "try {\n"
.$preSource."\n"
.'$data = parent::'.$method->getName().$parametersString.";\n"
.$postSource."\n"
."return \$data;\n"
."} catch(\\Exception \$e){\n"
.$exceptionSource."\n"
."throw \$e;\n"
.'};';
}
$methodGenerator->setBody($body);

return $methodGenerator;
}
Expand Down
1 change: 1 addition & 0 deletions src/Proxy/Strategy/ServiceProxyCacheStrategy.php
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,7 @@ public function execute(ServiceProxyStrategyRequestInterface $request)
->create()
->withPreSource($this->generatePreSource($request))
->withPostSource($this->generatePostSource($request->getAnnotation()))
->withExceptionSource('')
->withProperties($this->generateProperties())
->withMethods($this->generateMethods())
->build();
Expand Down
1 change: 0 additions & 1 deletion src/ServiceProxyFactory.php
Original file line number Diff line number Diff line change
Expand Up @@ -28,7 +28,6 @@ class ServiceProxyFactory implements ServiceProxyFactoryInterface
public function createProxy($class)
{
$proxy = $this->proxyFactory->createProxy($class);

if ($proxy instanceof ServiceProxyCacheInterface) {
if (null === $this->cacheProvider) {
throw new InvalidCacheProviderException();
Expand Down
1 change: 1 addition & 0 deletions src/ServiceProxyInterface.php
Original file line number Diff line number Diff line change
Expand Up @@ -7,4 +7,5 @@
*/
interface ServiceProxyInterface
{
public function setProxy_RealSubject($realSubject);
}
12 changes: 11 additions & 1 deletion tests/Doubles/WithoutAnnotationClass.php
Original file line number Diff line number Diff line change
Expand Up @@ -7,12 +7,22 @@
*/
class WithoutAnnotationClass
{
/**
* @var mixed
*/
public $field;

/**
* @return bool
*/
public function aMethodWithoutAnnotation()
{
return true;
return $this->field;
}

public function aSetterMethod($value)
{
$this->field = $value;
}

/**
Expand Down
1 change: 1 addition & 0 deletions tests/ServiceProxyBuilderTest.php
Original file line number Diff line number Diff line change
Expand Up @@ -31,6 +31,7 @@ class ServiceProxyBuilderTest extends \PHPUnit_Framework_TestCase
public function WithoutAnnotation_ReturnServiceProxyInterface()
{
$inputClass = new WithoutAnnotationClass();
$inputClass->field = true;
/** @var WithoutAnnotationClass|ServiceProxyInterface $proxy */
$proxy = $this->builder
->create($inputClass)
Expand Down
1 change: 1 addition & 0 deletions tests/ServiceProxyFactoryTest.php
Original file line number Diff line number Diff line change
Expand Up @@ -30,6 +30,7 @@ class ServiceProxyFactoryTest extends \PHPUnit_Framework_TestCase
public function WithoutAnnotation_ReturnServiceProxyInterface()
{
$inputClass = new WithoutAnnotationClass();
$inputClass->field = true;
/** @var WithoutAnnotationClass|ServiceProxyInterface $proxy */
$proxy = $this->factory->createProxy($inputClass);

Expand Down

0 comments on commit 98005c6

Please sign in to comment.