.+\.(?:css|js))$'
=> 'CelerityResourceController',
),
);
}
public function buildRequest() {
$request = new AphrontRequest($this->getHost(), $this->getPath());
$request->setRequestData($_GET + $_POST);
$request->setApplicationConfiguration($this);
return $request;
}
public function handleException(Exception $ex) {
// Always log the unhandled exception.
phlog($ex);
$class = phutil_escape_html(get_class($ex));
$message = phutil_escape_html($ex->getMessage());
- $string = (string)$ex;
- $string = phutil_escape_html($string);
- $string = str_replace("\n", '
', $string);
+ if (PhabricatorEnv::getEnvConfig('phabricator.show-stack-traces')) {
+ $trace = $this->renderStackTrace($ex->getTrace());
+ } else {
+ $trace = null;
+ }
$content =
''.
- '
Unhandled Exception "'.$class.'": '.$message.'
'.
- '
'.$string.''.
+ '
'.$message.'
'.
+ $trace.
'
';
$user = $this->getRequest()->getUser();
if (!$user) {
// If we hit an exception very early, we won't have a user.
$user = new PhabricatorUser();
}
$dialog = new AphrontDialogView();
$dialog
- ->setTitle('Exception!')
+ ->setTitle('Unhandled Exception ("'.$class.'")')
->setClass('aphront-exception-dialog')
->setUser($user)
- ->appendChild($content)
- ->addCancelButton('/');
+ ->appendChild($content);
+
+ if ($this->getRequest()->isAjax()) {
+ $dialog->addCancelButton('/', 'Close');
+ }
$response = new AphrontDialogResponse();
$response->setDialog($dialog);
return $response;
}
public function willSendResponse(AphrontResponse $response) {
$request = $this->getRequest();
$response->setRequest($request);
if ($response instanceof AphrontDialogResponse) {
if (!$request->isAjax()) {
$view = new PhabricatorStandardPageView();
$view->setRequest($request);
$view->appendChild(
''.
$response->buildResponseString().
'
');
$response = new AphrontWebpageResponse();
$response->setContent($view->render());
return $response;
} else {
return id(new AphrontAjaxResponse())
->setContent(array(
'dialog' => $response->buildResponseString(),
));
}
} else if ($response instanceof AphrontRedirectResponse) {
if ($request->isAjax()) {
return id(new AphrontAjaxResponse())
->setContent(
array(
'redirect' => $response->getURI(),
));
}
} else if ($response instanceof Aphront404Response) {
$failure = new AphrontRequestFailureView();
$failure->setHeader('404 Not Found');
$failure->appendChild(
'The page you requested was not found.
');
$view = new PhabricatorStandardPageView();
$view->setTitle('404 Not Found');
$view->setRequest($this->getRequest());
$view->appendChild($failure);
$response = new AphrontWebpageResponse();
$response->setContent($view->render());
$response->setHTTPResponseCode(404);
return $response;
}
return $response;
}
public function build404Controller() {
return array(new Phabricator404Controller($this->getRequest()), array());
}
public function buildRedirectController($uri) {
return array(
new PhabricatorRedirectController($this->getRequest()),
array(
'uri' => $uri,
));
}
+ private function renderStackTrace($trace) {
+
+ $libraries = PhutilBootloader::getInstance()->getAllLibraries();
+
+ // TODO: Make this configurable?
+ $host = 'https://secure.phabricator.com';
+
+ $browse = array(
+ 'arcanist' =>
+ $host.'/diffusion/ARC/browse/origin:master/src/',
+ 'phutil' =>
+ $host.'/diffusion/PHU/browse/origin:master/src/',
+ 'phabricator' =>
+ $host.'/diffusion/P/browse/origin:master/src/',
+ );
+
+ $rows = array();
+ $depth = count($trace);
+ foreach ($trace as $part) {
+ $lib = null;
+ $file = $part['file'];
+ $relative = $file;
+ foreach ($libraries as $library) {
+ $root = phutil_get_library_root($library);
+ if (Filesystem::isDescendant($file, $root)) {
+ $lib = $library;
+ $relative = Filesystem::readablePath($file, $root);
+ break;
+ }
+ }
+
+ $where = '';
+ if (isset($part['class'])) {
+ $where .= $part['class'].'::';
+ }
+ if (isset($part['function'])) {
+ $where .= $part['function'].'()';
+ }
+
+ if (isset($browse[$lib])) {
+ $file_name = phutil_render_tag(
+ 'a',
+ array(
+ 'href' => $browse[$lib].$relative.'$'.$part['line'],
+ 'title' => $file,
+ 'target' => '_blank',
+ ),
+ phutil_escape_html($relative));
+ } else {
+ $file_name = phutil_render_tag(
+ 'span',
+ array(
+ 'title' => $file,
+ ),
+ phutil_escape_html($relative));
+ }
+ $file_name = $file_name.' : '.(int)$part['line'];
+
+
+ $rows[] = array(
+ $depth--,
+ phutil_escape_html($lib),
+ $file_name,
+ phutil_escape_html($where),
+ );
+ }
+ $table = new AphrontTableView($rows);
+ $table->setHeaders(
+ array(
+ 'Depth',
+ 'Library',
+ 'File',
+ 'Where',
+ ));
+ $table->setColumnClasses(
+ array(
+ 'n',
+ '',
+ '',
+ 'wide',
+ ));
+
+ return
+ ''.
+ ''.
+ $table->render().
+ '
';
+ }
+
}
diff --git a/src/aphront/default/configuration/__init__.php b/src/aphront/default/configuration/__init__.php
index 46cf91a597..9e2f375d92 100644
--- a/src/aphront/default/configuration/__init__.php
+++ b/src/aphront/default/configuration/__init__.php
@@ -1,26 +1,30 @@