$count) { $count++; $arr = array_shift(self::$userErrorMessageBuffer); $message = $arr['message']; $calledInsideWithNoReplacement = $arr['calledInsideWithNoReplacement']; if ($calledInsideWithNoReplacement && !self::$showNoReplacementNotices) { continue; } self::$isTriggeringError = true; user_error($message, E_USER_DEPRECATED); self::$isTriggeringError = false; } // Make absolutely sure the buffer is empty - array_shift seems to leave an item in the array // if we're not using numeric keys. self::$userErrorMessageBuffer = []; } /** * 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 * * @param string $atVersion The version at which this notice should start being raised * @param string $string The notice to raise * @param int $scope Notice relates to the method or class context its called in. */ public static function notice($atVersion, $string = '', $scope = Deprecation::SCOPE_METHOD) { if (static::$insideNotice) { return; } static::$insideNotice = true; // try block needs to wrap all code in case anything inside the try block // calls something else that calls Deprecation::notice() try { $data = null; if ($scope === self::SCOPE_CONFIG) { // Deprecated config set via yaml will only be shown in the browser when using ?flush=1 // It will not show in CLI when running dev/build flush=1 $data = [ 'key' => sha1($string), 'message' => $string, 'calledInsideWithNoReplacement' => self::$insideWithNoReplacement ]; } else { if (!self::isEnabled()) { // Do not add to self::$userErrorMessageBuffer, as the backtrace is too expensive return; } // Getting a backtrace is slow, so we only do it if we need it $backtrace = null; // Get the calling scope if ($scope == Deprecation::SCOPE_METHOD) { $backtrace = debug_backtrace(0); $caller = self::get_called_method_from_trace($backtrace, 1); } elseif ($scope == Deprecation::SCOPE_CLASS) { $backtrace = debug_backtrace(0); $caller = isset($backtrace[1]['class']) ? $backtrace[1]['class'] : '(unknown)'; } else { $caller = false; } if (substr($string, -1) != '.') { $string .= "."; } $level = self::$insideWithNoReplacement ? 4 : 2; $string .= " Called from " . self::get_called_method_from_trace($backtrace, $level) . '.'; if ($caller) { $string = $caller . ' is deprecated.' . ($string ? ' ' . $string : ''); } $data = [ 'key' => sha1($string), 'message' => $string, 'calledInsideWithNoReplacement' => self::$insideWithNoReplacement ]; } if ($data && !array_key_exists($data['key'], self::$userErrorMessageBuffer)) { // Store de-duplicated data in a buffer to be outputted when outputNotices() is called self::$userErrorMessageBuffer[$data['key']] = $data; // Use a shutdown function rather than immediately calling user_error() so that notices // do not interfere with setting session varibles i.e. headers already sent error // it also means the deprecation notices appear below all phpunit output in CI // which is far nicer than having it spliced between phpunit output if (!self::$haveSetShutdownFunction && self::isEnabled()) { register_shutdown_function(function () { self::outputNotices(); }); self::$haveSetShutdownFunction = true; } } } catch (BadMethodCallException $e) { if ($e->getMessage() === InjectorLoader::NO_MANIFESTS_AVAILABLE) { // noop // this can happen when calling Deprecation::notice() before manifests are available, i.e. // some of the code involved in creating the manifests calls Deprecation::notice() } else { throw $e; } } finally { static::$insideNotice = false; } } /** * This method is no longer used * * @return array Opaque array that should only be used to pass to {@see Deprecation::restore_settings()} * @deprecated 4.12.0 Will be removed without equivalent functionality to replace it */ public static function dump_settings() { static::notice('4.12.0', 'Will be removed without equivalent functionality to replace it'); // noop } /** * This method is no longer used * * @param $settings array An array as returned by {@see Deprecation::dump_settings()} * @deprecated 4.12.0 Will be removed without equivalent functionality to replace it */ public static function restore_settings($settings) { static::notice('4.12.0', 'Will be removed without equivalent functionality to replace it'); // noop } private static function varAsBoolean($val): bool { if (is_string($val)) { $truthyStrings = [ 'on', 'true', '1', ]; if (in_array(strtolower($val), $truthyStrings, true)) { return true; } $falsyStrings = [ 'off', 'false', '0', ]; if (in_array(strtolower($val), $falsyStrings, true)) { return false; } } return (bool) $val; } }