getModules() as $name => $path) { if (strpos($callingfile, $path) === 0) { return $name; } } } /** * Given a backtrace, get the method name from the immediate parent caller (the caller of #notice) * * @static * @param $backtrace array - a backtrace as returned from debug_backtrace * @param $level - 1 (default) will return immediate caller, 2 will return caller's caller, etc. * @return string - the name of the method */ protected static function get_called_method_from_trace($backtrace, $level = 1) { $level = (int)$level; if(!$level) $level = 1; $called = $backtrace[$level]; if (isset($called['class'])) { return $called['class'] . $called['type'] . $called['function']; } else { return $called['function']; } } /** * Raise a notice indicating the method is deprecated if the version passed as the second argument is greater * than or equal to the check version set via ::notification_version * * @static * @param $string - The notice to raise * @param $atVersion - The version at which this notice should start being raised * @param Boolean $scope - Notice relates to the method or class context its called in. * @return void */ public static function notice($atVersion, $string = '', $scope = Deprecation::SCOPE_METHOD) { // Never raise deprecation notices in a live environment if(Director::isLive()) return; // If you pass #.#, assume #.#.0 if(preg_match('/^[0-9]+\.[0-9]+$/', $atVersion)) $atVersion .= '.0'; $checkVersion = self::$version; // Getting a backtrace is slow, so we only do it if we need it $backtrace = null; if(self::$module_version_overrides) { $module = self::get_calling_module_from_trace($backtrace = debug_backtrace(0)); if(isset(self::$module_version_overrides[$module])) { $checkVersion = self::$module_version_overrides[$module]; } } // Check the version against the notice version if ($checkVersion && version_compare($checkVersion, $atVersion, '>=')) { // Get the calling scope if($scope == Deprecation::SCOPE_METHOD) { if (!$backtrace) $backtrace = debug_backtrace(0); $caller = self::get_called_method_from_trace($backtrace); } elseif($scope == Deprecation::SCOPE_CLASS) { if (!$backtrace) $backtrace = debug_backtrace(0); $caller = isset($backtrace[1]['class']) ? $backtrace[1]['class'] : '(unknown)'; } else { $caller = false; } // Get the level to raise the notice as $level = self::$notice_level; if (!$level) $level = E_USER_DEPRECATED; // Then raise the notice if(substr($string,-1) != '.') $string .= "."; $string .= " Called from " . self::get_called_method_from_trace($backtrace, 2) . '.'; if($caller) { user_error($caller.' is deprecated.'.($string ? ' '.$string : ''), $level); } else { user_error($string, $level); } } } /** * Method for when testing. Dump all the current version settings to a variable for later passing to restore * @return array - opaque array that should only be used to pass to ::restore_version_settings */ public static function dump_settings() { return array( 'level' => self::$notice_level, 'version' => self::$version, 'moduleVersions' => self::$module_version_overrides ); } /** * Method for when testing. Restore all the current version settings from a variable * @static * @param $settings array - An array as returned by ::dump_version_settings * @return void */ public static function restore_settings($settings) { self::$notice_level = $settings['level']; self::$version = $settings['version']; self::$module_version_overrides = $settings['moduleVersions']; } }