mirror of
https://github.com/Combodo/iTop.git
synced 2026-05-01 22:48:45 +02:00
Merge branch 'develop' into feature/faf_event_service
This commit is contained in:
340
sources/Application/WebPage/AjaxPage.php
Normal file
340
sources/Application/WebPage/AjaxPage.php
Normal file
@@ -0,0 +1,340 @@
|
||||
<?php
|
||||
/*
|
||||
* @copyright Copyright (C) 2010-2021 Combodo SARL
|
||||
* @license http://opensource.org/licenses/AGPL-3.0
|
||||
*/
|
||||
|
||||
use Combodo\iTop\Application\TwigBase\Twig\TwigHelper;
|
||||
use Combodo\iTop\Application\UI\Base\Component\Panel\PanelUIBlockFactory;
|
||||
use Combodo\iTop\Application\UI\Base\iUIBlock;
|
||||
use Combodo\iTop\Application\UI\Base\Layout\iUIContentBlock;
|
||||
use Combodo\iTop\Renderer\BlockRenderer;
|
||||
use Combodo\iTop\Renderer\Console\ConsoleBlockRenderer;
|
||||
use Combodo\iTop\Service\EventName;
|
||||
use Combodo\iTop\Service\EventService;
|
||||
|
||||
class AjaxPage extends WebPage implements iTabbedPage
|
||||
{
|
||||
/**
|
||||
* Jquery style ready script
|
||||
*
|
||||
* @var array
|
||||
*/
|
||||
protected $m_oTabs;
|
||||
private $m_sMenu; // If set, then the menu will be updated
|
||||
|
||||
const DEFAULT_PAGE_TEMPLATE_REL_PATH = 'pages/backoffice/ajaxpage/layout';
|
||||
/** @var string */
|
||||
private $sPromiseId;
|
||||
|
||||
/**
|
||||
* @var bool if false will also output extra JS & CSS
|
||||
* @since 3.0.1 3.1.0 N°4836 Introduce this new option to AjaxPage, as sometimes we only need to return a simple string
|
||||
*/
|
||||
protected $bOutputDataOnly = false;
|
||||
|
||||
/**
|
||||
* constructor for the web page
|
||||
*
|
||||
* @param string $s_title Not used
|
||||
* @param bool $bOutputExtraResources if true will output also JS & CSS resources
|
||||
*/
|
||||
function __construct($s_title)
|
||||
{
|
||||
$oKpi = new ExecutionKPI();
|
||||
$sPrintable = utils::ReadParam('printable', '0');
|
||||
$bPrintable = ($sPrintable == '1');
|
||||
|
||||
parent::__construct($s_title, $bPrintable);
|
||||
//$this->add_header("Content-type: text/html; charset=utf-8");
|
||||
$this->no_cache();
|
||||
$this->add_xframe_options();
|
||||
$this->m_oTabs = new TabManager();
|
||||
$this->sContentType = 'text/html';
|
||||
$this->sContentDisposition = 'inline';
|
||||
$this->m_sMenu = "";
|
||||
$this->sPromiseId = utils::ReadParam('ajax_promise_id', uniqid('ajax_', true));
|
||||
|
||||
utils::InitArchiveMode();
|
||||
$oKpi->ComputeStats(get_class($this).' creation', 'AjaxPage');
|
||||
}
|
||||
|
||||
/**
|
||||
* @see static::$bOutputDataOnly
|
||||
* @param bool $bFlag
|
||||
*
|
||||
* @return $this
|
||||
*
|
||||
* @since 3.0.1 3.1.0 N°4836 Method creation : sometimes we only want to output a simple string
|
||||
*/
|
||||
public function SetOutputDataOnly(bool $bFlag)
|
||||
{
|
||||
$this->bOutputDataOnly = $bFlag;
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* @inheritDoc
|
||||
* @throws \Exception
|
||||
*/
|
||||
public function AddTabContainer($sTabContainer, $sPrefix = '', iUIContentBlock $oParentBlock = null)
|
||||
{
|
||||
if (is_null($oParentBlock)) {
|
||||
$oParentBlock = PanelUIBlockFactory::MakeNeutral('');
|
||||
$this->AddUiBlock($oParentBlock);
|
||||
}
|
||||
|
||||
$oParentBlock->AddSubBlock($this->m_oTabs->AddTabContainer($sTabContainer, $sPrefix));
|
||||
}
|
||||
|
||||
/**
|
||||
* @inheritDoc
|
||||
* @throws \Exception
|
||||
*/
|
||||
public function AddToTab($sTabContainer, $sTabCode, $sHtml)
|
||||
{
|
||||
$this->add($this->m_oTabs->AddToTab($sTabContainer, $sTabCode, $sHtml));
|
||||
}
|
||||
|
||||
/**
|
||||
* @inheritDoc
|
||||
*/
|
||||
public function SetCurrentTabContainer($sTabContainer = '')
|
||||
{
|
||||
return $this->m_oTabs->SetCurrentTabContainer($sTabContainer);
|
||||
}
|
||||
|
||||
/**
|
||||
* @inheritDoc
|
||||
*/
|
||||
public function SetCurrentTab($sTabCode = '', $sTabTitle = null)
|
||||
{
|
||||
return $this->m_oTabs->SetCurrentTab($sTabCode, $sTabTitle);
|
||||
}
|
||||
|
||||
/**
|
||||
* @inheritDoc
|
||||
* @throws \Exception
|
||||
*/
|
||||
public function AddAjaxTab($sTabCode, $sUrl, $bCache = true, $sTabTitle = null, $sPlaceholder = null)
|
||||
{
|
||||
$this->add($this->m_oTabs->AddAjaxTab($sTabCode, $sUrl, $bCache, $sTabTitle, $sPlaceholder));
|
||||
}
|
||||
|
||||
/**
|
||||
* @inheritDoc
|
||||
*/
|
||||
public function GetCurrentTab()
|
||||
{
|
||||
return $this->m_oTabs->GetCurrentTab();
|
||||
}
|
||||
|
||||
/**
|
||||
* @inheritDoc
|
||||
*/
|
||||
public function RemoveTab($sTabCode, $sTabContainer = null)
|
||||
{
|
||||
$this->m_oTabs->RemoveTab($sTabCode, $sTabContainer);
|
||||
}
|
||||
|
||||
/**
|
||||
* @inheritDoc
|
||||
*/
|
||||
public function FindTab($sPattern, $sTabContainer = null)
|
||||
{
|
||||
return $this->m_oTabs->FindTab($sPattern, $sTabContainer);
|
||||
}
|
||||
|
||||
/**
|
||||
* Make the given tab the active one, as if it were clicked
|
||||
* DOES NOT WORK: apparently in the *old* version of jquery
|
||||
* that we are using this is not supported... TO DO upgrade
|
||||
* the whole jquery bundle...
|
||||
*/
|
||||
public function SelectTab($sTabContainer, $sTabCode)
|
||||
{
|
||||
$this->add_ready_script($this->m_oTabs->SelectTab($sTabContainer, $sTabCode));
|
||||
}
|
||||
|
||||
/**
|
||||
* @param string $sHtml
|
||||
*
|
||||
* @deprecated Will be removed in 3.0.0
|
||||
*/
|
||||
public function AddToMenu($sHtml)
|
||||
{
|
||||
DeprecatedCallsLog::NotifyDeprecatedPhpMethod();
|
||||
$this->m_sMenu .= $sHtml;
|
||||
}
|
||||
|
||||
/**
|
||||
* @inheritDoc
|
||||
*/
|
||||
public function output()
|
||||
{
|
||||
$oKpi = new ExecutionKPI();
|
||||
$s_captured_output = $this->ob_get_clean_safe();
|
||||
|
||||
if (!empty($this->sContentType)) {
|
||||
$this->add_header('Content-type: '.$this->sContentType);
|
||||
}
|
||||
if (!empty($this->sContentDisposition)) {
|
||||
$this->add_header('Content-Disposition: '.$this->sContentDisposition.'; filename="'.$this->sContentFileName.'"');
|
||||
}
|
||||
foreach ($this->a_headers as $s_header) {
|
||||
header($s_header);
|
||||
}
|
||||
|
||||
if (false === $this->bOutputDataOnly) {
|
||||
// Prepare internal parts (js files, css files, js snippets, css snippets, ...)
|
||||
// - Generate necessary dict. files
|
||||
if ($this->bAddJSDict) {
|
||||
$this->output_dict_entries();
|
||||
}
|
||||
|
||||
ConsoleBlockRenderer::AddCssJsToPage($this, $this->oContentLayout);
|
||||
|
||||
$this->outputCollapsibleSectionInit();
|
||||
}
|
||||
|
||||
// Render the blocks
|
||||
$aData = [];
|
||||
$aData['oLayout'] = $this->oContentLayout;
|
||||
$aData['aDeferredBlocks'] = $this->GetDeferredBlocks($this->oContentLayout);
|
||||
|
||||
$aData['aPage'] = [
|
||||
'sAbsoluteUrlAppRoot' => addslashes(utils::GetAbsoluteUrlAppRoot()),
|
||||
'sTitle' => $this->s_title,
|
||||
'aMetadata' => [
|
||||
'sCharset' => static::PAGES_CHARSET,
|
||||
'sLang' => $this->GetLanguageForMetadata(),
|
||||
],
|
||||
'aCssFiles' => $this->a_linked_stylesheets,
|
||||
'aCssInline' => $this->a_styles,
|
||||
'aJsFiles' => $this->a_linked_scripts,
|
||||
'aJsInlineLive' => $this->a_scripts,
|
||||
'aJsInlineOnDomReady' => $this->GetReadyScripts(),
|
||||
'aJsInlineOnInit' => $this->a_init_scripts,
|
||||
'bEscapeContent' => ($this->sContentType == 'text/html') && ($this->sContentDisposition == 'inline'),
|
||||
// TODO 3.0.0: TEMP, used while developping, remove it.
|
||||
'sSanitizedContent' => utils::FilterXSS($this->s_content),
|
||||
'sDeferredContent' => utils::FilterXSS(addslashes(str_replace("\n", '', $this->s_deferred_content))),
|
||||
'sCapturedOutput' => utils::FilterXSS($s_captured_output),
|
||||
'sPromiseId' => $this->sPromiseId,
|
||||
];
|
||||
|
||||
$aData['aBlockParams'] = $this->GetBlockParams();
|
||||
|
||||
$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)');
|
||||
$this->FireAfterDisplayEvent();
|
||||
ExecutionKPI::ReportStats();
|
||||
}
|
||||
|
||||
/**
|
||||
* Adds a paragraph with a smaller font into the page
|
||||
* NOT implemented (i.e does nothing)
|
||||
*
|
||||
* @param string $sText Content of the (small) paragraph
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
public function small_p($sText)
|
||||
{
|
||||
}
|
||||
|
||||
/**
|
||||
* @inheritDoc
|
||||
* @throws \Exception
|
||||
*/
|
||||
public function add($sHtml)
|
||||
{
|
||||
if (($this->m_oTabs->GetCurrentTabContainer() != '') && ($this->m_oTabs->GetCurrentTab() != '')) {
|
||||
$this->m_oTabs->AddToTab($this->m_oTabs->GetCurrentTabContainer(), $this->m_oTabs->GetCurrentTab(), $sHtml);
|
||||
} else {
|
||||
parent::add($sHtml);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @inheritDoc
|
||||
*/
|
||||
public function AddUiBlock(?iUIBlock $oBlock): ?iUIBlock
|
||||
{
|
||||
if (is_null($oBlock)) {
|
||||
return null;
|
||||
}
|
||||
if (($this->m_oTabs->GetCurrentTabContainer() != '') && ($this->m_oTabs->GetCurrentTab() != '')) {
|
||||
return $this->m_oTabs->AddUIBlockToCurrentTab($oBlock);
|
||||
}
|
||||
|
||||
return parent::AddUiBlock($oBlock);
|
||||
}
|
||||
|
||||
/**
|
||||
* @inheritDoc
|
||||
*/
|
||||
public function start_capture()
|
||||
{
|
||||
$sCurrentTabContainer = $this->m_oTabs->GetCurrentTabContainer();
|
||||
$sCurrentTab = $this->m_oTabs->GetCurrentTab();
|
||||
|
||||
if (!empty($sCurrentTabContainer) && !empty($sCurrentTab)) {
|
||||
$iOffset = $this->m_oTabs->GetCurrentTabLength();
|
||||
return array('tc' => $sCurrentTabContainer, 'tab' => $sCurrentTab, 'offset' => $iOffset);
|
||||
} else {
|
||||
return parent::start_capture();
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @inheritDoc
|
||||
*/
|
||||
public function end_capture($offset)
|
||||
{
|
||||
if (is_array($offset)) {
|
||||
if ($this->m_oTabs->TabExists($offset['tc'], $offset['tab'])) {
|
||||
$sCaptured = $this->m_oTabs->TruncateTab($offset['tc'], $offset['tab'], $offset['offset']);
|
||||
} else {
|
||||
$sCaptured = '';
|
||||
}
|
||||
} else {
|
||||
$sCaptured = parent::end_capture($offset);
|
||||
}
|
||||
return $sCaptured;
|
||||
}
|
||||
|
||||
/**
|
||||
* @inheritDoc
|
||||
*/
|
||||
public function add_at_the_end($s_html, $sId = null)
|
||||
{
|
||||
if ($sId != '') {
|
||||
$this->add_script("$('#{$sId}').remove();"); // Remove any previous instance of the same Id
|
||||
}
|
||||
$this->s_deferred_content .= $s_html;
|
||||
}
|
||||
|
||||
/**
|
||||
* @inheritDoc
|
||||
*/
|
||||
public function GetUniqueId()
|
||||
{
|
||||
assert(false);
|
||||
}
|
||||
|
||||
/**
|
||||
* @inheritDoc
|
||||
*/
|
||||
public static function FilterXSS($sHTML)
|
||||
{
|
||||
return str_ireplace(array('<script', '</script>'), array('<!-- <removed-script', '</removed-script> -->'), $sHTML);
|
||||
}
|
||||
}
|
||||
14
sources/Application/WebPage/CLILikeWebPage.php
Normal file
14
sources/Application/WebPage/CLILikeWebPage.php
Normal file
@@ -0,0 +1,14 @@
|
||||
<?php
|
||||
/**
|
||||
* @copyright Copyright (C) 2010-2021 Combodo SARL
|
||||
* @license http://opensource.org/licenses/AGPL-3.0
|
||||
*/
|
||||
|
||||
|
||||
class CLILikeWebPage extends WebPage
|
||||
{
|
||||
public function add_comment($sText)
|
||||
{
|
||||
$this->add('#'.$sText."<br/>\n");
|
||||
}
|
||||
}
|
||||
105
sources/Application/WebPage/CLIPage.php
Normal file
105
sources/Application/WebPage/CLIPage.php
Normal file
@@ -0,0 +1,105 @@
|
||||
<?php
|
||||
// Copyright (C) 2010-2021 Combodo SARL
|
||||
//
|
||||
// This file is part of iTop.
|
||||
//
|
||||
// iTop is free software; you can redistribute it and/or modify
|
||||
// it under the terms of the GNU Affero General Public License as published by
|
||||
// the Free Software Foundation, either version 3 of the License, or
|
||||
// (at your option) any later version.
|
||||
//
|
||||
// iTop is distributed in the hope that it will be useful,
|
||||
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
// GNU Affero General Public License for more details.
|
||||
//
|
||||
// You should have received a copy of the GNU Affero General Public License
|
||||
// along with iTop. If not, see <http://www.gnu.org/licenses/>
|
||||
use Combodo\iTop\Service\EventName;
|
||||
use Combodo\iTop\Service\EventService;
|
||||
|
||||
/**
|
||||
* CLI page
|
||||
* The page adds the content-type text/XML and the encoding into the headers
|
||||
*
|
||||
* @copyright Copyright (C) 2010-2021 Combodo SARL
|
||||
* @license http://opensource.org/licenses/AGPL-3.0
|
||||
*/
|
||||
|
||||
|
||||
class CLIPage implements Page
|
||||
{
|
||||
/** @var string */
|
||||
public $s_title;
|
||||
|
||||
function __construct($s_title)
|
||||
{
|
||||
$this->s_title = $s_title;
|
||||
}
|
||||
|
||||
public function output()
|
||||
{
|
||||
$this->FireAfterDisplayEvent();
|
||||
if (class_exists('DBSearch')) {
|
||||
DBSearch::RecordQueryTrace();
|
||||
}
|
||||
if (class_exists('ExecutionKPI')) {
|
||||
ExecutionKPI::ReportStats();
|
||||
}
|
||||
}
|
||||
|
||||
protected function FireAfterDisplayEvent()
|
||||
{
|
||||
$aData['debug_info'] = 'from: '.get_class($this).":[$this->s_title]";
|
||||
$aData['object'] = $this;
|
||||
EventService::FireEvent(EventName::AFTER_DISPLAY_PAGE, get_class($this), $aData);
|
||||
}
|
||||
|
||||
public function add($sText)
|
||||
{
|
||||
echo $sText;
|
||||
}
|
||||
|
||||
public function p($sText)
|
||||
{
|
||||
echo $sText."\n";
|
||||
}
|
||||
|
||||
public function pre($sText)
|
||||
{
|
||||
echo $sText."\n";
|
||||
}
|
||||
|
||||
public function add_comment($sText)
|
||||
{
|
||||
echo "#".$sText."\n";
|
||||
}
|
||||
|
||||
public function table($aConfig, $aData, $aParams = array())
|
||||
{
|
||||
$aCells = array();
|
||||
foreach($aConfig as $sName=>$aDef)
|
||||
{
|
||||
if (strlen($aDef['description']) > 0)
|
||||
{
|
||||
$aCells[] = $aDef['label'].' ('.$aDef['description'].')';
|
||||
}
|
||||
else
|
||||
{
|
||||
$aCells[] = $aDef['label'];
|
||||
}
|
||||
}
|
||||
echo implode(';', $aCells)."\n";
|
||||
|
||||
foreach($aData as $aRow)
|
||||
{
|
||||
$aCells = array();
|
||||
foreach($aConfig as $sName=>$aAttribs)
|
||||
{
|
||||
$sValue = $aRow["$sName"];
|
||||
$aCells[] = $sValue;
|
||||
}
|
||||
echo implode(';', $aCells)."\n";
|
||||
}
|
||||
}
|
||||
}
|
||||
112
sources/Application/WebPage/CSVPage.php
Normal file
112
sources/Application/WebPage/CSVPage.php
Normal file
@@ -0,0 +1,112 @@
|
||||
<?php
|
||||
// Copyright (C) 2010-2021 Combodo SARL
|
||||
//
|
||||
// This file is part of iTop.
|
||||
//
|
||||
// iTop is free software; you can redistribute it and/or modify
|
||||
// it under the terms of the GNU Affero General Public License as published by
|
||||
// the Free Software Foundation, either version 3 of the License, or
|
||||
// (at your option) any later version.
|
||||
//
|
||||
// iTop is distributed in the hope that it will be useful,
|
||||
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
// GNU Affero General Public License for more details.
|
||||
//
|
||||
// You should have received a copy of the GNU Affero General Public License
|
||||
// along with iTop. If not, see <http://www.gnu.org/licenses/>
|
||||
use Combodo\iTop\Service\EventName;
|
||||
use Combodo\iTop\Service\EventService;
|
||||
|
||||
/**
|
||||
* Simple web page with no includes or fancy formatting, useful to generateXML documents
|
||||
* The page adds the content-type text/XML and the encoding into the headers
|
||||
*
|
||||
* @copyright Copyright (C) 2010-2021 Combodo SARL
|
||||
* @license http://opensource.org/licenses/AGPL-3.0
|
||||
*/
|
||||
|
||||
|
||||
class CSVPage extends WebPage
|
||||
{
|
||||
function __construct($s_title)
|
||||
{
|
||||
$oKpi = new ExecutionKPI();
|
||||
parent::__construct($s_title);
|
||||
$this->add_header("Content-type: text/plain; charset=".self::PAGES_CHARSET);
|
||||
$this->no_cache();
|
||||
$this->add_xframe_options();
|
||||
//$this->add_header("Content-Transfer-Encoding: binary");
|
||||
$oKpi->ComputeStats(get_class($this).' creation', 'CSVPage');
|
||||
}
|
||||
|
||||
public function output()
|
||||
{
|
||||
$this->add_header("Content-Length: ".strlen(trim($this->s_content)));
|
||||
|
||||
// Get the unexpected output but do nothing with it
|
||||
$sTrash = $this->ob_get_clean_safe();
|
||||
|
||||
$oKpi = new ExecutionKPI();
|
||||
foreach ($this->a_headers as $s_header) {
|
||||
header($s_header);
|
||||
}
|
||||
echo trim($this->s_content);
|
||||
echo "\n";
|
||||
$oKpi->ComputeAndReport('Echoing ('.round(strlen($this->s_content) / 1024).' Kb)');
|
||||
$this->FireAfterDisplayEvent();
|
||||
|
||||
if (class_exists('DBSearch')) {
|
||||
DBSearch::RecordQueryTrace();
|
||||
}
|
||||
ExecutionKPI::ReportStats();
|
||||
}
|
||||
|
||||
public function small_p($sText)
|
||||
{
|
||||
}
|
||||
|
||||
public function add($sText)
|
||||
{
|
||||
$this->s_content .= $sText;
|
||||
}
|
||||
|
||||
public function p($sText)
|
||||
{
|
||||
$this->s_content .= $sText."\n";
|
||||
}
|
||||
|
||||
public function add_comment($sText)
|
||||
{
|
||||
$this->s_content .= "#".$sText."\n";
|
||||
}
|
||||
|
||||
public function table($aConfig, $aData, $aParams = array())
|
||||
{
|
||||
$aCells = array();
|
||||
foreach($aConfig as $sName=>$aDef)
|
||||
{
|
||||
if (strlen($aDef['description']) > 0)
|
||||
{
|
||||
$aCells[] = $aDef['label'].' ('.$aDef['description'].')';
|
||||
}
|
||||
else
|
||||
{
|
||||
$aCells[] = $aDef['label'];
|
||||
}
|
||||
}
|
||||
$this->s_content .= implode(';', $aCells)."\n";
|
||||
|
||||
foreach($aData as $aRow)
|
||||
{
|
||||
$aCells = array();
|
||||
foreach($aConfig as $sName=>$aAttribs)
|
||||
{
|
||||
$sValue = $aRow["$sName"];
|
||||
$aCells[] = $sValue;
|
||||
}
|
||||
$this->s_content .= implode(';', $aCells)."\n";
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
91
sources/Application/WebPage/CaptureWebPage.php
Normal file
91
sources/Application/WebPage/CaptureWebPage.php
Normal file
@@ -0,0 +1,91 @@
|
||||
<?php
|
||||
// Copyright (C) 2021 Combodo SARL
|
||||
//
|
||||
// This file is part of iTop.
|
||||
//
|
||||
// iTop is free software; you can redistribute it and/or modify
|
||||
// it under the terms of the GNU Affero General Public License as published by
|
||||
// the Free Software Foundation, either version 3 of the License, or
|
||||
// (at your option) any later version.
|
||||
//
|
||||
// iTop is distributed in the hope that it will be useful,
|
||||
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
// GNU Affero General Public License for more details.
|
||||
//
|
||||
// You should have received a copy of the GNU Affero General Public License
|
||||
// along with iTop. If not, see <http://www.gnu.org/licenses/>
|
||||
use Combodo\iTop\Application\UI\Base\iUIBlock;
|
||||
use Combodo\iTop\Renderer\BlockRenderer;
|
||||
|
||||
/**
|
||||
* Adapter class: when an API requires WebPage and you want to produce something else
|
||||
*
|
||||
* @copyright Copyright (C) 2021 Combodo SARL
|
||||
* @license http://opensource.org/licenses/AGPL-3.0
|
||||
*/
|
||||
|
||||
|
||||
class CaptureWebPage extends WebPage
|
||||
{
|
||||
function __construct()
|
||||
{
|
||||
$oKpi = new ExecutionKPI();
|
||||
parent::__construct('capture web page');
|
||||
$oKpi->ComputeStats(get_class($this).' creation', 'CaptureWebPage');
|
||||
}
|
||||
|
||||
public function GetHtml()
|
||||
{
|
||||
$trash = $this->ob_get_clean_safe();
|
||||
|
||||
$oBlockRenderer = new BlockRenderer($this->oContentLayout);
|
||||
return $oBlockRenderer->RenderHtml();
|
||||
}
|
||||
|
||||
public function GetJS()
|
||||
{
|
||||
$sRet = implode("\n", $this->a_scripts);
|
||||
if (!empty($this->s_deferred_content))
|
||||
{
|
||||
$sRet .= "\n\$('body').append('".addslashes(str_replace("\n", '', $this->s_deferred_content))."');";
|
||||
}
|
||||
|
||||
$oBlockRenderer = new BlockRenderer($this->oContentLayout);
|
||||
$sRet .= $oBlockRenderer->RenderJsInline(iUIBlock::ENUM_JS_TYPE_LIVE);
|
||||
$sRet .= $oBlockRenderer->RenderJsInline(iUIBlock::ENUM_JS_TYPE_ON_INIT);
|
||||
|
||||
return $sRet;
|
||||
}
|
||||
|
||||
public function GetReadyJS()
|
||||
{
|
||||
$sRet = "\$(document).ready(function() {\n".implode("\n", $this->a_init_scripts).implode("\n", $this->a_ready_scripts)."\n});";
|
||||
|
||||
$oBlockRenderer = new BlockRenderer($this->oContentLayout);
|
||||
$sRet .= $oBlockRenderer->RenderJsInline(iUIBlock::ENUM_JS_TYPE_ON_READY);
|
||||
|
||||
return $sRet;
|
||||
}
|
||||
|
||||
public function GetCSS()
|
||||
{
|
||||
return $this->a_styles;
|
||||
}
|
||||
|
||||
public function GetJSFiles()
|
||||
{
|
||||
return $this->a_linked_scripts;
|
||||
}
|
||||
|
||||
public function GetCSSFiles()
|
||||
{
|
||||
return $this->a_linked_stylesheets;
|
||||
}
|
||||
|
||||
public function output()
|
||||
{
|
||||
throw new Exception(__method__.' should not be called');
|
||||
}
|
||||
}
|
||||
|
||||
61
sources/Application/WebPage/DownloadPage.php
Normal file
61
sources/Application/WebPage/DownloadPage.php
Normal file
@@ -0,0 +1,61 @@
|
||||
<?php
|
||||
/*
|
||||
* @copyright Copyright (C) 2010-2021 Combodo SARL
|
||||
* @license http://opensource.org/licenses/AGPL-3.0
|
||||
*/
|
||||
|
||||
use Combodo\iTop\Service\EventName;
|
||||
use Combodo\iTop\Service\EventService;
|
||||
|
||||
|
||||
/**
|
||||
* Class DownloadPage
|
||||
*
|
||||
* Use it to download a file raw content (no extra / meta data from iTop)
|
||||
*
|
||||
* @api
|
||||
* @author Eric Espie <eric.espie@combodo.com>
|
||||
* @since 3.0.0
|
||||
*/
|
||||
class DownloadPage extends AjaxPage
|
||||
{
|
||||
/** @var string */
|
||||
protected $sContent;
|
||||
|
||||
/**
|
||||
* @inheritDoc
|
||||
*/
|
||||
public function add($sContent)
|
||||
{
|
||||
$this->sContent .= $sContent;
|
||||
}
|
||||
|
||||
/**
|
||||
* @inheritDoc
|
||||
*/
|
||||
public function output()
|
||||
{
|
||||
$oKpi = new ExecutionKPI();
|
||||
if (!empty($this->sContentType)) {
|
||||
$this->add_header('Content-type: '.$this->sContentType);
|
||||
}
|
||||
if (!empty($this->sContentDisposition)) {
|
||||
$this->add_header('Content-Disposition: '.$this->sContentDisposition.'; filename="'.$this->sContentFileName.'"');
|
||||
}
|
||||
foreach ($this->a_headers as $s_header) {
|
||||
header($s_header);
|
||||
}
|
||||
|
||||
if (($this->sContentType == 'text/html') && ($this->sContentDisposition == 'inline')) {
|
||||
// inline content != attachment && html => filter all scripts for malicious XSS scripts
|
||||
$sContent = self::FilterXSS($this->sContent);
|
||||
} else {
|
||||
$sContent = $this->sContent;
|
||||
}
|
||||
$oKpi->ComputeAndReport(get_class($this).' output');
|
||||
echo $sContent;
|
||||
$oKpi->ComputeAndReport('Echoing ('.round(strlen($sContent) / 1024).' Kb)');
|
||||
$this->FireAfterDisplayEvent();
|
||||
ExecutionKPI::ReportStats();
|
||||
}
|
||||
}
|
||||
102
sources/Application/WebPage/ErrorPage.php
Normal file
102
sources/Application/WebPage/ErrorPage.php
Normal file
@@ -0,0 +1,102 @@
|
||||
<?php
|
||||
|
||||
use Combodo\iTop\Application\Branding;
|
||||
use Combodo\iTop\Application\UI\Base\Component\Title\Title;
|
||||
use Combodo\iTop\Application\UI\Base\Component\Title\TitleUIBlockFactory;
|
||||
use Combodo\iTop\Application\UI\Base\Layout\UIContentBlockUIBlockFactory;
|
||||
|
||||
/**
|
||||
* @copyright Copyright (C) 2010-2021 Combodo SARL
|
||||
* @license http://opensource.org/licenses/AGPL-3.0
|
||||
*/
|
||||
|
||||
|
||||
/**
|
||||
* @since 2.7.1 N°2641 class creation
|
||||
*/
|
||||
class ErrorPage extends NiceWebPage
|
||||
{
|
||||
public function __construct($sTitle)
|
||||
{
|
||||
$oKpi = new ExecutionKPI();
|
||||
parent::__construct($sTitle);
|
||||
$this->add_linked_script("../js/jquery.blockUI.js");
|
||||
$this->add_linked_script("../setup/setup.js");
|
||||
$this->add_linked_stylesheet(utils::GetAbsoluteUrlAppRoot().'css/font-awesome/css/all.min.css');
|
||||
$this->add_linked_stylesheet(utils::GetAbsoluteUrlAppRoot().'css/font-combodo/font-combodo.css');
|
||||
$this->add_saas("css/setup.scss");
|
||||
$oKpi->ComputeStats(get_class($this).' creation', 'ErrorPage');
|
||||
}
|
||||
|
||||
public function info($sText)
|
||||
{
|
||||
$this->add("<p class=\"info\">$sText</p>\n");
|
||||
$this->log_info($sText);
|
||||
}
|
||||
|
||||
public function ok($sText)
|
||||
{
|
||||
$this->add("<div class=\"message message-valid\"><span class=\"message-title\">Success:</span>$sText</div>");
|
||||
$this->log_ok($sText);
|
||||
}
|
||||
|
||||
public function warning($sText)
|
||||
{
|
||||
$this->add("<div class=\"message message-warning\"><span class=\"message-title\">Warning:</span>$sText</div>");
|
||||
$this->log_warning($sText);
|
||||
}
|
||||
|
||||
public function error($sText)
|
||||
{
|
||||
$this->add("<div class=\"message message-error\">$sText</div>");
|
||||
if(utils::IsEasterEggAllowed())
|
||||
{
|
||||
$this->add('<div class="message message-valid">'.Dict::S('UI:ErrorPage:UnstableVersion').'</div>');
|
||||
$this->add('<img src="../images/alpha-fatal-error.gif">');
|
||||
$this->add('<div class="message message-valid">'.nl2br(Dict::S('UI:ErrorPage:KittyDisclaimer')).'</div>');
|
||||
}
|
||||
$this->log_error($sText);
|
||||
}
|
||||
|
||||
public function output()
|
||||
{
|
||||
$sLogo = Branding::GetFullMainLogoAbsoluteUrl();
|
||||
$oSetupPage = UIContentBlockUIBlockFactory::MakeStandard('ibo_setup_container', ['ibo-setup']);
|
||||
$oHeader = UIContentBlockUIBlockFactory::MakeStandard('header', ['ibo-setup--header']);
|
||||
$oSetupPage->AddSubBlock($oHeader);
|
||||
$oTitle = TitleUIBlockFactory::MakeForPageWithIcon($this->s_title, $sLogo, Title::DEFAULT_ICON_COVER_METHOD, false);
|
||||
$oHeader->AddSubBlock($oTitle);
|
||||
$oSetup = UIContentBlockUIBlockFactory::MakeStandard('setup', ['ibo-setup--body']);
|
||||
$oSetupPage->AddSubBlock($oSetup);
|
||||
$oSetup->AddSubBlock($this->oContentLayout);
|
||||
|
||||
$this->oContentLayout = $oSetupPage;
|
||||
|
||||
return parent::output();
|
||||
}
|
||||
|
||||
public static function log_error($sText)
|
||||
{
|
||||
IssueLog::Error($sText);
|
||||
}
|
||||
|
||||
public static function log_warning($sText)
|
||||
{
|
||||
IssueLog::Warning($sText);
|
||||
}
|
||||
|
||||
public static function log_info($sText)
|
||||
{
|
||||
IssueLog::Info($sText);
|
||||
}
|
||||
|
||||
public static function log_ok($sText)
|
||||
{
|
||||
IssueLog::Ok($sText);
|
||||
}
|
||||
|
||||
public static function log($sText)
|
||||
{
|
||||
IssueLog::Ok($sText);
|
||||
}
|
||||
}
|
||||
109
sources/Application/WebPage/JsonPage.php
Normal file
109
sources/Application/WebPage/JsonPage.php
Normal file
@@ -0,0 +1,109 @@
|
||||
<?php
|
||||
/*
|
||||
* @copyright Copyright (C) 2010-2021 Combodo SARL
|
||||
* @license http://opensource.org/licenses/AGPL-3.0
|
||||
*/
|
||||
|
||||
use Combodo\iTop\Service\EventName;
|
||||
use Combodo\iTop\Service\EventService;
|
||||
|
||||
/**
|
||||
* Class JsonPage
|
||||
*
|
||||
* @author Anne-Catherine Cognet <anne-catherine.cognet@combodo.com>
|
||||
* @author Eric Espie <eric.espie@combodo.com>
|
||||
* @since 3.0.0
|
||||
*/
|
||||
class JsonPage extends WebPage
|
||||
{
|
||||
/** @var array Bags of data to include in the response */
|
||||
protected $aData = [];
|
||||
/**
|
||||
* @var bool If true, only static::$aData will be output; otherwise data and scripts will be output in a structured object.
|
||||
* This can be useful when feeding response to a third party lib that doesn't understand the structured format.
|
||||
*/
|
||||
protected $bOutputDataOnly = false;
|
||||
|
||||
/**
|
||||
* JsonPage constructor.
|
||||
*/
|
||||
public function __construct()
|
||||
{
|
||||
$oKpi = new ExecutionKPI();
|
||||
parent::__construct('');
|
||||
$oKpi->ComputeStats(get_class($this).' creation', 'JsonPage');
|
||||
}
|
||||
|
||||
/**
|
||||
* @return array
|
||||
*/
|
||||
public function GetData(): array
|
||||
{
|
||||
return $this->aData;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param array $aData
|
||||
*
|
||||
* @return $this
|
||||
*/
|
||||
public function SetData(array $aData)
|
||||
{
|
||||
$this->aData = $aData;
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param array $aDataRow
|
||||
*
|
||||
* @return $this
|
||||
*/
|
||||
public function AddData(array $aDataRow)
|
||||
{
|
||||
$this->aData[] = $aDataRow;
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* @see static::$bOutputDataOnly
|
||||
* @param bool $bFlag
|
||||
*
|
||||
* @return $this
|
||||
*/
|
||||
public function SetOutputDataOnly(bool $bFlag)
|
||||
{
|
||||
$this->bOutputDataOnly = $bFlag;
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* @inheritDoc
|
||||
*/
|
||||
public function output()
|
||||
{
|
||||
$oKpi = new ExecutionKPI();
|
||||
$this->add_header('Content-type: application/json');
|
||||
|
||||
foreach ($this->a_headers as $s_header) {
|
||||
header($s_header);
|
||||
}
|
||||
|
||||
$aScripts = array_merge($this->a_init_scripts, $this->a_scripts, $this->a_ready_scripts);
|
||||
|
||||
$aJson = $this->bOutputDataOnly ? $this->aData : [
|
||||
'data' => $this->aData,
|
||||
'scripts' => $aScripts,
|
||||
];
|
||||
$sJSON = json_encode($aJson);
|
||||
$oKpi->ComputeAndReport(get_class($this).' output');
|
||||
|
||||
echo $sJSON;
|
||||
$oKpi->ComputeAndReport('Echoing ('.round(strlen($sJSON) / 1024).' Kb)');
|
||||
$this->FireAfterDisplayEvent();
|
||||
ExecutionKPI::ReportStats();
|
||||
}
|
||||
|
||||
}
|
||||
268
sources/Application/WebPage/NiceWebPage.php
Normal file
268
sources/Application/WebPage/NiceWebPage.php
Normal file
@@ -0,0 +1,268 @@
|
||||
<?php
|
||||
/**
|
||||
* Copyright (C) 2013-2021 Combodo SARL
|
||||
*
|
||||
* This file is part of iTop.
|
||||
*
|
||||
* iTop is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU Affero General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* iTop is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU Affero General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Affero General Public License
|
||||
*/
|
||||
|
||||
/**
|
||||
* Web page with some associated CSS and scripts (jquery) for a fancier display
|
||||
*/
|
||||
class NiceWebPage extends WebPage
|
||||
{
|
||||
/** @inheritDoc */
|
||||
protected const COMPATIBILITY_MOVED_LINKED_SCRIPTS_REL_PATH = [
|
||||
// - DisplayableGraph, impact analysis
|
||||
'js/jquery.positionBy.js',
|
||||
'js/jquery.popupmenu.js',
|
||||
// - SearchForm
|
||||
'js/search/search_form_handler.js',
|
||||
'js/search/search_form_handler_history.js',
|
||||
'js/search/search_form_criteria.js',
|
||||
'js/search/search_form_criteria_raw.js',
|
||||
'js/search/search_form_criteria_string.js',
|
||||
'js/search/search_form_criteria_external_field.js',
|
||||
'js/search/search_form_criteria_numeric.js',
|
||||
'js/search/search_form_criteria_enum.js',
|
||||
'js/search/search_form_criteria_tag_set.js',
|
||||
'js/search/search_form_criteria_external_key.js',
|
||||
'js/search/search_form_criteria_hierarchical_key.js',
|
||||
'js/search/search_form_criteria_date_abstract.js',
|
||||
'js/search/search_form_criteria_date.js',
|
||||
'js/search/search_form_criteria_date_time.js',
|
||||
// - DataTable UIBlock
|
||||
'js/field_sorter.js',
|
||||
'js/table-selectable-lines.js',
|
||||
// - Not used internally or by extensions yet
|
||||
'js/clipboard.min.js',
|
||||
'js/clipboardwidget.js',
|
||||
// - SearchForm
|
||||
'js/searchformforeignkeys.js',
|
||||
];
|
||||
/** @inheritDoc */
|
||||
protected const COMPATIBILITY_DEPRECATED_LINKED_SCRIPTS_REL_PATH = [
|
||||
/** @deprecated 3.0.0 Not used in the backoffice since the introduction of the new tooltip lib. */
|
||||
'js/hovertip.js',
|
||||
/** @deprecated 3.0.0 N°2737 - Migrate table to DataTables plugin to be iso with the end-users portal, will be removed in 3.x */
|
||||
'js/datatable.js',
|
||||
'js/jquery.tablesorter.js',
|
||||
'js/jquery.tablesorter.pager.js',
|
||||
'js/jquery.tablehover.js',
|
||||
];
|
||||
|
||||
const DEFAULT_PAGE_TEMPLATE_REL_PATH = 'pages/backoffice/nicewebpage/layout';
|
||||
|
||||
var $m_sRootUrl;
|
||||
|
||||
public function __construct($s_title, $bPrintable = false)
|
||||
{
|
||||
$oKpi = new ExecutionKPI();
|
||||
$this->m_sRootUrl = $this->GetAbsoluteUrlAppRoot();
|
||||
parent::__construct($s_title, $bPrintable);
|
||||
|
||||
$this->LoadTheme();
|
||||
$oKpi->ComputeStats(get_class($this).' creation', 'NiceWebPage');
|
||||
}
|
||||
|
||||
/**
|
||||
* @inheritDoc
|
||||
* @since 3.0.0
|
||||
*/
|
||||
protected function InitializeScripts(): void
|
||||
{
|
||||
parent::InitializeScripts();
|
||||
|
||||
$sAbsURLAppRoot = addslashes($this->m_sRootUrl);
|
||||
$sAbsURLModulesRoot = addslashes($this->GetAbsoluteUrlModulesRoot());
|
||||
$sEnvironment = addslashes(utils::GetCurrentEnvironment());
|
||||
$sAppContext = addslashes($this->GetApplicationContext());
|
||||
|
||||
$this->add_script(
|
||||
<<<EOF
|
||||
function GetAbsoluteUrlAppRoot()
|
||||
{
|
||||
return '$sAbsURLAppRoot';
|
||||
}
|
||||
|
||||
function GetAbsoluteUrlModulesRoot()
|
||||
{
|
||||
return '$sAbsURLModulesRoot';
|
||||
}
|
||||
|
||||
function GetAbsoluteUrlModulePage(sModule, sPage, aArguments)
|
||||
{
|
||||
// aArguments is optional, it default to an empty hash
|
||||
aArguments = typeof aArguments !== 'undefined' ? aArguments : {};
|
||||
|
||||
var sUrl = '$sAbsURLAppRoot'+'pages/exec.php?exec_module='+sModule+'&exec_page='+sPage+'&exec_env='+'$sEnvironment';
|
||||
for (var sArgName in aArguments)
|
||||
{
|
||||
if (aArguments.hasOwnProperty(sArgName))
|
||||
{
|
||||
sUrl = sUrl + '&'+sArgName+'='+aArguments[sArgname];
|
||||
}
|
||||
}
|
||||
return sUrl;
|
||||
}
|
||||
|
||||
function AddAppContext(sURL)
|
||||
{
|
||||
var sContext = '$sAppContext';
|
||||
if (sContext.length > 0)
|
||||
{
|
||||
if (sURL.indexOf('?') == -1)
|
||||
{
|
||||
return sURL+'?'+sContext;
|
||||
}
|
||||
return sURL+'&'+sContext;
|
||||
}
|
||||
return sURL;
|
||||
}
|
||||
EOF
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* @inheritDoc
|
||||
* @since 3.0.0
|
||||
*/
|
||||
protected function InitializeLinkedScripts(): void
|
||||
{
|
||||
parent::InitializeLinkedScripts();
|
||||
|
||||
// Used throughout the app.
|
||||
$this->add_linked_script(utils::GetAbsoluteUrlAppRoot().'js/jquery.min.js');
|
||||
$this->add_linked_script(utils::GetAbsoluteUrlAppRoot().'js/jquery.blockUI.js');
|
||||
if (utils::IsDevelopmentEnvironment()) // Needed since many other plugins still rely on oldies like $.browser
|
||||
{
|
||||
$this->add_linked_script(utils::GetAbsoluteUrlAppRoot().'js/jquery-migrate.dev-params.js');
|
||||
$this->add_linked_script(utils::GetAbsoluteUrlAppRoot().'js/jquery-migrate.dev.js');
|
||||
} else {
|
||||
$this->add_linked_script(utils::GetAbsoluteUrlAppRoot().'js/jquery-migrate.prod.min.js');
|
||||
}
|
||||
$this->add_linked_script(utils::GetAbsoluteUrlAppRoot().'js/jquery-ui.custom.min.js');
|
||||
|
||||
// Used throughout the app.
|
||||
$this->add_linked_script(utils::GetAbsoluteUrlAppRoot().'js/utils.js');
|
||||
$this->add_linked_script(utils::GetAbsoluteUrlAppRoot().'js/latinise/latinise.min.js');
|
||||
}
|
||||
|
||||
/**
|
||||
* @inheritDoc
|
||||
* @since 3.0.0
|
||||
*/
|
||||
protected function InitializeDictEntries(): void
|
||||
{
|
||||
parent::InitializeDictEntries();
|
||||
|
||||
$this->add_dict_entries('UI:Combo');
|
||||
}
|
||||
|
||||
|
||||
public function SetRootUrl($sRootUrl)
|
||||
{
|
||||
$this->m_sRootUrl = $sRootUrl;
|
||||
}
|
||||
|
||||
public function small_p($sText)
|
||||
{
|
||||
$this->add("<p style=\"font-size:smaller\">$sText</p>\n");
|
||||
}
|
||||
|
||||
public function GetAbsoluteUrlAppRoot()
|
||||
{
|
||||
return utils::GetAbsoluteUrlAppRoot();
|
||||
}
|
||||
|
||||
public function GetAbsoluteUrlModulesRoot()
|
||||
{
|
||||
return utils::GetAbsoluteUrlModulesRoot();
|
||||
}
|
||||
|
||||
function GetApplicationContext()
|
||||
{
|
||||
$oAppContext = new ApplicationContext();
|
||||
return $oAppContext->GetForLink();
|
||||
}
|
||||
|
||||
// By Rom, used by CSVImport and Advanced search
|
||||
public function MakeClassesSelect($sName, $sDefaultValue, $iWidthPx, $iActionCode = null)
|
||||
{
|
||||
// $aTopLevelClasses = array('bizService', 'bizContact', 'logInfra', 'bizDocument');
|
||||
// These are classes wich root class is cmdbAbstractObject !
|
||||
$this->add("<select id=\"select_$sName\" name=\"$sName\">");
|
||||
$aValidClasses = array();
|
||||
foreach(MetaModel::GetClasses('bizmodel') as $sClassName)
|
||||
{
|
||||
if (is_null($iActionCode) || UserRights::IsActionAllowed($sClassName, $iActionCode))
|
||||
{
|
||||
$sSelected = ($sClassName == $sDefaultValue) ? " SELECTED" : "";
|
||||
$sDescription = MetaModel::GetClassDescription($sClassName);
|
||||
$sDisplayName = MetaModel::GetName($sClassName);
|
||||
$aValidClasses[$sDisplayName] = "<option style=\"width: ".$iWidthPx." px;\" title=\"$sDescription\" value=\"$sClassName\"$sSelected>$sDisplayName</option>";
|
||||
}
|
||||
}
|
||||
ksort($aValidClasses);
|
||||
$this->add(implode("\n", $aValidClasses));
|
||||
|
||||
$this->add("</select>");
|
||||
}
|
||||
|
||||
// By Rom, used by Advanced search
|
||||
public function add_select($aChoices, $sName, $sDefaultValue, $iWidthPx)
|
||||
{
|
||||
$this->add("<select id=\"select_$sName\" name=\"$sName\">");
|
||||
foreach($aChoices as $sKey => $sValue)
|
||||
{
|
||||
$sSelected = ($sKey == $sDefaultValue) ? " SELECTED" : "";
|
||||
$this->add("<option style=\"width: ".$iWidthPx." px;\" value=\"".htmlspecialchars($sKey)."\"$sSelected>".htmlentities($sValue,
|
||||
ENT_QUOTES, self::PAGES_CHARSET)."</option>");
|
||||
}
|
||||
$this->add("</select>");
|
||||
}
|
||||
|
||||
/**
|
||||
* @inheritDoc
|
||||
* @throws \Exception
|
||||
*/
|
||||
protected function LoadTheme()
|
||||
{
|
||||
// TODO 3.0.0: Remove light-grey when development of Full Moon is done.
|
||||
// TODO 3.0.0: Reuse theming mechanism for Full Moon
|
||||
$sCssThemeUrl = ThemeHandler::GetCurrentThemeUrl();
|
||||
$this->add_linked_stylesheet($sCssThemeUrl);
|
||||
|
||||
$sCssRelPath = utils::GetCSSFromSASS(
|
||||
'css/backoffice/main.scss',
|
||||
array(
|
||||
APPROOT.'css/backoffice/',
|
||||
)
|
||||
);
|
||||
}
|
||||
|
||||
protected function GetReadyScriptsStartedTrigger(): ?string
|
||||
{
|
||||
return <<<JS
|
||||
$("body").attr("data-ready-scripts", "start");
|
||||
JS;
|
||||
}
|
||||
|
||||
protected function GetReadyScriptsFinishedTrigger(): ?string
|
||||
{
|
||||
return <<<JS
|
||||
$("body").attr("data-ready-scripts", "done");
|
||||
JS;
|
||||
}
|
||||
}
|
||||
171
sources/Application/WebPage/PDFPage.php
Normal file
171
sources/Application/WebPage/PDFPage.php
Normal file
@@ -0,0 +1,171 @@
|
||||
<?php
|
||||
/**
|
||||
* Copyright (C) 2013-2021 Combodo SARL
|
||||
*
|
||||
* This file is part of iTop.
|
||||
*
|
||||
* iTop is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU Affero General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* iTop is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU Affero General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Affero General Public License
|
||||
*/
|
||||
|
||||
use Combodo\iTop\Renderer\BlockRenderer;
|
||||
use Combodo\iTop\Service\EventName;
|
||||
use Combodo\iTop\Service\EventService;
|
||||
|
||||
|
||||
/**
|
||||
* Special class of WebPage for printing into a PDF document
|
||||
*/
|
||||
class PDFPage extends WebPage
|
||||
{
|
||||
/** @var \iTopPDF Instance of the TCPDF object for creating the PDF */
|
||||
protected $oPdf;
|
||||
|
||||
public function __construct($s_title, $sPageFormat = 'A4', $sPageOrientation = 'L')
|
||||
{
|
||||
$oKpi = new ExecutionKPI();
|
||||
parent::__construct($s_title);
|
||||
define('K_PATH_FONTS', APPROOT.'lib/combodo/tcpdf/fonts/');
|
||||
$this->oPdf = new iTopPDF($sPageOrientation, 'mm', $sPageFormat, true, self::PAGES_CHARSET, false);
|
||||
|
||||
// set document information
|
||||
$this->oPdf->SetCreator(PDF_CREATOR);
|
||||
$this->oPdf->SetAuthor('iTop');
|
||||
$this->oPdf->SetTitle($s_title);
|
||||
$this->oPdf->SetDocumentTitle($s_title);
|
||||
|
||||
$this->oPdf->setFontSubsetting(true);
|
||||
|
||||
// dejavusans is a UTF-8 Unicode font. Standard PDF fonts like helvetica or times new roman are NOT UTF-8
|
||||
$this->oPdf->SetFontParams('', 10, '', true);
|
||||
|
||||
// set auto page breaks
|
||||
$this->oPdf->SetAutoPageBreak(true, 15); // 15 mm break margin at the bottom
|
||||
$this->oPdf->SetTopMargin(15);
|
||||
|
||||
// Add a page, we're ready to start
|
||||
$this->oPdf->AddPage();
|
||||
|
||||
$this->SetContentDisposition('inline', $s_title.'.pdf');
|
||||
$this->SetDefaultStyle();
|
||||
$oKpi->ComputeStats(get_class($this).' creation', 'PDFPage');
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets a default style (suitable for printing) to be included each time $this->oPdf->writeHTML() is called
|
||||
*/
|
||||
protected function SetDefaultStyle()
|
||||
{
|
||||
$this->add_style(
|
||||
<<<EOF
|
||||
table {
|
||||
padding: 2pt;
|
||||
}
|
||||
table.ibo-datatable td, table.listResults td {
|
||||
border: 0.5pt solid #000 ;
|
||||
}
|
||||
table.ibo-datatable th, table.listResults th {
|
||||
background-color: #eee;
|
||||
border: 0.5pt solid #000 ;
|
||||
}
|
||||
a {
|
||||
text-decoration: none;
|
||||
color: #000;
|
||||
}
|
||||
table.section td {
|
||||
vertical-align: middle;
|
||||
font-size: 10pt;
|
||||
background-color:#eee;
|
||||
}
|
||||
td.icon {
|
||||
width: 30px;
|
||||
}
|
||||
h2{
|
||||
font-size: 10pt;
|
||||
vertical-align: middle;
|
||||
background-color:#eee;
|
||||
padding: 2pt;
|
||||
margin:2pt;
|
||||
}
|
||||
EOF
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* Get access to the underlying TCPDF object
|
||||
*
|
||||
* @return \iTopPDF
|
||||
*/
|
||||
public function get_tcpdf()
|
||||
{
|
||||
$this->flush();
|
||||
|
||||
return $this->oPdf;
|
||||
}
|
||||
|
||||
/**
|
||||
* Writes the currently buffered HTML content into the PDF. This can be useful:
|
||||
* - to sync the flow in case you want to access the underlying TCPDF object for some specific/graphic output
|
||||
* - to process the HTML by smaller chunks instead of processing the whole page at once for performance reasons
|
||||
*/
|
||||
public function flush()
|
||||
{
|
||||
$sHtml = '';
|
||||
if (count($this->a_styles) > 0) {
|
||||
$sHtml .= "<style>\n".implode("\n", $this->a_styles)."\n</style>\n";
|
||||
}
|
||||
if (strlen($this->s_content) > 0) {
|
||||
$sHtml .= $this->s_content;
|
||||
$this->s_content = '';
|
||||
}
|
||||
$sHtml .= BlockRenderer::RenderBlockTemplates($this->oContentLayout);
|
||||
$this->oPdf->writeHTML($sHtml); // The style(s) must be supplied each time we call writeHtml
|
||||
}
|
||||
|
||||
/**
|
||||
* Whether or not the page is a PDF page
|
||||
*
|
||||
* @return boolean
|
||||
*/
|
||||
public function is_pdf()
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* Generates the PDF document and returns the PDF content as a string
|
||||
*
|
||||
* @see WebPage::output()
|
||||
*/
|
||||
public function output()
|
||||
{
|
||||
$this->add_header('Content-type: application/x-pdf');
|
||||
if (!empty($this->sContentDisposition))
|
||||
{
|
||||
$this->add_header('Content-Disposition: '.$this->sContentDisposition.'; filename="'.$this->sContentFileName.'"');
|
||||
}
|
||||
foreach ($this->a_headers as $s_header)
|
||||
{
|
||||
header($s_header);
|
||||
}
|
||||
$this->flush();
|
||||
echo $this->oPdf->Output($this->s_title.'.pdf', 'S');
|
||||
$this->FireAfterDisplayEvent();
|
||||
}
|
||||
|
||||
public function get_pdf()
|
||||
{
|
||||
$this->flush();
|
||||
|
||||
return $this->oPdf->Output($this->s_title.'.pdf', 'S');
|
||||
}
|
||||
}
|
||||
67
sources/Application/WebPage/Page.php
Normal file
67
sources/Application/WebPage/Page.php
Normal file
@@ -0,0 +1,67 @@
|
||||
<?php
|
||||
/**
|
||||
* @copyright Copyright (C) 2010-2021 Combodo SARL
|
||||
* @license http://opensource.org/licenses/AGPL-3.0
|
||||
*/
|
||||
|
||||
|
||||
/**
|
||||
* Generic interface common to CLI and Web pages
|
||||
*/
|
||||
interface Page
|
||||
{
|
||||
/**
|
||||
* Outputs (via some echo) the complete HTML page by assembling all its elements
|
||||
*
|
||||
* @return mixed
|
||||
*/
|
||||
public function output();
|
||||
|
||||
/**
|
||||
* Add any text or HTML fragment to the body of the page
|
||||
*
|
||||
* @param string $sText
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
public function add($sText);
|
||||
|
||||
/**
|
||||
* Add a paragraph to the body of the page
|
||||
*
|
||||
* @param string $sText
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
public function p($sText);
|
||||
|
||||
/**
|
||||
* Add a pre-formatted text to the body of the page
|
||||
*
|
||||
* @param string $sText
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
public function pre($sText);
|
||||
|
||||
/**
|
||||
* Add a comment
|
||||
*
|
||||
* @param string $sText
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
public function add_comment($sText);
|
||||
|
||||
/**
|
||||
* Adds a tabular content to the web page
|
||||
*
|
||||
* @param string[] $aConfig Configuration of the table: hash array of 'column_id' => 'Column Label'
|
||||
* @param string[] $aData Hash array. Data to display in the table: each row is made of 'column_id' => Data. A
|
||||
* column 'pkey' is expected for each row
|
||||
* @param array $aParams Hash array. Extra parameters for the table.
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
public function table($aConfig, $aData, $aParams = array());
|
||||
}
|
||||
357
sources/Application/WebPage/TabManager.php
Normal file
357
sources/Application/WebPage/TabManager.php
Normal file
@@ -0,0 +1,357 @@
|
||||
<?php
|
||||
/**
|
||||
* @copyright Copyright (C) 2010-2021 Combodo SARL
|
||||
* @license http://opensource.org/licenses/AGPL-3.0
|
||||
*/
|
||||
|
||||
use Combodo\iTop\Application\UI\Base\iUIBlock;
|
||||
use Combodo\iTop\Application\UI\Base\Layout\TabContainer\Tab\Tab;
|
||||
use Combodo\iTop\Application\UI\Base\Layout\TabContainer\TabContainer;
|
||||
|
||||
|
||||
/**
|
||||
* Helper class to implement JQueryUI tabs inside a page
|
||||
*/
|
||||
class TabManager
|
||||
{
|
||||
const ENUM_TAB_TYPE_HTML = 'html';
|
||||
const ENUM_TAB_TYPE_AJAX = 'ajax';
|
||||
|
||||
const DEFAULT_TAB_TYPE = self::ENUM_TAB_TYPE_HTML;
|
||||
|
||||
/**
|
||||
* @var TabContainer[]
|
||||
*/
|
||||
protected $m_aTabs;
|
||||
protected $m_sCurrentTabContainer;
|
||||
protected $m_sCurrentTab;
|
||||
|
||||
public function __construct()
|
||||
{
|
||||
$this->m_aTabs = [];
|
||||
$this->m_sCurrentTabContainer = '';
|
||||
$this->m_sCurrentTab = '';
|
||||
}
|
||||
|
||||
/**
|
||||
* @param string $sTabContainer
|
||||
* @param string $sPrefix
|
||||
*
|
||||
* @return \Combodo\iTop\Application\UI\Base\iUIBlock
|
||||
*/
|
||||
public function AddTabContainer(string $sTabContainer, $sPrefix = ''): TabContainer
|
||||
{
|
||||
$oTabContainer = new TabContainer($sTabContainer, $sPrefix);
|
||||
$this->m_aTabs[$sTabContainer] = $oTabContainer;
|
||||
|
||||
return $oTabContainer;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param string $sHtml
|
||||
*
|
||||
* @throws \Exception
|
||||
*/
|
||||
public function AddToCurrentTab(string $sHtml): void
|
||||
{
|
||||
$this->AddToTab($this->m_sCurrentTabContainer, $this->m_sCurrentTab, $sHtml);
|
||||
}
|
||||
|
||||
public function AddUIBlockToCurrentTab(iUIBlock $oBlock): iUIBlock
|
||||
{
|
||||
$this->AddUIBlockToTab($this->m_sCurrentTabContainer, $this->m_sCurrentTab, $oBlock);
|
||||
return $oBlock;
|
||||
}
|
||||
|
||||
public function AddUIBlockToTab(string $sTabContainer, string $sTabCode, iUIBlock $oBlock, $sTabTitle = null): void
|
||||
{
|
||||
if (!$this->TabExists($sTabContainer, $sTabCode)) {
|
||||
$this->InitTab($sTabContainer, $sTabCode, static::ENUM_TAB_TYPE_HTML, $sTabTitle);
|
||||
}
|
||||
|
||||
$oTab = $this->GetTab($sTabContainer, $sTabCode);
|
||||
|
||||
// Append to the content of the tab
|
||||
$oTab->AddSubBlock($oBlock);
|
||||
}
|
||||
|
||||
/**
|
||||
* @return int
|
||||
* @deprecated 3.0.0
|
||||
*/
|
||||
public function GetCurrentTabLength()
|
||||
{
|
||||
DeprecatedCallsLog::NotifyDeprecatedPhpMethod();
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* Truncates the given tab to the specifed length and returns the truncated part
|
||||
*
|
||||
* @param string $sTabContainer The tab container in which to truncate the tab
|
||||
* @param string $sTab The name/identifier of the tab to truncate
|
||||
* @param integer $iLength The length/offset at which to truncate the tab
|
||||
*
|
||||
* @return string The truncated part
|
||||
* @deprecated 3.0.0
|
||||
*/
|
||||
public function TruncateTab(string $sTabContainer, string $sTab, int $iLength)
|
||||
{
|
||||
DeprecatedCallsLog::NotifyDeprecatedPhpMethod();
|
||||
|
||||
return '';
|
||||
}
|
||||
|
||||
/**
|
||||
* @param string $sTabContainer
|
||||
* @param string $sTab
|
||||
*
|
||||
* @return bool
|
||||
*/
|
||||
public function TabExists(string $sTabContainer, string $sTab)
|
||||
{
|
||||
return isset($this->m_aTabs[$sTabContainer]) ? $this->m_aTabs[$sTabContainer]->TabExists($sTab) : false;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return int
|
||||
*/
|
||||
public function TabsContainerCount()
|
||||
{
|
||||
return count($this->m_aTabs);
|
||||
}
|
||||
|
||||
private function GetTab(string $sTabContainer, string $sTab): ?Tab
|
||||
{
|
||||
if ($this->TabExists($sTabContainer, $sTab)) {
|
||||
return $this->m_aTabs[$sTabContainer]->GetTab($sTab);
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param string $sTabContainer
|
||||
* @param string $sTabCode
|
||||
* @param string $sHtml
|
||||
* @param string|null $sTabTitle
|
||||
*
|
||||
* @return string
|
||||
* @throws \Exception
|
||||
*/
|
||||
public function AddToTab(string $sTabContainer, string $sTabCode, string $sHtml, $sTabTitle = null): string
|
||||
{
|
||||
if (!$this->TabExists($sTabContainer, $sTabCode)) {
|
||||
$this->InitTab($sTabContainer, $sTabCode, static::ENUM_TAB_TYPE_HTML, $sTabTitle);
|
||||
}
|
||||
|
||||
$oTab = $this->GetTab($sTabContainer, $sTabCode);
|
||||
|
||||
// Append to the content of the tab
|
||||
$oTab->AddHtml($sHtml);
|
||||
|
||||
return ''; // Nothing to add to the page for now
|
||||
}
|
||||
|
||||
/**
|
||||
* @param string $sTabContainer
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
public function SetCurrentTabContainer($sTabContainer = '')
|
||||
{
|
||||
$sPreviousTabContainer = $this->m_sCurrentTabContainer;
|
||||
$this->m_sCurrentTabContainer = $sTabContainer;
|
||||
|
||||
return $sPreviousTabContainer;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param string $sTabCode
|
||||
*
|
||||
* @param string|null $sTabTitle
|
||||
*
|
||||
* @return string
|
||||
* @throws \Combodo\iTop\Application\UI\Base\UIException
|
||||
*/
|
||||
public function SetCurrentTab(string $sTabCode = '', string $sTabTitle = null): ?string
|
||||
{
|
||||
$sPreviousTabCode = $this->m_sCurrentTab;
|
||||
$this->m_sCurrentTab = $sTabCode;
|
||||
|
||||
if ($sTabCode != '') {
|
||||
// Init tab to HTML tab if not existing
|
||||
if (!$this->TabExists($this->GetCurrentTabContainer(), $sTabCode)) {
|
||||
$this->InitTab($this->GetCurrentTabContainer(), $sTabCode, static::ENUM_TAB_TYPE_HTML, $sTabTitle);
|
||||
}
|
||||
}
|
||||
|
||||
return $sPreviousTabCode;
|
||||
}
|
||||
|
||||
/**
|
||||
* Add a tab which content will be loaded asynchronously via the supplied URL
|
||||
*
|
||||
* Limitations:
|
||||
* Cross site scripting is not not allowed for security reasons. Use a normal tab with an IFRAME if you want to
|
||||
* pull content from another server. Static content cannot be added inside such tabs.
|
||||
*
|
||||
* @param string $sTabCode The (localised) label of the tab
|
||||
* @param string $sUrl The URL to load (on the same server)
|
||||
* @param boolean $bCache Whether or not to cache the content of the tab once it has been loaded. false will cause
|
||||
* the tab to be reloaded upon each activation.
|
||||
*
|
||||
* @param string|null $sTabTitle
|
||||
* @param string $sPlaceholder
|
||||
*
|
||||
* @return string
|
||||
*
|
||||
* @throws \Combodo\iTop\Application\UI\Base\UIException
|
||||
* @since 2.0.3
|
||||
*/
|
||||
public function AddAjaxTab(string $sTabCode, string $sUrl, bool $bCache = true, string $sTabTitle = null, string $sPlaceholder = null): string
|
||||
{
|
||||
// Set the content of the tab
|
||||
/** @var \Combodo\iTop\Application\UI\Base\Layout\TabContainer\Tab\AjaxTab $oTab */
|
||||
$oTab = $this->InitTab($this->m_sCurrentTabContainer, $sTabCode, static::ENUM_TAB_TYPE_AJAX, $sTabTitle, $sPlaceholder);
|
||||
$oTab->SetUrl($sUrl)
|
||||
->SetCache($bCache);
|
||||
|
||||
return ''; // Nothing to add to the page for now
|
||||
}
|
||||
|
||||
/**
|
||||
* @return string
|
||||
*/
|
||||
public function GetCurrentTabContainer()
|
||||
{
|
||||
return $this->m_sCurrentTabContainer;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return string
|
||||
*/
|
||||
public function GetCurrentTab()
|
||||
{
|
||||
return $this->m_sCurrentTab;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param string $sTabCode
|
||||
* @param string|null $sTabContainer
|
||||
*/
|
||||
public function RemoveTab(string $sTabCode, string $sTabContainer = null)
|
||||
{
|
||||
if ($sTabContainer == null) {
|
||||
$sTabContainer = $this->m_sCurrentTabContainer;
|
||||
}
|
||||
if (isset($this->m_aTabs[$sTabContainer]) && $this->m_aTabs[$sTabContainer]->TabExists($sTabCode)) {
|
||||
// Delete the content of the tab
|
||||
$this->m_aTabs[$sTabContainer]->RemoveTab($sTabCode);
|
||||
|
||||
// If we just removed the active tab, let's reset the active tab
|
||||
if (($this->m_sCurrentTabContainer == $sTabContainer) && ($this->m_sCurrentTab == $sTabCode)) {
|
||||
$this->m_sCurrentTab = '';
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Finds the tab whose title matches a given pattern
|
||||
*
|
||||
* @param string $sPattern
|
||||
* @param string|null $sTabContainer
|
||||
*
|
||||
* @return mixed The actual name of the tab (as a string) or false if not found
|
||||
*/
|
||||
public function FindTab(string $sPattern, string $sTabContainer = null)
|
||||
{
|
||||
$result = false;
|
||||
if ($sTabContainer == null) {
|
||||
$sTabContainer = $this->m_sCurrentTabContainer;
|
||||
}
|
||||
if (isset($this->m_aTabs[$sTabContainer])) {
|
||||
foreach ($this->m_aTabs[$sTabContainer]->GetSubBlocks() as $sTabCode => $void) {
|
||||
if (preg_match($sPattern, $sTabCode)) {
|
||||
$result = $sTabCode;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return $result;
|
||||
}
|
||||
|
||||
/**
|
||||
* Make the given tab the active one, as if it were clicked
|
||||
* DOES NOT WORK: apparently in the *old* version of jquery
|
||||
* that we are using this is not supported... TO DO upgrade
|
||||
* the whole jquery bundle...
|
||||
*
|
||||
* @param string $sTabContainer
|
||||
* @param string $sTabCode
|
||||
*
|
||||
* @return string
|
||||
* @deprecated 3.0.0
|
||||
*/
|
||||
public function SelectTab(string $sTabContainer, string $sTabCode)
|
||||
{
|
||||
DeprecatedCallsLog::NotifyDeprecatedPhpMethod();
|
||||
|
||||
return '';
|
||||
}
|
||||
|
||||
/**
|
||||
* @param string $sContent
|
||||
* @param \WebPage $oPage
|
||||
*
|
||||
* @return mixed
|
||||
* @deprecated 3.0.0
|
||||
*/
|
||||
public function RenderIntoContent(string $sContent, WebPage $oPage)
|
||||
{
|
||||
DeprecatedCallsLog::NotifyDeprecatedPhpMethod();
|
||||
|
||||
return '';
|
||||
}
|
||||
|
||||
/**
|
||||
* @param string $sTabContainer
|
||||
* @param string $sTabCode
|
||||
* @param string $sTabType
|
||||
* @param string|null $sTabTitle
|
||||
* @param string|null $sPlaceholder
|
||||
*
|
||||
* @return \Combodo\iTop\Application\UI\Base\Layout\TabContainer\Tab\Tab
|
||||
* @throws \Combodo\iTop\Application\UI\Base\UIException
|
||||
* @since 2.7.0
|
||||
*/
|
||||
protected function InitTab(string $sTabContainer, string $sTabCode, string $sTabType = self::DEFAULT_TAB_TYPE, string $sTabTitle = null, string $sPlaceholder = null): Tab
|
||||
{
|
||||
$oTab = null;
|
||||
if (!$this->TabExists($sTabContainer, $sTabCode)) {
|
||||
if (!isset($this->m_aTabs[$sTabContainer])) {
|
||||
$oTabContainer = $this->AddTabContainer($sTabContainer);
|
||||
} else {
|
||||
$oTabContainer = $this->m_aTabs[$sTabContainer];
|
||||
}
|
||||
|
||||
$sTitle = ($sTabTitle !== null) ? Dict::S($sTabTitle) : Dict::S($sTabCode);
|
||||
|
||||
switch ($sTabType) {
|
||||
case static::ENUM_TAB_TYPE_AJAX:
|
||||
$oTab = $oTabContainer->AddAjaxTab($sTabCode, $sTitle, $sPlaceholder);
|
||||
break;
|
||||
|
||||
case static::ENUM_TAB_TYPE_HTML:
|
||||
default:
|
||||
$oTab = $oTabContainer->AddTab($sTabCode, $sTitle);
|
||||
break;
|
||||
}
|
||||
} else {
|
||||
$oTab = $this->GetTab($sTabContainer, $sTabCode);
|
||||
}
|
||||
|
||||
return $oTab;
|
||||
}
|
||||
}
|
||||
265
sources/Application/WebPage/UnauthenticatedWebPage.php
Normal file
265
sources/Application/WebPage/UnauthenticatedWebPage.php
Normal file
@@ -0,0 +1,265 @@
|
||||
<?php
|
||||
/**
|
||||
* Copyright (C) 2013-2020 Combodo SARL
|
||||
*
|
||||
* This file is part of iTop.
|
||||
*
|
||||
* iTop is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU Affero General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* iTop is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU Affero General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Affero General Public License
|
||||
*/
|
||||
|
||||
|
||||
use Combodo\iTop\Application\Branding;
|
||||
use Combodo\iTop\Application\TwigBase\Twig\TwigHelper;
|
||||
use Combodo\iTop\Renderer\BlockRenderer;
|
||||
use Combodo\iTop\Renderer\Console\ConsoleBlockRenderer;
|
||||
use Combodo\iTop\Service\EventName;
|
||||
use Combodo\iTop\Service\EventService;
|
||||
|
||||
$sPortalBaseFolderRelPath = 'env-' . utils::GetCurrentEnvironment() . '/itop-portal-base/portal/';
|
||||
$sPortalSourcesFolderRelPath = $sPortalBaseFolderRelPath . 'src/';
|
||||
$sPortalPublicFolderRelPath = $sPortalBaseFolderRelPath . 'public/';
|
||||
|
||||
$sPortalBaseFolderAbsPath = APPROOT . $sPortalBaseFolderRelPath;
|
||||
$sPortalSourcesFolderAbsPath = APPROOT . $sPortalSourcesFolderRelPath;
|
||||
$sPortalPublicFolderAbsPath = APPROOT . $sPortalPublicFolderRelPath;
|
||||
|
||||
/** @noinspection PhpUnhandledExceptionInspection */
|
||||
$sPortalPublicFolderAbsUrl = utils::GetAbsoluteUrlModulesRoot().'/itop-portal-base/portal/public/';
|
||||
|
||||
// Constants to be used in the UnauthenticatedWebPage
|
||||
if(!defined('UAWP_PORTAL_PUBLIC_FOLDER_ABSOLUTE_URL'))
|
||||
{
|
||||
define('UAWP_PORTAL_PUBLIC_FOLDER_ABSOLUTE_URL', $sPortalPublicFolderAbsUrl);
|
||||
}
|
||||
if(!defined('UAWP_PORTAL_PUBLIC_FOLDER_RELATIVE_PATH'))
|
||||
{
|
||||
define('UAWP_PORTAL_PUBLIC_FOLDER_RELATIVE_PATH', $sPortalPublicFolderRelPath);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Class UnauthenticatedWebPage
|
||||
*
|
||||
* @author Stephen Abello <stephen.abello@combodo.com>
|
||||
*
|
||||
* @since 3.0.0
|
||||
*/
|
||||
class UnauthenticatedWebPage extends NiceWebPage
|
||||
{
|
||||
const DEFAULT_PAGE_TEMPLATE_REL_PATH = 'pages/backoffice/unauthenticatedwebpage/layout';
|
||||
private $sContent;
|
||||
private $sPanelTitle;
|
||||
private $sPanelIcon;
|
||||
|
||||
// TODO 3.0 Find a clever way to allow theme customization for unauthenticated webpages
|
||||
private $sCustomThemeUrl;
|
||||
|
||||
/**
|
||||
* @inheritDoc
|
||||
* @throws \Exception
|
||||
*/
|
||||
public function __construct($s_title, $bPrintable = false)
|
||||
{
|
||||
$oKpi = new ExecutionKPI();
|
||||
parent::__construct($s_title, $bPrintable);
|
||||
|
||||
$this->sContent = '';
|
||||
$this->sPanelTitle = '';
|
||||
$this->sPanelIcon = Branding::GetFullMainLogoAbsoluteUrl();
|
||||
$this->SetContentType('text/html');
|
||||
|
||||
|
||||
// - bootstrap
|
||||
$this->add_linked_script(UAWP_PORTAL_PUBLIC_FOLDER_ABSOLUTE_URL . 'lib/bootstrap/js/bootstrap.min.js');
|
||||
|
||||
// Note: Since 2.6.0 moment was moved from portal to iTop core
|
||||
$sMomentURL = utils::GetAbsoluteUrlAppRoot().'/js/moment-with-locales.min.js';
|
||||
$this->add_linked_script($sMomentURL);
|
||||
|
||||
$this->add_linked_script(UAWP_PORTAL_PUBLIC_FOLDER_ABSOLUTE_URL . 'lib/bootstrap-datetimepicker/js/bootstrap-datetimepicker.min.js');
|
||||
|
||||
// CSS files
|
||||
$this->add_linked_stylesheet(UAWP_PORTAL_PUBLIC_FOLDER_ABSOLUTE_URL . 'lib/bootstrap/css/bootstrap.min.css');
|
||||
$this->add_saas(UAWP_PORTAL_PUBLIC_FOLDER_RELATIVE_PATH . 'css/bootstrap-theme-combodo.scss');
|
||||
$this->add_linked_stylesheet(UAWP_PORTAL_PUBLIC_FOLDER_ABSOLUTE_URL . 'lib/bootstrap-datetimepicker/css/bootstrap-datetimepicker.css');
|
||||
|
||||
// Default theme
|
||||
$this->add_saas('css/unauthenticated.scss');
|
||||
$oKpi->ComputeStats(get_class($this).' creation', $s_title);
|
||||
}
|
||||
|
||||
/**
|
||||
* @inheritdoc
|
||||
*/
|
||||
public function add($sHtml)
|
||||
{
|
||||
$this->sContent .= $sHtml;
|
||||
}
|
||||
|
||||
/**
|
||||
* @inheritdoc
|
||||
*/
|
||||
public function output()
|
||||
{
|
||||
$oKpi = new ExecutionKPI();
|
||||
// Send headers
|
||||
foreach ($this->a_headers as $sHeader) {
|
||||
header($sHeader);
|
||||
}
|
||||
|
||||
$s_captured_output = $this->ob_get_clean_safe();
|
||||
|
||||
$aData = [];
|
||||
|
||||
// Prepare internal parts (js files, css files, js snippets, css snippets, ...)
|
||||
// - Generate necessary dict. files
|
||||
if ($this->bAddJSDict) {
|
||||
$this->output_dict_entries();
|
||||
}
|
||||
|
||||
$aData['oLayout'] = $this->oContentLayout;
|
||||
$aData['aDeferredBlocks'] = $this->GetDeferredBlocks($this->oContentLayout);
|
||||
|
||||
ConsoleBlockRenderer::AddCssJsToPage($this, $this->oContentLayout);
|
||||
|
||||
// Base structure of data to pass to the TWIG template
|
||||
$aData['aPage'] = [
|
||||
'sAbsoluteUrlAppRoot' => addslashes(utils::GetAbsoluteUrlAppRoot()),
|
||||
'sTitle' => $this->s_title,
|
||||
'aMetadata' => [
|
||||
'sCharset' => static::PAGES_CHARSET,
|
||||
'sLang' => $this->GetLanguageForMetadata(),
|
||||
],
|
||||
'aCssFiles' => $this->a_linked_stylesheets,
|
||||
'aCssInline' => $this->a_styles,
|
||||
'aJsInlineEarly' => $this->a_early_scripts,
|
||||
'aJsFiles' => $this->a_linked_scripts,
|
||||
'aJsInlineLive' => $this->a_scripts,
|
||||
'aJsInlineOnDomReady' => $this->GetReadyScripts(),
|
||||
'aJsInlineOnInit' => $this->a_init_scripts,
|
||||
|
||||
// TODO 3.0.0: TEMP, used while developing, remove it.
|
||||
'sCapturedOutput' => utils::FilterXSS($s_captured_output),
|
||||
'sDeferredContent' => utils::FilterXSS($this->s_deferred_content),
|
||||
'sContent' => $this->sContent,
|
||||
'sPanelIcon' => $this->sPanelIcon,
|
||||
'sPanelTitle' => $this->sPanelTitle
|
||||
];
|
||||
|
||||
$aData['aBlockParams'] = $this->GetBlockParams();
|
||||
|
||||
if ($this->a_base['href'] != '') {
|
||||
$aData['aPage']['aMetadata']['sBaseUrl'] = $this->a_base['href'];
|
||||
}
|
||||
|
||||
if ($this->a_base['target'] != '') {
|
||||
$aData['aPage']['aMetadata']['sBaseTarget'] = $this->a_base['target'];
|
||||
}
|
||||
|
||||
// Favicon
|
||||
$aData['aPage']['sFaviconUrl'] = $this->GetFaviconAbsoluteUrl();
|
||||
|
||||
$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 $sHtml;
|
||||
$oKpi->ComputeAndReport('Echoing ('.round(strlen($sHtml) / 1024).' Kb)');
|
||||
$this->FireAfterDisplayEvent();
|
||||
ExecutionKPI::ReportStats();
|
||||
}
|
||||
|
||||
/**
|
||||
* Displays a success message.
|
||||
*
|
||||
* @param string $sMessage
|
||||
*
|
||||
* @throws \Exception
|
||||
*/
|
||||
public function DisplaySuccessMessage($sMessage)
|
||||
{
|
||||
$this->Display('<div class="alert alert-success">'.$sMessage.'</div>');
|
||||
}
|
||||
|
||||
/**
|
||||
* Displays an error message.
|
||||
*
|
||||
* @param string $sMessage
|
||||
*
|
||||
* @throws \Exception
|
||||
*/
|
||||
public function DisplayErrorMessage($sMessage)
|
||||
{
|
||||
$sFormTitle = Dict::S('UnauthenticatedForms:Form:DefaultLabel:Form:Title');
|
||||
$sHtml = '<div class="alert alert-danger">'.$sMessage.'</div>';
|
||||
|
||||
$this->set_title($sMessage);
|
||||
$this->Display($sHtml, $sFormTitle);
|
||||
}
|
||||
|
||||
/**
|
||||
* @return string
|
||||
*/
|
||||
public function GetPanelTitle(): string
|
||||
{
|
||||
return $this->sPanelTitle;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param string $sPanelTitle
|
||||
*
|
||||
* @return \UnauthenticatedWebPage
|
||||
*/
|
||||
public function SetPanelTitle(string $sPanelTitle): UnauthenticatedWebPage
|
||||
{
|
||||
$this->sPanelTitle = $sPanelTitle;
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return string
|
||||
*/
|
||||
public function GetPanelIcon(): string
|
||||
{
|
||||
return $this->sPanelIcon;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param string $sPanelIcon
|
||||
*
|
||||
* @return \UnauthenticatedWebPage
|
||||
*/
|
||||
public function SetPanelIcon(string $sPanelIcon): UnauthenticatedWebPage
|
||||
{
|
||||
$this->sPanelIcon = $sPanelIcon;
|
||||
return $this;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* @inheritDoc
|
||||
* @throws \Exception
|
||||
*/
|
||||
protected function LoadTheme()
|
||||
{
|
||||
$this->add_linked_stylesheet(utils::GetAbsoluteUrlAppRoot().'css/font-awesome/css/all.min.css');
|
||||
// Default theme
|
||||
$this->add_saas('css/unauthenticated.scss');
|
||||
// Custom theme to allow admin to override the default one.
|
||||
if(!empty($this->sCustomThemeUrl))
|
||||
{
|
||||
$this->add_linked_stylesheet($this->sCustomThemeUrl);
|
||||
}
|
||||
}
|
||||
}
|
||||
1794
sources/Application/WebPage/WebPage.php
Normal file
1794
sources/Application/WebPage/WebPage.php
Normal file
File diff suppressed because it is too large
Load Diff
113
sources/Application/WebPage/XMLPage.php
Normal file
113
sources/Application/WebPage/XMLPage.php
Normal file
@@ -0,0 +1,113 @@
|
||||
<?php
|
||||
// Copyright (C) 2010-2021 Combodo SARL
|
||||
//
|
||||
// This file is part of iTop.
|
||||
//
|
||||
// iTop is free software; you can redistribute it and/or modify
|
||||
// it under the terms of the GNU Affero General Public License as published by
|
||||
// the Free Software Foundation, either version 3 of the License, or
|
||||
// (at your option) any later version.
|
||||
//
|
||||
// iTop is distributed in the hope that it will be useful,
|
||||
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
// GNU Affero General Public License for more details.
|
||||
//
|
||||
// You should have received a copy of the GNU Affero General Public License
|
||||
// along with iTop. If not, see <http://www.gnu.org/licenses/>
|
||||
|
||||
/**
|
||||
* Class XMLPage
|
||||
*
|
||||
* @copyright Copyright (C) 2010-2021 Combodo SARL
|
||||
* @license http://opensource.org/licenses/AGPL-3.0
|
||||
*/
|
||||
|
||||
use Combodo\iTop\Service\EventName;
|
||||
use Combodo\iTop\Service\EventService;
|
||||
|
||||
/**
|
||||
* Simple web page with no includes or fancy formatting, useful to generateXML documents
|
||||
* The page adds the content-type text/XML and the encoding into the headers
|
||||
*/
|
||||
class XMLPage extends WebPage
|
||||
{
|
||||
/**
|
||||
* For big XML files, it's better NOT to store everything in memory and output the XML piece by piece
|
||||
*/
|
||||
var $m_bPassThrough;
|
||||
var $m_bHeaderSent;
|
||||
|
||||
function __construct($s_title, $bPassThrough = false)
|
||||
{
|
||||
$oKpi = new ExecutionKPI();
|
||||
parent::__construct($s_title);
|
||||
$this->m_bPassThrough = $bPassThrough;
|
||||
$this->m_bHeaderSent = false;
|
||||
$this->add_header("Content-type: text/xml; charset=".self::PAGES_CHARSET);
|
||||
$this->no_cache();
|
||||
$this->add_xframe_options();
|
||||
$this->add_header("Content-location: export.xml");
|
||||
$oKpi->ComputeStats(get_class($this).' creation', 'XMLPage');
|
||||
}
|
||||
|
||||
public function output()
|
||||
{
|
||||
if (!$this->m_bPassThrough)
|
||||
{
|
||||
$oKpi = new ExecutionKPI();
|
||||
|
||||
// Get the unexpected output but do nothing with it
|
||||
$sTrash = $this->ob_get_clean_safe();
|
||||
|
||||
$sCharset = self::PAGES_CHARSET;
|
||||
$this->s_content = "<?xml version=\"1.0\" encoding=\"$sCharset\"?".">\n".trim($this->s_content);
|
||||
$this->add_header("Content-Length: ".strlen($this->s_content));
|
||||
foreach($this->a_headers as $s_header)
|
||||
{
|
||||
header($s_header);
|
||||
}
|
||||
$oKpi->ComputeAndReport(get_class($this).' output');
|
||||
echo $this->s_content;
|
||||
$oKpi->ComputeAndReport('Echoing ('.round(strlen($this->s_content) / 1024).' Kb)');
|
||||
}
|
||||
if (class_exists('DBSearch')) {
|
||||
DBSearch::RecordQueryTrace();
|
||||
}
|
||||
$this->FireAfterDisplayEvent();
|
||||
ExecutionKPI::ReportStats();
|
||||
}
|
||||
|
||||
public function add($sText)
|
||||
{
|
||||
if (!$this->m_bPassThrough) {
|
||||
parent::add($sText);
|
||||
} else {
|
||||
if ($this->m_bHeaderSent) {
|
||||
echo $sText;
|
||||
}
|
||||
else
|
||||
{
|
||||
$s_captured_output = $this->ob_get_clean_safe();
|
||||
foreach($this->a_headers as $s_header)
|
||||
{
|
||||
header($s_header);
|
||||
}
|
||||
$sCharset = self::PAGES_CHARSET;
|
||||
echo "<?xml version=\"1.0\" encoding=\"$sCharset\"?".">\n";
|
||||
echo trim($s_captured_output);
|
||||
echo trim($this->s_content);
|
||||
echo $sText;
|
||||
$this->m_bHeaderSent = true;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public function small_p($sText)
|
||||
{
|
||||
}
|
||||
|
||||
public function table($aConfig, $aData, $aParams = array())
|
||||
{
|
||||
}
|
||||
}
|
||||
80
sources/Application/WebPage/iTabbedPage.php
Normal file
80
sources/Application/WebPage/iTabbedPage.php
Normal file
@@ -0,0 +1,80 @@
|
||||
<?php
|
||||
|
||||
use Combodo\iTop\Application\UI\Base\Layout\iUIContentBlock;
|
||||
|
||||
/**
|
||||
* @copyright Copyright (C) 2010-2021 Combodo SARL
|
||||
* @license http://opensource.org/licenses/AGPL-3.0
|
||||
*/
|
||||
interface iTabbedPage
|
||||
{
|
||||
/**
|
||||
* @param string $sTabContainer
|
||||
* @param string $sPrefix
|
||||
*
|
||||
* @param \Combodo\iTop\Application\UI\Base\Layout\iUIContentBlock|null $oParentBlock
|
||||
*
|
||||
* @return mixed
|
||||
*/
|
||||
public function AddTabContainer($sTabContainer, $sPrefix = '', iUIContentBlock $oParentBlock = null);
|
||||
|
||||
/**
|
||||
* @param string $sTabContainer
|
||||
* @param string $sTabCode
|
||||
* @param string $sHtml
|
||||
*
|
||||
* @return mixed
|
||||
*/
|
||||
public function AddToTab($sTabContainer, $sTabCode, $sHtml);
|
||||
|
||||
/**
|
||||
* @param string $sTabContainer
|
||||
*
|
||||
* @return mixed
|
||||
*/
|
||||
public function SetCurrentTabContainer($sTabContainer = '');
|
||||
|
||||
/**
|
||||
* @param string $sTabCode
|
||||
*
|
||||
* @return mixed
|
||||
*/
|
||||
public function SetCurrentTab($sTabCode = '');
|
||||
|
||||
/**
|
||||
* Add a tab which content will be loaded asynchronously via the supplied URL
|
||||
*
|
||||
* Limitations:
|
||||
* Cross site scripting is not not allowed for security reasons. Use a normal tab with an IFRAME if you want to
|
||||
* pull content from another server. Static content cannot be added inside such tabs.
|
||||
*
|
||||
* @param string $sTabCode The (localised) label of the tab
|
||||
* @param string $sUrl The URL to load (on the same server)
|
||||
* @param boolean $bCache Whether or not to cache the content of the tab once it has been loaded. flase will cause
|
||||
* the tab to be reloaded upon each activation.
|
||||
* @param string|null $sTabTitle
|
||||
*
|
||||
* @since 2.0.3
|
||||
*/
|
||||
public function AddAjaxTab($sTabCode, $sUrl, $bCache = true, $sTabTitle = null);
|
||||
|
||||
public function GetCurrentTab();
|
||||
|
||||
/**
|
||||
* @param string $sTabCode
|
||||
* @param string|null $sTabContainer
|
||||
*
|
||||
* @return mixed
|
||||
*/
|
||||
public function RemoveTab($sTabCode, $sTabContainer = null);
|
||||
|
||||
/**
|
||||
* Finds the tab whose title matches a given pattern
|
||||
*
|
||||
* @param string $sPattern
|
||||
* @param string|null $sTabContainer
|
||||
*
|
||||
* @return mixed The name of the tab as a string or false if not found
|
||||
*/
|
||||
public function FindTab($sPattern, $sTabContainer = null);
|
||||
}
|
||||
119
sources/Application/WebPage/iTopPDF.php
Normal file
119
sources/Application/WebPage/iTopPDF.php
Normal file
@@ -0,0 +1,119 @@
|
||||
<?php
|
||||
/**
|
||||
* @copyright Copyright (C) 2010-2021 Combodo SARL
|
||||
* @license http://opensource.org/licenses/AGPL-3.0
|
||||
*/
|
||||
|
||||
use Combodo\iTop\Application\Branding;
|
||||
|
||||
|
||||
/**
|
||||
* Custom class derived from TCPDF for providing custom headers and footers
|
||||
*
|
||||
* @author denis
|
||||
*
|
||||
*/
|
||||
class iTopPDF extends TCPDF
|
||||
{
|
||||
protected $sDocumentTitle;
|
||||
|
||||
/**
|
||||
* Shortcut for {@link TCPDF::SetFont}, to use the font configured
|
||||
*
|
||||
* @param string $style
|
||||
* @param int $size
|
||||
* @param string $fontfile
|
||||
* @param string $subset
|
||||
* @param bool $out
|
||||
*
|
||||
* @uses \TCPDF::SetFont()
|
||||
* @uses \iTopPDF::GetPdfFont()
|
||||
* @since 2.7.0
|
||||
*/
|
||||
public function SetFontParams($style, $size, $fontfile = '', $subset = 'default', $out = true)
|
||||
{
|
||||
$siTopFont = self::GetPdfFont();
|
||||
$this->SetFont($siTopFont, $style, $size, $fontfile, $subset, $out);
|
||||
}
|
||||
|
||||
public function SetDocumentTitle($sDocumentTitle)
|
||||
{
|
||||
$this->sDocumentTitle = $sDocumentTitle;
|
||||
}
|
||||
|
||||
/**
|
||||
* Add image
|
||||
*
|
||||
* @param string $sImagePath Name of the SVG file or a '@' character followed by the SVG data string.
|
||||
* @param $x (float) Abscissa of the upper-left corner.
|
||||
* @param $y (float) Ordinate of the upper-left corner.
|
||||
* @param $w (float) Width of the image in the page. If not specified or equal to zero, it is automatically calculated.
|
||||
* @param $h (float) Height of the image in the page. If not specified or equal to zero, it is automatically calculated.
|
||||
*/
|
||||
public function AddImage($sImagePath, $x = '', $y = '', $w = 0, $h = 0)
|
||||
{
|
||||
/*if (endsWith(strtolower($sImagePath), ".svg")) {
|
||||
$this->ImageSVG($sImagePath, $x, $y, $w, $h);
|
||||
} else {
|
||||
$this->Image($sImagePath, $x, $y, $w, $h);
|
||||
}*/
|
||||
$imgtype = TCPDF_IMAGES::getImageFileType($sImagePath);
|
||||
if (($imgtype == 'eps') or ($imgtype == 'ai')) {
|
||||
$this->ImageEps($sImagePath, $x, $y, $w, $h);;
|
||||
} elseif ($imgtype == 'svg') {
|
||||
$this->ImageSVG($sImagePath, $x, $y, $w, $h);;
|
||||
} else {
|
||||
$this->Image($sImagePath, $x, $y, $w, $h);;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Builds the custom header. Called for each new page.
|
||||
*
|
||||
* @see TCPDF::Header()
|
||||
*/
|
||||
public function Header()
|
||||
{
|
||||
// Title
|
||||
// Set font
|
||||
$this->SetFontParams('B', 10);
|
||||
|
||||
$iPageNumberWidth = 25;
|
||||
$aMargins = $this->getMargins();
|
||||
|
||||
// Display the title (centered)
|
||||
$this->SetXY($aMargins['left'] + $iPageNumberWidth, 0);
|
||||
$this->MultiCell($this->getPageWidth() - $aMargins['left'] - $aMargins['right'] - 2 * $iPageNumberWidth, 15, $this->sDocumentTitle,
|
||||
0, 'C', false, 0 /* $ln */, '', '', true, 0, false, true, 15, 'M' /* $valign */);
|
||||
$this->SetFontParams('', 10);
|
||||
|
||||
// Display the page number (right aligned)
|
||||
// Warning: the 'R'ight alignment does not work when using placeholders like $this->getAliasNumPage() or $this->getAliasNbPages()
|
||||
$this->MultiCell($iPageNumberWidth, 15, Dict::Format('Core:BulkExport:PDF:PageNumber', $this->page), 0, 'R', false, 0 /* $ln */, '',
|
||||
'', true, 0, false, true, 15, 'M' /* $valign */);
|
||||
|
||||
// Branding logo
|
||||
$sBrandingIcon = Branding::GetLogoRelativePath(Branding::ENUM_LOGO_TYPE_MAIN_LOGO_FULL);
|
||||
|
||||
$this->AddImage($sBrandingIcon, $aMargins['left'], 5, 0, 10);
|
||||
}
|
||||
|
||||
// Page footer
|
||||
public function Footer()
|
||||
{
|
||||
// No footer
|
||||
}
|
||||
|
||||
/**
|
||||
* dejavusans is a UTF-8 Unicode font. Standard PDF fonts like helvetica or times new roman are NOT UTF-8
|
||||
*
|
||||
* @return string font in the config file (export_pdf_font)
|
||||
*/
|
||||
public static function GetPdfFont()
|
||||
{
|
||||
$oConfig = utils::GetConfig();
|
||||
$sPdfFont = $oConfig->Get('export_pdf_font');
|
||||
|
||||
return $sPdfFont;
|
||||
}
|
||||
}
|
||||
1247
sources/Application/WebPage/iTopWebPage.php
Normal file
1247
sources/Application/WebPage/iTopWebPage.php
Normal file
File diff suppressed because it is too large
Load Diff
57
sources/Application/WebPage/iTopWizardWebPage.php
Normal file
57
sources/Application/WebPage/iTopWizardWebPage.php
Normal file
@@ -0,0 +1,57 @@
|
||||
<?php
|
||||
// Copyright (C) 2010-2021 Combodo SARL
|
||||
//
|
||||
// This file is part of iTop.
|
||||
//
|
||||
// iTop is free software; you can redistribute it and/or modify
|
||||
// it under the terms of the GNU Affero General Public License as published by
|
||||
// the Free Software Foundation, either version 3 of the License, or
|
||||
// (at your option) any later version.
|
||||
//
|
||||
// iTop is distributed in the hope that it will be useful,
|
||||
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
// GNU Affero General Public License for more details.
|
||||
//
|
||||
// You should have received a copy of the GNU Affero General Public License
|
||||
// along with iTop. If not, see <http://www.gnu.org/licenses/>
|
||||
|
||||
|
||||
/**
|
||||
* Class iTopWizardWebPage
|
||||
*
|
||||
* @copyright Copyright (C) 2010-2021 Combodo SARL
|
||||
* @license http://opensource.org/licenses/AGPL-3.0
|
||||
*/
|
||||
|
||||
/**
|
||||
* Web page to display a wizard in the iTop framework
|
||||
*/
|
||||
class iTopWizardWebPage extends iTopWebPage
|
||||
{
|
||||
var $m_iCurrentStep;
|
||||
var $m_aSteps;
|
||||
public function __construct($sTitle, $currentOrganization, $iCurrentStep, $aSteps)
|
||||
{
|
||||
$oKpi = new ExecutionKPI();
|
||||
parent::__construct($sTitle." - step $iCurrentStep of ".count($aSteps)." - ".$aSteps[$iCurrentStep - 1], $currentOrganization);
|
||||
$this->m_iCurrentStep = $iCurrentStep;
|
||||
$this->m_aSteps = $aSteps;
|
||||
$oKpi->ComputeStats(get_class($this).' creation', 'iTopWizardWebPage');
|
||||
}
|
||||
|
||||
public function output()
|
||||
{
|
||||
$aSteps = array();
|
||||
$iIndex = 0;
|
||||
foreach($this->m_aSteps as $sStepTitle)
|
||||
{
|
||||
$iIndex++;
|
||||
$sStyle = ($iIndex == $this->m_iCurrentStep) ? 'wizActiveStep' : 'wizStep';
|
||||
$aSteps[] = "<div class=\"$sStyle\"><span>$sStepTitle</span></div>";
|
||||
}
|
||||
$sWizardHeader = "<div class=\"wizHeader\"><h1>".htmlentities($this->s_title, ENT_QUOTES, 'UTF-8')."</h1>\n".implode("<div class=\"wizSeparator\"><img align=\"bottom\" src=\"../images/wizArrow.gif\"></div>", $aSteps)."<br style=\"clear:both;\"/></div>\n";
|
||||
$this->s_content = "$sWizardHeader<div class=\"wizContainer\">".$this->s_content."</div>";
|
||||
parent::output();
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user