/** * Will generate the code used before the original function body * * @param bool $injectNeeded Determine if we have to use a try...catch block * @param FunctionDefinition $functionDefinition The function definition object * * @return string */ protected function generateBeforeCode($injectNeeded, FunctionDefinition $functionDefinition) { $suffix = PBC_ORIGINAL_FUNCTION_SUFFIX . str_replace('.', '', microtime(true)); $code = PBC_CONTRACT_CONTEXT . ' = \\TechDivision\\PBC\\ContractContext::open();'; // Invariant is not needed in private or static functions. // Also make sure that there is none in front of the constructor check if ($functionDefinition->getVisibility() !== 'private' && !$functionDefinition->getIsStatic() && $functionDefinition->getName() !== '__construct') { $code .= PBC_INVARIANT_PLACEHOLDER . PBC_PLACEHOLDER_CLOSE; } $code .= PBC_PRECONDITION_PLACEHOLDER . $functionDefinition->getName() . PBC_PLACEHOLDER_CLOSE . PBC_OLD_SETUP_PLACEHOLDER . $functionDefinition->getName() . PBC_PLACEHOLDER_CLOSE; // If we inject something we might need a try ... catch around the original call. if ($injectNeeded === true) { $code .= 'try {'; } // Build up the call to the original function. $code .= PBC_KEYWORD_RESULT . ' = ' . $functionDefinition->getHeader('call', $suffix) . ';'; // Finish the try ... catch and place the inject marker if ($injectNeeded === true) { $code .= '} catch (\\Exception $e) {}' . PBC_METHOD_INJECT_PLACEHOLDER . $functionDefinition->getName() . PBC_PLACEHOLDER_CLOSE; } // No just place all the other placeholder for other filters to come $code .= PBC_POSTCONDITION_PLACEHOLDER . $functionDefinition->getName() . PBC_PLACEHOLDER_CLOSE; // Invariant is not needed in private or static functions if ($functionDefinition->getVisibility() !== 'private' && !$functionDefinition->getIsStatic()) { $code .= PBC_INVARIANT_PLACEHOLDER . PBC_PLACEHOLDER_CLOSE; } $code .= 'if (' . PBC_CONTRACT_CONTEXT . ') {\\TechDivision\\PBC\\ContractContext::close();} return ' . PBC_KEYWORD_RESULT . ';}'; $code .= $functionDefinition->getHeader('definition', $suffix, true) . '{'; return $code; }
/** * Will change code to create an entry for the old object state. * * @param string $bucketData Payload of the currently * filtered bucket * @param \TechDivision\PBC\Entities\Definitions\FunctionDefinition $functionDefinition Currently handled function * * @throws \TechDivision\PBC\Exceptions\GeneratorException * * @return boolean */ private function injectOldCode(&$bucketData, FunctionDefinition &$functionDefinition) { // Do we even need to do anything? if ($functionDefinition->getUsesOld() !== true) { return false; } // If the function is static it should not use the pbcOld keyword as there is no state to the class! if ($functionDefinition->getIsStatic() === true) { throw new GeneratorException('Cannot clone class state in static method ' . $functionDefinition->getName()); } // Still here? Then inject the clone statement to preserve an instance of the object prior to our call. $bucketData = str_replace(PBC_OLD_SETUP_PLACEHOLDER . $functionDefinition->getName() . PBC_PLACEHOLDER_CLOSE, PBC_KEYWORD_OLD . ' = clone $this;', $bucketData); // Still here? We encountered no error then. return true; }