/** * @param $advice string[]|object[]|string * @param $advice_class_name string * @param $advice_method_name string * @param $advice_function_name string * @param $advice_parameters_string string * @param $advice_has_return boolean * @param $is_advice_static boolean * @param $joinpoint_code string * @param $i2 string * @param $result string * @return string */ private function generateAdviceCode($advice, $advice_class_name, $advice_method_name, $advice_function_name, $advice_parameters_string, $advice_has_return, $is_advice_static, $joinpoint_code, $i2, $result) { // $advice_code if (is_array($advice)) { $methods_flags = [Reflection_Class::T_DOC_EXTENDS, T_EXTENDS, T_USE]; $method = $advice[0] == '$this' ? $this->class->getMethods($methods_flags)[$advice_method_name] : Reflection_Method::of($advice_class_name, $advice_method_name, $methods_flags); $ref = $method->returnsReference() ? '&' : ''; // static method call if ($is_advice_static) { return $joinpoint_code . $i2 . ($advice_has_return ? $result . SP . '=' . $ref . SP : '') . (in_array($advice[0], ['self', 'static']) ? $advice[0] : BS . $advice_class_name) . '::' . $advice_method_name . '(' . $advice_parameters_string . ');'; } elseif ($advice[0] == '$this') { return $joinpoint_code . $i2 . ($advice_has_return ? $result . SP . '=' . $ref . SP : '') . '$this->' . $advice_method_name . '(' . $advice_parameters_string . ');'; } else { return $i2 . '/** @var $object_ ' . BS . $advice_class_name . ' */' . $i2 . '$object_ = \\SAF\\Framework\\Session::current()->plugins->get(' . "'{$advice_class_name}'" . ');' . $joinpoint_code . $i2 . ($advice_has_return ? 'if ($object_) ' . $result . SP . '=' . $ref . SP : '') . '$object_->' . $advice_method_name . '(' . $advice_parameters_string . ');'; } } else { $ref = (new ReflectionFunction($advice_function_name))->returnsReference() ? '&' : ''; return $joinpoint_code . $i2 . ($advice_has_return ? $result . SP . '=' . $ref . SP : '') . $advice_function_name . '(' . $advice_parameters_string . ');'; } }
/** * Scan weaver for all parent AOP aspects on abstract methods * - for each methods implemented in the class or its traits * - for each parent abstract method of these methods * - for all the parent chain between the method and its parent * - if any advice : add it for the current class * * @param $methods array [$method][$index] = [$type, callback $advice] * @param $class Reflection_Class * @param $only_method string Internal use only : the method name we are up-scanning */ private function scanForAbstract(&$methods, Reflection_Class $class, $only_method = null) { if ($class->getParentName()) { $parent_class = $class->getParentClass(); $parent_methods = $parent_class->getMethods([T_EXTENDS, T_IMPLEMENTS]); foreach ($class->getMethods($only_method ? [T_EXTENDS, T_IMPLEMENTS] : [T_USE]) as $method) { if (!$only_method || $only_method === $method->name) { if (isset($parent_methods[$method->name]) && $parent_methods[$method->name]->isAbstract()) { $this->scanForAbstract($methods, $parent_class, $method->name); $joinpoints = $this->weaver->getJoinpoint([$parent_class->name, $method->name]); foreach ($joinpoints as $pointcut) { $methods[$method->name][] = $pointcut; } } } } } }