public static function init()
{
if (!defined('SOFTMOCKS_ROOT_PATH')) {
define('SOFTMOCKS_ROOT_PATH', '/');
}
if (!empty($_ENV['SOFT_MOCKS_DEBUG'])) {
self::$debug = true;
}
self::$func_mocks['call_user_func_array'] = ['args' => '', 'code' => 'return \\' . self::class . '::call($params[0], $params[1]);'];
self::$func_mocks['call_user_func'] = ['args' => '', 'code' => '$func = array_shift($params); return \\' . self::class . '::call($func, $params);'];
self::$func_mocks['is_callable'] = ['args' => '$arg', 'code' => 'return \\' . self::class . '::isCallable($arg);'];
self::$func_mocks['function_exists'] = ['args' => '$arg', 'code' => 'return \\' . self::class . '::isCallable($arg);'];
self::$func_mocks['constant'] = ['args' => '$constant', 'code' => 'return \\' . self::class . '::getConst("", $constant);'];
self::$func_mocks['defined'] = ['args' => '$constant', 'code' => 'return \\' . self::class . '::constDefined($constant);'];
self::$func_mocks['debug_backtrace'] = ['args' => '', 'code' => function () {
$params = func_get_args();
$limit = 0;
$provide_object = true;
$ignore_args = false;
if (isset($params[0])) {
if ($params[0] === false) {
$provide_object = false;
} else {
if ($params[0] === true) {
$provide_object = true;
} else {
$provide_object = $params[0] & DEBUG_BACKTRACE_PROVIDE_OBJECT;
$ignore_args = $params[0] & DEBUG_BACKTRACE_IGNORE_ARGS;
}
}
}
if (isset($params[1])) {
$limit = $params[1];
}
$result = debug_backtrace();
// remove our part of backtrace
while (count($result) > 0) {
if (isset($result[0]['class']) && $result[0]['class'] === self::class && isset($result[0]['function']) && $result[0]['function'] === 'callFunction') {
array_shift($result);
break;
}
array_shift($result);
}
// remove calls that occur inside our file
$result = array_values(array_filter($result, function ($el) {
return !isset($el['file']) || $el['file'] !== __FILE__;
}));
$unset_indices = [];
// replace paths
foreach ($result as $i => &$p) {
if (isset($p["file"])) {
$p["file"] = self::replaceFilename($p["file"], true);
if ($p["file"] && $p["file"][0] !== '/') {
$p["file"] = SOFTMOCKS_ROOT_PATH . $p['file'];
}
}
if (isset($p['class']) && $p['class'] == self::class && isset($p['args'])) {
$args = $p['args'];
if ($p['function'] === 'callFunction') {
unset($p['class']);
unset($p['type']);
$p['function'] = $args[1];
$p['args'] = $args[2];
$unset_indices[] = $i - 1;
// reflection adds another line in trace that is not needed
} else {
if ($p['function'] === 'callMethod') {
$p['object'] = $args[0];
$p['class'] = get_class($args[0]);
$p['function'] = $args[1];
$p['args'] = $args[2];
$p['type'] = '->';
$unset_indices[] = $i - 1;
// reflection adds another line in trace that is not needed
} else {
if ($p['function'] === 'callStaticMethod') {
$p['class'] = $args[0];
$p['function'] = $args[1];
$p['args'] = $args[2];
$p['type'] = '::';
$unset_indices[] = $i - 1;
// reflection adds another line in trace that is not needed
}
}
}
}
if ($ignore_args) {
unset($p['args']);
}
if (!$provide_object) {
unset($p['object']);
}
}
foreach ($unset_indices as $i) {
unset($result[$i]);
}
$result = array_values($result);
if (!$limit) {
return $result;
}
$limited_result = [];
for ($i = 0; $i < $limit; $i++) {
$limited_result[] = $result[$i];
}
return $limited_result;
}];
self::$internal_func_mocks = [];
foreach (self::$func_mocks as $func => $mock) {
self::$internal_func_mocks[$func] = $mock;
}
$functions = get_defined_functions();
foreach ($functions['internal'] as $func) {
self::$internal_functions[$func] = true;
}
self::ignoreFiles(get_included_files());
self::injectIntoPhpunit();
}