/** * @param \Runkit\RunkitMethod $method * * @return boolean */ public function addMethod(\Runkit\RunkitMethod $method) { if (!function_exists('runkit_method_add')) { return false; } return runkit_method_add($method->getClass(), $method->getName(), (string) $method->getArguments(), $method->getCode()->get(), $method->getAccess()); }
/** * Reimplements the given function. */ public static function reimplementMethod($class, $method, $arguments, $code) { $originalMethod = "__original_{$method}"; if (!method_exists($class, $originalMethod)) { runkit_method_rename($class, $method, $originalMethod); } runkit_method_add($class, $method, $arguments, $code); }
public static function replaceMethod($className, $methodName, $args, $code, $flags) { yTest_debugCC("replaceMethod {$className}::{$methodName}({$args}) with code (flags = " . self::flagsToString($flags) . "):\n" . $code); $res = runkit_method_rename($className, $methodName, strtolower(self::getOriginalMethodName($methodName))); yTest_assert($res); $res = runkit_method_add($className, strtolower($methodName), $args, $code, $flags); yTest_assert($res); //var_dump(get_class_methods($className)); }
/** * Apply a mutation to the relevant file * * @param array $mutation */ public function applyMutation(array $mutation) { require_once $mutation['mutation']->getFilename(); $newBlock = $mutation['mutation']->mutate($mutation['tokens'], $mutation['index']); $this->_methodPreserveCode = md5($mutation['method']); if (runkit_method_rename($mutation['class'], $mutation['method'], $mutation['method'] . $this->_methodPreserveCode) == false) { throw new \Exception('runkit_method_rename() failed from ' . $mutation['class'] . '::' . $mutation['method'] . ' to ' . $mutation['class'] . '::' . $mutation['method'] . $this->_methodPreserveCode . ' (mutation application)'); } if (runkit_method_add($mutation['class'], $mutation['method'], $mutation['args'], $newBlock, $this->getMethodFlags($mutation)) == false) { throw new \Exception('runkit_method_add() failed when replacing original ' . $mutation['class'] . '::' . $mutation['method'] . '(' . var_export($mutation['args']) . ') with a mutation of' . ' type ' . get_class($mutation['mutation']) . ' using the' . ' following (mutated) source code from ' . $mutation['mutation']->getFilename() . ':' . PHP_EOL . $newBlock); } }
/** * Mock * * @return \MockFunction */ public function mock() { if ($this->_mock) { return $this; } $this->_mock = true; foreach ($this->_methods as $method) { runkit_method_rename($this->_class_name, $method, "_origin_" . $method); runkit_method_add($this->_class_name, $method, '', $this->getMockCode($method)); } return $this; }
protected function _redirectCallToMethod() { $newOrigFuncName = $this->_functionName . $this->_origFuncSuffix; $spyFuncName = $this->_functionName . $this->_spyFuncSuffix; $isStatic = (new \ReflectionMethod($this->_context, $this->_functionName))->isStatic(); $isInherited = !method_exists($this->_context, $this->_functionName) && method_exists(get_parent_class($this->_context), $this->_functionName); runkit_method_add($this->_context, $spyFuncName, '', $this->_getSpyFunctionBody(), RUNKIT_ACC_PRIVATE | ($isStatic ? RUNKIT_ACC_STATIC : 0)); if (!method_exists($this->_context, $newOrigFuncName)) { runkit_method_copy($this->_context, $newOrigFuncName, $this->_context, $this->_functionName); } //keep memory address of function to prevent seg fault $runkit_method_modifier = $isInherited ? 'runkit_method_add' : 'runkit_method_redefine'; $runkit_method_modifier($this->_context, $this->_functionName, '', $this->_getReplaceFunctionBody(), RUNKIT_ACC_PUBLIC | ($isStatic ? RUNKIT_ACC_STATIC : 0)); }
public function apply() { $runkitFlags = RUNKIT_ACC_PUBLIC; if (yTest_Reflection::isStaticProperty($this->className, $this->propertyName)) { $setter = 'self::$' . $this->propertyName . ' = $value;'; $getter = 'return self::$' . $this->propertyName . ';'; $runkitFlags |= RUNKIT_ACC_STATIC; } else { $setter = '$this->' . $this->propertyName . ' = $value;'; $getter = 'return $this->' . $this->propertyName . ';'; } runkit_method_add($this->className, $this->setterName, '$value', $setter, $runkitFlags); runkit_method_add($this->className, $this->getterName, '', $getter, $runkitFlags); }
public function apply() { if (method_exists($this->className, yTest_Reflection::getOriginalMethodName($this->methodName))) { throw new yTest_Exception('trying to create public delegate (letMeCall) on the already rewired method ' . $this->className . '::' . $this->methodName); } $params = yTest_Signature::getParamsDecl($this->methodName, $this->className); $runkitFlags = RUNKIT_ACC_PUBLIC; if (yTest_Reflection::isStaticMethod($this->className, $this->methodName)) { $code = 'return self::' . $this->methodName . '(' . yTest_Signature::getArgsForSimpleCall($this->methodName, $this->className) . ');'; $runkitFlags |= RUNKIT_ACC_STATIC; } else { $code = 'return $this->' . $this->methodName . '(' . yTest_Signature::getArgsForSimpleCall($this->methodName, $this->className) . ');'; } yTest_debugCC("PARAMS: {$params}", "CODE: {$code}"); runkit_method_add($this->className, $this->delegateName, $params, $code, $runkitFlags); }
/** * Apply a mutation to the relevant file * * @param MutantInterface $mutant * * @throws \Exception */ public function applyMutation(MutantInterface $mutant) { $class = $mutant->getClassName(); $method = $mutant->getMethodName(); $args = $mutant->getArguments(); $filename = $mutant->getFileName(); require_once $filename; $newBlock = $mutant->mutate(); $this->_methodPreserveCode = md5($method); if (runkit_method_rename($class, $method, $method . $this->_methodPreserveCode) == false) { throw new \Exception('runkit_method_rename() failed from ' . $class . '::' . $method . ' to ' . $class . '::' . $method . $this->_methodPreserveCode . ' (mutation application)'); } if (runkit_method_add($class, $method, $args, $newBlock, $this->getMethodFlags($mutant)) == false) { throw new \Exception('runkit_method_add() failed when replacing original ' . $class . '::' . $method . '(' . var_export($args) . ') with a mutation of' . ' type ' . get_class($mutant->getMutation()) . ' using the' . ' following (mutated) source code from ' . $filename . ':' . PHP_EOL . $newBlock); } }
function setup() { global $conf; // set purge to avoid trying to retrieve from cache $this->purge = isset($_REQUEST['purge']) ? $_REQUEST['purge'] : null; $_REQUEST['purge'] = 1; if (!isset($conf['cachedir'])) { $conf['cachedir'] = ''; $this->cachedir = false; } else { $this->cachedir = true; } if (function_exists('io_makefiledir')) { runkit_function_rename('io_makefiledir', 'io_makefiledir_real'); } runkit_function_rename('xhtml_htmlphp_test_io_makefiledir', 'io_makefiledir'); if (function_exists('io_savefile')) { runkit_function_rename('io_savefile', 'io_savefile_real'); } runkit_function_rename('xhtml_htmlphp_test_io_savefile', 'io_savefile'); runkit_method_rename('GeSHi', 'parse_code', 'parse_code_real'); runkit_method_add('GeSHi', 'parse_code', '', '{ return hsc($this->source); }'); parent::setup(); }
protected function updateState($type, $id, $state) { $parts = explode('|', $id); switch ($type) { case self::STATIC_METHOD: case self::DYNAMIC_METHOD: $className = $parts[1]; $methodName = $parts[2]; $savedName = self::SAVED_PREFIX . $methodName; if ($state) { // enable is_callable("{$className}::{$methodName}"); $flags = RUNKIT_ACC_PUBLIC | ($type == self::STATIC_METHOD ? RUNKIT_ACC_STATIC : 0); runkit_method_rename($className, $methodName, $savedName); // save the original method runkit_method_add($className, $methodName, '', $this->getExecuteCallCode($type, $id, $type === self::DYNAMIC_METHOD), $flags); } else { // diable runkit_method_remove($className, $methodName); // remove the redefined instance runkit_method_rename($className, $savedName, $methodName); // restore the original } break; case self::GLOBAL_FUNCTION: $functionName = $parts[1]; list($namespace, $baseName) = self::parseGlobalFunctionName($functionName); $functionName = $namespace . $baseName; $savedName = $namespace . self::SAVED_PREFIX . $baseName; if ($state) { // enable $tempName = "WikiaMockProxyTempFuncName"; // workaround for namespaces functions runkit_function_rename($functionName, $savedName); runkit_function_add($tempName, '', $this->getExecuteCallCode($type, $id)); runkit_function_rename($tempName, $functionName); } else { // disable runkit_function_remove($functionName); // remove the redefined instance runkit_function_rename($savedName, $functionName); // restore the original } break; } }
/** * Added the information of the pseudo implementation * * @param string $method_name * @param callable $func anonymous function * @return $this * @throws MethodNotFoundException */ public function addMethod($method_name, \Closure $func) { if (!method_exists($this->class_name, $method_name)) { throw new MethodNotFoundException("{$this->class_name} doesn't have such a method ({$method_name})"); } $this->methods[$method_name] = $func; /** * Stash the original implementation temporarily as a method of different name. * Need to check the existence of stashed method not to write psuedo implementation * twice and forget the original implementation */ if (!$this->stashedMethodExists($method_name)) { runkit_method_rename($this->class_name, $method_name, $this->getStashedMethodName($method_name)); } else { runkit_method_remove($this->class_name, $method_name); } $code = $this->getFakeCode($this->class_name, $method_name); runkit_method_add($this->class_name, $method_name, '', $code, RUNKIT_ACC_STATIC); return $this; }
/** * Redefine constructor of the class. * Note: loading (including) any of classes, extending this one will fail * with fatal error, so pre-loading is needed. * * @param string $class - name of the class to redefine constructor in * @param string $args - comma-seperated list of arguments * @param string $body - body of method * @param int $access - any of RUNKIT_ACC_* constants */ public function redefineConstructor($class, $args, $code, $access = RUNKIT_ACC_PUBLIC) { $this->loadClass($class); $backupMethod = $this->getBackupName(self::CONSTRUCTOR); try { $this->checkMethodNotDefined($class, $backupMethod); } catch (PStub_RunkitAdapter_Exception $e) { throw new PStub_RunkitAdapter_Exception('Constructor of the class ' . $class . ' can not be redefined more than once'); } $tempMethod = $this->getTempName(self::CONSTRUCTOR); // this is a workaround for runkit bugs, just redefing won't work runkit_method_rename($class, self::CONSTRUCTOR, $backupMethod); runkit_method_add($class, $tempMethod, $args, $code, $access); runkit_method_rename($class, $tempMethod, self::CONSTRUCTOR); }