/** * 创建并织入一个用于集中调用各个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")); }
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; }