diff --git a/application/core/ErrorHandler.php b/application/core/ErrorHandler.php index c6c8fafc..9d365362 100644 --- a/application/core/ErrorHandler.php +++ b/application/core/ErrorHandler.php @@ -3,6 +3,7 @@ namespace ManiaControl; use ManiaControl\Files\FileUtil; +use ManiaControl\Plugins\PluginManager; use ManiaControl\Update\UpdateManager; /** @@ -51,7 +52,8 @@ class ErrorHandler { $message = "[ManiaControl EXCEPTION]: {$exception->getMessage()}"; $exceptionClass = get_class($exception); - $traceString = $exception->getTraceAsString(); + $sourceClass = null; + $traceString = $this->parseBackTrace($exception->getTrace(), $sourceClass); $logMessage = $message . PHP_EOL . 'Class: ' . $exceptionClass . PHP_EOL . 'Trace:' . PHP_EOL . $traceString; $this->maniaControl->log($logMessage); @@ -62,6 +64,8 @@ class ErrorHandler { $error['Message'] = $message; $error['Class'] = $exceptionClass; $error['FileLine'] = $exception->getFile() . ': ' . $exception->getLine(); + $error['SourceClass'] = $sourceClass; + $error['PluginId'] = PluginManager::getPluginId($sourceClass); $error['Backtrace'] = $traceString; $error['OperatingSystem'] = php_uname(); $error['PHPVersion'] = phpversion(); @@ -98,6 +102,72 @@ class ErrorHandler { } } + /** + * Parse the Debug Backtrace into a String for the Error Report + * + * @param array $backtrace + * @param string $sourceClass + * @return string + */ + private function parseBackTrace(array $backtrace, &$sourceClass = null) { + $traceString = ''; + $stepCount = 0; + foreach ($backtrace as $traceStep) { + $traceString .= PHP_EOL . '#' . $stepCount . ': '; + if (isset($traceStep['class'])) { + if (!$sourceClass) { + $sourceClass = $traceStep['class']; + } + $traceString .= $traceStep['class']; + } + if (isset($traceStep['type'])) { + $traceString .= $traceStep['type']; + } + if (isset($traceStep['function'])) { + $traceString .= $traceStep['function'] . '('; + if (isset($traceStep['args'])) { + $traceString .= $this->parseArgumentsArray($traceStep['args']); + } + $traceString .= ')'; + } + if (isset($traceStep['file'])) { + $traceString .= ' in File '; + $traceString .= $traceStep['file']; + } + if (isset($traceStep['line'])) { + $traceString .= ' on Line '; + $traceString .= $traceStep['line']; + } + $stepCount++; + } + return $traceString; + } + + /** + * Build a String from an Arguments Array + * + * @param array $args + * @return string + */ + private function parseArgumentsArray(array $args) { + $string = ''; + $argsCount = count($args); + foreach ($args as $index => $arg) { + if (is_object($arg)) { + $string .= 'object(' . get_class($arg) . ')'; + } else if (is_array($arg)) { + $string .= 'array(' . $this->parseArgumentsArray($arg) . ')'; + } else { + $type = gettype($arg); + $string .= $type . '(' . print_r($arg, true) . ')'; + } + if ($index < $argsCount - 1) { + $string .= ', '; + } + } + return $string; + } + /** * Test if ManiaControl should restart automatically * @@ -135,11 +205,12 @@ class ErrorHandler { return false; } - $errorTag = $this->getErrorTag($errorNumber); + $errorTag = $this->getErrorTag($errorNumber); + $sourceClass = null; $message = $errorTag . ': ' . $errorString; $fileLine = $errorFile . ': ' . $errorLine; - $traceString = $this->parseBackTrace(debug_backtrace()); + $traceString = $this->parseBackTrace(debug_backtrace(), $sourceClass); $logMessage = $message . PHP_EOL . 'File&Line: ' . $fileLine . PHP_EOL . 'Trace: ' . $traceString; $this->maniaControl->log($logMessage); @@ -149,6 +220,8 @@ class ErrorHandler { $error['Type'] = 'Error'; $error['Message'] = $message; $error['FileLine'] = $fileLine; + $error['SourceClass'] = $sourceClass; + $error['PluginId'] = PluginManager::getPluginId($sourceClass); $error['Backtrace'] = $traceString; $error['OperatingSystem'] = php_uname(); $error['PHPVersion'] = phpversion(); @@ -215,39 +288,6 @@ class ErrorHandler { return "[PHP ERROR '{$errorLevel}']"; } - /** - * Parse the Debug Backtrace into a String for the Error Report - * - * @param array $backtrace - * @return string - */ - private function parseBackTrace(array $backtrace) { - $traceString = ''; - $stepCount = 0; - foreach ($backtrace as $traceStep) { - $traceString .= PHP_EOL . '#' . $stepCount . ': '; - if (isset($traceStep['class'])) { - $traceString .= $traceStep['class']; - } - if (isset($traceStep['type'])) { - $traceString .= $traceStep['type']; - } - if (isset($traceStep['function'])) { - $traceString .= $traceStep['function']; - } - if (isset($traceStep['file'])) { - $traceString .= ' in File '; - $traceString .= $traceStep['file']; - } - if (isset($traceStep['line'])) { - $traceString .= ' on Line '; - $traceString .= $traceStep['line']; - } - $stepCount++; - } - return $traceString; - } - /** * Check if the given Error Number is a User Error * diff --git a/application/core/Plugins/PluginManager.php b/application/core/Plugins/PluginManager.php index 6043428a..2824935b 100644 --- a/application/core/Plugins/PluginManager.php +++ b/application/core/Plugins/PluginManager.php @@ -77,6 +77,50 @@ class PluginManager { return true; } + /** + * Get the Plugin Id if the given Class is a Plugin + * + * @param string $pluginClass + * @return int + */ + public static function getPluginId($pluginClass) { + if (self::isPluginClass($pluginClass)) { + /** @var Plugin $pluginClass */ + return $pluginClass::getId(); + } + return null; + } + + /** + * Check if the given class implements the plugin interface + * + * @param string $pluginClass + * @return bool + */ + public static function isPluginClass($pluginClass) { + $pluginClass = self::getClass($pluginClass); + if (!class_exists($pluginClass, false)) { + return false; + } + if (!in_array(Plugin::PLUGIN_INTERFACE, class_implements($pluginClass, false))) { + return false; + } + return true; + } + + /** + * Get the Class of the Object + * + * @param mixed $object + * @return string + */ + private static function getClass($object) { + if (is_object($object)) { + return get_class($object); + } + return (string)$object; + } + /** * Deactivate the Plugin with the given Class * @@ -133,36 +177,6 @@ class PluginManager { return $pluginClass; } - /** - * Get the Class of the Object - * - * @param mixed $object - * @return string - */ - private static function getClass($object) { - if (is_object($object)) { - return get_class($object); - } - return (string)$object; - } - - /** - * Check if the given class implements the plugin interface - * - * @param string $pluginClass - * @return bool - */ - public static function isPluginClass($pluginClass) { - $pluginClass = self::getClass($pluginClass); - if (!class_exists($pluginClass, false)) { - return false; - } - if (!in_array(Plugin::PLUGIN_INTERFACE, class_implements($pluginClass, false))) { - return false; - } - return true; - } - /** * Check if the Plugin is currently running *