], ApplicationEvents::AFTER_RESPOND => [ 'onAfterRespond', Priority::MIN, ], 'onAfterDisconnect' => 'onAfterDisconnect', ]; } /** * @param array $config An optional associative array of configuration settings. * @param CMSApplicationInterface $app The app * @param DatabaseInterface $db The db * * @since 1.5 */ public function __construct(array $config, CMSApplicationInterface $app, DatabaseInterface $db) { parent::__construct($config); $this->setApplication($app); $this->setDatabase($db); $app = $this->getApplication(); $this->debugLang = $app->get('debug_lang'); // Skip the plugin if debug is off if (!$this->debugLang && !$app->get('debug')) { return; } $app->set('gzip', false); ob_start(); ob_implicit_flush(false); /** @var \Joomla\Database\Monitor\DebugMonitor */ $this->queryMonitor = $this->getDatabase()->getMonitor(); if (!$this->params->get('queries', 1)) { // Remove the database driver monitor $this->getDatabase()->setMonitor(null); } $this->debugBar = new DebugBar(); // Check whether we want to track the request history for future use. if ($this->params->get('track_request_history', false)) { $storagePath = JPATH_CACHE . '/plg_system_debug_' . $app->getName(); $this->debugBar->setStorage(new FileStorage($storagePath)); } $this->debugBar->setHttpDriver(new JoomlaHttpDriver($app)); $this->isAjax = $app->getInput()->get('option') === 'com_ajax' && $app->getInput()->get('plugin') === 'debug' && $app->getInput()->get('group') === 'system'; $this->showLogs = (bool) $this->params->get('logs', true); // Log deprecated class aliases if ($this->showLogs && $app->get('log_deprecated')) { foreach (\JLoader::getDeprecatedAliases() as $deprecation) { Log::add( \sprintf( '%1$s has been aliased to %2$s and the former class name is deprecated. The alias will be removed in %3$s.', $deprecation['old'], $deprecation['new'], $deprecation['version'] ), Log::WARNING, 'deprecation-notes' ); } } } /** * Add an assets for debugger. * * @param BeforeCompileHeadEvent $event The event instance. * * @return void * * @since 4.0.0 */ public function onBeforeCompileHead(BeforeCompileHeadEvent $event): void { // Only if debugging or language debug is enabled. if ((JDEBUG || $this->debugLang) && $this->isAuthorisedDisplayDebug() && $this->getApplication()->getDocument() instanceof HtmlDocument) { // Use our own jQuery and fontawesome instead of the debug bar shipped version $assetManager = $this->getApplication()->getDocument()->getWebAssetManager(); $assetManager->registerAndUseStyle( 'plg.system.debug', 'plg_system_debug/debug.css', [], [], ['fontawesome'] ); $assetManager->registerAndUseScript( 'plg.system.debug', 'plg_system_debug/debug.min.js', [], ['defer' => true], ['jquery'] ); } // Disable asset media version if needed. if (JDEBUG && (int) $this->params->get('refresh_assets', 1) === 0) { $this->getApplication()->getDocument()->setMediaVersion(''); } } /** * Show the debug info. * * @param AfterRespondEvent|ApplicationEvent $event The event instance. * * @return void * * @since 1.6 */ public function onAfterRespond(AfterRespondEvent|ApplicationEvent $event): void { $endTime = microtime(true) - $this->timeInOnAfterDisconnect; $endMemory = memory_get_peak_usage(false); // Do not collect data if debugging or language debug is not enabled. if ((!JDEBUG && !$this->debugLang) || $this->isAjax) { return; } // User has to be authorised to see the debug information. if (!$this->isAuthorisedDisplayDebug()) { return; } // Load language. $this->loadLanguage(); $this->debugBar->addCollector(new InfoCollector($this->params, $this->debugBar->getCurrentRequestId())); $this->debugBar->addCollector(new UserCollector()); if (JDEBUG) { if ($this->params->get('memory', 1)) { $this->debugBar->addCollector(new MemoryCollector($this->params, $endMemory)); } if ($this->params->get('request', 1)) { $this->debugBar->addCollector(new RequestDataCollector()); } if ($this->params->get('session', 1)) { $this->debugBar->addCollector(new SessionCollector($this->params, true)); } if ($this->params->get('profile', 1)) { $this->debugBar->addCollector((new ProfileCollector($this->params))->setRequestEndTime($endTime)); } if ($this->params->get('queries', 1)) { // Remember session form token for possible future usage. $formToken = Session::getFormToken(); // Close session to collect possible session-related queries. $this->getApplication()->getSession()->close(); // Call $db->disconnect() here to trigger the onAfterDisconnect() method here in this class! $this->getDatabase()->disconnect(); $this->debugBar->addCollector(new QueryCollector($this->params, $this->queryMonitor, $this->sqlShowProfileEach, $this->explains)); } if ($this->showLogs) { $this->collectLogs(); } } if ($this->debugLang) { $this->debugBar->addCollector(new LanguageFilesCollector($this->params)); $this->debugBar->addCollector(new LanguageStringsCollector($this->params)); $this->debugBar->addCollector(new LanguageErrorsCollector($this->params)); } // Only render for HTML output. if (!($this->getApplication()->getDocument() instanceof HtmlDocument)) { $this->debugBar->stackData(); return; } $debugBarRenderer = new JavascriptRenderer($this->debugBar, Uri::root(true) . '/media/vendor/debugbar/'); if ($this->params->get('track_request_history', false)) { $openHandlerUrl = Uri::base(true) . '/index.php?option=com_ajax&plugin=debug&group=system&format=raw&action=openhandler'; $openHandlerUrl .= '&' . ($formToken ?? Session::getFormToken()) . '=1'; $debugBarRenderer->setOpenHandlerUrl($openHandlerUrl); } /** * @todo disable highlightjs from the DebugBar, import it through NPM * and deliver it through Joomla's API * Also every DebugBar script and stylesheet needs to use Joomla's API * $debugBarRenderer->disableVendor('highlightjs'); */ // Capture output. $contents = ob_get_contents(); if ($contents) { ob_end_clean(); } // No debug for Safari and Chrome redirection. if ( str_starts_with($contents, 'loadResult(); if ($hasProfiling) { // Run a SHOW PROFILE query. $db->setQuery('SHOW PROFILES'); $sqlShowProfiles = $db->loadAssocList(); if ($sqlShowProfiles) { foreach ($sqlShowProfiles as $qn) { // Run SHOW PROFILE FOR QUERY for each query where a profile is available (max 100). $db->setQuery('SHOW PROFILE FOR QUERY ' . (int) $qn['Query_ID']); $this->sqlShowProfileEach[$qn['Query_ID'] - 1] = $db->loadAssocList(); } } } else { $this->sqlShowProfileEach[0] = [['Error' => 'MySql have_profiling = off']]; } } catch (\Exception $e) { $this->sqlShowProfileEach[0] = [['Error' => $e->getMessage()]]; } } if ($this->params->get('query_explains') && \in_array($db->getServerType(), ['mysql', 'postgresql'], true)) { $logs = $this->queryMonitor->getLogs(); $boundParams = $this->queryMonitor->getBoundParams(); foreach ($logs as $k => $query) { $dbVersion56 = $db->getServerType() === 'mysql' && version_compare($db->getVersion(), '5.6', '>='); $dbVersion80 = $db->getServerType() === 'mysql' && version_compare($db->getVersion(), '8.0', '>='); if ($dbVersion80) { $dbVersion56 = false; } if ((stripos($query, 'select') === 0) || ($dbVersion56 && ((stripos($query, 'delete') === 0) || (stripos($query, 'update') === 0)))) { try { $queryInstance = $db->getQuery(true); $queryInstance->setQuery('EXPLAIN ' . ($dbVersion56 ? 'EXTENDED ' : '') . $query); if ($boundParams[$k]) { foreach ($boundParams[$k] as $key => $obj) { $queryInstance->bind($key, $obj->value, $obj->dataType, $obj->length, $obj->driverOptions); } } $this->explains[$k] = $db->setQuery($queryInstance)->loadAssocList(); } catch (\Exception $e) { $this->explains[$k] = [['error' => $e->getMessage()]]; } } } } $this->timeInOnAfterDisconnect = microtime(true) - $startTime; } /** * Store log messages so they can be displayed later. * This function is passed log entries by JLogLoggerCallback. * * @param LogEntry $entry A log entry. * * @return void * * @since 3.1 * * @deprecated 4.3 will be removed in 6.0 * Use \Joomla\CMS\Log\Log::add(LogEntry $entry) instead */ public function logger(LogEntry $entry) { if (!$this->showLogs) { return; } $this->logEntries[] = $entry; } /** * Collect log messages. * * @return void * * @since 4.0.0 */ private function collectLogs() { $loggerOptions = ['group' => 'default']; $logger = new InMemoryLogger($loggerOptions); $logEntries = $logger->getCollectedEntries(); if (!$this->logEntries && !$logEntries) { return; } if ($this->logEntries) { $logEntries = array_merge($logEntries, $this->logEntries); } $logDeprecated = $this->getApplication()->get('log_deprecated', 0); $logDeprecatedCore = $this->params->get('log-deprecated-core', 0); $this->debugBar->addCollector(new MessagesCollector('log')); if ($logDeprecated) { $this->debugBar->addCollector(new MessagesCollector('deprecated')); $this->debugBar->addCollector(new MessagesCollector('deprecation-notes')); } if ($logDeprecatedCore) { $this->debugBar->addCollector(new MessagesCollector('deprecated-core')); } foreach ($logEntries as $entry) { switch ($entry->category) { case 'deprecation-notes': if ($logDeprecated) { $this->debugBar[$entry->category]->addMessage($entry->message); } break; case 'deprecated': if (!$logDeprecated && !$logDeprecatedCore) { break; } $file = ''; $line = ''; // Find the caller, skip Log methods and trigger_error function foreach ($entry->callStack as $stackEntry) { if ( !empty($stackEntry['class']) && ($stackEntry['class'] === 'Joomla\CMS\Log\LogEntry' || $stackEntry['class'] === 'Joomla\CMS\Log\Log') ) { continue; } if ( empty($stackEntry['class']) && !empty($stackEntry['function']) && $stackEntry['function'] === 'trigger_error' ) { continue; } $file = $stackEntry['file'] ?? ''; $line = $stackEntry['line'] ?? ''; break; } $category = $entry->category; $relative = $file ? str_replace(JPATH_ROOT, '', $file) : ''; if ($relative && str_starts_with($relative, '/libraries/src')) { if (!$logDeprecatedCore) { break; } $category .= '-core'; } elseif (!$logDeprecated) { break; } $message = [ 'message' => $entry->message, 'caller' => $file . ':' . $line, // @todo 'stack' => $entry->callStack; ]; $this->debugBar[$category]->addMessage($message, 'warning'); break; case 'databasequery': // Should be collected by its own collector break; default: switch ($entry->priority) { case Log::EMERGENCY: case Log::ALERT: case Log::CRITICAL: case Log::ERROR: $level = 'error'; break; case Log::WARNING: $level = 'warning'; break; default: $level = 'info'; } $this->debugBar['log']->addMessage($entry->category . ' - ' . $entry->message, $level); break; } } } /** * Add server timing headers when profile is activated. * * @param BeforeRespondEvent $event The event instance. * * @return void * * @since 4.1.0 */ public function onBeforeRespond(BeforeRespondEvent $event): void { if (!JDEBUG || !$this->params->get('profile', 1)) { return; } $metrics = ''; $moduleTime = 0; $accessTime = 0; foreach (Profiler::getInstance('Application')->getMarks() as $index => $mark) { // Ignore the before mark as the after one contains the timing of the action if (stripos($mark->label, 'before') !== false) { continue; } // Collect the module render time if (str_contains($mark->label, 'mod_')) { $moduleTime += $mark->time; continue; } // Collect the access render time if (str_contains($mark->label, 'Access:')) { $accessTime += $mark->time; continue; } $desc = str_ireplace('after', '', $mark->label); $name = preg_replace('/[^\da-z]/i', '', $desc); $metrics .= \sprintf('%s;dur=%f;desc="%s", ', $index . $name, $mark->time, $desc); // Do not create too large headers, some web servers don't love them if (\strlen($metrics) > 3000) { $metrics .= 'System;dur=0;desc="Data truncated to 3000 characters", '; break; } } // Add the module entry $metrics .= 'Modules;dur=' . $moduleTime . ';desc="Modules", '; // Add the access entry $metrics .= 'Access;dur=' . $accessTime . ';desc="Access"'; $this->getApplication()->setHeader('Server-Timing', $metrics); } } 0 - Class "Joomla\Plugin\System\Debug\Extension\Debug" not found
0 - Class "Joomla\Plugin\System\Debug\Extension\Debug" not found

Die Seite kann nicht angezeigt werden, weil:

  1. ein veraltetes Lesezeichen aufgerufen wurde.
  2. über eine Suchmaschine ein veralteter Index dieser Website aufgerufen wurde.
  3. eine falsche Adresse aufgerufen wurde.
  4. keine Zugriffsrechte für diese Seite vorhanden sind.
  5. Die angefragte Quelle wurde nicht gefunden.
  6. Während der Anfrage ist ein Fehler aufgetreten.

Bitte eine der folgenden Seiten ausprobieren:

Bei Problemen ist der Administrator dieser Website zuständig.

Class "Joomla\Plugin\System\Debug\Extension\Debug" not found