/**
  * 创建并织入一个用于集中调用各个advice的函数
  */
 protected function generateAdviceDispatchFunction(GenerateStat $aStat)
 {
     Assert::type("org\\jecat\\framework\\lang\\compile\\object\\FunctionDefine", $aStat->aExecutePoint);
     if (!$aStat->aExecutePoint->bodyToken()) {
         throw new Exception("AOP织入遇到错误:正在对一个抽象方法(%s::%s)进行织入操作。", array($aStat->aExecutePoint->belongsClass()->fullName(), $aStat->aExecutePoint->name()));
     }
     // 新建同名方法
     $aOriFuncStart = $aStat->aExecutePoint->startToken();
     $aOriFuncEnd = $aStat->aExecutePoint->endToken();
     $aStat->aAdvicesDispatchFunc = new FunctionDefine($aStat->aExecutePoint, new Token(T_STRING, $aStat->aExecutePoint->name(), 0), null, null);
     // static declare
     if ($aStat->aExecutePoint->staticToken()) {
         $aStaticClareToken = new Token(T_STATIC, 'static', 0);
         $aStat->aAdvicesDispatchFunc->setStaticToken($aStaticClareToken);
         $aStat->aTokenPool->insertBefore($aOriFuncStart, $aStaticClareToken);
         $aStat->aTokenPool->insertBefore($aOriFuncStart, new Token(T_WHITESPACE, ' ', 0));
     }
     // private, protected, public
     $aOriAccess = $aStat->aExecutePoint->accessToken();
     $aNewAccess = $aOriAccess ? new Token($aOriAccess->tokenType(), $aOriAccess->sourceCode(), 0) : new Token(T_PUBLIC, 'public', 0);
     $aStat->aAdvicesDispatchFunc->setAccessToken($aNewAccess);
     $aStat->aTokenPool->insertBefore($aOriFuncStart, $aNewAccess);
     $aStat->aTokenPool->insertBefore($aOriFuncStart, new Token(T_WHITESPACE, ' ', 0));
     // function keyword
     $aStat->aTokenPool->insertBefore($aOriFuncStart, $aStat->aAdvicesDispatchFunc);
     $aStat->aTokenPool->insertBefore($aOriFuncStart, new Token(T_WHITESPACE, ' ', 0));
     // function name
     $aStat->aTokenPool->insertBefore($aOriFuncStart, $aStat->aAdvicesDispatchFunc->nameToken());
     // 参数表
     $aArgvLstStart = new ClosureToken($aStat->aExecutePoint->argListToken());
     $aArgvLstEnd = new ClosureToken($aStat->aExecutePoint->argListToken()->theOther());
     $aArgvLstStart->setTheOther($aArgvLstEnd);
     $aStat->aAdvicesDispatchFunc->setArgListToken($aArgvLstStart);
     $aStat->aTokenPool->insertBefore($aOriFuncStart, $aArgvLstStart);
     foreach ($this->cloneFunctionArgvLst($aStat->aTokenPool, $aStat->aExecutePoint) as $aToken) {
         $aStat->aTokenPool->insertBefore($aOriFuncStart, $aToken);
     }
     $aStat->aTokenPool->insertBefore($aOriFuncStart, $aArgvLstEnd);
     // 换行
     $aStat->aTokenPool->insertBefore($aOriFuncStart, new Token(T_WHITESPACE, "\r\n\t"));
     // 函数体
     $aBodyStart = new ClosureToken($aStat->aExecutePoint->bodyToken());
     $aBodyEnd = new ClosureToken($aOriFuncEnd);
     $aBodyStart->setTheOther($aBodyEnd);
     $aStat->aAdvicesDispatchFunc->setBodyToken($aBodyStart);
     $aStat->aTokenPool->insertBefore($aOriFuncStart, $aBodyStart);
     $aStat->aTokenPool->insertBefore($aOriFuncStart, $aBodyEnd);
     // init call state 对像
     $sLines = "\r\n";
     $sLines .= "\t\t\$__apo_aCallState = new \\org\\jecat\\framework\\lang\\aop\\AdviceCallState() ;\r\n";
     if (!$aStat->aExecutePoint->staticToken()) {
         $sLines .= "\t\t\$__apo_aCallState->aOriginObject = \$this ;\r\n";
     }
     $sLines .= "\t\t\$__apo_aCallState->sOriginClass = '" . addslashes($aStat->aAdvicesDispatchFunc->belongsClass()->fullName()) . "';\r\n";
     $sLines .= "\t\t\$__apo_aCallState->sOriginMethod = '" . $aStat->aAdvicesDispatchFunc->name() . "' ;\r\n";
     foreach ($this->parseArgvs($aStat->aTokenPool, $aStat->aAdvicesDispatchFunc) as $sArgvName => $sArgv) {
         $sLines .= "\t\t\$__apo_aCallState->arrAvgvs['{$sArgvName}'] =& \${$sArgvName} ;\r\n";
     }
     $aStat->aTokenPool->insertAfter($aBodyStart, new Token(T_WHITESPACE, $sLines));
     // 换行
     $aStat->aTokenPool->insertBefore($aOriFuncStart, new Token(T_WHITESPACE, "\r\n\r\n\t"));
 }
