diff --git a/core/metamodel.class.php b/core/metamodel.class.php index f244f06bc..70a2150f4 100644 --- a/core/metamodel.class.php +++ b/core/metamodel.class.php @@ -728,11 +728,22 @@ abstract class MetaModel final static public function GetAttributeDef($sClass, $sAttCode) { self::_check_subclass($sClass); - if (!isset(self::$m_aAttribDefs[$sClass][$sAttCode])) + if (isset(self::$m_aAttribDefs[$sClass][$sAttCode])) + { + return self::$m_aAttribDefs[$sClass][$sAttCode]; + } + elseif (($iPos = strpos($sAttCode, '->')) !== false) + { + $sExtKeyAttCode = substr($sAttCode, 0, $iPos); + $sRemoteAttCode = substr($sAttCode, $iPos + 2); + $oKeyAttDef = self::GetAttributeDef($sClass, $sExtKeyAttCode); + $sRemoteClass = $oKeyAttDef->GetTargetClass(); + return self::GetAttributeDef($sRemoteClass, $sRemoteAttCode); + } + else { throw new Exception("Unknown attribute $sAttCode from class $sClass"); } - return self::$m_aAttribDefs[$sClass][$sAttCode]; } final static public function GetExternalKeys($sClass) @@ -841,25 +852,7 @@ abstract class MetaModel public static function GetLabel($sClass, $sAttCodeEx, $bShowMandatory = false) { $sLabel = ''; - if (preg_match('/(.+)->(.+)/', $sAttCodeEx, $aMatches) > 0) - { - $sAttribute = $aMatches[1]; - $sField = $aMatches[2]; - $oAttDef = MetaModel::GetAttributeDef($sClass, $sAttribute); - $sMandatory = ($bShowMandatory && !$oAttDef->IsNullAllowed()) ? '*' : ''; - if ($oAttDef->IsExternalKey()) - { - $sTargetClass = $oAttDef->GetTargetClass(); - $oTargetAttDef = MetaModel::GetAttributeDef($sTargetClass, $sField); - $sLabel = $oAttDef->GetLabel().$sMandatory.'->'.$oTargetAttDef->GetLabel(); - } - else - { - // Let's return something displayable... but this should never happen! - $sLabel = $oAttDef->GetLabel().$sMandatory.'->'.$aMatches[2]; - } - } - else + if (($iPos = strpos($sAttCodeEx, '->')) === false) { if ($sAttCodeEx == 'id') { @@ -867,11 +860,20 @@ abstract class MetaModel } else { - $oAttDef = MetaModel::GetAttributeDef($sClass, $sAttCodeEx); + $oAttDef = self::GetAttributeDef($sClass, $sAttCodeEx); $sMandatory = ($bShowMandatory && !$oAttDef->IsNullAllowed()) ? '*' : ''; $sLabel = $oAttDef->GetLabel().$sMandatory; } } + else + { + $sExtKeyAttCode = substr($sAttCodeEx, 0, $iPos); + $sRemoteAttCode = substr($sAttCodeEx, $iPos + 2); + $oKeyAttDef = MetaModel::GetAttributeDef($sClass, $sExtKeyAttCode); + $sRemoteClass = $oKeyAttDef->GetTargetClass(); + // Recurse + $sLabel = self::GetLabel($sClass, $sExtKeyAttCode).'->'.self::GetLabel($sRemoteClass, $sRemoteAttCode); + } return $sLabel; } diff --git a/core/tabularbulkexport.class.inc.php b/core/tabularbulkexport.class.inc.php index eba74edac..8a90b246e 100644 --- a/core/tabularbulkexport.class.inc.php +++ b/core/tabularbulkexport.class.inc.php @@ -349,33 +349,21 @@ EOF throw new Exception("You do not have enough permissions to bulk read data of class '$sClass' (alias: $sAlias)"); } - switch($sAttCode) + if ($this->bLocalizeOutput) { - case 'id': - $sLabel = 'id'; - $oAttDef = null; - break; - - default: - $oAttDef = MetaModel::GetAttributeDef($sClass, $sAttCode); - if (($oAttDef instanceof AttributeExternalField) || (($oAttDef instanceof AttributeFriendlyName) && ($oAttDef->GetKeyAttCode() != 'id'))) + try { - $oKeyAttDef = MetaModel::GetAttributeDef($sClass, $oAttDef->GetKeyAttCode()); - $oExtAttDef = MetaModel::GetAttributeDef($oKeyAttDef->GetTargetClass(), $oAttDef->GetExtAttCode()); - if ($this->bLocalizeOutput) - { - $sLabel = $oKeyAttDef->GetLabel().'->'.$oExtAttDef->GetLabel(); - } - else - { - $sLabel = $oKeyAttDef->GetCode().'->'.$oExtAttDef->GetCode(); - } + $sLabel = MetaModel::GetLabel($sClass, $sAttCode); } - else + catch (Exception $e) { - $sLabel = $this->bLocalizeOutput ? $oAttDef->GetLabel() : $sAttCode; + throw new Exception("Wrong field specification '$sFieldSpec': ".$e->getMessage()); } } + else + { + $sLabel = $sAttCode; + } if (count($aAuthorizedClasses) > 1) { $sColLabel = $sAlias.'.'.$sLabel; @@ -404,6 +392,7 @@ EOF foreach($this->aStatusInfo['fields'] as $iCol => $aFieldSpec) { + $sClass = $aFieldSpec['sClass']; $sAlias = $aFieldSpec['sAlias']; $sAttCode = $aFieldSpec['sAttCode']; @@ -411,12 +400,47 @@ EOF { $aColumnsToLoad[$sAlias] = array(); } + // id is not a real attribute code and, moreover, is always loaded if ($sAttCode != 'id') { - // id is not a real attribute code and, moreover, is always loaded - $aColumnsToLoad[$sAlias][] = $sAttCode; + // Extended attributes are not recognized by DBObjectSet::OptimizeColumnLoad + if (($iPos = strpos($sAttCode, '->')) === false) + { + $aColumnsToLoad[$sAlias][] = $sAttCode; + $sClass = '???'; + } + else + { + $sExtKeyAttCode = substr($sAttCode, 0, $iPos); + $sRemoteAttCode = substr($sAttCode, $iPos + 2); + + // Load the external key to avoid an object reload! + $aColumnsToLoad[$sAlias][] = $sExtKeyAttCode; + + // Load the external field (if any) to avoid getting the remote object (see DBObject::Get that does the same) + $oExtFieldAtt = MetaModel::FindExternalField($sClass, $sExtKeyAttCode, $sRemoteAttCode); + if (!is_null($oExtFieldAtt)) + { + $aColumnsToLoad[$sAlias][] = $oExtFieldAtt->GetCode(); + } + } } } + + // Add "always loaded attributes" + // + $aSelectedClasses = $this->oSearch->GetSelectedClasses(); + foreach ($aSelectedClasses as $sAlias => $sClass) + { + foreach (MetaModel::ListAttributeDefs($sClass) as $sAttCode => $oAttDef) + { + if ($oAttDef->AlwaysLoadInTables()) + { + $aColumnsToLoad[$sAlias][] = $sAttCode; + } + } + } + $oSet->OptimizeColumnLoad($aColumnsToLoad); } }