public static function redefineMethod($class, $method, $functionArgs, $fakeCode, $strict = true)
{
if (self::$debug) {
self::debug("Asked to redefine {$class}::{$method}({$functionArgs})");
}
if (SoftMocksTraverser::isClassIgnored($class)) {
throw new \RuntimeException("Class {$class} cannot be mocked using Soft Mocks");
}
self::$mocks[$class][$method] = ['args' => $functionArgs, 'code' => $fakeCode];
try {
$Rm = new \ReflectionMethod($class, $method);
self::$mocks[$class][$method]['code'] = self::generateCode($functionArgs, $Rm) . self::$mocks[$class][$method]['code'];
if ($strict) {
return;
}
$Dc = $Rm->getDeclaringClass();
if ($Dc) {
if ($Dc->getTraits() && ($DeclaringTrait = self::getDeclaringTrait($Dc->getName(), $method))) {
$Dc = $DeclaringTrait;
}
$decl_class = $Dc->getName();
// do not mock declaring class again if there already exists a proper mock for it
$no_mock_for_parent = empty(self::$mocks[$decl_class][$method]);
$installed_from_current_mock = false;
if (isset(self::$mocks[$class][$method]['installed_by']) && self::$mocks[$class][$method]['installed_by'] === $class) {
$installed_from_current_mock = true;
}
if ($no_mock_for_parent || $installed_from_current_mock) {
if (self::$debug) {
self::debug("Redefine also {$decl_class}::{$method}({$functionArgs})");
}
self::$mocks[$decl_class][$method] = self::$mocks[$class][$method] + ['installed_by' => $class];
self::$mocks[$class][$method]['decl_class'] = $decl_class;
}
}
} catch (\Exception $e) {
self::$mocks[$class][$method]['code'] = self::generateCode($functionArgs, null) . self::$mocks[$class][$method]['code'];
if (self::$debug) {
self::debug("Could not new ReflectionMethod({$class}, {$method}), cannot accept function calls by reference: " . $e);
}
}
}