示例#2
0
 protected function createMethod($sFuncName, $argLstToken = null, $sAccess, $bStatic = false, TokenPool $aTokenPool, Token $aTargetToken, $sWhere = 'insertAfter')
 {
     $aFuncToken = new FunctionDefine(new Token(T_FUNCTION, 'function'));
     // 函数体
     $aBodyStart = new ClosureToken(new Token(T_STRING, '{'));
     $aBodyEnd = new ClosureToken(new Token(T_STRING, '}'));
     $aBodyStart->setTheOther($aBodyEnd);
     $aTokenPool->{$sWhere}($aTargetToken, $aBodyStart);
     $aTokenPool->insertAfter($aBodyStart, $aBodyEnd);
     $aTokenPool->insertAfter($aBodyEnd, new Token(T_WHITESPACE, "\r\n"));
     $aTokenPool->insertBefore($aBodyStart, new Token(T_WHITESPACE, "\r\n\t"));
     // static
     if ($bStatic) {
         $aStaticToken = new Token(T_PRIVATE, 'static');
         $aTokenPool->insertBefore($aBodyStart, $aStaticToken);
         $aTokenPool->insertBefore($aBodyStart, new Token(T_WHITESPACE, "\r\n\t"));
         $aFuncToken->setStaticToken($aStaticToken);
     }
     // access
     $arrAccessTokenTypes = array('private' => T_PRIVATE, 'protected' => T_PROTECTED, 'public' => T_PUBLIC);
     $aAccessToken = new Token($arrAccessTokenTypes[$sAccess], $sAccess);
     $aTokenPool->insertBefore($aBodyStart, $aAccessToken);
     $aTokenPool->insertBefore($aBodyStart, new Token(T_WHITESPACE, ' '));
     $aFuncToken->setAccessToken($aAccessToken);
     // function
     $aTokenPool->insertBefore($aBodyStart, $aFuncToken);
     $aTokenPool->insertBefore($aBodyStart, new Token(T_WHITESPACE, ' '));
     $aFuncToken->setBodyToken($aBodyStart);
     // function name
     $aFuncNameToken = new Token(T_STRING, $sFuncName);
     $aTokenPool->insertBefore($aBodyStart, $aFuncNameToken);
     $aFuncToken->setNameToken($aFuncNameToken);
     // 参数表
     $aArgvLstStart = new ClosureToken(new Token(T_STRING, '('));
     $aArgvLstEnd = new ClosureToken(new Token(T_STRING, ')'));
     $aArgvLstStart->setTheOther($aArgvLstEnd);
     $aTokenPool->insertBefore($aBodyStart, $aArgvLstStart);
     if ($argLstToken) {
         $aTokenPool->insertBefore($aBodyStart, new Token(T_STRING, $argLstToken));
     }
     $aTokenPool->insertBefore($aBodyStart, $aArgvLstEnd);
     $aTokenPool->insertBefore($aBodyStart, new Token(T_WHITESPACE, "\r\n\t"));
     $aFuncToken->setArgListToken($aArgvLstStart);
     return $aFuncToken;
 }