N°3912 - Polishing: Export - export of impact analysis

This commit is contained in:
acognet
2021-06-21 09:21:48 +02:00
parent 108bc2fa1d
commit ee5847ec82
5 changed files with 255 additions and 107 deletions

View File

@@ -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", "<br/>", 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

View File

@@ -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 <br/>)
* @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');

View File

@@ -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('<div class="page_header"><h1>'.Dict::S('UI:RelationshipList').'</h1></div>');
$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 = "<div class=\"page_header\">\n";
$sHtml .= "<table class=\"section\"><tr><td>".MetaModel::GetClassIcon($sListClass, true, 'width: 24px; height: 24px;')." ".Dict::Format('UI:Search:Count_ObjectsOf_Class_Found', $oSet->Count(),
Metamodel::GetName($sListClass))."</td></tr></table>\n";
$sHtml .= "</div>\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("<img src=\"$sIconUrl\" style=\"vertical-align:middle;width: 24px; height: 24px;\"/> ".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('<div class="page_header"><h1>'.Dict::S('UI:RelationGroups').'</h1></div>');
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 = "<div class=\"page_header\">\n";
$sHtml .= "<table class=\"section\"><tr><td>".MetaModel::GetClassIcon($sListClass, true, 'width: 24px; height: 24px;')." ".Dict::Format('UI:RelationGroupNumber_N', (1 + $idx))."</td></tr></table>\n";
$sHtml .= "</div>\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("<img src=\"$sIconUrl\" style=\"vertical-align:middle;width: 24px; height: 24px;\"/> ".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);

View File

@@ -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
);
}

View File

@@ -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.
*