diff --git a/application/cmdbabstract.class.inc.php b/application/cmdbabstract.class.inc.php index f0284c815..fb0edca6b 100644 --- a/application/cmdbabstract.class.inc.php +++ b/application/cmdbabstract.class.inc.php @@ -1172,6 +1172,146 @@ EOF return $sHtml; } + static function DisplaySetAsHTMLSpreadsheet(WebPage $oPage, CMDBObjectSet $oSet, $aParams = array()) + { + $oPage->add(self::GetSetAsHTMLSpreadsheet($oSet, $aParams)); + } + + static function GetSetAsHTMLSpreadsheet(DBObjectSet $oSet, $aParams = array()) + { + $aFields = null; + if (isset($aParams['fields']) && (strlen($aParams['fields']) > 0)) + { + $aFields = explode(',', $aParams['fields']); + } + + $aList = array(); + + $oAppContext = new ApplicationContext(); + $aClasses = $oSet->GetFilter()->GetSelectedClasses(); + $aAuthorizedClasses = array(); + foreach($aClasses as $sAlias => $sClassName) + { + if (UserRights::IsActionAllowed($sClassName, UR_ACTION_READ, $oSet) && (UR_ALLOWED_YES || UR_ALLOWED_DEPENDS)) + { + $aAuthorizedClasses[$sAlias] = $sClassName; + } + } + $aAttribs = array(); + $aHeader = array(); + foreach($aAuthorizedClasses as $sAlias => $sClassName) + { + foreach(MetaModel::ListAttributeDefs($sClassName) as $sAttCode => $oAttDef) + { + if (is_null($aFields) || (count($aFields) == 0)) + { + // Standard list of attributes (no link sets) + if ($oAttDef->IsScalar() && ($oAttDef->IsWritable() || $oAttDef->IsExternalField())) + { + $aList[$sClassName][$sAttCode] = $oAttDef; + } + } + else + { + // User defined list of attributes + if (in_array($sAttCode, $aFields)) + { + $aList[$sClassName][$sAttCode] = $oAttDef; + } + } + } + $aHeader[] = 'id'; + foreach($aList[$sClassName] as $sAttCode => $oAttDef) + { + $sStar = ''; + if ($oAttDef->IsExternalField()) + { + $sExtKeyLabel = MetaModel::GetLabel($sClassName, $oAttDef->GetKeyAttCode()); + $oExtKeyAttDef = MetaModel::GetAttributeDef($sClassName, $oAttDef->GetKeyAttCode()); + if (!$oExtKeyAttDef->IsNullAllowed() && isset($aParams['showMandatoryFields'])) + { + $sStar = '*'; + } + $sRemoteAttLabel = MetaModel::GetLabel($oAttDef->GetTargetClass(), $oAttDef->GetExtAttCode()); + $oTargetAttDef = MetaModel::GetAttributeDef($oAttDef->GetTargetClass(), $oAttDef->GetExtAttCode()); + $sSuffix = ''; + if ($oTargetAttDef->IsExternalKey()) + { + $sSuffix = '->id'; + } + $sColLabel = $sExtKeyLabel.'->'.$sRemoteAttLabel.$sSuffix.$sStar; + } + else + { + if (!$oAttDef->IsNullAllowed() && isset($aParams['showMandatoryFields'])) + { + $sStar = '*'; + } + $sColLabel = MetaModel::GetLabel($sClassName, $sAttCode).$sStar; + } + $oFinalAttDef = $oAttDef->GetFinalAttDef(); + if (get_class($oFinalAttDef) == 'AttributeDateTime') + { + $aHeader[] = $sColLabel.' ('.Dict::S('UI:SplitDateTime-Date').')'; + $aHeader[] = $sColLabel.' ('.Dict::S('UI:SplitDateTime-Time').')'; + } + else + { + $aHeader[] = $sColLabel; + } + } + } + + + $sHtml = "\n"; + $sHtml .= "\n"; + $sHtml .= "\n"; + $sHtml .= "\n"; + $oSet->Seek(0); + while ($aObjects = $oSet->FetchAssoc()) + { + $aRow = array(); + foreach($aAuthorizedClasses as $sAlias => $sClassName) + { + $oObj = $aObjects[$sAlias]; + if (is_null($oObj)) + { + $aRow[] = ''; + } + else + { + $aRow[] = ''; + } + foreach($aList[$sClassName] as $sAttCode => $oAttDef) + { + if (is_null($oObj)) + { + $aRow[] = ''; + } + else + { + $oFinalAttDef = $oAttDef->GetFinalAttDef(); + if (get_class($oFinalAttDef) == 'AttributeDateTime') + { + $iDate = AttributeDateTime::GetAsUnixSeconds($oObj->Get($sAttCode)); + $aRow[] = ''; + $aRow[] = ''; + } + else + { + $aRow[] = ''; + } + } + } + } + $sHtml .= implode("\n", $aRow); + $sHtml .= "\n"; + } + $sHtml .= "
".implode("", $aHeader)."
'.$oObj->GetKey().''.date('Y-m-d', $iDate).''.date('h:i:s', $iDate).''.(string) $oObj->Get($sAttCode).'
\n"; + + return $sHtml; + } + static function DisplaySetAsXML(WebPage $oPage, CMDBObjectSet $oSet, $aParams = array()) { $oAppContext = new ApplicationContext(); diff --git a/core/attributedef.class.inc.php b/core/attributedef.class.inc.php index 01ccd0681..8ab182eee 100644 --- a/core/attributedef.class.inc.php +++ b/core/attributedef.class.inc.php @@ -162,6 +162,10 @@ abstract class AttributeDefinition return ""; // e.g: return array("Site", "infrid", "name"); } + public function GetFinalAttDef() + { + return $this; + } public function IsDirectField() {return false;} public function IsScalar() {return false;} public function IsLinkSet() {return false;} @@ -2761,6 +2765,13 @@ class AttributeExternalField extends AttributeDefinition } public function GetEditClass() {return "ExtField";} + + public function GetFinalAttDef() + { + $oExtAttDef = $this->GetExtAttDef(); + return $oExtAttDef->GetFinalAttDef(); + } + protected function GetSQLCol() { // throw new CoreException("external attribute: does it make any sense to request its type ?"); diff --git a/dictionaries/dictionary.itop.ui.php b/dictionaries/dictionary.itop.ui.php index e060859b9..d22890747 100644 --- a/dictionaries/dictionary.itop.ui.php +++ b/dictionaries/dictionary.itop.ui.php @@ -429,6 +429,8 @@ Dict::Add('EN US', 'English', 'English', array( 'UI:UndefinedObject' => 'undefined', 'UI:Document:OpenInNewWindow:Download' => 'Open in new window: %1$s, Download: %2$s', 'UI:SelectAllToggle+' => 'Select / Deselect All', + 'UI:SplitDateTime-Date' => 'date', + 'UI:SplitDateTime-Time' => 'time', 'UI:TruncatedResults' => '%1$d objects displayed out of %2$d', 'UI:DisplayAll' => 'Display All', 'UI:CollapseList' => 'Collapse', diff --git a/dictionaries/fr.dictionary.itop.ui.php b/dictionaries/fr.dictionary.itop.ui.php index d7792f271..3d5ca2e36 100644 --- a/dictionaries/fr.dictionary.itop.ui.php +++ b/dictionaries/fr.dictionary.itop.ui.php @@ -316,6 +316,8 @@ Dict::Add('FR FR', 'French', 'Français', array( 'UI:Document:OpenInNewWindow:Download' => 'Ouvrir dans un nouvelle fenêtre: %1$s, Télécharger: %2$s', 'UI:SelectAllToggle+' => 'Tout sélectionner / Tout déselectionner', 'UI:TruncatedResults' => '%1$d objets affichés sur %2$d', + 'UI:SplitDateTime-Date' => 'date', + 'UI:SplitDateTime-Time' => 'heure', 'UI:DisplayAll' => 'Tout afficher', 'UI:CollapseList' => 'Refermer', 'UI:CountOfResults' => '%1$d objet(s)', diff --git a/pages/UI.php b/pages/UI.php index ba277b33b..af0281cdb 100644 --- a/pages/UI.php +++ b/pages/UI.php @@ -2109,7 +2109,7 @@ EOF DisplayWelcomePopup($oP); $oP->output(); } -catch(CoreException $e) +catch(xxxCoreException $e) { require_once(APPROOT.'/setup/setuppage.class.inc.php'); $oP = new SetupWebPage(Dict::S('UI:PageTitle:FatalError')); @@ -2152,7 +2152,7 @@ catch(CoreException $e) // For debugging only //throw $e; } -catch(Exception $e) +catch(xxxException $e) { require_once(APPROOT.'/setup/setuppage.class.inc.php'); $oP = new SetupWebPage(Dict::S('UI:PageTitle:FatalError')); diff --git a/webservices/export.php b/webservices/export.php index ab138a1c8..b9c59e6b6 100644 --- a/webservices/export.php +++ b/webservices/export.php @@ -126,6 +126,19 @@ if (!empty($sExpression)) cmdbAbstractObject::DisplaySetAsCSV($oP, $oSet, array('fields' => $sFields)); break; + case 'spreadsheet': + $oP = new WebPage("iTop - Export for spreadsheet"); + + // Integration within MS-Excel web queries + HTTPS + IIS: + // MS-IIS set these header values with no-cache... while Excel fails to do the job if using HTTPS + // Then the fix is to force the reset of header values Pragma and Cache-control + header("Pragma:", true); + header("Cache-control:", true); + + $sFields = implode(',', $aFields); + cmdbAbstractObject::DisplaySetAsHTMLSpreadsheet($oP, $oSet, array('fields' => $sFields)); + break; + case 'xml': $oP = new XMLPage("iTop - Export", true /* passthrough */); cmdbAbstractObject::DisplaySetAsXML($oP, $oSet);