Skip to content

Instantly share code, notes, and snippets.

@khuppenbauer
Last active August 29, 2015 14:08
Show Gist options
  • Save khuppenbauer/b3f30bbebd0106444f6e to your computer and use it in GitHub Desktop.
Save khuppenbauer/b3f30bbebd0106444f6e to your computer and use it in GitHub Desktop.
<?php
namespace TYPO3\Flow\Aop\Builder;
/* *
* This script belongs to the TYPO3 Flow framework. *
* *
* It is free software; you can redistribute it and/or modify it under *
* the terms of the GNU Lesser General Public License, either version 3 *
* of the License, or (at your option) any later version. *
* *
* The TYPO3 project - inspiring people to share! *
* */
use TYPO3\Flow\Annotations as Flow;
/**
* A method interceptor build for constructors with advice.
*
* @Flow\Proxy(false)
* @Flow\Scope("singleton")
*/
class AdvicedConstructorInterceptorBuilder extends \TYPO3\Flow\Aop\Builder\AbstractMethodInterceptorBuilder {
/**
* Builds interception PHP code for an adviced constructor
*
* @param string $methodName Name of the method to build an interceptor for
* @param array $interceptedMethods An array of method names and their meta information, including advices for the method (if any)
* @param string $targetClassName Name of the target class to build the interceptor for
* @return string PHP code of the interceptor
* @throws \TYPO3\Flow\Aop\Exception
*/
public function build($methodName, array $interceptedMethods, $targetClassName) {
if ($methodName !== '__construct') {
throw new \TYPO3\Flow\Aop\Exception('The ' . __CLASS__ . ' can only build constructor interceptor code.', 1231789021);
}
$declaringClassName = $interceptedMethods[$methodName]['declaringClassName'];
$proxyMethod = $this->compiler->getProxyClass($targetClassName)->getConstructor();
if ($declaringClassName !== $targetClassName) {
$proxyMethod->setMethodParametersCode($this->buildMethodParametersCode($declaringClassName, $methodName, TRUE));
}
$groupedAdvices = $interceptedMethods[$methodName]['groupedAdvices'];
$advicesCode = $this->buildAdvicesCode($groupedAdvices, $methodName, $targetClassName, $declaringClassName);
if ($methodName !== NULL) {
if ($methodName === 'dispatch') {
$dispatch = 'unset($this->Flow_Aop_Proxy_methodIsInAdviceMode[\'' . $methodName . '\']);';
} else {
$dispatch = '';
}
$proxyMethod->addPreParentCallCode('
if (isset($this->Flow_Aop_Proxy_methodIsInAdviceMode[\'' . $methodName . '\'])) {
' . $dispatch . '
');
$proxyMethod->addPostParentCallCode('
} else {
$this->Flow_Aop_Proxy_methodIsInAdviceMode[\'' . $methodName . '\'] = TRUE;
try {
' . $advicesCode . '
} catch (\Exception $e) {
unset($this->Flow_Aop_Proxy_methodIsInAdviceMode[\'' . $methodName . '\']);
throw $e;
}
unset($this->Flow_Aop_Proxy_methodIsInAdviceMode[\'' . $methodName . '\']);
return;
}
');
}
}
}
<?php
namespace TYPO3\Flow\Aop\Builder;
/* *
* This script belongs to the TYPO3 Flow framework. *
* *
* It is free software; you can redistribute it and/or modify it under *
* the terms of the GNU Lesser General Public License, either version 3 *
* of the License, or (at your option) any later version. *
* *
* The TYPO3 project - inspiring people to share! *
* */
use TYPO3\Flow\Annotations as Flow;
/**
* An AOP interceptor code builder for methods enriched by advices.
*
* @Flow\Scope("singleton")
*/
class AdvicedMethodInterceptorBuilder extends \TYPO3\Flow\Aop\Builder\AbstractMethodInterceptorBuilder {
/**
* Builds interception PHP code for an adviced method
*
* @param string $methodName Name of the method to build an interceptor for
* @param array $interceptedMethods An array of method names and their meta information, including advices for the method (if any)
* @param string $targetClassName Name of the target class to build the interceptor for
* @return string PHP code of the interceptor
* @throws \TYPO3\Flow\Aop\Exception
*/
public function build($methodName, array $interceptedMethods, $targetClassName) {
if ($methodName === '__construct') {
throw new \TYPO3\Flow\Aop\Exception('The ' . __CLASS__ . ' cannot build constructor interceptor code.', 1173107446);
}
$declaringClassName = $interceptedMethods[$methodName]['declaringClassName'];
$proxyMethod = $this->compiler->getProxyClass($targetClassName)->getMethod($methodName);
if ($declaringClassName !== $targetClassName) {
$proxyMethod->setMethodParametersCode($proxyMethod->buildMethodParametersCode($declaringClassName, $methodName, TRUE));
}
$groupedAdvices = $interceptedMethods[$methodName]['groupedAdvices'];
$advicesCode = $this->buildAdvicesCode($groupedAdvices, $methodName, $targetClassName, $declaringClassName);
if ($methodName !== NULL || $methodName === '__wakeup') {
if ($methodName === 'dispatch') {
$dispatch = 'unset($this->Flow_Aop_Proxy_methodIsInAdviceMode[\'' . $methodName . '\']);';
} else {
$dispatch = '';
}
$proxyMethod->addPreParentCallCode('
// FIXME this can be removed again once Doctrine is fixed (see fixMethodsAndAdvicesArrayForDoctrineProxiesCode())
$this->Flow_Aop_Proxy_fixMethodsAndAdvicesArrayForDoctrineProxies();
if (isset($this->Flow_Aop_Proxy_methodIsInAdviceMode[\'' . $methodName . '\'])) {
' . $dispatch . '
');
$proxyMethod->addPostParentCallCode('
} else {
$this->Flow_Aop_Proxy_methodIsInAdviceMode[\'' . $methodName . '\'] = TRUE;
try {
' . $advicesCode . '
} catch (\Exception $e) {
unset($this->Flow_Aop_Proxy_methodIsInAdviceMode[\'' . $methodName . '\']);
throw $e;
}
unset($this->Flow_Aop_Proxy_methodIsInAdviceMode[\'' . $methodName . '\']);
}
');
}
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment