Protect dashboard/dashlets against exceptions, with a graceful degradation for non-existing classes

SVN:trunk[2072]
This commit is contained in:
Denis Flaven
2012-05-30 14:21:10 +00:00
parent 9e10de70c9
commit e64e008aad
2 changed files with 157 additions and 73 deletions

View File

@@ -99,7 +99,7 @@ abstract class DashboardLayoutMultiCol extends DashboardLayout
{
if ($oDashlet->IsVisible())
{
$oDashlet->DoRender($oPage, $bEditMode, $aExtraParams);
$oDashlet->DoRender($oPage, $bEditMode, true /* bEnclosingDiv */, $aExtraParams);
}
}
}

View File

@@ -109,20 +109,47 @@ abstract class Dashlet
}
}
public function DoRender($oPage, $bEditMode = false, $aExtraParams = array())
public function DoRender($oPage, $bEditMode = false, $bEnclosingDiv = true, $aExtraParams = array())
{
$sCSSClasses = implode(' ', $this->aCSSClasses);
if ($bEditMode)
$sId = $this->GetID();
if ($bEnclosingDiv)
{
$sId = $this->GetID();
$oPage->add('<div class="'.$sCSSClasses.'" id="dashlet_'.$sId.'">');
if ($bEditMode)
{
$oPage->add('<div class="'.$sCSSClasses.'" id="dashlet_'.$sId.'">');
}
else
{
$oPage->add('<div class="'.$sCSSClasses.'">');
}
}
else
try
{
$oPage->add('<div class="'.$sCSSClasses.'">');
$this->Render($oPage, $bEditMode, $aExtraParams);
}
$this->Render($oPage, $bEditMode, $aExtraParams);
$oPage->add('</div>');
catch(UnknownClassOqlException $e)
{
// Maybe the class is part of a non-installed module, fail silently
// Except in Edit mode
if ($bEditMode)
{
$oPage->add('<div class="dashlet-content">');
$oPage->add('<h2>Unknown Class: '.$e->GetWrongWord().', did you mean '.OqlException::FindClosestString($e->GetWrongWord(), $e->GetSuggestions()).'?</h2>'); //TODO localize and
$oPage->add('</div>');
}
}
catch(Exception $e)
{
$oPage->p($e->getMessage());
}
if ($bEnclosingDiv)
{
$oPage->add('</div>');
}
if ($bEditMode)
{
$sClass = get_class($this);
@@ -478,33 +505,40 @@ abstract class DashletGroupBy extends Dashlet
$oField = new DesignerLongTextField('query', 'Query', $this->aProperties['query']);
$oForm->AddField($oField);
// Group by field: build the list of possible values (attribute codes + ...)
$oSearch = DBObjectSearch::FromOQL($this->aProperties['query']);
$sClass = $oSearch->GetClass();
$aGroupBy = array();
foreach(MetaModel::ListAttributeDefs($sClass) as $sAttCode => $oAttDef)
try
{
if (!$oAttDef->IsScalar()) continue; // skip link sets
$sLabel = $oAttDef->GetLabel();
if ($oAttDef->IsExternalKey(EXTKEY_ABSOLUTE))
// Group by field: build the list of possible values (attribute codes + ...)
$oSearch = DBObjectSearch::FromOQL($this->aProperties['query']);
$sClass = $oSearch->GetClass();
$aGroupBy = array();
foreach(MetaModel::ListAttributeDefs($sClass) as $sAttCode => $oAttDef)
{
$sLabel = $oAttDef->GetLabel().' (strict)';
}
$aGroupBy[$sAttCode] = $sLabel;
if ($oAttDef instanceof AttributeDateTime)
{
$aGroupBy[$sAttCode.':hour'] = $oAttDef->GetLabel().' (hour)';
$aGroupBy[$sAttCode.':month'] = $oAttDef->GetLabel().' (month)';
$aGroupBy[$sAttCode.':day_of_week'] = $oAttDef->GetLabel().' (day of week)';
$aGroupBy[$sAttCode.':day_of_month'] = $oAttDef->GetLabel().' (day of month)';
if (!$oAttDef->IsScalar()) continue; // skip link sets
$sLabel = $oAttDef->GetLabel();
if ($oAttDef->IsExternalKey(EXTKEY_ABSOLUTE))
{
$sLabel = $oAttDef->GetLabel().' (strict)';
}
$aGroupBy[$sAttCode] = $sLabel;
if ($oAttDef instanceof AttributeDateTime)
{
$aGroupBy[$sAttCode.':hour'] = $oAttDef->GetLabel().' (hour)';
$aGroupBy[$sAttCode.':month'] = $oAttDef->GetLabel().' (month)';
$aGroupBy[$sAttCode.':day_of_week'] = $oAttDef->GetLabel().' (day of week)';
$aGroupBy[$sAttCode.':day_of_month'] = $oAttDef->GetLabel().' (day of month)';
}
}
$oField = new DesignerComboField('group_by', 'Group by', $this->aProperties['group_by']);
$oField->SetAllowedValues($aGroupBy);
}
catch(Exception $e)
{
$oField = new DesignerTextField('group_by', 'Group by', $this->aProperties['group_by']);
}
$oField = new DesignerComboField('group_by', 'Group by', $this->aProperties['group_by']);
$oField->SetAllowedValues($aGroupBy);
$oForm->AddField($oField);
$aStyles = array(
@@ -522,19 +556,26 @@ abstract class DashletGroupBy extends Dashlet
{
if (in_array('query', $aUpdatedFields))
{
$sCurrQuery = $aValues['query'];
$oCurrSearch = DBObjectSearch::FromOQL($sCurrQuery);
$sCurrClass = $oCurrSearch->GetClass();
$sPrevQuery = $this->aProperties['query'];
$oPrevSearch = DBObjectSearch::FromOQL($sPrevQuery);
$sPrevClass = $oPrevSearch->GetClass();
if ($sCurrClass != $sPrevClass)
try
{
$sCurrQuery = $aValues['query'];
$oCurrSearch = DBObjectSearch::FromOQL($sCurrQuery);
$sCurrClass = $oCurrSearch->GetClass();
$sPrevQuery = $this->aProperties['query'];
$oPrevSearch = DBObjectSearch::FromOQL($sPrevQuery);
$sPrevClass = $oPrevSearch->GetClass();
if ($sCurrClass != $sPrevClass)
{
$this->bFormRedrawNeeded = true;
// wrong but not necessary - unset($aUpdatedFields['group_by']);
$this->aProperties['group_by'] = '';
}
}
catch(Exception $e)
{
$this->bFormRedrawNeeded = true;
// wrong but not necessary - unset($aUpdatedFields['group_by']);
$this->aProperties['group_by'] = '';
}
}
$oDashlet = parent::Update($aValues, $aUpdatedFields);
@@ -584,27 +625,34 @@ abstract class DashletGroupBy extends Dashlet
$oField = new DesignerHiddenField('query', 'Query', $sOQL);
$oForm->AddField($oField);
// Group by field: build the list of possible values (attribute codes + ...)
$oSearch = DBObjectSearch::FromOQL($this->aProperties['query']);
$sClass = $oSearch->GetClass();
$aGroupBy = array();
foreach(MetaModel::ListAttributeDefs($sClass) as $sAttCode => $oAttDef)
try
{
if (!$oAttDef->IsScalar()) continue; // skip link sets
if ($oAttDef->IsExternalKey(EXTKEY_ABSOLUTE)) continue; // skip external keys
$aGroupBy[$sAttCode] = $oAttDef->GetLabel();
if ($oAttDef instanceof AttributeDateTime)
// Group by field: build the list of possible values (attribute codes + ...)
$oSearch = DBObjectSearch::FromOQL($this->aProperties['query']);
$sClass = $oSearch->GetClass();
$aGroupBy = array();
foreach(MetaModel::ListAttributeDefs($sClass) as $sAttCode => $oAttDef)
{
//date_format(start_date, '%d')
$aGroupBy['date_of_'.$sAttCode] = 'Day of '.$oAttDef->GetLabel();
if (!$oAttDef->IsScalar()) continue; // skip link sets
if ($oAttDef->IsExternalKey(EXTKEY_ABSOLUTE)) continue; // skip external keys
$aGroupBy[$sAttCode] = $oAttDef->GetLabel();
if ($oAttDef instanceof AttributeDateTime)
{
//date_format(start_date, '%d')
$aGroupBy['date_of_'.$sAttCode] = 'Day of '.$oAttDef->GetLabel();
}
}
$oField = new DesignerComboField('group_by', 'Group by', $this->aProperties['group_by']);
$oField->SetAllowedValues($aGroupBy);
}
catch(Exception $e)
{
$oField = new DesignerTextField('group_by', 'Group by', $this->aProperties['group_by']);
}
$oField = new DesignerComboField('group_by', 'Group by', $this->aProperties['group_by']);
$oField->SetAllowedValues($aGroupBy);
$oForm->AddField($oField);
$oField = new DesignerHiddenField('style', '', $this->aProperties['style']);
@@ -906,30 +954,66 @@ class DashletHeaderDynamic extends Dashlet
$oField = new DesignerTextField('query', 'Query', $this->aProperties['query']);
$oForm->AddField($oField);
// Group by field: build the list of possible values (attribute codes + ...)
$oSearch = DBObjectSearch::FromOQL($this->aProperties['query']);
$sClass = $oSearch->GetClass();
$aGroupBy = array();
foreach(MetaModel::ListAttributeDefs($sClass) as $sAttCode => $oAttDef)
try
{
if (!$oAttDef->IsScalar()) continue; // skip link sets
$sLabel = $oAttDef->GetLabel();
if ($oAttDef->IsExternalKey(EXTKEY_ABSOLUTE))
// Group by field: build the list of possible values (attribute codes + ...)
$oSearch = DBObjectSearch::FromOQL($this->aProperties['query']);
$sClass = $oSearch->GetClass();
$aGroupBy = array();
foreach(MetaModel::ListAttributeDefs($sClass) as $sAttCode => $oAttDef)
{
$sLabel = $oAttDef->GetLabel().' (strict)';
if (!$oAttDef->IsScalar()) continue; // skip link sets
$sLabel = $oAttDef->GetLabel();
if ($oAttDef->IsExternalKey(EXTKEY_ABSOLUTE))
{
$sLabel = $oAttDef->GetLabel().' (strict)';
}
$aGroupBy[$sAttCode] = $sLabel;
}
$aGroupBy[$sAttCode] = $sLabel;
$oField = new DesignerComboField('group_by', 'Group by', $this->aProperties['group_by']);
$oField->SetAllowedValues($aGroupBy);
}
catch(Exception $e)
{
$oField = new DesignerTextField('group_by', 'Group by', $this->aProperties['group_by']);
}
$oField = new DesignerComboField('group_by', 'Group by', $this->aProperties['group_by']);
$oField->SetAllowedValues($aGroupBy);
$oForm->AddField($oField);
$oField = new DesignerTextField('values', 'Values (CSV list)', $this->aProperties['values']);
$oForm->AddField($oField);
}
public function Update($aValues, $aUpdatedFields)
{
if (in_array('query', $aUpdatedFields))
{
try
{
$sCurrQuery = $aValues['query'];
$oCurrSearch = DBObjectSearch::FromOQL($sCurrQuery);
$sCurrClass = $oCurrSearch->GetClass();
$sPrevQuery = $this->aProperties['query'];
$oPrevSearch = DBObjectSearch::FromOQL($sPrevQuery);
$sPrevClass = $oPrevSearch->GetClass();
if ($sCurrClass != $sPrevClass)
{
$this->bFormRedrawNeeded = true;
// wrong but not necessary - unset($aUpdatedFields['group_by']);
$this->aProperties['group_by'] = '';
}
}
catch(Exception $e)
{
$this->bFormRedrawNeeded = true;
}
}
return parent::Update($aValues, $aUpdatedFields);
}
static public function GetInfo()
{
return array(