ILIAS  release_5-1 Revision 5.0.0-5477-g43f3e3fab5f
PrettyPageHandler.php
Go to the documentation of this file.
1 <?php
7 namespace Whoops\Handler;
8 
14 
16 {
23  private $searchPaths = array();
24 
30  private $resourceCache = array();
31 
37  private $customCss = null;
38 
42  private $extraTables = array();
43 
47  private $handleUnconditionally = false;
48 
52  private $pageTitle = "Whoops! There was an error.";
53 
64  protected $editor;
65 
70  protected $editors = array(
71  "sublime" => "subl://open?url=file://%file&line=%line",
72  "textmate" => "txmt://open?url=file://%file&line=%line",
73  "emacs" => "emacs://open?url=file://%file&line=%line",
74  "macvim" => "mvim://open/?url=file://%file&line=%line",
75  );
76 
80  public function __construct()
81  {
82  if (ini_get('xdebug.file_link_format') || extension_loaded('xdebug')) {
83  // Register editor using xdebug's file_link_format option.
84  $this->editors['xdebug'] = function ($file, $line) {
85  return str_replace(array('%f', '%l'), array($file, $line), ini_get('xdebug.file_link_format'));
86  };
87  }
88 
89  // Add the default, local resource search path:
90  $this->searchPaths[] = __DIR__ . "/../Resources";
91  }
92 
96  public function handle()
97  {
98  if (!$this->handleUnconditionally()) {
99  // Check conditions for outputting HTML:
100  // @todo: Make this more robust
101  if (php_sapi_name() === 'cli') {
102  // Help users who have been relying on an internal test value
103  // fix their code to the proper method
104  if (isset($_ENV['whoops-test'])) {
105  throw new \Exception(
106  'Use handleUnconditionally instead of whoops-test'
107  .' environment variable'
108  );
109  }
110 
111  return Handler::DONE;
112  }
113  }
114 
115  // @todo: Make this more dynamic
116  $helper = new TemplateHelper();
117 
118  $templateFile = $this->getResource("views/layout.html.php");
119  $cssFile = $this->getResource("css/whoops.base.css");
120  $zeptoFile = $this->getResource("js/zepto.min.js");
121  $jsFile = $this->getResource("js/whoops.base.js");
122 
123  if ($this->customCss) {
124  $customCssFile = $this->getResource($this->customCss);
125  }
126 
127  $inspector = $this->getInspector();
128  $frames = $inspector->getFrames();
129 
130  $code = $inspector->getException()->getCode();
131 
132  if ($inspector->getException() instanceof \ErrorException) {
134  }
135 
136  // List of variables that will be passed to the layout template.
137  $vars = array(
138  "page_title" => $this->getPageTitle(),
139 
140  // @todo: Asset compiler
141  "stylesheet" => file_get_contents($cssFile),
142  "zepto" => file_get_contents($zeptoFile),
143  "javascript" => file_get_contents($jsFile),
144 
145  // Template paths:
146  "header" => $this->getResource("views/header.html.php"),
147  "frame_list" => $this->getResource("views/frame_list.html.php"),
148  "frame_code" => $this->getResource("views/frame_code.html.php"),
149  "env_details" => $this->getResource("views/env_details.html.php"),
150 
151  "title" => $this->getPageTitle(),
152  "name" => explode("\\", $inspector->getExceptionName()),
153  "message" => $inspector->getException()->getMessage(),
154  "code" => $code,
155  "plain_exception" => Formatter::formatExceptionPlain($inspector),
156  "frames" => $frames,
157  "has_frames" => !!count($frames),
158  "handler" => $this,
159  "handlers" => $this->getRun()->getHandlers(),
160 
161  "tables" => array(
162  "Server/Request Data" => $_SERVER,
163  "GET Data" => $_GET,
164  "POST Data" => $_POST,
165  "Files" => $_FILES,
166  "Cookies" => $_COOKIE,
167  "Session" => isset($_SESSION) ? $_SESSION : array(),
168  "Environment Variables" => $_ENV,
169  ),
170  );
171 
172  if (isset($customCssFile)) {
173  $vars["stylesheet"] .= file_get_contents($customCssFile);
174  }
175 
176  // Add extra entries list of data tables:
177  // @todo: Consolidate addDataTable and addDataTableCallback
178  $extraTables = array_map(function ($table) {
179  return $table instanceof \Closure ? $table() : $table;
180  }, $this->getDataTables());
181  $vars["tables"] = array_merge($extraTables, $vars["tables"]);
182 
183  $helper->setVariables($vars);
184  $helper->render($templateFile);
185 
186  return Handler::QUIT;
187  }
188 
196  public function addDataTable($label, array $data)
197  {
198  $this->extraTables[$label] = $data;
199  }
200 
211  public function addDataTableCallback($label, /* callable */ $callback)
212  {
213  if (!is_callable($callback)) {
214  throw new InvalidArgumentException('Expecting callback argument to be callable');
215  }
216 
217  $this->extraTables[$label] = function () use ($callback) {
218  try {
219  $result = call_user_func($callback);
220 
221  // Only return the result if it can be iterated over by foreach().
222  return is_array($result) || $result instanceof \Traversable ? $result : array();
223  } catch (\Exception $e) {
224  // Don't allow failure to break the rendering of the original exception.
225  return array();
226  }
227  };
228  }
229 
237  public function getDataTables($label = null)
238  {
239  if ($label !== null) {
240  return isset($this->extraTables[$label]) ?
241  $this->extraTables[$label] : array();
242  }
243 
244  return $this->extraTables;
245  }
246 
254  public function handleUnconditionally($value = null)
255  {
256  if (func_num_args() == 0) {
258  }
259 
260  $this->handleUnconditionally = (bool) $value;
261  }
262 
279  public function addEditor($identifier, $resolver)
280  {
281  $this->editors[$identifier] = $resolver;
282  }
283 
298  public function setEditor($editor)
299  {
300  if (!is_callable($editor) && !isset($this->editors[$editor])) {
301  throw new InvalidArgumentException(
302  "Unknown editor identifier: $editor. Known editors:" .
303  implode(",", array_keys($this->editors))
304  );
305  }
306 
307  $this->editor = $editor;
308  }
309 
321  public function getEditorHref($filePath, $line)
322  {
323  if ($this->editor === null) {
324  return false;
325  }
326 
328  if (is_string($editor)) {
329  $editor = $this->editors[$editor];
330  }
331 
332  if (is_callable($editor)) {
333  $editor = call_user_func($editor, $filePath, $line);
334  }
335 
336  // Check that the editor is a string, and replace the
337  // %line and %file placeholders:
338  if (!is_string($editor)) {
339  throw new InvalidArgumentException(
340  __METHOD__ . " should always resolve to a string; got something else instead"
341  );
342  }
343 
344  $editor = str_replace("%line", rawurlencode($line), $editor);
345  $editor = str_replace("%file", rawurlencode($filePath), $editor);
346 
347  return $editor;
348  }
349 
354  public function setPageTitle($title)
355  {
356  $this->pageTitle = (string) $title;
357  }
358 
362  public function getPageTitle()
363  {
364  return $this->pageTitle;
365  }
366 
376  public function addResourcePath($path)
377  {
378  if (!is_dir($path)) {
379  throw new InvalidArgumentException(
380  "'$path' is not a valid directory"
381  );
382  }
383 
384  array_unshift($this->searchPaths, $path);
385  }
386 
393  public function addCustomCss($name)
394  {
395  $this->customCss = $name;
396  }
397 
401  public function getResourcePaths()
402  {
403  return $this->searchPaths;
404  }
405 
417  protected function getResource($resource)
418  {
419  // If the resource was found before, we can speed things up
420  // by caching its absolute, resolved path:
421  if (isset($this->resourceCache[$resource])) {
422  return $this->resourceCache[$resource];
423  }
424 
425  // Search through available search paths, until we find the
426  // resource we're after:
427  foreach ($this->searchPaths as $path) {
428  $fullPath = $path . "/$resource";
429 
430  if (is_file($fullPath)) {
431  // Cache the result:
432  $this->resourceCache[$resource] = $fullPath;
433  return $fullPath;
434  }
435  }
436 
437  // If we got this far, nothing was found.
438  throw new RuntimeException(
439  "Could not find resource '$resource' in any resource paths."
440  . "(searched: " . join(", ", $this->searchPaths). ")"
441  );
442  }
443 
449  public function getResourcesPath()
450  {
451  $allPaths = $this->getResourcePaths();
452 
453  // Compat: return only the first path added
454  return end($allPaths) ?: null;
455  }
456 
463  public function setResourcesPath($resourcesPath)
464  {
465  $this->addResourcePath($resourcesPath);
466  }
467 }
print $file
if((!isset($_SERVER['DOCUMENT_ROOT'])) OR(empty($_SERVER['DOCUMENT_ROOT']))) $_SERVER['DOCUMENT_ROOT']
$_POST['username']
Definition: cron.php:12
$_SESSION["AccountId"]
$result
static translateErrorCode($error_code)
Translate ErrorException code into the represented constant.
Definition: Misc.php:32
$_GET["client_id"]
$code
Definition: example_050.php:99
Exposes useful tools for working with/in templates.
Whoops - php errors for cool kids.
$_COOKIE["ilClientId"]
Definition: cron.php:11
addResourcePath($path)
Adds a path to the list of paths to be searched for resources.
addEditor($identifier, $resolver)
handleUnconditionally($value=null)
Allows to disable all attempts to dynamically decide whether to handle or return prematurely.
getDataTables($label=null)
Returns all the extra data tables registered with this handler.
addDataTableCallback($label, $callback)
Lazily adds an entry to the list of tables displayed in the table.
$data
addDataTable($label, array $data)
Adds an entry to the list of tables displayed in the template.
const DONE
Return constants that can be returned from Handler::handle to message the handler walker...
Definition: Handler.php:22
static formatExceptionPlain(Inspector $inspector)
Definition: Formatter.php:50
getResource($resource)
Finds a resource, by its relative path, in all available search paths.
getEditorHref($filePath, $line)
Given a string file path, and an integer file line, executes the editor resolver and returns...
Abstract implementation of a Handler.
Definition: Handler.php:16
addCustomCss($name)
Adds a custom css file to be loaded.
$path
Definition: index.php:22