Debug.php 5.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189
  1. <?php
  2. /**
  3. * Copyright © Magento, Inc. All rights reserved.
  4. * See COPYING.txt for license details.
  5. */
  6. namespace Magento\Framework;
  7. /**
  8. * Magento Debug methods
  9. */
  10. class Debug
  11. {
  12. /**
  13. * @var int
  14. */
  15. public static $argLength = 16;
  16. /**
  17. * Magento Root path
  18. *
  19. * @var string
  20. */
  21. protected static $_filePath;
  22. /**
  23. * Retrieve real root path with last directory separator
  24. *
  25. * @return string
  26. */
  27. public static function getRootPath()
  28. {
  29. if (self::$_filePath === null) {
  30. if (defined('BP')) {
  31. self::$_filePath = BP;
  32. } else {
  33. self::$_filePath = dirname(__DIR__);
  34. }
  35. }
  36. return self::$_filePath;
  37. }
  38. /**
  39. * Prints or returns a backtrace
  40. *
  41. * @param bool $return return or print
  42. * @param bool $html output in HTML format
  43. * @param bool $withArgs add short arguments of methods
  44. * @return string|bool
  45. */
  46. public static function backtrace($return = false, $html = true, $withArgs = true)
  47. {
  48. $trace = debug_backtrace();
  49. return self::trace($trace, $return, $html, $withArgs);
  50. }
  51. /**
  52. * Prints or return a trace
  53. *
  54. * @param array $trace trace array
  55. * @param bool $return return or print
  56. * @param bool $html output in HTML format
  57. * @param bool $withArgs add short arguments of methods
  58. * @return string|bool
  59. * @SuppressWarnings(PHPMD.CyclomaticComplexity)
  60. * @SuppressWarnings(PHPMD.NPathComplexity)
  61. */
  62. public static function trace(array $trace, $return = false, $html = true, $withArgs = true)
  63. {
  64. $out = '';
  65. if ($html) {
  66. $out .= '<pre>';
  67. }
  68. foreach ($trace as $i => $data) {
  69. // skip self
  70. if ($i == 0) {
  71. continue;
  72. }
  73. // prepare method arguments
  74. $args = [];
  75. if (isset($data['args']) && $withArgs) {
  76. foreach ($data['args'] as $arg) {
  77. $args[] = self::_formatCalledArgument($arg);
  78. }
  79. }
  80. // prepare method's name
  81. if (isset($data['class']) && isset($data['function'])) {
  82. if (isset($data['object']) && get_class($data['object']) != $data['class']) {
  83. $className = get_class($data['object']) . '[' . $data['class'] . ']';
  84. } else {
  85. $className = $data['class'];
  86. }
  87. if (isset($data['object'])) {
  88. $className .= sprintf('#%s#', spl_object_hash($data['object']));
  89. }
  90. $methodName = sprintf(
  91. '%s%s%s(%s)',
  92. $className,
  93. isset($data['type']) ? $data['type'] : '->',
  94. $data['function'],
  95. join(', ', $args)
  96. );
  97. } elseif (isset($data['function'])) {
  98. $methodName = sprintf('%s(%s)', $data['function'], join(', ', $args));
  99. }
  100. if (isset($data['file'])) {
  101. $pos = strpos($data['file'], self::getRootPath());
  102. if ($pos !== false) {
  103. $data['file'] = substr($data['file'], strlen(self::getRootPath()) + 1);
  104. }
  105. $fileName = sprintf('%s:%d', $data['file'], $data['line']);
  106. } else {
  107. $fileName = false;
  108. }
  109. if ($fileName) {
  110. $out .= sprintf('#%d %s called at [%s]', $i, $methodName, $fileName);
  111. } else {
  112. $out .= sprintf('#%d %s', $i, $methodName);
  113. }
  114. $out .= "\n";
  115. }
  116. if ($html) {
  117. $out .= '</pre>';
  118. }
  119. if ($return) {
  120. return $out;
  121. } else {
  122. echo $out;
  123. return true;
  124. }
  125. }
  126. /**
  127. * Format argument in called method
  128. *
  129. * @param mixed $arg
  130. * @return string
  131. * @SuppressWarnings(PHPMD.CyclomaticComplexity)
  132. */
  133. protected static function _formatCalledArgument($arg)
  134. {
  135. $out = '';
  136. if (is_object($arg)) {
  137. $out .= sprintf("&%s#%s#", get_class($arg), spl_object_hash($arg));
  138. } elseif (is_resource($arg)) {
  139. $out .= '#[' . get_resource_type($arg) . ']';
  140. } elseif (is_array($arg)) {
  141. $isAssociative = false;
  142. $args = [];
  143. foreach ($arg as $k => $v) {
  144. if (!is_numeric($k)) {
  145. $isAssociative = true;
  146. }
  147. $args[$k] = self::_formatCalledArgument($v);
  148. }
  149. if ($isAssociative) {
  150. $arr = [];
  151. foreach ($args as $k => $v) {
  152. $arr[] = self::_formatCalledArgument($k) . ' => ' . $v;
  153. }
  154. $out .= 'array(' . join(', ', $arr) . ')';
  155. } else {
  156. $out .= 'array(' . join(', ', $args) . ')';
  157. }
  158. } elseif ($arg === null) {
  159. $out .= 'NULL';
  160. } elseif (is_numeric($arg) || is_float($arg)) {
  161. $out .= $arg;
  162. } elseif (is_string($arg)) {
  163. if (strlen($arg) > self::$argLength) {
  164. $arg = substr($arg, 0, self::$argLength) . "...";
  165. }
  166. $arg = strtr($arg, ["\t" => '\t', "\r" => '\r', "\n" => '\n', "'" => '\\\'']);
  167. $out .= "'" . $arg . "'";
  168. } elseif (is_bool($arg)) {
  169. $out .= $arg === true ? 'true' : 'false';
  170. }
  171. return $out;
  172. }
  173. }