diff --git a/datamodels/2.x/itop-portal-base/portal/src/handlers/exceptionhandler.class.inc.php b/datamodels/2.x/itop-portal-base/portal/src/handlers/exceptionhandler.class.inc.php deleted file mode 100644 index 38aa53bd45..0000000000 --- a/datamodels/2.x/itop-portal-base/portal/src/handlers/exceptionhandler.class.inc.php +++ /dev/null @@ -1,225 +0,0 @@ - - -namespace Combodo\iTop\Portal\Handler; - -use \Exception; -use \Silex\Application; -use \Symfony\Component\Debug\ExceptionHandler as BaseExceptionHandler; -use \Symfony\Component\Debug\Exception\FlattenException; -use \Symfony\Component\HttpFoundation\Request; -use \IssueLog; -use \Dict; - -/** - * Extends the default ExceptionHandler to provide a better template. - * - * @author Guillaume Lajarige - */ -class ExceptionHandler extends BaseExceptionHandler -{ - private $debug; - private $charset; - private $handler; - private $caughtBuffer; - private $caughtLength; - private $fileLinkFormat; - - /** - * Sends a response for the given Exception. - * - * To be as fail-safe as possible, the exception is first handled - * by our simple exception handler, then by the user exception handler. - * The latter takes precedence and any output from the former is cancelled, - * if and only if nothing bad happens in this handling path. - */ - public function handle(\Exception $exception) - { - IssueLog::Error('Portal: '.$exception->getMessage()); - - parent::handle($exception); - } - - /** - * Gets the HTML content associated with the given exception. - * - * @param FlattenException $exception A FlattenException instance - * - * @return string The content as a string - */ - public function getContent(FlattenException $exception) - { - switch ($exception->getStatusCode()) { - case 404: - $title = Dict::S('Error:HTTP:404'); - break; - default: - $title = Dict::S('Error:HTTP:500'); - } - - $content = ''; - if ($this->debug) { - try { - $count = count($exception->getAllPrevious()); - $total = $count + 1; - foreach ($exception->toArray() as $position => $e) { - $ind = $count - $position + 1; - $class = $this->formatClass($e['class']); - $message = nl2br($this->escapeHtml($e['message'])); - $content .= sprintf(<< - %d/%d - %s%s: - %s - -
-
    - -EOF - , $ind, $total, $class, $this->formatPath($e['trace'][0]['file'], $e['trace'][0]['line']), $message); - foreach ($e['trace'] as $trace) { - $content .= '
  1. '; - if ($trace['function']) { - $content .= sprintf('at %s%s%s(%s)', $this->formatClass($trace['class']), $trace['type'], $trace['function'], $this->formatArgs($trace['args'])); - } - if (isset($trace['file']) && isset($trace['line'])) { - $content .= $this->formatPath($trace['file'], $trace['line']); - } - $content .= "
  2. \n"; - } - - $content .= "
\n
\n"; - } - } catch (\Exception $e) { - // something nasty happened and we cannot throw an exception anymore - if ($this->debug) { - $title = sprintf('Exception thrown when handling an exception (%s: %s)', get_class($e), $this->escapeHtml($e->getMessage())); - } else { - $title = 'Whoops, looks like something went wrong.'; - } - } - } - else{ - $content = $exception->getMessage(); - } - - return << -

$title

-
$content
- -EOF; - } - - /** - * Gets the stylesheet associated with the given exception. - * - * @param FlattenException $exception A FlattenException instance - * - * @return string The stylesheet as a string - */ - public function getStylesheet(FlattenException $exception) - { - $parentStylesheet = parent::getStylesheet($exception); - $stylesheet = <<%s', $class, array_pop($parts)); - } - - /** - * Note: Duplicated as the original one is private. - * - * Formats an array as a string. - * - * @param array $args The argument array - * - * @return string - */ - private function formatArgs(array $args) - { - $result = array(); - foreach ($args as $key => $item) { - if ('object' === $item[0]) { - $formattedValue = sprintf('object(%s)', $this->formatClass($item[1])); - } elseif ('array' === $item[0]) { - $formattedValue = sprintf('array(%s)', is_array($item[1]) ? $this->formatArgs($item[1]) : $item[1]); - } elseif ('string' === $item[0]) { - $formattedValue = sprintf("'%s'", $this->escapeHtml($item[1])); - } elseif ('null' === $item[0]) { - $formattedValue = 'null'; - } elseif ('boolean' === $item[0]) { - $formattedValue = ''.strtolower(var_export($item[1], true)).''; - } elseif ('resource' === $item[0]) { - $formattedValue = 'resource'; - } else { - $formattedValue = str_replace("\n", '', var_export($this->escapeHtml((string) $item[1]), true)); - } - - $result[] = is_int($key) ? $formattedValue : sprintf("'%s' => %s", $key, $formattedValue); - } - - return implode(', ', $result); - } - - /** - * Note: Duplicated as the original one is private. - * - * HTML-encodes a string. - */ - private function escapeHtml($str) - { - return htmlspecialchars($str, ENT_QUOTES | (PHP_VERSION_ID >= 50400 ? ENT_SUBSTITUTE : 0), $this->charset); - } - - /** - * Note: Duplicated as the original one is private. - * - * @param $path - * @param $line - * @return string - */ - private function formatPath($path, $line) - { - $path = $this->escapeHtml($path); - $file = preg_match('#[^/\\\\]*$#', $path, $file) ? $file[0] : $path; - - if ($linkFormat = $this->fileLinkFormat) { - $link = strtr($this->escapeHtml($linkFormat), array('%f' => $path, '%l' => (int) $line)); - - return sprintf(' in %s line %d', $link, $file, $line); - } - - return sprintf(' in %s line %d', $path, $file, $line); - } -} \ No newline at end of file diff --git a/datamodels/2.x/itop-portal-base/portal/src/helpers/applicationhelper.class.inc.php b/datamodels/2.x/itop-portal-base/portal/src/helpers/applicationhelper.class.inc.php index 33455a3677..0d8d980918 100644 --- a/datamodels/2.x/itop-portal-base/portal/src/helpers/applicationhelper.class.inc.php +++ b/datamodels/2.x/itop-portal-base/portal/src/helpers/applicationhelper.class.inc.php @@ -22,8 +22,7 @@ namespace Combodo\iTop\Portal\Helper; use \Exception; use \Silex\Application; use \Symfony\Component\Debug\ErrorHandler; -//use \Symfony\Component\Debug\ExceptionHandler; -use \Combodo\iTop\Portal\Handler\ExceptionHandler; +use \Symfony\Component\Debug\ExceptionHandler; use \Symfony\Component\HttpFoundation\Request; use \Twig_Environment; use \Twig_SimpleFilter; @@ -259,7 +258,7 @@ class ApplicationHelper ExceptionHandler::register(($oApp['debug'] === true)); // Intercepting manually aborted request - if (!$oApp['debug']) + if (1 || !$oApp['debug']) { $oApp->error(function(Exception $e, $code) use ($oApp) { @@ -288,6 +287,66 @@ class ApplicationHelper } else { + // Preparing debug trace + $aSteps = array(); + foreach($e->getTrace() as $aStep) + { + // - Default file name + if(!isset($aStep['file'])) + { + $aStep['file'] = ''; + } + $aFileParts = explode('\\', $aStep['file']); + // - Default line number + if(!isset($aStep['line'])) + { + $aStep['line'] = 'unknown'; + } + // - Default class name + if(isset($aStep['class']) && isset($aStep['function']) && isset($aStep['type'])) + { + $aClassParts = explode('\\', $aStep['class']); + $sClassName = $aClassParts[count($aClassParts)-1]; + $sClassFQ = $aStep['class']; + + $aArgsAsString = array(); + foreach($aStep['args'] as $arg) + { + if(is_array($arg)) + { + $aArgsAsString[] = 'array(...)'; + } + elseif(is_object($arg)) + { + $aArgsAsString[] = 'object('.get_class($arg).')'; + } + else + { + $aArgsAsString[] = $arg; + } + } + + $sFunctionCall = $sClassName . $aStep['type'] . $aStep['function'] . '(' . implode(', ', $aArgsAsString) . ')'; + } + else + { + $sClassName = null; + $sClassFQ = null; + $sFunctionCall = null; + } + + $aSteps[] = array( + 'file_fq' => $aStep['file'], + 'file_name' => $aFileParts[count($aFileParts)-1], + 'line' => $aStep['line'], + 'class_name' => $sClassName, + 'class_fq' => $sClassFQ, + 'function_call' => $sFunctionCall, + ); + } + + $aData['debug_trace_steps'] = $aSteps; + $oResponse = $oApp['twig']->render('itop-portal-base/portal/src/views/errors/layout.html.twig', $aData); } diff --git a/datamodels/2.x/itop-portal-base/portal/src/views/errors/layout.html.twig b/datamodels/2.x/itop-portal-base/portal/src/views/errors/layout.html.twig index f91ef82c51..e4aa61a46e 100644 --- a/datamodels/2.x/itop-portal-base/portal/src/views/errors/layout.html.twig +++ b/datamodels/2.x/itop-portal-base/portal/src/views/errors/layout.html.twig @@ -11,7 +11,8 @@ margin: 50px auto; text-align: center; padding: 25px; - max-width: 600px; + min-width: 600px; + max-width: 1000px; } h1, h2, h3, p { margin: 0; @@ -27,6 +28,12 @@ vertical-align: -5%; margin-right: 5px; } + abbr[title]{ + border-bottom: none; + } + .traces.list_exception{ + text-align: left; + } + + {% if app['debug'] == true %} +
+
    + {% for aStep in debug_trace_steps %} +
  1. + {% if aStep.function_call is not null %}at {{ aStep.function_call }}{% endif %} + in {{ aStep.file_name }} line {{ aStep.line }} +
  2. + {% endfor %} +
+
+ {% endif %} {% endblock %} \ No newline at end of file diff --git a/datamodels/2.x/itop-portal-base/portal/web/index.php b/datamodels/2.x/itop-portal-base/portal/web/index.php index d7d7b5e6ef..c23e4923a7 100644 --- a/datamodels/2.x/itop-portal-base/portal/web/index.php +++ b/datamodels/2.x/itop-portal-base/portal/web/index.php @@ -31,7 +31,6 @@ require_once APPROOT . '/core/moduledesign.class.inc.php'; require_once APPROOT . '/application/loginwebpage.class.inc.php'; require_once APPROOT . '/sources/autoload.php'; // Portal -require_once __DIR__ . '/../src/handlers/exceptionhandler.class.inc.php'; require_once __DIR__ . '/../src/providers/urlgeneratorserviceprovider.class.inc.php'; require_once __DIR__ . '/../src/helpers/urlgeneratorhelper.class.inc.php'; require_once __DIR__ . '/../src/providers/contextmanipulatorserviceprovider.class.inc.php';