diff --git a/sources/Application/WebPage/WebPage.php b/sources/Application/WebPage/WebPage.php index ee9ae8e82..1144b97de 100644 --- a/sources/Application/WebPage/WebPage.php +++ b/sources/Application/WebPage/WebPage.php @@ -26,6 +26,7 @@ use Dict; use ExecutionKPI; use IssueLog; use MetaModel; +use Symfony\Component\HttpFoundation\Response; use UserRights; use utils; @@ -1331,12 +1332,65 @@ JS; */ public function output() { - $oKpi = new ExecutionKPI(); // Send headers foreach ($this->a_headers as $sHeader) { header($sHeader); } + // Render HTML content + $sHtml = $this->RenderContent(); + + // Echo global HTML + $oKpi = new ExecutionKPI(); + echo $sHtml; + $oKpi->ComputeAndReport('Echoing ('.round(strlen($sHtml) / 1024).' KB)'); + + if (class_exists('DBSearch')) { + DBSearch::RecordQueryTrace(); + } + ExecutionKPI::ReportStats(); + } + + /** + * @return \Symfony\Component\HttpFoundation\Response Generate the Symfony Response object (content + code + headers) for the current page, this is equivalent (and new way) of \WebPage::output() for Symfony controllers + * @since 3.2.0 N°6935 + */ + public function GenerateResponse(): Response + { + // Render HTML content + $sHtml = $this->RenderContent(); + + // Prepare Symfony Response + $oKpi = new ExecutionKPI(); + + // Format headers as a key => value array to match Symfony Response format + $aHeadersAsAssocArray = []; + foreach ($this->a_headers as $sHeader) { + // Limit explode to only split at the first occurrence + list($sHeaderName, $sHeaderValue) = explode(': ', $sHeader, 2); + $aHeadersAsAssocArray[$sHeaderName] = $sHeaderValue; + } + + $oResponse = new Response($sHtml, Response::HTTP_OK, $aHeadersAsAssocArray); + $oKpi->ComputeAndReport('Preparing response ('.round(strlen($sHtml) / 1024).' KB)'); + + if (class_exists('DBSearch')) { + DBSearch::RecordQueryTrace(); + } + ExecutionKPI::ReportStats(); + + return $oResponse; + } + + /** + * @return string Complete HTML content of the \WebPage + * @throws \CoreTemplateException + * @throws \Twig\Error\LoaderError + * @since 3.2.0 N°6935 + */ + protected function RenderContent(): string + { + $oKpi = new ExecutionKPI(); $s_captured_output = $this->ob_get_clean_safe(); $aData = []; @@ -1390,16 +1444,10 @@ JS; $oTwigEnv = TwigHelper::GetTwigEnvironment(BlockRenderer::TWIG_BASE_PATH, BlockRenderer::TWIG_ADDITIONAL_PATHS); // Render final TWIG into global HTML $sHtml = TwigHelper::RenderTemplate($oTwigEnv, $aData, $this->GetTemplateRelPath()); - $oKpi->ComputeAndReport(get_class($this).'output'); - // Echo global HTML - echo $sHtml; - $oKpi->ComputeAndReport('Echoing ('.round(strlen($sHtml) / 1024).' Kb)'); + $oKpi->ComputeAndReport("Rendering content (".static::class.")"); - if (class_exists('DBSearch')) { - DBSearch::RecordQueryTrace(); - } - ExecutionKPI::ReportStats(); + return $sHtml; } /** diff --git a/sources/Application/WebPage/iTopWebPage.php b/sources/Application/WebPage/iTopWebPage.php index aa8644cf0..c15f382af 100644 --- a/sources/Application/WebPage/iTopWebPage.php +++ b/sources/Application/WebPage/iTopWebPage.php @@ -829,6 +829,31 @@ HTML; * @throws \Exception */ public function output() + { + // Send headers + if ($this->GetOutputFormat() === 'html') { + foreach ($this->a_headers as $sHeader) { + header($sHeader); + } + } + + // Render HTKL content + $sHtml = $this->RenderContent(); + + // Echo global HTML + $oKpi = new ExecutionKPI(); + echo $sHtml; + $oKpi->ComputeAndReport('Echoing ('.round(strlen($sHtml) / 1024).' Kb)'); + + DBSearch::RecordQueryTrace(); + ExecutionKPI::ReportStats(); + } + + /** + * @inheritDoc + * @since 3.2.0 N°6935 + */ + protected function RenderContent(): string { $oKpi = new ExecutionKPI(); @@ -933,16 +958,16 @@ HTML; $aData['aDeferredBlocks']['oPageContent'] = $this->GetDeferredBlocks($this->GetContentLayout()); // - Prepare generic templates $aData['aTemplates'] = array(); - + // TODO 3.1 Replace hardcoded 'Please wait' with dict entries - + // - Modal template with loader $oModalTemplateContentBlock = new UIContentBlock(); $oModalTemplateContentBlock->AddCSSClass('ibo-modal') ->AddDataAttribute('role', 'ibo-modal') ->AddSubBlock(SpinnerUIBlockFactory::MakeMedium(null, 'Please wait')); $aData['aTemplates'][] = TemplateUIBlockFactory::MakeForBlock('ibo-modal-template', $oModalTemplateContentBlock); - + // - Small loader template $oSmallLoaderTemplateContentBlock = new UIContentBlock(); $oSmallLoaderTemplateContentBlock->AddSubBlock(SpinnerUIBlockFactory::MakeSmall(null , 'Please wait')); @@ -997,27 +1022,14 @@ HTML; $oTwigEnv = TwigHelper::GetTwigEnvironment(BlockRenderer::TWIG_BASE_PATH, BlockRenderer::TWIG_ADDITIONAL_PATHS); - // Send headers - if ($this->GetOutputFormat() === 'html') { - foreach ($this->a_headers as $sHeader) { - header($sHeader); - } - } - // Render final TWIG into global HTML $sHtml = TwigHelper::RenderTemplate($oTwigEnv, $aData, $this->GetTemplateRelPath()); - $oKpi->ComputeAndReport(get_class($this).' output'); - - // Echo global HTML - echo $sHtml; - $oKpi->ComputeAndReport('Echoing ('.round(strlen($sHtml) / 1024).' Kb)'); + $oKpi->ComputeAndReport("Rendering content (".static::class.")"); - DBSearch::RecordQueryTrace(); - ExecutionKPI::ReportStats(); + return $sHtml; } - /** * @inheritDoc * @throws \Exception