Compare commits

..

20 Commits

Author SHA1 Message Date
Daniel Seifert 81acc92151
fix shop dependency 2023-01-04 09:00:48 +01:00
Daniel Seifert 0c79c1c77a
fix typo 2023-01-03 15:53:36 +01:00
Daniel Seifert da26d03d58
Merge remote-tracking branch 'remotes/origin/dev_1.x_65' into rel_1.x 2023-01-03 15:44:17 +01:00
Daniel Seifert b1897c8ecf
adjust version informations 2023-01-03 15:41:57 +01:00
Daniel Seifert 09608bfd91
make installable in OXID 6.5.1 (CE 6.13) 2022-12-13 14:24:44 +01:00
Daniel Seifert 4c21a850d8
check for not existing controller function 2022-10-06 14:20:01 +02:00
Daniel Seifert a9c1863a8e
make installable in OXID CE 6.12 2022-08-19 23:17:30 +02:00
Daniel Seifert 75146c8a08
add option to show DebugBar only if logged in user is an admin user 2022-08-17 15:23:06 +02:00
Daniel Seifert 6eb4c213b9
cleanup code 2022-08-16 11:42:25 +02:00
Daniel Seifert 922d26d3ac
catch all possible exceptions and errors 2022-08-16 11:08:05 +02:00
Daniel Seifert 88b6a1d6fa
throw error type dependend exceptions 2022-08-16 00:18:25 +02:00
Daniel Seifert 236680ad7a
throw error exceptions on error levels only 2022-08-15 23:40:50 +02:00
Daniel Seifert ff606efef3
fix not existing component issue in admin panels login controller 2022-08-15 15:44:51 +02:00
Daniel Seifert 4b47e5ddb6
show warning on activation if asset files doesn't exist 2022-08-14 23:13:06 +02:00
Daniel Seifert 154a28f118
remove extra config item for current theme
it will displayed in shop tab
2022-08-14 01:08:52 +02:00
Daniel Seifert c892b3bd03
collect unhandled exceptions, errors from Smarty and PHP 2022-08-14 01:08:02 +02:00
Daniel Seifert a87bc1d9bd
add ToDo 2022-08-08 10:37:51 +02:00
Daniel Seifert 8cba6428ed
adjust documentation, add todo list 2022-08-05 09:41:07 +02:00
Daniel Seifert ef66dd22cb
remove useless exceptions tab 2022-08-05 09:23:48 +02:00
Daniel Seifert c1888bde70
add OXID version informations 2022-08-04 22:33:08 +02:00
30 changed files with 1056 additions and 67 deletions

View File

