diff --git a/application/cmdbabstract.class.inc.php b/application/cmdbabstract.class.inc.php index 780a7022c..b81fa21d3 100644 --- a/application/cmdbabstract.class.inc.php +++ b/application/cmdbabstract.class.inc.php @@ -10,6 +10,7 @@ use Combodo\iTop\Application\UI\Base\Component\Button\Button; use Combodo\iTop\Application\UI\Base\Component\Button\ButtonUIBlockFactory; use Combodo\iTop\Application\UI\Base\Component\DataTable\DataTableSettings; use Combodo\iTop\Application\UI\Base\Component\DataTable\DataTableUIBlockFactory; +use Combodo\iTop\Application\UI\Base\Component\DataTable\StaticTable\StaticTable; use Combodo\iTop\Application\UI\Base\Component\Field\Field; use Combodo\iTop\Application\UI\Base\Component\Field\FieldUIBlockFactory; use Combodo\iTop\Application\UI\Base\Component\FieldSet\FieldSet; @@ -1173,6 +1174,9 @@ HTML public static function GetDisplaySetBlock(WebPage $oPage, DBObjectSet $oSet, $aExtraParams = array()) { + if ($oPage->IsPrintableVersion() || $oPage->is_pdf()) { + return self::GetDisplaySetForPrinting($oPage, $oSet, $aExtraParams); + } if (empty($aExtraParams['currentId'])) { $iListId = utils::GetUniqueId(); // Works only if not in an Ajax page !! } else { @@ -1181,6 +1185,146 @@ HTML return DataTableUIBlockFactory::MakeForResult($oPage, $iListId, $oSet, $aExtraParams); } + + public static function GetDataTableFromDBObjectSet(DBObjectSet $oSet, $aParams = array()) + { + $aFields = null; + if (isset($aParams['fields']) && (strlen($aParams['fields']) > 0)) { + $aFields = explode(',', $aParams['fields']); + } + + $bFieldsAdvanced = false; + if (isset($aParams['fields_advanced'])) { + $bFieldsAdvanced = (bool)$aParams['fields_advanced']; + } + + $bLocalize = true; + if (isset($aParams['localize_values'])) { + $bLocalize = (bool)$aParams['localize_values']; + } + + $aList = array(); + + $aClasses = $oSet->GetFilter()->GetSelectedClasses(); + $aAuthorizedClasses = array(); + foreach ($aClasses as $sAlias => $sClassName) { + if (UserRights::IsActionAllowed($sClassName, UR_ACTION_READ, $oSet) != UR_ALLOWED_NO) { + $aAuthorizedClasses[$sAlias] = $sClassName; + } + } + $aHeader = array(); + foreach ($aAuthorizedClasses as $sAlias => $sClassName) { + $aList[$sAlias] = array(); + + foreach (MetaModel::GetZListItems($sClassName, 'list') as $sAttCode) { + $oAttDef = Metamodel::GetAttributeDef($sClassName, $sAttCode); + if (is_null($aFields) || (count($aFields) == 0)) { + // Standard list of attributes (no link sets) + if ($oAttDef->IsScalar() && ($oAttDef->IsWritable() || $oAttDef->IsExternalField())) { + $sAttCodeEx = $oAttDef->IsExternalField() ? $oAttDef->GetKeyAttCode().'->'.$oAttDef->GetExtAttCode() : $sAttCode; + + $aList[$sAlias][$sAttCodeEx] = $oAttDef; + + if ($bFieldsAdvanced && $oAttDef->IsExternalKey(EXTKEY_RELATIVE)) { + $sRemoteClass = $oAttDef->GetTargetClass(); + foreach (MetaModel::GetReconcKeys($sRemoteClass) as $sRemoteAttCode) { + $aList[$sAlias][$sAttCode.'->'.$sRemoteAttCode] = MetaModel::GetAttributeDef($sRemoteClass, + $sRemoteAttCode); + } + } + } + } else { + // User defined list of attributes + if (in_array($sAttCode, $aFields) || in_array($sAlias.'.'.$sAttCode, $aFields)) { + $aList[$sAlias][$sAttCode] = $oAttDef; + } + } + } + // Replace external key by the corresponding friendly name (if not already in the list) + foreach ($aList[$sAlias] as $sAttCode => $oAttDef) { + if ($oAttDef->IsExternalKey()) { + unset($aList[$sAlias][$sAttCode]); + $sFriendlyNameAttCode = $sAttCode.'_friendlyname'; + if (!array_key_exists($sFriendlyNameAttCode, + $aList[$sAlias]) && MetaModel::IsValidAttCode($sClassName, $sFriendlyNameAttCode)) { + $oFriendlyNameAtt = MetaModel::GetAttributeDef($sClassName, $sFriendlyNameAttCode); + $aList[$sAlias][$sFriendlyNameAttCode] = $oFriendlyNameAtt; + } + } + } + + foreach ($aList[$sAlias] as $sAttCodeEx => $oAttDef) { + $sColLabel = $bLocalize ? MetaModel::GetLabel($sClassName, $sAttCodeEx) : $sAttCodeEx; + + $oFinalAttDef = $oAttDef->GetFinalAttDef(); + if (get_class($oFinalAttDef) == 'AttributeDateTime') { + $aHeader[$oAttDef->GetCode().'/D'] = ['label' => $sColLabel.' ('.Dict::S('UI:SplitDateTime-Date').')']; + $aHeader[$oAttDef->GetCode().'/T'] = ['label' => $sColLabel.' ('.Dict::S('UI:SplitDateTime-Time').')']; + } else { + $aHeader[$oAttDef->GetCode()] = ['label' => $sColLabel]; + } + } + } + + + $oSet->Seek(0); + $aRows = []; + while ($aObjects = $oSet->FetchAssoc()) { + $aRow = []; + foreach ($aAuthorizedClasses as $sAlias => $sClassName) { + $oObj = $aObjects[$sAlias]; + foreach ($aList[$sAlias] as $sAttCodeEx => $oAttDef) { + if (is_null($oObj)) { + $aRow[$oAttDef->GetCode()] = ''; + } else { + $oFinalAttDef = $oAttDef->GetFinalAttDef(); + if (get_class($oFinalAttDef) == 'AttributeDateTime') { + $sDate = $oObj->Get($sAttCodeEx); + if ($sDate === null) { + $aRow[$oAttDef->GetCode().'/D'] = ''; + $aRow[$oAttDef->GetCode().'/T'] = ''; + } else { + $iDate = AttributeDateTime::GetAsUnixSeconds($sDate); + $aRow[$oAttDef->GetCode().'/D'] = date('Y-m-d', $iDate); // Format kept as-is for 100% backward compatibility of the exports + $aRow[$oAttDef->GetCode().'/T'] = date('H:i:s', $iDate); // Format kept as-is for 100% backward compatibility of the exports + } + } else { + if ($oAttDef instanceof AttributeCaseLog) { + $rawValue = $oObj->Get($sAttCodeEx); + $outputValue = str_replace("\n", "
", htmlentities($rawValue->__toString(), ENT_QUOTES, 'UTF-8')); + // Trick for Excel: treat the content as text even if it begins with an equal sign + $aRow[$oAttDef->GetCode()] = $outputValue; + } else { + $rawValue = $oObj->Get($sAttCodeEx); + // Due to custom formatting rules, empty friendlynames may be rendered as non-empty strings + // let's fix this and make sure we render an empty string if the key == 0 + if ($oAttDef instanceof AttributeExternalField && $oAttDef->IsFriendlyName()) { + $sKeyAttCode = $oAttDef->GetKeyAttCode(); + if ($oObj->Get($sKeyAttCode) == 0) { + $rawValue = ''; + } + } + if ($bLocalize) { + $outputValue = htmlentities($oFinalAttDef->GetEditValue($rawValue), ENT_QUOTES, 'UTF-8'); + } else { + $outputValue = htmlentities($rawValue, ENT_QUOTES, 'UTF-8'); + } + $aRow[$oAttDef->GetCode()] = $outputValue; + } + } + } + } + } + $aRows[] = $aRow; + } + $oTable = new StaticTable(); + $oTable->SetColumns($aHeader); + $oTable->SetData($aRows); + + return $oTable; + //DataTableUIBlockFactory::MakeForStaticData('', $aHeader, $aRows); + } + /** * @param \WebPage $oPage * @param \CMDBObjectSet $oSet diff --git a/core/displayablegraph.class.inc.php b/core/displayablegraph.class.inc.php index 47549f637..ed6e45c7d 100644 --- a/core/displayablegraph.class.inc.php +++ b/core/displayablegraph.class.inc.php @@ -119,13 +119,12 @@ class DisplayableNode extends GraphNode $Alpha = 1.0; $oPdf->SetFillColor(200, 200, 200); $oPdf->setAlpha(1); - + $sIconUrl = $this->GetProperty('icon_url'); $sIconPath = str_replace(utils::GetAbsoluteUrlModulesRoot(), APPROOT.'env-'.utils::GetCurrentEnvironment().'/', $sIconUrl); - - if ($this->GetProperty('source')) - { - $oPdf->SetLineStyle(array('width' => 2*$fScale, 'cap' => 'round', 'join' => 'miter', 'dash' => 0, 'color' => array(204, 51, 51))); + + if ($this->GetProperty('source')) { + $oPdf->SetLineStyle(array('width' => 2 * $fScale, 'cap' => 'round', 'join' => 'miter', 'dash' => 0, 'color' => array(204, 51, 51))); $oPdf->Circle($this->x * $fScale, $this->y * $fScale, 16 * 1.25 * $fScale, 0, 360, 'D'); } else if ($this->GetProperty('sink')) @@ -133,34 +132,30 @@ class DisplayableNode extends GraphNode $oPdf->SetLineStyle(array('width' => 2*$fScale, 'cap' => 'round', 'join' => 'miter', 'dash' => 0, 'color' => array(51, 51, 204))); $oPdf->Circle($this->x * $fScale, $this->y * $fScale, 16 * 1.25 * $fScale, 0, 360, 'D'); } - - if (!$this->GetProperty('is_reached')) - { + + if (!$this->GetProperty('is_reached')) { $sTempImageName = $this->CreateWhiteIcon($oGraph, $sIconPath); - if ($sTempImageName != null) - { - $oPdf->Image($sTempImageName, ($this->x - 16)*$fScale, ($this->y - 16)*$fScale, 32*$fScale, 32*$fScale, 'PNG'); + if ($sTempImageName != null) { + $oPdf->AddImage($sTempImageName, ($this->x - 16) * $fScale, ($this->y - 16) * $fScale, 32 * $fScale, 32 * $fScale, 'PNG'); } $Alpha = 0.4; $oPdf->setAlpha($Alpha); } - - $oPdf->Image($sIconPath, ($this->x - 16)*$fScale, ($this->y - 16)*$fScale, 32*$fScale, 32*$fScale); - + + $oPdf->AddImage($sIconPath, ($this->x - 16) * $fScale, ($this->y - 16) * $fScale, 32 * $fScale, 32 * $fScale); + $aContextRootCauses = $this->GetProperty('context_root_causes'); - if (!is_null($aContextRootCauses)) - { + if (!is_null($aContextRootCauses)) { $idx = 0; - foreach($aContextRootCauses as $key => $aObjects) - { - $sgn = 2*($idx %2) -1; - $coef = floor((1+$idx)/2) * $sgn; - $alpha = $coef*pi()/4 - pi()/2; - $x = $this->x * $fScale + cos($alpha) * 16*1.25 * $fScale; - $y = $this->y * $fScale + sin($alpha) * 16*1.25 * $fScale; + foreach ($aContextRootCauses as $key => $aObjects) { + $sgn = 2 * ($idx % 2) - 1; + $coef = floor((1 + $idx) / 2) * $sgn; + $alpha = $coef * pi() / 4 - pi() / 2; + $x = $this->x * $fScale + cos($alpha) * 16 * 1.25 * $fScale; + $y = $this->y * $fScale + sin($alpha) * 16 * 1.25 * $fScale; $l = 32 * $fScale / 3; $sIconPath = APPROOT.'env-'.utils::GetCurrentEnvironment().'/'.$aContextDefs[$key]['icon']; - $oPdf->Image($sIconPath, $x - $l/2, $y - $l/2, $l, $l); + $oPdf->AddImage($sIconPath, $x - $l / 2, $y - $l / 2, $l, $l); $idx++; } } @@ -779,8 +774,8 @@ class DisplayableGroupNode extends DisplayableNode { $aBorderColor = array(200, 200, 200); } - $oPdf->SetLineStyle(array('width' => 2*$fScale, 'cap' => 'round', 'join' => 'miter', 'dash' => 0, 'color' => $aBorderColor)); - + $oPdf->SetLineStyle(array('width' => 2 * $fScale, 'cap' => 'round', 'join' => 'miter', 'dash' => 0, 'color' => $aBorderColor)); + $sIconUrl = $this->GetProperty('icon_url'); $sIconPath = str_replace(utils::GetAbsoluteUrlModulesRoot(), APPROOT.'env-'.utils::GetCurrentEnvironment().'/', $sIconUrl); $oPdf->SetAlpha(1); @@ -794,13 +789,13 @@ class DisplayableGroupNode extends DisplayableNode { $oPdf->SetAlpha(0.4); } - $oPdf->Image($sIconPath, ($this->x - 17)*$fScale, ($this->y - 17)*$fScale, 16*$fScale, 16*$fScale); - $oPdf->Image($sIconPath, ($this->x + 1)*$fScale, ($this->y - 17)*$fScale, 16*$fScale, 16*$fScale); - $oPdf->Image($sIconPath, ($this->x -8)*$fScale, ($this->y +1)*$fScale, 16*$fScale, 16*$fScale); + $oPdf->AddImage($sIconPath, ($this->x - 17) * $fScale, ($this->y - 17) * $fScale, 16 * $fScale, 16 * $fScale); + $oPdf->AddImage($sIconPath, ($this->x + 1) * $fScale, ($this->y - 17) * $fScale, 16 * $fScale, 16 * $fScale); + $oPdf->AddImage($sIconPath, ($this->x - 8) * $fScale, ($this->y + 1) * $fScale, 16 * $fScale, 16 * $fScale); $oPdf->SetFontParams('', 24 * $fScale, '', true); $width = $oPdf->GetStringWidth($this->GetProperty('label')); $oPdf->SetTextColor(0, 0, 0); - $oPdf->Text($this->x*$fScale - $width/2, ($this->y + 25)*$fScale, $this->GetProperty('label')); + $oPdf->Text($this->x * $fScale - $width / 2, ($this->y + 25) * $fScale, $this->GetProperty('label')); } public function GetTooltip($aContextDefs) @@ -1185,7 +1180,7 @@ class DisplayableGraph extends SimpleGraph return json_encode($aData); } - + /** * Sort class "codes" based on their localized name * @param string $sClass1 @@ -1196,12 +1191,12 @@ class DisplayableGraph extends SimpleGraph { return strcasecmp(MetaModel::GetName($sClass1), MetaModel::GetName($sClass2)); } - + /** * Renders the graph in a PDF document: centered in the current page * @param PDFPage $oPage The PDFPage representing the PDF document to draw into * @param string $sComments An optional comment to display next to the graph (HTML entities will be escaped, \n replaced by
) - * @param string $sContextKey The key to fetch the queries in the configuration. Example: itop-tickets/relation_context/UserRequest/impacts/down + * @param string $sContextKey The key to fetch the queries in the configuration. Example: itop-tickets/relation_context/UserRequest/impacts/down * @param float $xMin Left coordinate of the bounding box to display the graph * @param float $xMax Right coordinate of the bounding box to display the graph * @param float $yMin Top coordinate of the bounding box to display the graph @@ -1329,20 +1324,18 @@ class DisplayableGraph extends SimpleGraph $yPos = $yMin + $fPadding; $oPdf->SetFillColor(225, 225, 225); $oPdf->Cell($fIconSize + $fPadding + $fMaxWidth, $fIconSize + $fPadding, Dict::S('UI:Relation:Key'), 0 /* border */, 1 /* ln */, 'C', true /* fill */); - $yPos += $fIconSize + 2*$fPadding; - foreach($aClasses as $sClass => $sLabel) - { + $yPos += $fIconSize + 2 * $fPadding; + foreach ($aClasses as $sClass => $sLabel) { $oPdf->SetX($xMin + $fIconSize + $fPadding); - $oPdf->Cell(0, $fIconSize + 2*$fPadding, $sLabel, 0 /* border */, 1 /* ln */); - $oPdf->Image($aIcons[$sClass], $xMin+1, $yPos, $fIconSize, $fIconSize); - $yPos += $fIconSize + 2*$fPadding; + $oPdf->Cell(0, $fIconSize + 2 * $fPadding, $sLabel, 0 /* border */, 1 /* ln */); + $oPdf->AddImage($aIcons[$sClass], $xMin + 1, $yPos, $fIconSize, $fIconSize); + $yPos += $fIconSize + 2 * $fPadding; } - foreach($aContexts as $key => $sLabel) - { + foreach ($aContexts as $key => $sLabel) { $oPdf->SetX($xMin + $fIconSize + $fPadding); - $oPdf->Cell(0, $fIconSize + 2*$fPadding, $sLabel, 0 /* border */, 1 /* ln */); - $oPdf->Image($aContextIcons[$key], $xMin+1+$fIconSize*0.125, $yPos+$fIconSize*0.125, $fIconSize*0.75, $fIconSize*0.75); - $yPos += $fIconSize + 2*$fPadding; + $oPdf->Cell(0, $fIconSize + 2 * $fPadding, $sLabel, 0 /* border */, 1 /* ln */); + $oPdf->AddImage($aContextIcons[$key], $xMin + 1 + $fIconSize * 0.125, $yPos + $fIconSize * 0.125, $fIconSize * 0.75, $fIconSize * 0.75); + $yPos += $fIconSize + 2 * $fPadding; } $oPdf->Rect($xMin, $yMin, $fMaxWidth + $fIconSize + 3*$fPadding, $yMax - $yMin, 'D'); diff --git a/pages/ajax.render.php b/pages/ajax.render.php index 169662352..578158e19 100644 --- a/pages/ajax.render.php +++ b/pages/ajax.render.php @@ -5,6 +5,9 @@ */ use Combodo\iTop\Application\TwigBase\Twig\TwigHelper; +use Combodo\iTop\Application\UI\Base\Component\DataTable\DataTableUIBlockFactory; +use Combodo\iTop\Application\UI\Base\Component\Html\Html; +use Combodo\iTop\Application\UI\Base\Component\Title\TitleUIBlockFactory; use Combodo\iTop\Controller\AjaxRenderController; use Combodo\iTop\Controller\Base\Layout\ActivityPanelController; use Combodo\iTop\Controller\PreferencesController; @@ -2002,63 +2005,51 @@ EOF $aContexts = utils::ReadParam('contexts', array(), false, 'raw_data'); $sContextKey = utils::ReadParam('context_key', '', false, 'raw_data'); $aPositions = null; - if ($sPositions != null) - { + if ($sPositions != null) { $aPositions = json_decode($sPositions, true); } // Get the list of source objects $aSources = utils::ReadParam('sources', array(), false, 'raw_data'); $aSourceObjects = array(); - foreach($aSources as $sClass => $aIDs) - { + foreach ($aSources as $sClass => $aIDs) { $oSearch = new DBObjectSearch($sClass); $oSearch->AddCondition('id', $aIDs, 'IN'); $oSet = new DBObjectSet($oSearch); - while ($oObj = $oSet->Fetch()) - { + while ($oObj = $oSet->Fetch()) { $aSourceObjects[] = $oObj; } } $sSourceClass = '*'; - if (count($aSourceObjects) == 1) - { + if (count($aSourceObjects) == 1) { $sSourceClass = get_class($aSourceObjects[0]); } // Get the list of excluded objects $aExcluded = utils::ReadParam('excluded', array(), false, 'raw_data'); $aExcludedObjects = array(); - foreach($aExcluded as $sClass => $aIDs) - { + foreach ($aExcluded as $sClass => $aIDs) { $oSearch = new DBObjectSearch($sClass); $oSearch->AddCondition('id', $aIDs, 'IN'); $oSet = new DBObjectSet($oSearch); - while ($oObj = $oSet->Fetch()) - { + while ($oObj = $oSet->Fetch()) { $aExcludedObjects[] = $oObj; } } $iMaxRecursionDepth = MetaModel::GetConfig()->Get('relations_max_depth'); - if ($sDirection == 'up') - { + if ($sDirection == 'up') { $oRelGraph = MetaModel::GetRelatedObjectsUp($sRelation, $aSourceObjects, $iMaxRecursionDepth, true, $aContexts); - } - else - { + } else { $oRelGraph = MetaModel::GetRelatedObjectsDown($sRelation, $aSourceObjects, $iMaxRecursionDepth, true, $aExcludedObjects, $aContexts); } // Remove excluded classes from the graph - if (count($aExcludedClasses) > 0) - { + if (count($aExcludedClasses) > 0) { $oIterator = new RelationTypeIterator($oRelGraph, 'Node'); - foreach($oIterator as $oNode) - { + foreach ($oIterator as $oNode) { $oObj = $oNode->GetProperty('object'); - if ($oObj && in_array(get_class($oObj), $aExcludedClasses)) - { + if ($oObj && in_array(get_class($oObj), $aExcludedClasses)) { $oRelGraph->FilterNode($oNode); } } @@ -2069,36 +2060,29 @@ EOF $oGraph = DisplayableGraph::FromRelationGraph($oRelGraph, $iGroupingThreshold, ($sDirection == 'down')); $oGraph->InitFromGraphviz(); - if ($aPositions != null) - { + if ($aPositions != null) { $oGraph->UpdatePositions($aPositions); } $aGroups = array(); $oIterator = new RelationTypeIterator($oGraph, 'Node'); - foreach($oIterator as $oNode) - { - if ($oNode instanceof DisplayableGroupNode) - { + foreach ($oIterator as $oNode) { + if ($oNode instanceof DisplayableGroupNode) { $aGroups[$oNode->GetProperty('group_index')] = $oNode->GetObjects(); } } // First page is the graph $oGraph->RenderAsPDF($oPage, $sComments, $sContextKey); - if ($bIncludeList) - { + if ($bIncludeList) { // Then the lists of objects (one table per finalclass) $aResults = array(); $oIterator = new RelationTypeIterator($oRelGraph, 'Node'); - foreach($oIterator as $oNode) - { + foreach ($oIterator as $oNode) { $oObj = $oNode->GetProperty('object'); // Some nodes (Redundancy Nodes and Group) do not contain an object - if ($oObj) - { + if ($oObj) { $sObjClass = get_class($oObj); - if (!array_key_exists($sObjClass, $aResults)) - { + if (!array_key_exists($sObjClass, $aResults)) { $aResults[$sObjClass] = array(); } $aResults[$sObjClass][] = $oObj; @@ -2107,49 +2091,43 @@ EOF $oPage->get_tcpdf()->AddPage(); $oPage->get_tcpdf()->SetFontSize(10); // Reset the font size to its default - $oPage->add(''); + $oPage->AddSubBlock(TitleUIBlockFactory::MakeNeutral(Dict::S('UI:RelationshipList'))); $iLoopTimeLimit = MetaModel::GetConfig()->Get('max_execution_time_per_loop'); - foreach($aResults as $sListClass => $aObjects) - { + foreach ($aResults as $sListClass => $aObjects) { set_time_limit($iLoopTimeLimit * count($aObjects)); $oSet = CMDBObjectSet::FromArray($sListClass, $aObjects); $oSet->SetShowObsoleteData(utils::ShowObsoleteData()); - $sHtml = "
\n"; - $sHtml .= "
".MetaModel::GetClassIcon($sListClass, true, 'width: 24px; height: 24px;')." ".Dict::Format('UI:Search:Count_ObjectsOf_Class_Found', $oSet->Count(), - Metamodel::GetName($sListClass))."
\n"; - $sHtml .= "
\n"; - $oPage->add($sHtml); - cmdbAbstractObject::DisplaySet($oPage, $oSet, array('table_id' => $sSourceClass.'_'.$sRelation.'_'.$sDirection.'_'.$sListClass)); - $oPage->p(''); // Some space + $sIconUrl = MetaModel::GetClassIcon($sListClass, false); + $sIconUrl = str_replace(utils::GetAbsoluteUrlModulesRoot(), APPROOT.'env-'.utils::GetCurrentEnvironment().'/', $sIconUrl); + $oTitle = new Html(" ".Dict::Format('UI:Search:Count_ObjectsOf_Class_Found', $oSet->Count(), Metamodel::GetName($sListClass))); + $oPage->AddSubBlock(TitleUIBlockFactory::MakeStandard($oTitle, 2)); + $oPage->AddSubBlock(cmdbAbstractObject::GetDataTableFromDBObjectSet($oSet, array('table_id' => $sSourceClass.'_'.$sRelation.'_'.$sDirection.'_'.$sListClass))); } // Then the content of the groups (one table per group) - if (count($aGroups) > 0) - { + if (count($aGroups) > 0) { $oPage->get_tcpdf()->AddPage(); - $oPage->add(''); - foreach($aGroups as $idx => $aObjects) - { + $oPage->AddSubBlock(TitleUIBlockFactory::MakeNeutral(Dict::S('UI:RelationGroups'))); + foreach ($aGroups as $idx => $aObjects) { set_time_limit($iLoopTimeLimit * count($aObjects)); $sListClass = get_class(current($aObjects)); $oSet = CMDBObjectSet::FromArray($sListClass, $aObjects); - $sHtml = "
\n"; - $sHtml .= "
".MetaModel::GetClassIcon($sListClass, true, 'width: 24px; height: 24px;')." ".Dict::Format('UI:RelationGroupNumber_N', (1 + $idx))."
\n"; - $sHtml .= "
\n"; - $oPage->add($sHtml); - cmdbAbstractObject::DisplaySet($oPage, $oSet); - $oPage->p(''); // Some space + $sIconUrl = MetaModel::GetClassIcon($sListClass, false); + $sIconUrl = str_replace(utils::GetAbsoluteUrlModulesRoot(), APPROOT.'env-'.utils::GetCurrentEnvironment().'/', $sIconUrl); + $oTitle = new Html(" ".Dict::Format('UI:RelationGroupNumber_N', (1 + $idx)), Metamodel::GetName($sListClass)); + $oPage->AddSubBlock(TitleUIBlockFactory::MakeStandard($oTitle, 2)); + $oPage->AddSubBlock(cmdbAbstractObject::GetDataTableFromDBObjectSet($oSet)); + } } } - if ($operation == 'relation_attachment') - { + if ($operation == 'relation_attachment') { $sObjClass = utils::ReadParam('obj_class', '', false, 'class'); $iObjKey = (int)utils::ReadParam('obj_key', 0, false, 'integer'); // Save the generated PDF as an attachment $sPDF = $oPage->get_pdf(); - $oPage = new ajax_page(''); + $oPage = new AjaxPage(''); $oAttachment = MetaModel::NewObject('Attachment'); $oAttachment->Set('item_class', $sObjClass); $oAttachment->Set('item_id', $iObjKey); diff --git a/sources/application/WebPage/PDFPage.php b/sources/application/WebPage/PDFPage.php index 403c51ed8..74e6d3fab 100644 --- a/sources/application/WebPage/PDFPage.php +++ b/sources/application/WebPage/PDFPage.php @@ -67,10 +67,10 @@ class PDFPage extends WebPage table { padding: 2pt; } -table.listResults td { +table.ibo-datatable td { border: 0.5pt solid #000 ; } -table.listResults th { +table.ibo-datatable th { background-color: #eee; border: 0.5pt solid #000 ; } @@ -86,6 +86,13 @@ table.section td { td.icon { width: 30px; } +h2{ + font-size: 10pt; + vertical-align: middle; + background-color:#eee; + padding: 2pt; + margin:2pt; +} EOF ); } diff --git a/sources/application/WebPage/iTopPDF.php b/sources/application/WebPage/iTopPDF.php index 87d75bd41..6fe2ffc07 100644 --- a/sources/application/WebPage/iTopPDF.php +++ b/sources/application/WebPage/iTopPDF.php @@ -39,6 +39,32 @@ class iTopPDF extends TCPDF $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. *