Esempio n. 1
0
 protected function interceptMethod(TypeInfoInterface $type, MethodInfoInterface $method, InstrumentationInterface $instrumentation)
 {
     $manager = $instrumentation->getTypeInfoManager();
     $advices = [];
     foreach ($this->getAdvisors(Advisor::TARGET_ELEMENT, $manager) as $advisor) {
         $match = $advisor->matches($manager, $type, $method);
         if ($match !== NULL) {
             $advice = clone $advisor->getAdvice();
             $interceptor = $advice->getInterceptor();
             if ($interceptor instanceof AbstractInterceptor) {
                 $interceptor->setSubject($match->getTarget());
                 $interceptor->setArgs($match->getArgs());
                 $interceptor->setReturns($match->getReturns());
             }
             $advices[] = $advice;
         }
     }
     if (empty($advices)) {
         return;
     }
     $code = '';
     if (!$type->is($method->getDeclaringType())) {
         if ($method->isFinal() || $method->isPrivate()) {
             return;
         }
         $code = $instrumentation->buildMethodSignature($method) . ' { ';
     }
     $code .= 'if(static::class == __CLASS__ && \\KoolKode\\Aop\\Advice::isAdviceEnabled()) { ';
     $code .= 'static $__i; ';
     $code .= 'if($__i === NULL) { $__i = [';
     $sorter = function (Advice $a, Advice $b) {
         $o1 = $a->getOrder();
         $o2 = $b->getOrder();
         if ($o1 === $o2) {
             return 0;
         }
         return $o1 > $o2 ? -1 : 1;
     };
     $merger = function (Advice $advice) use($manager, $method) {
         $interceptor = $advice->getInterceptor();
         if ($interceptor instanceof ContainerInterceptor) {
             return $interceptor->generateMethodInterceptionCode($manager, $method);
         }
         return $interceptor->exportCode();
     };
     $before = [];
     $around = [];
     $after = [];
     foreach ($advices as $advice) {
         if ($advice instanceof BeforeAdvice) {
             $before[] = $advice;
         } elseif ($advice instanceof AroundAdvice) {
             $around[] = $advice;
         } elseif ($advice instanceof AfterAdvice) {
             $after[] = $advice;
         }
     }
     usort($before, $sorter);
     usort($around, $sorter);
     usort($after, function (Advice $a, Advice $b) use($sorter) {
         return $sorter($b, $a);
     });
     $code .= '[' . implode(', ', array_map($merger, $before)) . '], ';
     $code .= '[' . implode(', ', array_map($merger, $after)) . '], ';
     if (empty($around)) {
         $code .= '[]';
     } else {
         $code .= '[1 => ' . implode(', ', array_map($merger, $around)) . ']';
     }
     $code .= ']; } ';
     if ($method->isReturnReference()) {
         $code .= 'unset($__r); $__r = ';
     } else {
         $code .= 'return ';
     }
     $code .= '(new \\KoolKode\\Aop\\MethodInvocation(\\KoolKode\\K2\\Kernel::getContainer(), ';
     $code .= '$this, __CLASS__ , __FUNCTION__, ';
     $code .= '\\func_get_args(), $__i))->proceed();';
     if ($method->isReturnReference()) {
         $code .= ' return $__r;';
     }
     $code .= ' }';
     if (!$type->is($method->getDeclaringType())) {
         if ($method->isReturnReference()) {
             $code .= ' unset($__r); $__r = call_user_func_array([';
             $code .= var_export($method->getDeclaringType()->getName(), true);
             $code .= ', __FUNCTION__], func_get_args()); return $__r;';
         } else {
             $code .= ' return call_user_func_array([';
             $code .= var_export($method->getDeclaringType()->getName(), true);
             $code .= ', __FUNCTION__], func_get_args());';
         }
         $instrumentation->introduceCode($code . ' }');
     } else {
         $instrumentation->prependMethodCode($method, $code);
     }
     return true;
 }