mirror of
https://github.com/Combodo/iTop.git
synced 2026-04-24 11:08:45 +02:00
N°8772 - Errors & turbo
This commit is contained in:
@@ -62,6 +62,9 @@ abstract class Controller extends AbstractController
|
|||||||
const ENUM_PAGE_TYPE_TURBO_FORM_AJAX = 'turbo_ajax';
|
const ENUM_PAGE_TYPE_TURBO_FORM_AJAX = 'turbo_ajax';
|
||||||
const ENUM_PAGE_TYPE_SETUP = 'setup';
|
const ENUM_PAGE_TYPE_SETUP = 'setup';
|
||||||
|
|
||||||
|
const TWIG_ERROR = 'error';
|
||||||
|
const TWIG_WARNING = 'warning';
|
||||||
|
|
||||||
/** @var \Twig\Environment */
|
/** @var \Twig\Environment */
|
||||||
private $oTwig;
|
private $oTwig;
|
||||||
/** @var string */
|
/** @var string */
|
||||||
@@ -105,12 +108,15 @@ abstract class Controller extends AbstractController
|
|||||||
/** @var CsrfTokenManager Csrf manager (from Symfony form component @link https://symfony.com/doc/current/security/csrf.html) */
|
/** @var CsrfTokenManager Csrf manager (from Symfony form component @link https://symfony.com/doc/current/security/csrf.html) */
|
||||||
private CsrfTokenManager $oCsrfTokenManager;
|
private CsrfTokenManager $oCsrfTokenManager;
|
||||||
private ?string $sContentType = null;
|
private ?string $sContentType = null;
|
||||||
|
private ?string $sPageType = null;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Controller constructor.
|
* Controller constructor.
|
||||||
*
|
*
|
||||||
* @param string $sViewPath Path of the twig files
|
* @param string $sViewPath Path of the twig files
|
||||||
* @param string $sModuleName name of the module (or 'core' if not a module)
|
* @param string $sModuleName name of the module (or 'core' if not a module)
|
||||||
|
*
|
||||||
|
* @throws \ReflectionException
|
||||||
*/
|
*/
|
||||||
public function __construct($sViewPath = '', $sModuleName = 'core', $aAdditionalPaths = [])
|
public function __construct($sViewPath = '', $sModuleName = 'core', $aAdditionalPaths = [])
|
||||||
{
|
{
|
||||||
@@ -475,9 +481,9 @@ abstract class Controller extends AbstractController
|
|||||||
$this->DisplayPage($aParams, $sTemplateName, 'setup');
|
$this->DisplayPage($aParams, $sTemplateName, 'setup');
|
||||||
}
|
}
|
||||||
|
|
||||||
public function DisplayTurboAjaxPage($aParams = array(), $sTemplateName = 'turbo-ajax-update.html.twig')
|
public function DisplayTurboAjaxPage($aParams = array())
|
||||||
{
|
{
|
||||||
$this->DisplayPage($aParams, $sTemplateName, self::ENUM_PAGE_TYPE_TURBO_FORM_AJAX);
|
$this->DisplayPage($aParams, 'application/forms/turbo-ajax-update', self::ENUM_PAGE_TYPE_TURBO_FORM_AJAX);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -497,31 +503,36 @@ abstract class Controller extends AbstractController
|
|||||||
$sTemplateName = $this->m_sOperation;
|
$sTemplateName = $this->m_sOperation;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
$this->sPageType = $sPageType;
|
||||||
|
|
||||||
$aParams = array_merge($this->GetDefaultParameters(), $aParams);
|
$aParams = array_merge($this->GetDefaultParameters(), $aParams);
|
||||||
$this->CreatePage($sPageType);
|
$this->CreatePage($sPageType);
|
||||||
$sHTMLContent = $this->RenderTemplate($aParams, $sTemplateName, 'html', $sErrorMsg);
|
$sHTMLContent = $this->RenderTemplate($aParams, $sTemplateName, 'html', $aErrors);
|
||||||
if ($sHTMLContent !== false) {
|
if ($sHTMLContent !== false) {
|
||||||
$this->AddToPage($sHTMLContent);
|
$this->AddToPage($sHTMLContent);
|
||||||
}
|
}
|
||||||
$sJSScript = $this->RenderTemplate($aParams, $sTemplateName, 'js', $sErrorMsg);
|
$sJSScript = $this->RenderTemplate($aParams, $sTemplateName, 'js', $aErrors);
|
||||||
if ($sJSScript !== false) {
|
if ($sJSScript !== false) {
|
||||||
$this->AddScriptToPage($sJSScript);
|
$this->AddScriptToPage($sJSScript);
|
||||||
}
|
}
|
||||||
$sReadyScript = $this->RenderTemplate($aParams, $sTemplateName, 'ready.js', $sErrorMsg);
|
$sReadyScript = $this->RenderTemplate($aParams, $sTemplateName, 'ready.js', $aErrors);
|
||||||
if ($sReadyScript !== false) {
|
if ($sReadyScript !== false) {
|
||||||
$this->AddReadyScriptToPage($sReadyScript);
|
$this->AddReadyScriptToPage($sReadyScript);
|
||||||
}
|
}
|
||||||
$sStyle = $this->RenderTemplate($aParams, $sTemplateName, 'css', $sErrorMsg);
|
$sStyle = $this->RenderTemplate($aParams, $sTemplateName, 'css', $aErrors);
|
||||||
if ($sStyle !== false) {
|
if ($sStyle !== false) {
|
||||||
$this->AddStyleToPage($sStyle);
|
$this->AddStyleToPage($sStyle);
|
||||||
}
|
}
|
||||||
if ($sHTMLContent === false && $sJSScript === false && $sReadyScript === false && $sStyle === false) {
|
if ($sHTMLContent === false && $sJSScript === false && $sReadyScript === false && $sStyle === false) {
|
||||||
if (utils::IsNullOrEmptyString($sErrorMsg)) {
|
if (is_null($aErrors) || count($aErrors) === 0) {
|
||||||
$sErrorMsg = "Missing TWIG template for $sTemplateName";
|
$aErrors[self::TWIG_ERROR] = "Missing TWIG template for $sTemplateName";
|
||||||
}
|
}
|
||||||
IssueLog::Error($sErrorMsg);
|
IssueLog::Error(implode("\n",$aErrors[self::TWIG_ERROR] ?? [])."\n".implode("\n",$aErrors[self::TWIG_WARNING] ?? []));
|
||||||
$this->AddToPage($this->oTwig->render('application/forms/itop_error.html.twig', ['sControllerError' => $sErrorMsg]));
|
} else {
|
||||||
|
// Ignore warnings
|
||||||
|
$aErrors[self::TWIG_WARNING] = [];
|
||||||
}
|
}
|
||||||
|
$this->RenderErrors($aErrors);
|
||||||
|
|
||||||
$this->ManageDebugExtensions($aParams, $sPageType);
|
$this->ManageDebugExtensions($aParams, $sPageType);
|
||||||
|
|
||||||
@@ -546,6 +557,7 @@ abstract class Controller extends AbstractController
|
|||||||
}
|
}
|
||||||
$this->SetContentTypeToPage();
|
$this->SetContentTypeToPage();
|
||||||
$this->OutputPage();
|
$this->OutputPage();
|
||||||
|
$this->sPageType = null;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -801,8 +813,11 @@ abstract class Controller extends AbstractController
|
|||||||
* @return string|false
|
* @return string|false
|
||||||
* @throws \Exception
|
* @throws \Exception
|
||||||
*/
|
*/
|
||||||
private function RenderTemplate(array $aParams, string $sName, string $sTemplateFileExtension, string &$sErrorMsg = null): string|false
|
private function RenderTemplate(array $aParams, string $sName, string $sTemplateFileExtension, ?array &$aErrors): string|false
|
||||||
{
|
{
|
||||||
|
if (is_null($aErrors)) {
|
||||||
|
$aErrors = [];
|
||||||
|
}
|
||||||
$sTemplateFile = $sName.'.'.$sTemplateFileExtension.'.twig';
|
$sTemplateFile = $sName.'.'.$sTemplateFileExtension.'.twig';
|
||||||
if (empty($this->oTwig)) {
|
if (empty($this->oTwig)) {
|
||||||
throw new Exception('Not initialized. Call Controller::InitFromModule() or Controller::SetViewPath() before any display');
|
throw new Exception('Not initialized. Call Controller::InitFromModule() or Controller::SetViewPath() before any display');
|
||||||
@@ -812,23 +827,20 @@ abstract class Controller extends AbstractController
|
|||||||
}
|
}
|
||||||
catch (SyntaxError $e) {
|
catch (SyntaxError $e) {
|
||||||
IssueLog::Error($e->getMessage().' - file: '.$e->getFile().'('.$e->getLine().')');
|
IssueLog::Error($e->getMessage().' - file: '.$e->getFile().'('.$e->getLine().')');
|
||||||
|
$aErrors[self::TWIG_ERROR][] = $e->getMessage();
|
||||||
return $this->oTwig->render('application/forms/itop_error.html.twig', ['sControllerError' => $e->getMessage()]);
|
return false;
|
||||||
}
|
}
|
||||||
catch (Exception $e) {
|
catch (Exception $e) {
|
||||||
$sExceptionMessage = $e->getMessage();
|
$sExceptionMessage = $e->getMessage();
|
||||||
if (str_contains($sExceptionMessage, 'at line')) {
|
if (str_contains($sExceptionMessage, 'at line')) {
|
||||||
IssueLog::Error($sExceptionMessage);
|
IssueLog::Error($sExceptionMessage);
|
||||||
|
$aErrors[self::TWIG_ERROR][] = $sExceptionMessage;
|
||||||
return $this->oTwig->render('application/forms/itop_error.html.twig', ['sControllerError' => $sExceptionMessage]);
|
return false;
|
||||||
}
|
}
|
||||||
if (!str_contains($sExceptionMessage, 'Unable to find template')) {
|
if (!str_contains($sExceptionMessage, 'Unable to find template')) {
|
||||||
IssueLog::Error($sExceptionMessage);
|
IssueLog::Error($sExceptionMessage);
|
||||||
}
|
}
|
||||||
if (is_null($sErrorMsg)) {
|
$aErrors[self::TWIG_WARNING][] = $sExceptionMessage;
|
||||||
$sErrorMsg = '';
|
|
||||||
}
|
|
||||||
$sErrorMsg .= $sExceptionMessage."\n";
|
|
||||||
}
|
}
|
||||||
|
|
||||||
return false;
|
return false;
|
||||||
@@ -1024,4 +1036,35 @@ abstract class Controller extends AbstractController
|
|||||||
$this->AddToPage($this->oTwig->render('application/forms/itop_debug_update.html.twig', ['aProfilesInfo' => $aProfilesInfo]));
|
$this->AddToPage($this->oTwig->render('application/forms/itop_debug_update.html.twig', ['aProfilesInfo' => $aProfilesInfo]));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* render error message
|
||||||
|
*
|
||||||
|
* @param array $aErrors
|
||||||
|
*
|
||||||
|
* @return string
|
||||||
|
* @throws \Twig\Error\LoaderError
|
||||||
|
* @throws \Twig\Error\RuntimeError
|
||||||
|
* @throws \Twig\Error\SyntaxError
|
||||||
|
*/
|
||||||
|
public function RenderErrors(array $aErrors): void
|
||||||
|
{
|
||||||
|
if (is_null($this->sPageType)) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
$sErrorMsg = '';
|
||||||
|
if (count($aErrors[self::TWIG_ERROR] ?? []) > 0) {
|
||||||
|
$sErrorMsg .= implode("\n", $aErrors[self::TWIG_ERROR]);
|
||||||
|
$sErrorMsg .= "\n";
|
||||||
|
}
|
||||||
|
if (count($aErrors[self::TWIG_WARNING] ?? []) > 0) {
|
||||||
|
$sErrorMsg .= implode("\n", $aErrors[self::TWIG_WARNING]);
|
||||||
|
}
|
||||||
|
|
||||||
|
if ($this->sPageType === self::ENUM_PAGE_TYPE_TURBO_FORM_AJAX) {
|
||||||
|
$this->AddToPage($this->oTwig->render('application/forms/itop_error_update.html.twig', ['sControllerError' => $sErrorMsg]));
|
||||||
|
}
|
||||||
|
|
||||||
|
$this->AddToPage($this->oTwig->render('application/forms/itop_error.html.twig', ['sControllerError' => $sErrorMsg]));
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,11 +1,9 @@
|
|||||||
{# @copyright Copyright (C) 2010-2025 Combodo SARL #}
|
{# @copyright Copyright (C) 2010-2025 Combodo SARL #}
|
||||||
{# @license http://opensource.org/licenses/AGPL-3.0 #}
|
{# @license http://opensource.org/licenses/AGPL-3.0 #}
|
||||||
|
|
||||||
<turbo-frame id="itop_profiler_turbo_frame">
|
|
||||||
<div id="turbo_itop_profiler">
|
<div id="turbo_itop_profiler">
|
||||||
{% for aProfileInfo in aProfilesInfo %}
|
{% for aProfileInfo in aProfilesInfo %}
|
||||||
{% set aProfileData = aProfileInfo.aProfileData %}
|
{% set aProfileData = aProfileInfo.aProfileData %}
|
||||||
{{ include(aProfileInfo.sTemplate) }}
|
{{ include(aProfileInfo.sTemplate) }}
|
||||||
{% endfor %}
|
{% endfor %}
|
||||||
</div>
|
</div>
|
||||||
</turbo-frame>
|
|
||||||
@@ -1,6 +1,14 @@
|
|||||||
{# @copyright Copyright (C) 2010-2025 Combodo SARL #}
|
{# @copyright Copyright (C) 2010-2025 Combodo SARL #}
|
||||||
{# @license http://opensource.org/licenses/AGPL-3.0 #}
|
{# @license http://opensource.org/licenses/AGPL-3.0 #}
|
||||||
|
|
||||||
{% if sControllerError %}
|
<div id="turbo_itop_error">
|
||||||
{% UIAlert ForDanger { sTitle:'UI:Error:TwigController'|dict_s, sContent:sControllerError } %}{% EndUIAlert %}
|
{% if sControllerError %}
|
||||||
{% endif %}
|
<div class="ibo-alert ibo-content-block ibo-block ibo-is-danger ibo-is-opened" data-role="ibo-alert">
|
||||||
|
<div class="ibo-alert--action-button ibo-alert--maximize-button" data-role="ibo-alert--collapse-toggler"><i class="fas fa-caret-down"></i></div>
|
||||||
|
<div class="ibo-alert--action-button ibo-alert--minimize-button" data-role="ibo-alert--collapse-toggler"><i class="fas fa-caret-up"></i></div>
|
||||||
|
<div class="ibo-alert--action-button ibo-alert--close-button" data-role="ibo-alert--close-button"><i class="fas fa-times"></i></div>
|
||||||
|
<div class="ibo-alert--title" data-role="ibo-alert--collapse-toggler">{{ 'UI:Error:TwigController'|dict_s }}</div>
|
||||||
|
<div class="ibo-alert--body">{{ sControllerError }}</div>
|
||||||
|
</div>
|
||||||
|
{% endif %}
|
||||||
|
</div>
|
||||||
16
templates/application/forms/itop_error_update.html.twig
Normal file
16
templates/application/forms/itop_error_update.html.twig
Normal file
@@ -0,0 +1,16 @@
|
|||||||
|
{# @copyright Copyright (C) 2010-2025 Combodo SARL #}
|
||||||
|
{# @license http://opensource.org/licenses/AGPL-3.0 #}
|
||||||
|
|
||||||
|
<turbo-stream action="update" target="turbo_itop_error">
|
||||||
|
<template>
|
||||||
|
{% if sControllerError %}
|
||||||
|
<div class="ibo-alert ibo-content-block ibo-block ibo-is-danger ibo-is-opened" data-role="ibo-alert">
|
||||||
|
<div class="ibo-alert--action-button ibo-alert--maximize-button" data-role="ibo-alert--collapse-toggler"><i class="fas fa-caret-down"></i></div>
|
||||||
|
<div class="ibo-alert--action-button ibo-alert--minimize-button" data-role="ibo-alert--collapse-toggler"><i class="fas fa-caret-up"></i></div>
|
||||||
|
<div class="ibo-alert--action-button ibo-alert--close-button" data-role="ibo-alert--close-button"><i class="fas fa-times"></i></div>
|
||||||
|
<div class="ibo-alert--title" data-role="ibo-alert--collapse-toggler">{{ 'UI:Error:TwigController'|dict_s }}</div>
|
||||||
|
<div class="ibo-alert--body">{{ sControllerError }}</div>
|
||||||
|
</div>
|
||||||
|
{% endif %}
|
||||||
|
</template>
|
||||||
|
</turbo-stream>
|
||||||
Reference in New Issue
Block a user