[ Index ] |
PHP Cross Reference of Joomla 4.2.2 documentation |
[Summary view] [Print] [Text view]
1 <?php 2 3 /** 4 * Joomla! Content Management System 5 * 6 * @copyright (C) 2012 Open Source Matters, Inc. <https://www.joomla.org> 7 * @license GNU General Public License version 2 or later; see LICENSE.txt 8 */ 9 10 namespace Joomla\CMS\Exception; 11 12 use Joomla\CMS\Application\CMSApplication; 13 use Joomla\CMS\Error\AbstractRenderer; 14 use Joomla\CMS\Factory; 15 use Joomla\CMS\Log\Log; 16 17 // phpcs:disable PSR1.Files.SideEffects 18 \defined('JPATH_PLATFORM') or die; 19 // phpcs:enable PSR1.Files.SideEffects 20 21 /** 22 * Displays the custom error page when an uncaught exception occurs. 23 * 24 * @since 3.0 25 */ 26 class ExceptionHandler 27 { 28 /** 29 * Handles an error triggered with the E_USER_DEPRECATED level. 30 * 31 * @param integer $errorNumber The level of the raised error, represented by the E_* constants. 32 * @param string $errorMessage The error message. 33 * @param string $errorFile The file the error was triggered from. 34 * @param integer $errorLine The line number the error was triggered from. 35 * 36 * @return boolean 37 * 38 * @since 4.0.0 39 */ 40 public static function handleUserDeprecatedErrors(int $errorNumber, string $errorMessage, string $errorFile, int $errorLine): bool 41 { 42 // We only want to handle user deprecation messages, these will be triggered in code 43 if ($errorNumber === E_USER_DEPRECATED) { 44 try { 45 Log::add("$errorMessage - $errorFile - Line $errorLine", Log::WARNING, 'deprecated'); 46 } catch (\Exception $e) { 47 // Silence 48 } 49 50 // If debug mode is enabled, we want to let PHP continue to handle the error; otherwise, we can bail early 51 if (\defined('JDEBUG') && JDEBUG) { 52 return true; 53 } 54 } 55 56 // Always return false, this will tell PHP to handle the error internally 57 return false; 58 } 59 60 /** 61 * Handles exceptions: logs errors and renders error page. 62 * 63 * @param \Exception|\Throwable $error An Exception or Throwable (PHP 7+) object for which to render the error page. 64 * 65 * @return void 66 * 67 * @since 3.10.0 68 */ 69 public static function handleException(\Throwable $error) 70 { 71 static::logException($error); 72 static::render($error); 73 } 74 75 /** 76 * Render the error page based on an exception. 77 * 78 * @param \Throwable $error An Exception or Throwable (PHP 7+) object for which to render the error page. 79 * 80 * @return void 81 * 82 * @since 3.0 83 */ 84 public static function render(\Throwable $error) 85 { 86 try { 87 $app = Factory::getApplication(); 88 89 // Flag if we are on cli 90 $isCli = $app->isClient('cli'); 91 92 // If site is offline and it's a 404 error, just go to index (to see offline message, instead of 404) 93 if (!$isCli && $error->getCode() == '404' && $app->get('offline') == 1) { 94 $app->redirect('index.php'); 95 } 96 97 /* 98 * Try and determine the format to render the error page in 99 * 100 * First we check if a Document instance was registered to Factory and use the type from that if available 101 * If a type doesn't exist for that format, we try to use the format from the application's Input object 102 * Lastly, if all else fails, we default onto the HTML format to at least render something 103 */ 104 if (Factory::$document) { 105 $format = Factory::$document->getType(); 106 } else { 107 $format = $app->input->getString('format', 'html'); 108 } 109 110 try { 111 $renderer = AbstractRenderer::getRenderer($format); 112 } catch (\InvalidArgumentException $e) { 113 // Default to the HTML renderer 114 $renderer = AbstractRenderer::getRenderer('html'); 115 } 116 117 // Reset the document object in the factory, this gives us a clean slate and lets everything render properly 118 Factory::$document = $renderer->getDocument(); 119 Factory::getApplication()->loadDocument(Factory::$document); 120 121 $data = $renderer->render($error); 122 123 // If nothing was rendered, just use the message from the Exception 124 if (empty($data)) { 125 $data = $error->getMessage(); 126 } 127 128 if ($isCli) { 129 echo $data; 130 } else { 131 /** @var CMSApplication $app */ 132 133 // Do not allow cache 134 $app->allowCache(false); 135 136 $app->setBody($data); 137 } 138 139 // This return is needed to ensure the test suite does not trigger the non-Exception handling below 140 return; 141 } catch (\Throwable $errorRendererError) { 142 // Pass the error down 143 } 144 145 /* 146 * To reach this point in the code means there was an error creating the error page. 147 * 148 * Let global handler to handle the error, @see bootstrap.php 149 */ 150 if (isset($errorRendererError)) { 151 /* 152 * Here the thing, at this point we have 2 exceptions: 153 * $errorRendererError - the error caused by error renderer 154 * $error - the main error 155 * 156 * We need to show both exceptions, without loss of trace information, so use a bit of magic to merge them. 157 * 158 * Use exception nesting feature: rethrow the exceptions, an exception thrown in a finally block 159 * will take unhandled exception as previous. 160 * So PHP will add $error Exception as previous to $errorRendererError Exception to keep full error stack. 161 */ 162 try { 163 try { 164 throw $error; 165 } finally { 166 throw $errorRendererError; 167 } 168 } catch (\Throwable $finalError) { 169 throw $finalError; 170 } 171 } else { 172 throw $error; 173 } 174 } 175 176 /** 177 * Checks if given error belong to PHP exception class (\Throwable for PHP 7+, \Exception for PHP 5-). 178 * 179 * @param mixed $error Any error value. 180 * 181 * @return boolean 182 * 183 * @since 3.10.0 184 */ 185 protected static function isException($error) 186 { 187 return $error instanceof \Throwable; 188 } 189 190 /** 191 * Logs exception, catching all possible errors during logging. 192 * 193 * @param \Throwable $error An Exception or Throwable (PHP 7+) object to get error message from. 194 * 195 * @return void 196 * 197 * @since 3.10.0 198 */ 199 protected static function logException(\Throwable $error) 200 { 201 // Try to log the error, but don't let the logging cause a fatal error 202 try { 203 Log::add( 204 sprintf( 205 'Uncaught Throwable of type %1$s thrown with message "%2$s". Stack trace: %3$s', 206 \get_class($error), 207 $error->getMessage(), 208 $error->getTraceAsString() 209 ), 210 Log::CRITICAL, 211 'error' 212 ); 213 } catch (\Throwable $e) { 214 // Logging failed, don't make a stink about it though 215 } 216 } 217 }
title
Description
Body
title
Description
Body
title
Description
Body
title
Body
Generated: Wed Sep 7 05:41:13 2022 | Chilli.vc Blog - For Webmaster,Blog-Writer,System Admin and Domainer |