[TASK] Use null coalescing operator where possible
[Packages/TYPO3.CMS.git] / typo3 / sysext / core / Classes / Utility / DebugUtility.php
1 <?php
2 namespace TYPO3\CMS\Core\Utility;
3
4 /*
5 * This file is part of the TYPO3 CMS project.
6 *
7 * It is free software; you can redistribute it and/or modify it under
8 * the terms of the GNU General Public License, either version 2
9 * of the License, or any later version.
10 *
11 * For the full copyright and license information, please read the
12 * LICENSE.txt file that was distributed with this source code.
13 *
14 * The TYPO3 project - inspiring people to share!
15 */
16 use TYPO3\CMS\Extbase\Utility\DebuggerUtility;
17
18 /**
19 * Class to handle debug
20 */
21 class DebugUtility
22 {
23 /**
24 * @var bool
25 */
26 protected static $plainTextOutput = true;
27
28 /**
29 * @var bool
30 */
31 protected static $ansiColorUsage = true;
32
33 /**
34 * Debug
35 *
36 * Directly echos out debug information as HTML (or plain in CLI context)
37 *
38 * @param string $var
39 * @param string $header
40 * @param string $group
41 */
42 public static function debug($var = '', $header = '', $group = 'Debug')
43 {
44 // buffer the output of debug if no buffering started before
45 if (ob_get_level() === 0) {
46 ob_start();
47 }
48 if (TYPO3_MODE === 'BE' && !self::isCommandLine()) {
49 $tabHeader = $header ?: 'Debug';
50 $debug = self::renderDump($var);
51 $debugPlain = PHP_EOL . self::renderDump($var, '', true, false);
52 $script = '
53 (function debug() {
54 var message = ' . GeneralUtility::quoteJSvalue($debug) . ',
55 messagePlain = ' . GeneralUtility::quoteJSvalue($debugPlain) . ',
56 header = ' . GeneralUtility::quoteJSvalue($tabHeader) . ',
57 group = ' . GeneralUtility::quoteJSvalue($group) . ';
58 if (top.TYPO3 && top.TYPO3.DebugConsole) {
59 top.TYPO3.DebugConsole.add(message, header, group);
60 } else {
61 var consoleMessage = [group, header, messagePlain].join(" | ");
62 if (typeof console === "object" && typeof console.log === "function") {
63 console.log(consoleMessage);
64 }
65 };
66 })();
67 ';
68 echo GeneralUtility::wrapJS($script);
69 } else {
70 echo self::renderDump($var);
71 }
72 }
73
74 /**
75 * Converts a variable to a string
76 *
77 * @param mixed $variable
78 * @return string plain, not HTML encoded string
79 */
80 public static function convertVariableToString($variable)
81 {
82 $string = self::renderDump($variable, '', true, false);
83 return $string === '' ? '| debug |' : $string;
84 }
85
86 /**
87 * Opens a debug message inside a popup window
88 *
89 * @param mixed $debugVariable
90 * @param string $header
91 * @param string $group
92 */
93 public static function debugInPopUpWindow($debugVariable, $header = 'Debug', $group = 'Debug')
94 {
95 $debugString = self::renderDump($debugVariable, sprintf('%s (%s)', $header, $group));
96 $script = '
97 (function debug() {
98 var debugMessage = ' . GeneralUtility::quoteJSvalue($debugString) . ',
99 header = ' . GeneralUtility::quoteJSvalue($header) . ',
100 group = ' . GeneralUtility::quoteJSvalue($group) . ',
101
102 browserWindow = function(debug, header, group) {
103 var newWindow = window.open("", "TYPO3DebugWindow_" + group,
104 "width=600,height=400,menubar=0,toolbar=1,status=0,scrollbars=1,resizable=1"
105 );
106 if (newWindow.document.body.innerHTML) {
107 newWindow.document.body.innerHTML = newWindow.document.body.innerHTML +
108 "<hr />" + debugMessage;
109 } else {
110 newWindow.document.writeln(
111 "<html><head><title>Debug: " + header + "(" + group + ")</title></head>"
112 + "<body onload=\\"self.focus()\\">"
113 + debugMessage
114 + "</body></html>"
115 );
116 }
117 };
118
119 if (top && typeof top.TYPO3 !== "undefined" && typeof top.TYPO3.Modal !== "undefined") {
120 top.TYPO3.Modal.show(
121 "Debug: " + header + " (" + group + ")",
122 debugMessage,
123 top.TYPO3.Severity.notice
124 );
125 } else {
126 browserWindow(debugMessage, header, group);
127 }
128 })();
129 ';
130 echo GeneralUtility::wrapJS($script);
131 }
132
133 /**
134 * Displays the "path" of the function call stack in a string, using debug_backtrace
135 *
136 * @param bool $prependFileNames If set to true file names are added to the output
137 * @return string plain, not HTML encoded string
138 */
139 public static function debugTrail($prependFileNames = false)
140 {
141 $trail = debug_backtrace(0);
142 $trail = array_reverse($trail);
143 array_pop($trail);
144 $path = [];
145 foreach ($trail as $dat) {
146 $fileInformation = $prependFileNames && !empty($dat['file']) ? $dat['file'] . ':' : '';
147 $pathFragment = $fileInformation . $dat['class'] . $dat['type'] . $dat['function'];
148 // add the path of the included file
149 if (in_array($dat['function'], ['require', 'include', 'require_once', 'include_once'])) {
150 $pathFragment .= '(' . PathUtility::stripPathSitePrefix($dat['args'][0]) . '),' . PathUtility::stripPathSitePrefix($dat['file']);
151 }
152 $path[] = $pathFragment . '#' . $dat['line'];
153 }
154 return implode(' // ', $path);
155 }
156
157 /**
158 * Displays an array as rows in a table. Useful to debug output like an array of database records.
159 *
160 * @param mixed $rows Array of arrays with similar keys
161 * @param string $header Table header
162 */
163 public static function debugRows($rows, $header = '')
164 {
165 self::debug($rows, $header);
166 }
167
168 /**
169 * Returns a string with a list of ascii-values for the first $characters characters in $string
170 *
171 * @param string $string String to show ASCII value for
172 * @param int $characters Number of characters to show
173 * @return string The string with ASCII values in separated by a space char.
174 */
175 public static function ordinalValue($string, $characters = 100)
176 {
177 if (strlen($string) < $characters) {
178 $characters = strlen($string);
179 }
180 $valuestring = '';
181 for ($i = 0; $i < $characters; $i++) {
182 $valuestring .= ' ' . ord(substr($string, $i, 1));
183 }
184 return trim($valuestring);
185 }
186
187 /**
188 * Returns HTML-code, which is a visual representation of a multidimensional array
189 * use \TYPO3\CMS\Core\Utility\GeneralUtility::print_array() in order to print an array
190 * Returns FALSE if $array_in is not an array
191 *
192 * @param mixed $array_in Array to view
193 * @return string HTML output
194 */
195 public static function viewArray($array_in)
196 {
197 return self::renderDump($array_in);
198 }
199
200 /**
201 * Prints an array
202 *
203 * @param mixed $array_in Array to print visually (in a table).
204 * @see viewArray()
205 */
206 public static function printArray($array_in)
207 {
208 echo self::renderDump($array_in);
209 }
210
211 /**
212 * Renders the dump according to the context, either for command line or as HTML output
213 *
214 * @param mixed $variable
215 * @param string $title
216 * @param bool|null $plainText
217 * @param bool|null $ansiColors
218 * @return string
219 */
220 protected static function renderDump($variable, $title = '', $plainText = null, $ansiColors = null)
221 {
222 $plainText = $plainText ?? self::isCommandLine() && self::$plainTextOutput;
223 $ansiColors = $ansiColors ?? self::isCommandLine() && self::$ansiColorUsage;
224 return trim(DebuggerUtility::var_dump($variable, $title, 8, $plainText, $ansiColors, true));
225 }
226
227 /**
228 * Checks some constants to determine if we are in CLI context
229 *
230 * @return bool
231 */
232 protected static function isCommandLine()
233 {
234 return (TYPO3_REQUESTTYPE & TYPO3_REQUESTTYPE_CLI) || PHP_SAPI === 'cli';
235 }
236
237 /**
238 * Preset plaintext output
239 *
240 * Warning:
241 * This is NOT a public API method and must not be used in own extensions!
242 * This method is usually only used in tests to preset the output behaviour
243 *
244 * @internal
245 * @param bool $plainTextOutput
246 */
247 public static function usePlainTextOutput($plainTextOutput)
248 {
249 static::$plainTextOutput = $plainTextOutput;
250 }
251
252 /**
253 * Preset ansi color usage
254 *
255 * Warning:
256 * This is NOT a public API method and must not be used in own extensions!
257 * This method is usually only used in tests to preset the ansi color usage
258 *
259 * @internal
260 * @param bool $ansiColorUsage
261 */
262 public static function useAnsiColor($ansiColorUsage)
263 {
264 static::$ansiColorUsage = $ansiColorUsage;
265 }
266 }