@ -15,14 +15,24 @@ declare(strict_types=1);
namespace D3\DebugBar\Application\Component;
use D3\DebugBar\Application\Models\AvailabilityCheck;
use D3\DebugBar\Application\Models\Collectors\OxidConfigCollector;
use D3\DebugBar\Application\Models\Collectors\OxidShopCollector;
use D3\DebugBar\Application\Models\Collectors\OxidVersionCollector;
use D3\DebugBar\Application\Models\Collectors\SmartyCollector;
use D3\DebugBar\Application\Models\Exceptions\UnavailableException;
use D3\DebugBar\Application\Models\TimeDataCollectorHandler;
use DebugBar\Bridge\DoctrineCollector;
use DebugBar\Bridge\MonologCollector;
use DebugBar\DataCollector\ExceptionsCollector;
use DebugBar\DataCollector\MemoryCollector;
use DebugBar\DataCollector\MessagesCollector;
use DebugBar\DataCollector\PhpInfoCollector;
use DebugBar\DataCollector\RequestDataCollector;
use DebugBar\DataCollector\TimeDataCollector;
use DebugBar\DebugBar;
use DebugBar\DebugBarException;
use DebugBar\JavascriptRenderer;
use DebugBar\StandardDebugBar;
use Doctrine\DBAL\Connection;
use Doctrine\DBAL\Logging\DebugStack;
use Monolog\Logger;
@ -35,8 +45,8 @@ use ReflectionException;
class DebugBarComponent extends BaseController
{
/** @var StandardDebugBar */
protected $debugBar;
/** @var DebugBar|null */
protected $debugBar = null;
/** @var JavascriptRenderer */
protected $debugBarRenderer;
@ -55,8 +65,8 @@ class DebugBarComponent extends BaseController
{
parent::__construct();
if (false === isAdmin()) {
$debugbar = new StandardDebugBar();
if (AvailabilityCheck::isAvailable()) {
$debugbar = new DebugBar();
$this->addCollectors($debugbar);
@ -102,6 +112,14 @@ class DebugBarComponent extends BaseController
return new SmartyCollector($smarty);
}
/**
* @return OxidShopCollector
*/
public function getOxidShopCollector(): OxidShopCollector
{
return oxNew(OxidShopCollector::class);
}
/**
* @return OxidConfigCollector
*/
@ -110,6 +128,14 @@ class DebugBarComponent extends BaseController
return oxNew(OxidConfigCollector::class, Registry::getConfig());
}
/**
* @return OxidVersionCollector
*/
public function getOxidVersionCollector(): OxidVersionCollector
{
return oxNew(OxidVersionCollector::class);
}
/**
* @param object $object
* @param string $propName
@ -126,18 +152,29 @@ class DebugBarComponent extends BaseController
}
/**
* @param StandardDebugBar $debugbar
* @param DebugBar $debugbar
* @return void
* @throws DatabaseConnectionException
* @throws DebugBarException
* @throws ReflectionException
*/
public function addCollectors(StandardDebugBar $debugbar): void
public function addCollectors(DebugBar $debugbar): void
{
// add all default collectors except the useless ExceptionCollector
$debugbar->addCollector(new PhpInfoCollector());
$debugbar->addCollector(new MessagesCollector());
$debugbar->addCollector(new RequestDataCollector());
$debugbar->addCollector(new TimeDataCollector());
$debugbar->addCollector(new MemoryCollector());
$debugbar->addCollector(new ExceptionsCollector());
// add custom collectors
$debugbar->addCollector($this->getOxidShopCollector());
$debugbar->addCollector($this->getOxidConfigCollector());
$debugbar->addCollector($this->getSmartyCollector());
$debugbar->addCollector($this->getMonologCollector());
$debugbar->addCollector($this->getDoctrineCollector());
$debugbar->addCollector($this->getSmartyCollector());
$debugbar->addCollector($this->getOxidConfigCollector());
$debugbar->addCollector($this->getOxidVersionCollector());
}
/**
@ -145,6 +182,10 @@ class DebugBarComponent extends BaseController
*/
public function addTimelineMessures(): void
{
if (false === $this->debugBar instanceof DebugBar) {
throw new UnavailableException();
}
$collectors = $this->debugBar->getCollectors();
$collectors['time'] = TimeDataCollectorHandler::getInstance();
@ -155,10 +196,15 @@ class DebugBarComponent extends BaseController
}
/**
* @return StandardDebugBar
* @return DebugBar
* @throws UnavailableException
*/
public function getDebugBar(): StandardDebugBar
public function getDebugBar(): DebugBar
{
if (false === $this->debugBar instanceof DebugBar) {
throw new UnavailableException();
}
return $this->debugBar;
}

View File

@ -0,0 +1,83 @@
<?php
/**
* For the full copyright and license information, please view the LICENSE
* file that was distributed with this source code.
*
* https://www.d3data.de
*
* @copyright (C) D3 Data Development (Inh. Thomas Dartsch)
* @author D3 Data Development - Daniel Seifert <info@shopmodule.com>
* @link https://www.oxidmodule.com
*/
declare(strict_types=1);
namespace D3\DebugBar\Application\Models;
use OxidEsales\Eshop\Application\Model\User;
use OxidEsales\Eshop\Core\Registry;
class AvailabilityCheck
{
/**
* @return bool
*/
public static function isAvailable(): bool
{
return !isAdmin() && (
Registry::getConfig()->getShopConfVar('d3debugbar_showForAdminUsersOnly') != true ||
self::userIsMallAdmin()
);
}
/**
* @return bool
*/
public static function userIsMallAdmin(): bool
{
$user = Registry::getConfig()->getUser();
return $user != null &&
$user->isMallAdmin();
}
/**
* @return bool
*/
public static function ifDebugBarNotSet(): bool
{
global $debugBarSet;
return $debugBarSet !== 1;
}
/**
* @return void
*/
public static function markDebugBarAsSet(): void
{
global $debugBarSet;
$debugBarSet = 1;
}
/**
* @return bool
*/
public static function ifNoErrorOccured(): bool
{
global $debugBarErrorOccured;
return $debugBarErrorOccured !== 1;
}
/**
* @return void
*/
public static function markErrorOccured(): void
{
global $debugBarErrorOccured;
$debugBarErrorOccured = 1;
}
}

View File

@ -36,6 +36,11 @@ class OxidConfigCollector extends DataCollector implements Renderable
*/
protected $useHtmlVarDumper = false;
/**
* @param Config $config
*
* @throws ReflectionException
*/
public function __construct(Config $config)
{
$config->init();
@ -111,9 +116,9 @@ class OxidConfigCollector extends DataCollector implements Renderable
* Indicates whether the Symfony HtmlDumper will be used to dump variables for rich variable
* rendering.
*
* @return mixed
* @return bool
*/
public function isHtmlVarDumperUsed()
public function isHtmlVarDumperUsed(): bool
{
return $this->useHtmlVarDumper;
}
@ -128,7 +133,7 @@ class OxidConfigCollector extends DataCollector implements Renderable
: "PhpDebugBar.Widgets.VariableListWidget";
return [
"Configuration" => [
"icon" => "tags",
"icon" => "database",
"widget" => $widget,
"map" => "oxidconfig.vars",
"default" => "{}",

View File

@ -0,0 +1,161 @@
<?php
/**
* For the full copyright and license information, please view the LICENSE
* file that was distributed with this source code.
*
* https://www.d3data.de
*
* @copyright (C) D3 Data Development (Inh. Thomas Dartsch)
* @author D3 Data Development - Daniel Seifert <info@shopmodule.com>
* @link https://www.oxidmodule.com
*/
declare(strict_types=1);
namespace D3\DebugBar\Application\Models\Collectors;
use Composer\InstalledVersions;
use DebugBar\DataCollector\DataCollector;
use DebugBar\DataCollector\Renderable;
use Exception;
use OxidEsales\Eshop\Core\Config;
use OxidEsales\Eshop\Core\Module\Module;
use OxidEsales\Eshop\Core\ShopVersion;
use OxidEsales\Eshop\Core\Theme;
use OxidEsales\EshopCommunity\Internal\Container\ContainerFactory;
use OxidEsales\EshopCommunity\Internal\Framework\Module\Configuration\Bridge\ShopConfigurationDaoBridge;
use OxidEsales\EshopCommunity\Internal\Framework\Module\Configuration\Bridge\ShopConfigurationDaoBridgeInterface;
use OxidEsales\Facts\Facts;
use Psr\Container\ContainerExceptionInterface;
use Psr\Container\NotFoundExceptionInterface;
class OxidShopCollector extends DataCollector implements Renderable
{
/** @var Config */
protected $config;
/** @var array */
protected $configVars = [];
/**
* @var bool
*/
protected $useHtmlVarDumper = true;
/**
* @throws ContainerExceptionInterface
* @throws NotFoundExceptionInterface
* @throws Exception
*/
public function __construct()
{
$facts = new Facts();
$theme = new Theme();
/** @var Theme|null $parent */
$parent = $theme->getParent();
$parentThemeId = $parent ? $parent->getId() : '--';
$moduleList = $this->getInstalledModules();
array_walk(
$moduleList,
function (Module &$module) {
$str = trim(strip_tags($module->getTitle())).' - '.$module->getInfo('version').' ';
$module = $str;
}
);
$this->configVars = [
'Shop Edition:' => $facts->getEdition(),
'Shop Version:' => ShopVersion::getVersion(),
'CE Version:' => InstalledVersions::getVersion('oxid-esales/oxideshop-ce'),
'Theme:' => $theme->getActiveThemeId(),
'Parent Theme:' => $parentThemeId,
'Modules:' => implode(chr(10), $moduleList),
];
}
/**
* @return string
*/
public function getName(): string
{
return 'oxidshop';
}
/**
* @return array
*/
public function collect(): array
{
$data = [];
$vars = $this->configVars;
foreach ($vars as $idx => $var) {
if ($this->isHtmlVarDumperUsed()) {
$data[$idx] = $this->getVarDumper()->renderVar($var);
} else {
$data[$idx] = $this->getDataFormatter()->formatVar($var);
}
}
return ['vars' => $data, 'count' => count($data)];
}
/**
* Indicates whether the Symfony HtmlDumper will be used to dump variables for rich variable
* rendering.
*
* @return bool
*/
public function isHtmlVarDumperUsed(): bool
{
return $this->useHtmlVarDumper;
}
/**
* @return array
*/
public function getWidgets(): array
{
$widget = $this->isHtmlVarDumperUsed()
? "PhpDebugBar.Widgets.HtmlVariableListWidget"
: "PhpDebugBar.Widgets.VariableListWidget";
return [
"Shop" => [
"icon" => "shopping-cart",
"widget" => $widget,
"map" => $this->getName().".vars",
"default" => "{}",
],
];
}
/**
* @return array
* @throws ContainerExceptionInterface
* @throws NotFoundExceptionInterface
*/
protected function getInstalledModules(): array
{
$container = ContainerFactory::getInstance()->getContainer();
/** @var ShopConfigurationDaoBridge $shopConfigurationDaoBridge */
$shopConfigurationDaoBridge = $container->get(ShopConfigurationDaoBridgeInterface::class);
$shopConfiguration = $shopConfigurationDaoBridge->get();
$modules = [];
foreach ($shopConfiguration->getModuleConfigurations() as $moduleConfiguration) {
$module = oxNew(Module::class);
$module->load($moduleConfiguration->getId());
$modules[] = $module;
}
usort($modules, function ($a, $b) {
return strcmp($a->getTitle(), $b->getTitle());
});
return $modules;
}
}

View File

@ -0,0 +1,64 @@
<?php
/**
* For the full copyright and license information, please view the LICENSE
* file that was distributed with this source code.
*
* https://www.d3data.de
*
* @copyright (C) D3 Data Development (Inh. Thomas Dartsch)
* @author D3 Data Development - Daniel Seifert <info@shopmodule.com>
* @link https://www.oxidmodule.com
*/
declare(strict_types=1);
namespace D3\DebugBar\Application\Models\Collectors;
use DebugBar\DataCollector\DataCollector;
use DebugBar\DataCollector\Renderable;
use Exception;
use OxidEsales\Eshop\Core\ShopVersion;
use OxidEsales\Facts\Facts;
/**
* Collects info about OXID shop
*/
class OxidVersionCollector extends DataCollector implements Renderable
{
/**
* @return string
*/
public function getName(): string
{
return 'oxidversion';
}
/**
* @return array
* @throws Exception
*/
public function collect(): array
{
$facts = new Facts();
return [
'version' => $facts->getEdition().' '.ShopVersion::getVersion(),
];
}
/**
* @return string[][]
*/
public function getWidgets(): array
{
return [
"oxidversion" => [
"icon" => "shopping-cart",
"tooltip" => 'OXID Version',
"map" => $this->getName().".version",
"default" => "",
],
];
}
}

View File

@ -6,6 +6,7 @@
*
* https://www.d3data.de
*
* @copyright (c) 2016 Dmitry Kosenkov
* @copyright (C) D3 Data Development (Inh. Thomas Dartsch)
* @author D3 Data Development - Daniel Seifert <info@shopmodule.com>
* @link https://www.oxidmodule.com
@ -37,7 +38,7 @@ class SmartyCollector extends DataCollector implements Renderable
* @param bool $value
* @return $this
*/
public function useHtmlVarDumper($value = true)
public function useHtmlVarDumper(bool $value = true): SmartyCollector
{
$this->useHtmlVarDumper = $value;
@ -48,9 +49,9 @@ class SmartyCollector extends DataCollector implements Renderable
* Indicates whether the Symfony HtmlDumper will be used to dump variables for rich variable
* rendering.
*
* @return mixed
* @return bool
*/
public function isHtmlVarDumperUsed()
public function isHtmlVarDumperUsed(): bool
{
return $this->useHtmlVarDumper;
}
@ -101,12 +102,12 @@ class SmartyCollector extends DataCollector implements Renderable
: "PhpDebugBar.Widgets.VariableListWidget";
return [
"smarty" => [
"icon" => "tags",
"icon" => "file-text",
"widget" => $widget,
"map" => "smarty.vars",
"default" => "{}",
],
"smarty:badge" => [
"smarty:badge" => [
"map" => "smarty.count",
"default" => 0,
],

View File

@ -0,0 +1,81 @@
<?php
/**
* For the full copyright and license information, please view the LICENSE
* file that was distributed with this source code.
*
* https://www.d3data.de
*
* @copyright (C) D3 Data Development (Inh. Thomas Dartsch)
* @author D3 Data Development - Daniel Seifert <info@shopmodule.com>
* @link https://www.oxidmodule.com
*/
declare(strict_types=1);
namespace D3\DebugBar\Application\Models;
use D3\DebugBar\Application\Component\DebugBarComponent;
use D3\DebugBar\Core\DebugBarErrorHandler;
use D3\DebugBar\Core\DebugBarExceptionHandler;
use OxidEsales\Eshop\Core\Registry;
class DebugBarHandler
{
/**
* @return void
*/
public function setErrorHandler(): void
{
if (AvailabilityCheck::isAvailable()) {
/** @var callable $callable */
$callable = [
new DebugBarErrorHandler(),
'callback',
];
set_error_handler($callable, $this->getHandledErrorTypes());
}
}
/**
* @return int
*/
protected function getHandledErrorTypes(): int
{
return E_ERROR | E_CORE_ERROR | E_COMPILE_ERROR | E_USER_ERROR | E_PARSE;
}
/**
* @return void
*/
public function setExceptionHandler(): void
{
if (AvailabilityCheck::isAvailable()) {
set_exception_handler([
new DebugBarExceptionHandler(),
'handleUncaughtException',
]);
}
}
/**
* @return void
*/
public function addDebugBarComponent(): void
{
if (AvailabilityCheck::isAvailable()) {
$userComponentNames = Registry::getConfig()->getConfigParam('aUserComponentNames');
$d3CmpName = DebugBarComponent::class;
$blDontUseCache = 1;
if (! is_array($userComponentNames)) {
$userComponentNames = [];
}
if (! in_array($d3CmpName, array_keys($userComponentNames))) {
$userComponentNames[ $d3CmpName ] = $blDontUseCache;
Registry::getConfig()->setConfigParam('aUserComponentNames', $userComponentNames);
}
}
}
}

View File

@ -0,0 +1,22 @@
<?php
/**
* For the full copyright and license information, please view the LICENSE
* file that was distributed with this source code.
*
* https://www.d3data.de
*
* @copyright (C) D3 Data Development (Inh. Thomas Dartsch)
* @author D3 Data Development - Daniel Seifert <info@shopmodule.com>
* @link https://www.oxidmodule.com
*/
declare(strict_types=1);
namespace D3\DebugBar\Application\Models\Exceptions;
use ErrorException;
class CompileErrorException extends ErrorException
{
}

View File

@ -0,0 +1,22 @@
<?php
/**
* For the full copyright and license information, please view the LICENSE
* file that was distributed with this source code.
*
* https://www.d3data.de
*
* @copyright (C) D3 Data Development (Inh. Thomas Dartsch)
* @author D3 Data Development - Daniel Seifert <info@shopmodule.com>
* @link https://www.oxidmodule.com
*/
declare(strict_types=1);
namespace D3\DebugBar\Application\Models\Exceptions;
use ErrorException;
class CoreErrorException extends ErrorException
{
}

View File

@ -0,0 +1,22 @@
<?php
/**
* For the full copyright and license information, please view the LICENSE
* file that was distributed with this source code.
*
* https://www.d3data.de
*
* @copyright (C) D3 Data Development (Inh. Thomas Dartsch)
* @author D3 Data Development - Daniel Seifert <info@shopmodule.com>
* @link https://www.oxidmodule.com
*/
declare(strict_types=1);
namespace D3\DebugBar\Application\Models\Exceptions;
use ErrorException;
class ParseException extends ErrorException
{
}

View File

@ -0,0 +1,22 @@
<?php
/**
* For the full copyright and license information, please view the LICENSE
* file that was distributed with this source code.
*
* https://www.d3data.de
*
* @copyright (C) D3 Data Development (Inh. Thomas Dartsch)
* @author D3 Data Development - Daniel Seifert <info@shopmodule.com>
* @link https://www.oxidmodule.com
*/
declare(strict_types=1);
namespace D3\DebugBar\Application\Models\Exceptions;
use OxidEsales\Eshop\Core\Exception\StandardException;
class UnavailableException extends StandardException
{
}

View File

@ -0,0 +1,22 @@
<?php
/**
* For the full copyright and license information, please view the LICENSE
* file that was distributed with this source code.
*
* https://www.d3data.de
*
* @copyright (C) D3 Data Development (Inh. Thomas Dartsch)
* @author D3 Data Development - Daniel Seifert <info@shopmodule.com>
* @link https://www.oxidmodule.com
*/
declare(strict_types=1);
namespace D3\DebugBar\Application\Models\Exceptions;
use ErrorException;
class UserErrorException extends ErrorException
{
}

View File

@ -0,0 +1,26 @@
<?php
/**
* For the full copyright and license information, please view the LICENSE
* file that was distributed with this source code.
*
* https://www.d3data.de
*
* @copyright (C) D3 Data Development (Inh. Thomas Dartsch)
* @author D3 Data Development - Daniel Seifert <info@shopmodule.com>
* @link https://www.oxidmodule.com
*/
declare(strict_types=1);
$sLangName = "Deutsch";
// -------------------------------
// RESOURCE IDENTITFIER = STRING
// -------------------------------
$aLang = [
//Navigation
'charset' => 'UTF-8',
'SHOP_MODULE_GROUP_d3debugbar_general' => 'Grundeinstellungen',
'SHOP_MODULE_d3debugbar_showForAdminUsersOnly' => 'DebugBar nur anzeigen, wenn angemeldeter Benutzer ein Adminbenutzer ist',
];

View File

@ -0,0 +1,26 @@
<?php
/**
* For the full copyright and license information, please view the LICENSE
* file that was distributed with this source code.
*
* https://www.d3data.de
*
* @copyright (C) D3 Data Development (Inh. Thomas Dartsch)
* @author D3 Data Development - Daniel Seifert <info@shopmodule.com>
* @link https://www.oxidmodule.com
*/
declare(strict_types=1);
$sLangName = "English";
// -------------------------------
// RESOURCE IDENTITFIER = STRING
// -------------------------------
$aLang = [
//Navigation
'charset' => 'UTF-8',
'SHOP_MODULE_GROUP_d3debugbar_general' => 'Default settings',
'SHOP_MODULE_d3debugbar_showForAdminUsersOnly' => 'show DebugBar only if logged in user is an admin user',
];

View File

@ -4,7 +4,35 @@ All notable changes to this project will be documented in this file.
The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/),
and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html).
## [Unreleased](https://git.d3data.de/D3Public/DebugBar/compare/1.0.0.0...rel_1.x)
## [Unreleased](https://git.d3data.de/D3Public/DebugBar/compare/1.2.0.0...rel_1.x)
## [1.2.0.0](https://git.d3data.de/D3Public/DebugBar/compare/1.1.0.0...1.2.0.0) - 2023-01-03
### Added
- make installable in OXID 6.5.x (CE 6.12 + 6.13)
- collect unhandled exceptions, errors from Smarty and PHP
- show warning on activation if asset files doesn't exist
- catch all possible exceptions and errors
- add option to show DebugBar only if logged in user is an admin user
### Changed
- remove extra config item for current theme
- throw error exceptions on error levels only
- throw error type dependend exceptions
### Fixed
- fix not existing component issue in admin panels login controller
## [1.1.0.0](https://git.d3data.de/D3Public/DebugBar/compare/1.0.0.0...1.1.0.0) - 2022-08-05
### Added
- shop edition and version information directly in the bar
- basic shop informations (edition, version, theme informations) in the shop tab
### Changed
- reorder tabs
- adjust tab icons for small viewports
### removed
- useless exceptions tab
## [1.0.0.0](https://git.d3data.de/D3Public/DebugBar/releases/tag/1.0.0.0) - 2022-07-30
### Added

View File

@ -0,0 +1,104 @@
<?php
/**
* For the full copyright and license information, please view the LICENSE
* file that was distributed with this source code.
*
* https://www.d3data.de
*
* @copyright (C) D3 Data Development (Inh. Thomas Dartsch)
* @author D3 Data Development - Daniel Seifert <info@shopmodule.com>
* @link https://www.oxidmodule.com
*/
declare(strict_types=1);
namespace D3\DebugBar\Core;
use D3\DebugBar\Application\Models\AvailabilityCheck;
use D3\DebugBar\Application\Models\Exceptions\CompileErrorException;
use D3\DebugBar\Application\Models\Exceptions\CoreErrorException;
use D3\DebugBar\Application\Models\Exceptions\ParseException;
use D3\DebugBar\Application\Models\Exceptions\UserErrorException;
use ErrorException;
use OxidEsales\Eshop\Core\Registry;
class DebugBarErrorHandler
{
/**
* @param int $severity
* @param string $message
* @param string $file
* @param int $line
*
* @return void|false
* @throws CompileErrorException
* @throws CoreErrorException
* @throws ErrorException
* @throws ParseException
* @throws UserErrorException
*/
public function callback(int $severity, string $message, string $file, int $line)
{
AvailabilityCheck::markErrorOccured();
if (0 === error_reporting() || !(error_reporting() & $severity)) {
// This error code is not included in error_reporting.
return false;
}
$smartyTemplate = $this->getSmartyTemplateLocationFromError($message);
if (is_array($smartyTemplate)) {
[ $file, $line ] = $smartyTemplate;
}
switch ($severity) {
case E_CORE_ERROR:
throw new CoreErrorException($message, 0, $severity, $file, $line);
case E_COMPILE_ERROR:
throw new CompileErrorException($message, 0, $severity, $file, $line);
case E_USER_ERROR:
throw new UserErrorException($message, 0, $severity, $file, $line);
case E_PARSE:
throw new ParseException($message, 0, $severity, $file, $line);
case E_ERROR:
throw new ErrorException($message, 0, $severity, $file, $line);
default:
$this->handleUnregisteredErrorTypes($message, $severity, $file, $line);
}
}
/**
* @param string $messsage
* @return array|null
*/
protected function getSmartyTemplateLocationFromError(string $messsage): ?array
{
if (stristr($messsage, 'Smarty error: [in ')) {
$start = strpos($messsage, '[')+1;
$end = strpos($messsage, ']');
$parts = explode(' ', substr($messsage, $start, $end - $start));
return [Registry::getConfig()->getTemplateDir(isAdmin()).$parts[1], (int) $parts[3]];
}
return null;
}
/**
* @param string $message
* @param int $severity
* @param string $file
* @param int $line
* @return void
*
* @throws ErrorException
*/
protected function handleUnregisteredErrorTypes(
string $message = '',
int $severity = 1,
string $file = __FILE__,
int $line = __LINE__
): void {
throw new ErrorException($message, 0, $severity, $file, $line);
}
}

View File

@ -0,0 +1,92 @@
<?php
/**
* For the full copyright and license information, please view the LICENSE
* file that was distributed with this source code.
*
* https://www.d3data.de
*
* @copyright (C) D3 Data Development (Inh. Thomas Dartsch)
* @author D3 Data Development - Daniel Seifert <info@shopmodule.com>
* @link https://www.oxidmodule.com
*/
declare(strict_types=1);
namespace D3\DebugBar\Core;
use D3\DebugBar\Application\Component\DebugBarComponent;
use D3\DebugBar\Application\Models\AvailabilityCheck;
use D3\DebugBar\Application\Models\Exceptions\UnavailableException;
use DebugBar\DataCollector\ExceptionsCollector;
use DebugBar\DebugBarException;
use OxidEsales\Eshop\Core\ConfigFile;
use OxidEsales\Eshop\Core\Exception\ExceptionHandler;
use OxidEsales\Eshop\Core\Registry;
use OxidEsales\EshopCommunity\Internal\Framework\Logger\LoggerServiceFactory;
use OxidEsales\EshopCommunity\Internal\Transition\Utility\Context;
use Throwable;
class DebugBarExceptionHandler
{
/**
* Handler for uncaught exceptions.
*
* @param Throwable $exception exception object
* @return void
*/
public function handleUncaughtException(Throwable $exception): void
{
try {
/** @var int $debugMode */
$debugMode = Registry::get(ConfigFile::class)->getVar('iDebug');
$defaultExceptionHandler = new ExceptionHandler($debugMode);
$defaultExceptionHandler->writeExceptionToLog($exception);
} catch (Throwable $loggerException) {
/**
* It's not possible to get the logger from the DI container.
* Try again to log original exception (without DI container) in order to show the root cause of a problem.
*/
try {
$loggerServiceFactory = new LoggerServiceFactory(new Context());
$logger = $loggerServiceFactory->getLogger();
$logger->error($exception->getTraceAsString());
} catch (Throwable $throwableWithoutPossibilityToWriteToLogFile) {
// It's not possible to log because e.g. the log file is not writable.
}
}
if (AvailabilityCheck::isAvailable() && AvailabilityCheck::ifDebugBarNotSet()) {
try {
/** @var DebugBarComponent $debugBarComponent */
$debugBarComponent = oxNew(DebugBarComponent::class);
/** @var ExceptionsCollector $excCollector */
$excCollector = $debugBarComponent->getDebugBar()->getCollector('exceptions');
$excCollector->addThrowable($exception);
echo <<<HTML
<!DOCTYPE html>
<html lang="en">
<head>
<title></title>
HTML;
echo $debugBarComponent->getRenderer()->renderHead();
$debugBarComponent->addTimelineMessures();
echo <<<HTML
</head>
<body>
HTML;
AvailabilityCheck::markDebugBarAsSet();
echo $debugBarComponent->getRenderer()->render();
echo <<<HTML
</body>
</html>
HTML;
} catch (DebugBarException|UnavailableException $e) {
Registry::getLogger()->error($e->getMessage());
Registry::getUtilsView()->addErrorToDisplay($e);
}
}
}
}

View File

@ -16,6 +16,11 @@ declare(strict_types=1);
namespace D3\DebugBar\Modules\Core {
use OxidEsales\Eshop\Core\ShopControl;
use OxidEsales\EshopCommunity\Core\Config;
class Config_DebugBar_parent extends Config
{
}
class ShopControl_DebugBar_parent extends ShopControl
{

View File

@ -0,0 +1,35 @@
<?php
/**
* For the full copyright and license information, please view the LICENSE
* file that was distributed with this source code.
*
* https://www.d3data.de
*
* @copyright (C) D3 Data Development (Inh. Thomas Dartsch)
* @author D3 Data Development - Daniel Seifert <info@shopmodule.com>
* @link https://www.oxidmodule.com
*/
declare(strict_types=1);
namespace D3\DebugBar\Modules\Core;
use D3\DebugBar\Application\Models\AvailabilityCheck;
use D3\DebugBar\Core\DebugBarExceptionHandler;
use OxidEsales\Eshop\Core\Exception\ExceptionHandler;
class Config_DebugBar extends Config_DebugBar_parent
{
/**
* @return DebugBarExceptionHandler|ExceptionHandler
*/
protected function getExceptionHandler()
{
if (AvailabilityCheck::isAvailable()) {
return new DebugBarExceptionHandler();
}
return parent::getExceptionHandler();
}
}

View File

@ -16,49 +16,82 @@ declare(strict_types=1);
namespace D3\DebugBar\Modules\Core;
use D3\DebugBar\Application\Component\DebugBarComponent;
use OxidEsales\Eshop\Application\Controller\FrontendController;
use D3\DebugBar\Application\Models\AvailabilityCheck;
use D3\DebugBar\Application\Models\DebugBarHandler;
use D3\DebugBar\Core\DebugBarExceptionHandler;
use OxidEsales\Eshop\Core\Exception\StandardException;
use OxidEsales\Eshop\Core\Registry;
use Throwable;
class ShopControl_DebugBar extends ShopControl_DebugBar_parent
{
public function __construct()
{
$this->_d3AddDebugBarComponent();
$handler = oxNew(DebugBarHandler::class);
$handler->setErrorHandler();
$handler->setExceptionHandler();
$handler->addDebugBarComponent();
parent::__construct();
}
/**
* @return void
* @param string|null $controllerKey
* @param string|null $function
* @param array $parameters
* @param array $viewsChain
*/
protected function _d3AddDebugBarComponent(): void
public function start($controllerKey = null, $function = null, $parameters = null, $viewsChain = null)
{
$userComponentNames = Registry::getConfig()->getConfigParam('aUserComponentNames');
$d3CmpName = DebugBarComponent::class;
$blDontUseCache = 1;
parent::start();
if (!is_array($userComponentNames)) {
$userComponentNames = [];
}
if (!in_array($d3CmpName, array_keys($userComponentNames))) {
$userComponentNames[$d3CmpName] = $blDontUseCache;
Registry::getConfig()->setConfigParam('aUserComponentNames', $userComponentNames);
}
}
public function __destruct()
{
if (!isAdmin()) {
/** @var FrontendController $activeView */
if (AvailabilityCheck::isAvailable() && AvailabilityCheck::ifDebugBarNotSet() && AvailabilityCheck::ifNoErrorOccured()) {
$activeView = Registry::getConfig()->getTopActiveView();
/** @var DebugBarComponent|null $debugBarComponent */
$debugBarComponent = $activeView->getComponent(DebugBarComponent::class);
$debugBarComponent = method_exists($activeView, 'getComponent')
? $activeView->getComponent(DebugBarComponent::class)
: null;
if ($debugBarComponent) {
AvailabilityCheck::markDebugBarAsSet();
echo $debugBarComponent->getRenderer()->renderHead();
$debugBarComponent->addTimelineMessures();
echo $debugBarComponent->getRenderer()->render();
}
}
}
/**
* @param Throwable $exception
* @return void
*/
protected function debugBarHandleException(Throwable $exception): void
{
$exceptionHandler = new DebugBarExceptionHandler();
$exceptionHandler->handleUncaughtException($exception);
}
/**
* @param StandardException $exception
*/
protected function _handleSystemException($exception)
{
$this->debugBarHandleException($exception);
}
/**
* @param StandardException $exception
*/
protected function _handleCookieException($exception)
{
$this->debugBarHandleException($exception);
}
/**
* @param StandardException $exception
*/
protected function _handleBaseException($exception)
{
$this->debugBarHandleException($exception);
}
}

View File

@ -14,13 +14,16 @@
declare(strict_types=1);
use D3\DebugBar\Application\Component\DebugBarComponent;
use D3\DebugBar\Application\Models\AvailabilityCheck;
use D3\DebugBar\Application\Models\Exceptions\UnavailableException;
use D3\DebugBar\Application\Models\TimeDataCollectorHandler;
use DebugBar\DataCollector\MessagesCollector;
use DebugBar\DebugBarException;
use OxidEsales\Eshop\Core\Registry;
/**
* @param $sProfileName
* @param string $sProfileName
*
* @return void
*/
function startProfile(string $sProfileName): void
@ -59,7 +62,6 @@ function stopProfile(string $sProfileName): void
$timeDataCollector = TimeDataCollectorHandler::getInstance();
$timeDataCollector->stopMeasure($hash);
global $aStartTimes;
global $executionCounts;
if (!isset($executionCounts[$sProfileName])) {
@ -89,17 +91,25 @@ function debugVar($mVar, bool $blToFile = false): void
fclose($f);
}
} else {
if (!isAdmin()) {
try {
if (! AvailabilityCheck::isAvailable()) {
throw new UnavailableException();
}
$activeView = Registry::getConfig()->getTopActiveView();
/** @var DebugBarComponent $debugBarComponent */
$debugBarComponent = $activeView->getComponent(DebugBarComponent::class);
/** @var DebugBarComponent|null $debugBarComponent */
$debugBarComponent = method_exists($activeView, 'getComponent')
? $activeView->getComponent(DebugBarComponent::class)
: null;
if ($debugBarComponent === null) {
throw new UnavailableException();
}
/** @var MessagesCollector $messages */
$messages = $debugBarComponent->getDebugBar()->getCollector('messages');
$trace = debug_backtrace(DEBUG_BACKTRACE_IGNORE_ARGS);
$trace = debug_backtrace(DEBUG_BACKTRACE_IGNORE_ARGS);
//$location = $trace[1]['class'] . '::' . $trace[1]['function']. '(' . $trace[0]['line'] . ')';
$location = $trace[1]['class'] . '::' . $trace[1]['function'];
$messages->addMessage($mVar, $location);
} else {
} catch (UnavailableException $e) {
dumpVar($mVar, $blToFile);
}
}

View File

@ -10,10 +10,11 @@ The debug bar enables the display of relevant debug information in the shop fron
## Table of content
- [Installation](#installation)
- [How to use](#how-to-use)
- [Changelog](#changelog)
- [Contributing](#contributing)
- [License](#license)
- [Further licences and terms of use](#further-licences-and-terms-of-use)
- [Further licenses and terms of use](#further-licenses-and-terms-of-use)
## Installation
@ -39,32 +40,37 @@ Please enter the following section in the `composer.json` of your project:
Open a command line and navigate to the root directory of the shop (parent directory of source and vendor). Execute the following command. Adapt the path details to your installation environment.
```bash
php composer require d3/oxid-debugbar:^1.0
```
If necessary, please confirm that you allow `composer-symlinker` and `composer-patches` to execute code.
Have the files of the package `oxid-esales/oxideshop-ce` overwritten.
Activate the module in Shopadmin under "Extensions -> Modules".
## How to use
__Please note that the DebugBar contains security-relevant information. It should therefore not be activated under any circumstances in a freely accessible installation.__
The DebugBar displays the following tabs:
- Messages
can contain individual debug output. Messages can be set within the PHP code with `debugVar($message)` and corresponds to the OXID function `dumpVar(...)`
can contain individual debug output. The messages can be set within the PHP code with `debugVar($message)` and corresponds to the OXID function `dumpVar(...)`
- Request
shows all information from GET and POST requests, as well as session, cookie and server variables
- Timeline
displays all areas defined with `startProfile` and `stopProfile` with single and summed execution time as well as a waterfall diagram
- Shop
shows basic shop information (edition, versions, theme information)
- Configuration
provides all configuration settings of the shop from database and config files
- Smarty
lists all variables of the template engine that are available on the current shop page
- Monolog
lists all log messages passed to the Monolog Logger
- Database
shows all database queries necessary to generate the current page
- Smarty
lists all Smarty variables available on the current shop page
- Configuration
Provides all configuration settings of the shop (from database and file).
## Changelog

View File

@ -10,6 +10,7 @@ Die Debug Bar ermöglicht die Darstellung relevanter Debuginformationen im Shopf
## Inhaltsverzeichnis
- [Installation](#installation)
- [Verwendung](#verwendung)
- [Changelog](#changelog)
- [Beitragen](#beitragen)
- [Lizenz](#lizenz)
@ -39,17 +40,20 @@ Bitte tragen Sie den folgenden Abschnitt in die `composer.json` Ihres Projektes
Ă–ffnen Sie eine Kommandozeile und navigieren Sie zum Stammverzeichnis des Shops (Elternverzeichnis von source und vendor). FĂĽhren Sie den folgenden Befehl aus. Passen Sie die Pfadangaben an Ihre Installationsumgebung an.
```bash
php composer require d3/oxid-debugbar:^1.0
```
Sofern nötig, bestätigen Sie bitte, dass Sie `composer-symlinker` und `composer-patches` erlauben, Code auszuführen.
Lassen Sie die Dateien des Paketes `oxid-esales/oxideshop-ce` ĂĽberschreiben.
Aktivieren Sie das Modul im Shopadmin unter "Erweiterungen -> Module".
## Verwendung
__Bitte beachten Sie, dass die DebugBar sicherheitsrelevante Informationen enthält. Diese sollte daher unter keinen Umständen in einer frei zugänglichen Installation aktiviert sein.__
Die DebugBar stellt folgende Tabs dar:
- Messages
kann individuelle Debugausgaben enthalten. Die Nachrichten können innerhalb des PHP-Codes mit `debugVar($message)` gesetzt werden und entspricht der OXID-Funktion `dumpVar(...)`.
@ -57,14 +61,16 @@ Die DebugBar stellt folgende Tabs dar:
zeigt alle Angaben aus GET- und POST-Requests, sowie Session-, Cookie- und Servervariablen
- Timeline
stellt alle mit `startProfile` und `stopProfile` definierten Bereiche mit einzelner und summierter AusfĂĽhrungszeit sowie als Wasserfalldiagramm dar
- Shop
zeigt grundlegende Shopinformationen (Edition, Versionen, Themeinformationen)
- Configuration
stellt alle Konfigurationseinstellungen des Shops aus Datenbank und config-Dateien zur VerfĂĽgung
- Smarty
listet alle Variablen der Template-Engine, die auf der aktuellen Shopseite zur VerfĂĽgung stehen
- Monolog
listet alle an den Monolog Logger ĂĽbergebenen Lognachrichten
- Database
zeigt alle zur Generierung der aktuellen Seite nötigen Datenbankabfragen
- Smarty
listet alle Smarty-Variablen, die auf der aktuellen Shopseite zur VerfĂĽgung stehen
- Configuration
stellt alle Konfigurationseinstellungen des Shops aus Datenbank und Dateien zur VerfĂĽgung
## Changelog

46
Setup/Events.php Normal file
View File

@ -0,0 +1,46 @@
<?php
/**
* For the full copyright and license information, please view the LICENSE
* file that was distributed with this source code.
*
* https://www.d3data.de
*
* @copyright (C) D3 Data Development (Inh. Thomas Dartsch)
* @author D3 Data Development - Daniel Seifert <info@shopmodule.com>
* @link https://www.oxidmodule.com
*/
declare(strict_types=1);
namespace D3\DebugBar\Setup;
use OxidEsales\Eshop\Core\Registry;
class Events
{
/**
* @return void
*/
public static function onActivate(): void
{
/** @var string $shopDir */
$shopDir = Registry::getConfig()->getConfigParam('sShopDir');
if (false === file_exists(
rtrim($shopDir, '/').'/out/debugbar/debugbar.js'
)) {
Registry::getUtilsView()->addErrorToDisplay(
'The asset files cannot be found. Have you forgotten an installation step described in <a href="https://git.d3data.de/D3Public/DebugBar/src/branch/main/README.en.md">README</a>? Then please run the installation again.'.
nl2br(PHP_EOL.PHP_EOL).
'Die Assetdateien können nicht gefunden werden. Hast Du einen Installationsschritt vergessen, der in <a href="https://git.d3data.de/D3Public/DebugBar/src/branch/main/README.md">README</a> beschrieben ist? Dann führe die Installation bitte noch einmal aus.'
);
}
}
/**
* @return void
*/
public static function onDeactivate(): void
{
}
}

5
ToDo.md Normal file
View File

@ -0,0 +1,5 @@
# ToDo
- clear tpl cache button
- phpinfo() overview
- automatic switch between Smarty and Twig

View File

@ -1,6 +1,6 @@
{
"name": "d3/oxid-debugbar",
"description": "add the DegugBar to OXID eShop",
"description": "add the DebugBar to OXID eShop",
"type": "oxideshop-module",
"keywords": [
"oxid",
@ -26,7 +26,7 @@
],
"require": {
"php": ">=7.3",
"oxid-esales/oxideshop-ce": "6.8 - 6.10",
"oxid-esales/oxideshop-ce": "6.8 - 6.13",
"maximebf/debugbar": "^1.18",
"ajgl/composer-symlinker": "^0.3.1",
"cweagans/composer-patches": "^1.7.2"

View File

@ -13,7 +13,9 @@
declare(strict_types=1);
use D3\DebugBar\Modules\Core\Config_DebugBar;
use D3\DebugBar\Modules\Core\ShopControl_DebugBar;
use OxidEsales\Eshop\Core\Config;
use OxidEsales\Eshop\Core\ShopControl;
$sMetadataVersion = '2.1';
@ -31,16 +33,26 @@ $aModule = [
'de' => '',
'en' => '',
],
'version' => '1.0.0.0',
'version' => '1.2.0.0',
'author' => 'D&sup3; Data Development (Inh.: Thomas Dartsch)',
'email' => 'support@shopmodule.com',
'url' => 'https://www.oxidmodule.com/',
'controllers' => [],
'extend' => [
Config::class => Config_DebugBar::class,
ShopControl::class => ShopControl_DebugBar::class,
],
'events' => [],
'events' => [
'onActivate' => '\D3\DebugBar\Setup\Events::onActivate',
],
'templates' => [],
'settings' => [],
'settings' => [
[
'group' => $sModuleId.'_general',
'name' => $sModuleId.'_showForAdminUsersOnly',
'type' => 'bool',
'value' => false,
],
],
'blocks' => [],
];

View File

@ -10,3 +10,7 @@ parameters:
ignoreErrors:
- '#setConfigParam\(\) expects string, array given.#'
- '#Offset .* does not exist on array{function: .*}.#'
- '#ShopControl_DebugBar::_handle.*Exception\(\) has no return type specified#'
- '#ShopControl_DebugBar::start\(\) has no return type specified.#'
- '#UtilsView::addErrorToDisplay\(\) expects OxidEsales\\Eshop\\Core\\Contract\\IDisplayError#'
- '#PHPDoc tag @throws with type .*\\ContainerExceptionInterface is not subtype of Throwable#'

Binary file not shown.

Before

Width:  |  Height:  |  Size: 59 KiB

After

Width:  |  Height:  |  Size: 71 KiB

View File

@ -5,5 +5,5 @@ services:
Psr\Log\LoggerInterface:
class: Monolog\Logger
factory: 'OxidEsales\EshopCommunity\Internal\Framework\Logger\Factory\LoggerFactoryInterface:create'
factory: ['@OxidEsales\EshopCommunity\Internal\Framework\Logger\Factory\LoggerFactoryInterface', 'create']
public: true