false]); if ($cleanedUpData === false) { $cleanedUpData = json_decode((string)$logData, true); } return is_array($cleanedUpData) ? $cleanedUpData : null; } /** * Replaces a string with placeholders (%s or {myPlaceholder}) with its substitutes. */ protected function formatLogDetails(string $detailString, mixed $substitutes): string { if (!is_array($substitutes)) { $substitutes = $this->unserializeLogData($substitutes) ?? []; } return self::formatLogDetailsStatic($detailString, $substitutes); } /** * Static version for ViewHelpers etc. * * Replaces a string with placeholders (%s or {myPlaceholder}) with its substitutes. */ protected static function formatLogDetailsStatic(string $detailString, array $substitutes): string { // Handles placeholders with "%" first try { $detailString = vsprintf($detailString, $substitutes); } catch (\ValueError|\ArgumentCountError) { // Ignore if $substitutes doesn't contain the number of "%" found in $detailString } // Handles placeholders with "{myPlaceholder}" $detailString = preg_replace_callback('/{([A-z]+)}/', static function (array $matches) use ($substitutes) { // $matches[0] contains the unsubstituted placeholder return $substitutes[$matches[1]] ?? $matches[0]; }, $detailString); // Remove possible pending %s return str_replace('%s', '', (string)$detailString); } }