/** * Cacheable methods * * @param MethodInvocation $invocation Invocation * * @Go\Lang\Annotation\Around("execution(public Twig_Template->display(*))") */ public function aroundDisplay(MethodInvocation $invocation) { $this->deepness++; $start = microtime(true); $result = $invocation->proceed(); $end = microtime(true); if (!is_null($timeDataCollector = $this->getTimeDataCollector())) { $name = sprintf("twig.render(%s)", $invocation->getThis()->getTemplateName()); $timeDataCollector->addMeasure($name, $start, $end); } $this->renderedTemplates[] = array('name' => str_repeat('-', $this->deepness) . '> ' . $invocation->getThis()->getTemplateName(), 'render_time' => $end - $start); $this->deepness--; return $result; }
/** * Checks if this method invocation is mockable. * * @param MethodInvocation $invocation * @return object The mock return value if this invocation is happening in test * environment and it is listed in the mockable_methods array null otherwise. */ private static function isMockable(MethodInvocation $invocation) { // Check for testing config, nothing is mockable if we are not testing if (Config::get('aopmock.testing') === false) { return null; } // Get the object $obj = $invocation->getThis(); // Get the method name $methodName = $invocation->getMethod()->name; // Get class name if ($invocation->getMethod()->isStatic()) { $class = $obj; $obj = new $class(); } else { $class = get_class($obj); } $types = Config::get('aopmock.mockable_methods'); foreach ($types as $type => $val) { if ($obj instanceof $type) { if (isset($types[$type][$methodName])) { return $types[$type][$methodName]; } } } return null; }
/** * Method invoker * * @param $invocation MethodInvocation the method invocation joinpoint * @return mixed the result of the call to {@see Joinpoint->proceed()} */ public final function invoke(MethodInvocation $invocation) { if ($this->pointcut->matches($invocation->getMethod(), $invocation->getThis(), $invocation->getArguments())) { return $this->adviceMethod->invoke($invocation); } return $invocation->proceed(); }
/** * Converts the given text area into a WYSIWYG editor. * * @param \Go\Aop\Intercept\MethodInvocation $invocation Invocation * @Around("execution(public CMS\View\Helper\FormHelper->textarea(*))") * @return bool Whether object invocation should proceed or not */ public function alterTextarea(MethodInvocation $invocation) { $helper = $invocation->getThis(); list($fieldName, $options) = array_pad($invocation->getArguments(), 2, null); if (!empty($options['class']) && strpos($options['class'], 'ckeditor') !== false && $helper instanceof FormHelper) { static::$_counter++; $editorId = 'ck-editor-' . static::$_counter; $options['class'] .= ' ' . $editorId; $view = $this->getProperty($helper, '_View'); if (!static::$_scriptsLoaded) { static::$_scriptsLoaded = true; $filebrowserBrowseUrl = $view->Url->build(['plugin' => 'Wysiwyg', 'controller' => 'finder']); $view->Html->script('Wysiwyg./ckeditor/ckeditor.js', ['block' => true]); $view->Html->script('Wysiwyg./ckeditor/adapters/jquery.js', ['block' => true]); $view->Html->scriptBlock('$(document).ready(function () { CKEDITOR.editorConfig = function(config) { config.filebrowserBrowseUrl = "' . $filebrowserBrowseUrl . '"; }; });', ['block' => true]); $this->_includeLinksToContents($view); } } $this->setProperty($invocation, 'arguments', [$fieldName, $options]); return $invocation->proceed(); }
/** * This advice intercepts an execution of __call methods * * Unlike traditional "execution" pointcut, "dynamic" is checking the name of method in * the runtime, allowing to write interceptors for __call more transparently. * * @param MethodInvocation $invocation Invocation * * @Before("dynamic(public Demo\Example\DynamicMethodsDemo->save*(*))") */ public function beforeMagicMethodExecution(MethodInvocation $invocation) { $obj = $invocation->getThis(); // we need to unpack args from invocation args list($methodName, $args) = $invocation->getArguments(); echo 'Calling Magic Interceptor for method: ', is_object($obj) ? get_class($obj) : $obj, $invocation->getMethod()->isStatic() ? '::' : '->', $methodName, '()', ' with arguments: ', json_encode($args), PHP_EOL; }
/** * @param MethodInvocation $methodInvocation * * @return void * * @throws \ErrorException */ public function __invoke(MethodInvocation $methodInvocation) { $reflectionParameters = $methodInvocation->getMethod()->getParameters(); $applyTypeChecks = $this->applyTypeChecks; foreach ($methodInvocation->getArguments() as $argumentIndex => $argument) { $applyTypeChecks($this->getParameterDocblockType(get_class($methodInvocation->getThis()), $reflectionParameters, $argumentIndex), $argument); } }
/** * Verifies pre-condition contract for the method * * @param MethodInvocation $invocation * @Before("@execution(PhpDeal\Annotation\Verify)") * * @throws ContractViolation */ public function preConditionContract(MethodInvocation $invocation) { $object = $invocation->getThis(); $args = $this->fetchMethodArguments($invocation); $scope = $invocation->getMethod()->getDeclaringClass()->name; $allContracts = $this->fetchAllContracts($invocation); $this->ensureContracts($invocation, $allContracts, $object, $scope, $args); }
/** * Adds custom templates to PaginatorHelper::$_defaultConfig['templates']. * * @param \Go\Aop\Intercept\MethodInvocation $invocation Joinpoint * @Before("execution(public Cake\View\Helper\PaginatorHelper->prev|numbers|next(*))") * @return bool Whether object invocation should proceed or not */ public function defaultTemplates(MethodInvocation $invocation) { if (!static::cache('bootstrapTemplates')) { $helper = $invocation->getThis(); $helper->templates($this->_templates); static::cache('bootstrapTemplates', true); } }
/** * @Go\After("execution(public **->__construct(*))") * * @param MethodInvocation $constructorInvocation * * @return mixed * * @throws \ErrorException|\Exception */ public function postConstruct(MethodInvocation $constructorInvocation) { $that = $constructorInvocation->getThis(); $scope = $constructorInvocation->getMethod()->getDeclaringClass()->getName(); array_map(function (callable $checker) use($that, $scope) { $checker($that, $scope); }, $this->stateCheckers); return $constructorInvocation->proceed(); }
/** * Adds prefix to every input element that may have a "name" attribute. * * @param \Go\Aop\Intercept\MethodInvocation $invocation Invocation * @Around("execution(public Cake\View\Helper\FormHelper->label|input|checkbox|radio|textarea|hidden|file|select|multiCheckbox|day|year|month|hour|minute|meridian|dateTime|time|date(*))") * @return bool Whether object invocation should proceed or not */ public function addInputPrefix(MethodInvocation $invocation) { $helper = $invocation->getThis(); $args = $invocation->getArguments(); if (!empty($args[0]) && is_string($args[0]) && $helper instanceof FormHelper) { $args[0] = $this->_fieldName($helper, $args[0]); } $this->setProperty($invocation, 'arguments', $args); return $invocation->proceed(); }
/** * * Adds a shortcut button to Comment's management submenu. * * @param \Go\Aop\Intercept\MethodInvocation $invocation Invocation * @Before("execution(public Menu\View\Helper\MenuHelper->render(*))") */ public function commentsNav(MethodInvocation $invocation) { $helper = $invocation->getThis(); $settings = plugin('Disqus')->settings; list($items, $options) = $invocation->getArguments(); if (!empty($settings['disqus_shortname']) && count($items) == 5 && $items[0]['title'] == __d('comment', 'All')) { $items[] = ['title' => __d('disqus', 'Go to Disqus Moderation'), 'url' => 'https://' . $settings['disqus_shortname'] . '.disqus.com/admin/moderate/', 'target' => '_blank']; $this->setProperty($invocation, 'arguments', [$items, $options]); } }
/** * Intercept any public method and store them on the object. * * @param MethodInvocation $invocation Invocation * @Before("execution(public Mage_Cms_Block_Page->*(*))") */ public function storeInterceptedPublicMethods(MethodInvocation $invocation) { $obj = $invocation->getThis(); $method = $invocation->getMethod()->getName(); $interceptedMethods = $obj->getInterceptedMethods(); if ($interceptedMethods === null) { $interceptedMethods = array(); } if (!in_array($method, $interceptedMethods)) { $interceptedMethods[] = $method; } $obj->setInterceptedMethods($interceptedMethods); }
/** * Verifies post-condition contract for the method * * @Around("@execution(PhpDeal\Annotation\Ensure)") * @param MethodInvocation $invocation * * @throws ContractViolation * @return mixed */ public function postConditionContract(MethodInvocation $invocation) { $object = $invocation->getThis(); $args = $this->fetchMethodArguments($invocation); $class = $invocation->getMethod()->getDeclaringClass(); if ($class->isCloneable()) { $args['__old'] = clone $object; } $result = $invocation->proceed(); $args['__result'] = $result; $allContracts = $this->fetchAllContracts($invocation); $this->ensureContracts($invocation, $allContracts, $object, $class->name, $args); return $result; }
/** * @param MethodInvocation $invocation Invocation * * @Go\Lang\Annotation\Around("execution(public Kohana_Route->uri(*))") */ public function aroundKohanaRouteGet(MethodInvocation $invocation) { $arguments = $invocation->getArguments(); $route = $invocation->getThis(); $name = Route::name($route); $parameters = $arguments[0]; if (empty($parameters)) { $parameters = array(); } try { return $this->getRouter()->generate($name, $parameters); } catch (RouteNotFoundException $e) { return $invocation->proceed(); } }
/** * This advice intercepts an execution of cacheable methods * * Logic is pretty simple: we look for the value in the cache and if it's not present here * then invoke original method and store it's result in the cache. * * Real-life examples will use APC or Memcache to store value in the cache * * @param MethodInvocation $invocation Invocation * * @Around("@execution(Demo\Annotation\Cacheable)") */ public function aroundCacheable(MethodInvocation $invocation) { static $memoryCache = array(); $time = microtime(true); $obj = $invocation->getThis(); $class = is_object($obj) ? get_class($obj) : $obj; $key = $class . ':' . $invocation->getMethod()->name; if (!isset($memoryCache[$key])) { // We can use ttl value from annotation, but Doctrine annotations doesn't work under GAE if (!isset($_SERVER['APPENGINE_RUNTIME'])) { echo "Ttl is: ", $invocation->getMethod()->getAnnotation('Demo\\Annotation\\Cacheable')->time, PHP_EOL; } $memoryCache[$key] = $invocation->proceed(); } echo "Take ", sprintf("%0.3f", (microtime(true) - $time) * 1000.0), "ms to call method {$key}", PHP_EOL; return $memoryCache[$key]; }
/** * @param MethodInvocation $invocation Invocation * @Before("execution(public Endpoint->call(*))") // This is our PointCut */ public function beforeServiceCall(MethodInvocation $invocation) { $methodThis = $invocation->getThis(); $service = $methodThis->service()->first(); $serviceName = $service->name; $serviceLimit = \DB::table('limits')->where('service_id', '=', $service->id)->first(); \DB::table('limits')->where('service_id', '=', $service->id)->update(array('current_hits' => 0)); $serviceLimit->current_hits = 0; $hasLimitBeenReached = $serviceLimit->current_hits >= $serviceLimit->max_hits; if ($hasLimitBeenReached) { echo "The limit number of calls for service \"" . $serviceName . "\" have been reached \n"; echo "Method execution stoped"; die; } \DB::table('limits')->where('service_id', '=', $service->id)->update(array('current_hits' => $serviceLimit->current_hits + 1)); $methodName = $invocation->getMethod()->getName(); $methodParams = implode(', ', $invocation->getArguments()); // echo "Calling method " . $methodName . " with params : " . $methodParams . "\n"; // echo "Method execution continues \n"; // echo "Method result \n"; }
/** * Implement this method to perform extra treatments before and * after the invocation. Polite implementations would certainly * like to invoke {@link Joinpoint::proceed()}. * * @param MethodInvocation $invocation the method invocation joinpoint * @return mixed the result of the call to {@link Joinpoint::proceed()}, * might be intercepted by the interceptor. */ public function invoke(MethodInvocation $invocation) { $this->adviceMethod->__invoke($invocation->getThis(), $invocation->getMethod(), $this->message, $this->level); return $invocation->proceed(); }
/** * Verifies invariants for contract class * * @Around("@within(PhpDeal\Annotation\Invariant) && execution(public **->*(*))") * @param MethodInvocation $invocation * * @throws ContractViolation * @return mixed */ public function invariantContract(MethodInvocation $invocation) { $object = $invocation->getThis(); $args = $this->getMethodArguments($invocation); $class = $invocation->getMethod()->getDeclaringClass(); if ($class->isCloneable()) { $args['__old'] = clone $object; } $result = $invocation->proceed(); $args['__result'] = $result; // TODO: Do not use reader directly and pack annotation information into reflection foreach ($this->reader->getClassAnnotations($class) as $annotation) { if (!$annotation instanceof Contract\Invariant) { continue; } if (!$this->isContractSatisfied($object, $class->name, $args, $annotation)) { throw new ContractViolation($invocation, $annotation->value); } } return $result; }
/** * Method that should be called before real method * * @param MethodInvocation $invocation Invocation * @Before("within(**)") */ public function beforeMethodExecution(MethodInvocation $invocation) { $obj = $invocation->getThis(); echo 'Calling Before Interceptor for method: ', is_object($obj) ? get_class($obj) : $obj, $invocation->getMethod()->isStatic() ? '::' : '->', $invocation->getMethod()->getName(), '()', ' with arguments: ', json_encode($invocation->getArguments()), "<br>\n"; }
/** * Fluent interface advice * * @Around("within(Demo\Aspect\FluentInterface+) && execution(public **->set*(*))") * * @param MethodInvocation $invocation * @return mixed|null|object */ protected function aroundMethodExecution(MethodInvocation $invocation) { $result = $invocation->proceed(); return $result !== null ? $result : $invocation->getThis(); }
/** * Method that advice to clean the teeth before going to sleep * * @param MethodInvocation $invocation Invocation * @Before("execution(public Demo\Example\HumanDemo->sleep(*))") */ protected function cleanTeethBeforeSleep(MethodInvocation $invocation) { /** @var $person \Demo\Example\HumanDemo */ $person = $invocation->getThis(); $person->cleanTeeth(); }
/** * Logic to notify all observers on subject * * @After("$this->subjectChange") * * @param MethodInvocation $invocation */ protected function afterSubjectChange(MethodInvocation $invocation) { $subject = $invocation->getThis(); $observers = $this->getObservers($subject); foreach ($observers as $observer) { $this->updateObserver($subject, $observer); } }