Exemplo n.º 1
0
 public function generateTargetCode(TokenPool $aTokenPool, Token $aObject)
 {
     if (!$aObject instanceof ClassDefine) {
         throw new ClassCompileException(null, $aObject, "传入的类新必须为 ClassDefine: %s", Type::detectType($aObject));
     }
     $aClassEnd = $aObject->bodyToken()->theOther();
     $sTargetClassName = $aObject->fullName();
     // 反射父类的所有方法
     $arrParentMethodNames = array();
     $aRefParentClass = null;
     if ($aObject->isClass()) {
         foreach ($aObject->parentClassNameIterator() as $sParentClass) {
             if (!class_exists($sParentClass)) {
                 throw new ClassCompileException(null, $aObject, "编译class时遇到错误,class %s 的父类 %s 不存在 ", array($sTargetClassName, $sParentClass));
             }
             $aRefParentClass = new \ReflectionClass($sParentClass);
             foreach ($aRefParentClass->getMethods() as $aRefParentMethod) {
                 if (!$aRefParentMethod->isPrivate() and !$aRefParentMethod->isAbstract() and !$aRefParentMethod->isFinal()) {
                     $arrParentMethodNames[$aRefParentMethod->getName()] = $aRefParentMethod;
                 }
             }
         }
     }
     // 需要编入的方法
     $arrNeedWeaveMethods = array();
     foreach ($this->aop()->aspects()->iterator() as $aAspect) {
         foreach ($aAspect->pointcuts()->iterator() as $aPointcut) {
             foreach ($aPointcut->jointPoints()->iterator() as $aJointPoint) {
                 if (!$aJointPoint instanceof JointPointMethodDefine) {
                     continue;
                 }
                 // 模糊匹配函数名 -----------------------
                 if ($aJointPoint->weaveMethodIsPattern()) {
                     foreach ($aTokenPool->functionIterator($aObject->fullName()) as $aMethodToken) {
                         // bingo !
                         if ($aJointPoint->matchExecutionPoint($aMethodToken)) {
                             $sMethodName = $aMethodToken->name();
                             if (empty($arrNeedWeaveMethods[$sMethodName])) {
                                 $arrNeedWeaveMethods[$sMethodName] = new GenerateStat($aTokenPool, $aMethodToken);
                             }
                             $arrNeedWeaveMethods[$sMethodName]->addAdvices($aPointcut->advices()->iterator());
                         }
                     }
                 } else {
                     if (!$aJointPoint->matchClass($sTargetClassName)) {
                         continue;
                     }
                     $sFuncName = $aJointPoint->weaveMethod();
                     if (empty($arrNeedWeaveMethods[$sFuncName])) {
                         $arrNeedWeaveMethods[$sFuncName] = new GenerateStat($aTokenPool);
                     }
                     $arrNeedWeaveMethods[$sFuncName]->addAdvices($aPointcut->advices()->iterator());
                     // 目标类的方法
                     if ($aMethodToken = $aTokenPool->findFunction($sFuncName, $sTargetClassName)) {
                         $arrNeedWeaveMethods[$sFuncName]->aExecutePoint = $aMethodToken;
                     } else {
                         if (isset($arrParentMethodNames[$sFuncName])) {
                             $aMethodRef = $arrParentMethodNames[$sFuncName];
                             $aMethodRef instanceof \ReflectionMethod;
                             // 产生函数定义和函数调用的参数表
                             $this->generateArgvsByReflection($arrNeedWeaveMethods[$sFuncName], $aMethodRef);
                             if ($aMethodRef->isPublic()) {
                                 $sAccess = 'public';
                             } else {
                                 if ($aMethodRef->isProtected()) {
                                     $sAccess = 'protected';
                                 } else {
                                     if ($aMethodRef->isPrivate()) {
                                         $sAccess = 'private';
                                     }
                                 }
                             }
                             // 创建一个覆盖父类的方法用于 aop
                             $aMethodToken = $this->createMethod($sFuncName, $arrNeedWeaveMethods[$sFuncName]->sOriginCallArgvsLit, $sAccess, $aMethodRef->isStatic(), $aTokenPool, $aClassEnd, 'insertBefore');
                             $aMethodToken->setBelongsClass($aObject);
                             $aMethodToken->setBelongsNamespace($aObject->belongsNamespace());
                             $arrNeedWeaveMethods[$sFuncName]->aExecutePoint = $aMethodToken;
                             // 创建函数内容
                             $aTokenPool->insertAfter($aMethodToken->bodyToken(), new Token(T_STRING, "\n\t\t\t// 调用父类方法\n\t\t\treturn parent::{$sFuncName}({$arrNeedWeaveMethods[$sFuncName]->sOriginCallArgvsLit}) ;\n\t\t"));
                         } else {
                             // 创建一个全新的方法用于 aop
                             $aMethodToken = $this->createMethod($sFuncName, $arrNeedWeaveMethods[$sFuncName]->sOriginCallArgvsLit, 'private', false, $aTokenPool, $aClassEnd, 'insertBefore');
                             $aMethodToken->setBelongsClass($aObject);
                             $aMethodToken->setBelongsNamespace($aObject->belongsNamespace());
                             $arrNeedWeaveMethods[$sFuncName]->aExecutePoint = $aMethodToken;
                             $aTokenPool->insertAfter($aMethodToken->bodyToken(), new Token(T_STRING, " // 这只是一个影子方法 "));
                         }
                     }
                 }
             }
         }
     }
     // 开始编织
     foreach ($arrNeedWeaveMethods as $aState) {
         if (!empty($aState->arrAdvices)) {
             $this->weave($aState);
         }
     }
 }