浏览代码

Obsolescence: finalizing the implementation of the flag (hide obsolete objects, show an icon on hyperlinks and a tag on the object details, user preference defaulting to the new setting 'show_obsolete_data')

git-svn-id: http://svn.code.sf.net/p/itop/code/trunk@4739 a333f486-631f-4898-b8df-5754b55c2be0
romainq 8 年之前
父节点
当前提交
b246164f18
共有 45 个文件被更改,包括 372 次插入57 次删除
  1. 7 0
      application/cmdbabstract.class.inc.php
  2. 3 2
      application/dashlet.class.inc.php
  3. 6 2
      application/displayblock.class.inc.php
  4. 6 4
      application/ui.extkeywidget.class.inc.php
  5. 13 6
      application/user.preferences.class.inc.php
  6. 15 0
      application/utils.inc.php
  7. 11 0
      core/attributedef.class.inc.php
  8. 8 0
      core/config.class.inc.php
  9. 15 5
      core/dbobject.class.php
  10. 14 6
      core/dbobjectsearch.class.php
  11. 12 0
      core/dbobjectset.class.php
  12. 10 0
      core/dbsearch.class.php
  13. 18 0
      core/dbunionsearch.class.php
  14. 33 18
      core/metamodel.class.php
  15. 10 2
      core/oql/expression.class.inc.php
  16. 16 6
      core/relationgraph.class.inc.php
  17. 8 1
      dictionaries/cs.dictionary.itop.core.php
  18. 3 1
      dictionaries/cs.dictionary.itop.ui.php
  19. 6 0
      dictionaries/da.dictionary.itop.core.php
  20. 5 0
      dictionaries/da.dictionary.itop.ui.php
  21. 6 0
      dictionaries/de.dictionary.itop.core.php
  22. 5 0
      dictionaries/de.dictionary.itop.ui.php
  23. 7 0
      dictionaries/dictionary.itop.core.php
  24. 4 0
      dictionaries/dictionary.itop.ui.php
  25. 7 0
      dictionaries/es_cr.dictionary.itop.core.php
  26. 5 0
      dictionaries/es_cr.dictionary.itop.ui.php
  27. 8 2
      dictionaries/fr.dictionary.itop.core.php
  28. 5 0
      dictionaries/fr.dictionary.itop.ui.php
  29. 6 0
      dictionaries/hu.dictionary.itop.core.php
  30. 5 0
      dictionaries/hu.dictionary.itop.ui.php
  31. 7 0
      dictionaries/it.dictionary.itop.core.php
  32. 5 0
      dictionaries/it.dictionary.itop.ui.php
  33. 6 0
      dictionaries/ja.dictionary.itop.core.php
  34. 5 0
      dictionaries/ja.dictionary.itop.ui.php
  35. 7 0
      dictionaries/nl.dictionary.itop.core.php
  36. 5 0
      dictionaries/nl.dictionary.itop.ui.php
  37. 7 0
      dictionaries/pt_br.dictionary.itop.core.php
  38. 5 0
      dictionaries/pt_br.dictionary.itop.ui.php
  39. 7 0
      dictionaries/ru.dictionary.itop.core.php
  40. 5 0
      dictionaries/ru.dictionary.itop.ui.php
  41. 6 0
      dictionaries/tr.dictionary.itop.core.php
  42. 5 0
      dictionaries/tr.dictionary.itop.ui.php
  43. 6 0
      dictionaries/zh.dictionary.itop.core.php
  44. 5 0
      dictionaries/zh.dictionary.itop.ui.php
  45. 14 2
      pages/preferences.php

+ 7 - 0
application/cmdbabstract.class.inc.php

@@ -304,6 +304,12 @@ EOF
 			$sTitle = htmlentities(Dict::S('Tag:Archived+'), ENT_QUOTES, 'UTF-8');
 			$aIcons[] = "<div class=\"tag\" title=\"$sTitle\"><span class=\"object-archived fa fa-archive fa-1x\">&nbsp;</span>&nbsp;$sLabel</div>";
 		}
+		elseif ($this->IsObsolete())
+		{
+			$sLabel = htmlentities(Dict::S('Tag:Obsolete'), ENT_QUOTES, 'UTF-8');
+			$sTitle = htmlentities(Dict::S('Tag:Obsolete+'), ENT_QUOTES, 'UTF-8');
+			$aIcons[] = "<div class=\"tag\" title=\"$sTitle\"><span class=\"object-obsolete fa fa-eye-slash fa-1x\">&nbsp;</span>&nbsp;$sLabel</div>";
+		}
 
 		$sObjectIcon = $this->GetIcon();
 		$sClassName = MetaModel::GetName(get_class($this));
@@ -402,6 +408,7 @@ EOF
 			
 			// $oSet = new DBObjectSet($this->Get($sAttCode)->GetFilter()); // Why do something so useless ?
 			$oSet = $this->Get($sAttCode);
+			$oSet->SetShowObsoleteData(utils::ShowObsoleteData());
 			$iCount = $oSet->Count();
 			$sCount = '';
 			if ($iCount != 0)

+ 3 - 2
application/dashlet.class.inc.php

@@ -1,5 +1,5 @@
 <?php
-// Copyright (C) 2012-2013 Combodo SARL
+// Copyright (C) 2012-2017 Combodo SARL
 //
 //   This file is part of iTop.
 //
@@ -21,7 +21,7 @@ require_once(APPROOT.'application/forms.class.inc.php');
 /**
  * Base class for all 'dashlets' (i.e. widgets to be inserted into a dashboard)
  *
- * @copyright   Copyright (C) 2010-2012 Combodo SARL
+ * @copyright   Copyright (C) 2010-2017 Combodo SARL
  * @license     http://opensource.org/licenses/AGPL-3.0
  */
 abstract class Dashlet
@@ -583,6 +583,7 @@ abstract class DashletGroupBy extends Dashlet
 
 		// First perform the query - if the OQL is not ok, it will generate an exception : no need to go further 
 		$oFilter = DBObjectSearch::FromOQL($sQuery);
+		$oFilter->SetShowObsoleteData(utils::ShowObsoleteData());
 
 		$sClass = $oFilter->GetClass();
 		$sClassAlias = $oFilter->GetClassAlias();

+ 6 - 2
application/displayblock.class.inc.php

@@ -390,6 +390,7 @@ class DisplayBlock
 			
 			$this->m_oSet = new CMDBObjectSet($this->m_oFilter, $aOrderBy, $aQueryParams);
 		}
+		$this->m_oSet->SetShowObsoleteData(utils::ShowObsoleteData());
 		switch($this->m_sStyle)
 		{
 			case 'count':
@@ -709,7 +710,8 @@ class DisplayBlock
 				{
 					$aQueryParams = $aExtraParams['query_params'];
 				}
-				$this->m_oSet = new CMDBObjectSet($this->m_oFilter, array(), $aQueryParams);				
+				$this->m_oSet = new CMDBObjectSet($this->m_oFilter, array(), $aQueryParams);
+				$this->m_oSet->SetShowObsoleteData(utils::ShowObsoleteData());
 			}
 			$iCount = $this->m_oSet->Count();
 			$sHyperlink = utils::GetAbsoluteUrlAppRoot().'pages/UI.php?operation=search&'.$oAppContext->GetForLink().'&filter='.urlencode($this->m_oFilter->serialize());
@@ -752,7 +754,8 @@ class DisplayBlock
 				{
 					$aQueryParams = $aExtraParams['query_params'];
 				}
-				$this->m_oSet = new CMDBObjectSet($this->m_oFilter, array(), $aQueryParams);				
+				$this->m_oSet = new CMDBObjectSet($this->m_oFilter, array(), $aQueryParams);
+				$this->m_oSet->SetShowObsoleteData(utils::ShowObsoleteData());
 			}
 			// Summary details
 			$aCounts = array();
@@ -766,6 +769,7 @@ class DisplayBlock
 					$oFilter = $this->m_oFilter->DeepClone();
 					$oFilter->AddCondition($sStateAttrCode, $sStateValue, '=');
 					$oSet = new DBObjectSet($oFilter);
+					$oSet->SetShowObsoleteData(utils::ShowObsoleteData());
 					$aCounts[$sStateValue] = $oSet->Count();
 					$aStateLabels[$sStateValue] = htmlentities($oAttDef->GetValueLabel($sStateValue), ENT_QUOTES, 'UTF-8');
 					if ($aCounts[$sStateValue] == 0)

+ 6 - 4
application/ui.extkeywidget.class.inc.php

@@ -1,5 +1,5 @@
 <?php
-// Copyright (C) 2010-2016 Combodo SARL
+// Copyright (C) 2010-2017 Combodo SARL
 //
 //   This file is part of iTop.
 //
@@ -54,7 +54,7 @@
  * | |   +--------+    +-----+                    | |
  * | +--------------------------------------------+ |
  * +------------------------------------------------+
- * @copyright   Copyright (C) 2010-2016 Combodo SARL
+ * @copyright   Copyright (C) 2010-2017 Combodo SARL
  * @license     http://opensource.org/licenses/AGPL-3.0
  */
 
@@ -101,7 +101,7 @@ class UIExtKeyWidget
 	 * @param Hash $aArgs Extra context arguments
 	 * @return string The HTML fragment to be inserted into the page
 	 */
-	public function Display(WebPage $oPage, $iMaxComboLength, $bAllowTargetCreation, $sTitle, $oAllowedValues, $value, $iInputId, $bMandatory, $sFieldName, $sFormPrefix = '', $aArgs = array(), $bSearchMode = null, $sDisplayStyle = 'select', $bSearchMultiple = true)
+	public function Display(WebPage $oPage, $iMaxComboLength, $bAllowTargetCreation, $sTitle, DBObjectset $oAllowedValues, $value, $iInputId, $bMandatory, $sFieldName, $sFormPrefix = '', $aArgs = array(), $bSearchMode = null, $sDisplayStyle = 'select', $bSearchMultiple = true)
 	{
 		if (!is_null($bSearchMode))
 		{
@@ -141,7 +141,8 @@ class UIExtKeyWidget
 		{
 			throw new Exception('Implementation: null value for allowed values definition');
 		}
-		elseif ($oAllowedValues->Count() < $iMaxComboLength)
+		$oAllowedValues->SetShowObsoleteData(utils::ShowObsoleteData());
+		if ($oAllowedValues->Count() < $iMaxComboLength)
 		{
 			// Discrete list of values, use a SELECT or RADIO buttons depending on the config
 			switch($sDisplayStyle)
@@ -497,6 +498,7 @@ EOF
 			$oFilter->SetModifierProperty('UserRightsGetSelectFilter', 'bSearchMode', $this->bSearchMode);
 			$oSet = new DBObjectSet($oFilter);
 		}
+		$oSet->SetShowObsoleteData(utils::ShowObsoleteData());
 
 		$sHKAttCode = MetaModel::IsHierarchicalClass($this->sTargetClass);
 		$this->DumpTree($oPage, $oSet, $sHKAttCode, $currValue);

+ 13 - 6
application/user.preferences.class.inc.php

@@ -1,5 +1,5 @@
 <?php
-// Copyright (C) 2010-2012 Combodo SARL
+// Copyright (C) 2010-2017 Combodo SARL
 //
 //   This file is part of iTop.
 //
@@ -19,7 +19,7 @@
 /**
  * Store and retrieve user's preferences (i.e persistent per user settings)
  *
- * @copyright   Copyright (C) 2010-2012 Combodo SARL
+ * @copyright   Copyright (C) 2010-2017 Combodo SARL
  * @license     http://opensource.org/licenses/AGPL-3.0
  */
 require_once(APPROOT.'/core/dbobject.class.php');
@@ -50,7 +50,7 @@ class appUserPreferences extends DBObject
 			self::Load();
 		}
 		$aPrefs = self::$oUserPrefs->Get('preferences');
-		if (isset($aPrefs[$sCode]))
+		if (array_key_exists($sCode, $aPrefs))
 		{
 			return $aPrefs[$sCode];
 		}
@@ -72,9 +72,16 @@ class appUserPreferences extends DBObject
 			self::Load();
 		}
 		$aPrefs = self::$oUserPrefs->Get('preferences');
-		$aPrefs[$sCode] = $sValue;
-		self::$oUserPrefs->Set('preferences', $aPrefs);
-		self::Save();
+		if (array_key_exists($sCode, $aPrefs) && ($aPrefs[$sCode] === $sValue))
+		{
+			// Do not write it again
+		}
+		else
+		{
+			$aPrefs[$sCode] = $sValue;
+			self::$oUserPrefs->Set('preferences', $aPrefs);
+			self::Save();
+		}
 	}
 	
 	/**

+ 15 - 0
application/utils.inc.php

@@ -188,6 +188,21 @@ class utils
 		return $bRet;
 	}
 
+	/**
+	 * Helper to be called by the GUI and define if the user will see obsolete data (otherwise, the user will have to dig further)
+	 * @return bool
+	 */
+	public static function ShowObsoleteData()
+	{
+		$bDefault = MetaModel::GetConfig()->Get('show_obsolete_data'); // default is false
+		$bShow = appUserPreferences::GetPref('show_obsolete_data', $bDefault);
+		if (static::IsArchiveMode())
+		{
+			$bShow = true;
+		}
+		return $bShow;
+	}
+
 	public static function ReadParam($sName, $defaultValue = "", $bAllowCLI = false, $sSanitizationFilter = 'parameter')
 	{
 		global $argv;

+ 11 - 0
core/attributedef.class.inc.php

@@ -7719,5 +7719,16 @@ class AttributeObsolescenceFlag extends AttributeBoolean
 
 	public function GetDefaultValue(DBObject $oHostObject = null) {return $this->MakeRealValue("", $oHostObject);}
 	public function IsNullAllowed() {return false;}
+
+	public function GetLabel($sDefault = null)
+	{
+		$sDefault = Dict::S('Core:AttributeObsolescenceFlag/Label', $sDefault);
+		return parent::GetLabel($sDefault);
+	}
+	public function GetDescription($sDefault = null)
+	{
+		$sDefault = Dict::S('Core:AttributeObsolescenceFlag/Label+', $sDefault);
+		return parent::GetDescription($sDefault);
+	}
 }
 

+ 8 - 0
core/config.class.inc.php

@@ -929,6 +929,14 @@ class Config
 			'source_of_value' => '',
 			'show_in_conf_sample' => false,
 		),
+		'show_obsolete_data' => array(
+			'type' => 'bool',
+			'description' => 'Default value for the user preference "show obsolete data"',
+			'default' => false,
+			'value' => '',
+			'source_of_value' => '',
+			'show_in_conf_sample' => false,
+		),
 	);
 
 	public function IsProperty($sPropCode)

+ 15 - 5
core/dbobject.class.php

@@ -780,7 +780,8 @@ abstract class DBObject implements iDisplay
 			{
 				$sHtmlLabel = htmlentities($this->Get($sAttCode.'_friendlyname'), ENT_QUOTES, 'UTF-8');
 				$bArchived = $this->IsArchived($sAttCode);
-				return $this->MakeHyperLink($sTargetClass, $iTargetKey, $sHtmlLabel, null, true, $bArchived);
+				$bObsolete = $this->IsObsolete($sAttCode);
+				return $this->MakeHyperLink($sTargetClass, $iTargetKey, $sHtmlLabel, null, true, $bArchived, $bObsolete);
 			}
 		}
 
@@ -860,10 +861,11 @@ abstract class DBObject implements iDisplay
 	 * @param null $sUrlMakerClass
 	 * @param bool|true $bWithNavigationContext
 	 * @param bool|false $bArchived
+	 * @param bool|false $bObsolete
 	 * @return string
 	 * @throws DictExceptionMissingString
 	 */
-	public static function MakeHyperLink($sObjClass, $sObjKey, $sHtmlLabel = '', $sUrlMakerClass = null, $bWithNavigationContext = true, $bArchived = false)
+	public static function MakeHyperLink($sObjClass, $sObjKey, $sHtmlLabel = '', $sUrlMakerClass = null, $bWithNavigationContext = true, $bArchived = false, $bObsolete = false)
 	{
 		if ($sObjKey <= 0) return '<em>'.Dict::S('UI:UndefinedObject').'</em>'; // Objects built in memory have negative IDs
 
@@ -894,6 +896,12 @@ abstract class DBObject implements iDisplay
 			$sFA = 'fa-archive object-archived';
 			$sHint = Dict::S('ObjectRef:Archived');
 		}
+		elseif ($bObsolete)
+		{
+			$sSpanClass = 'obsolete';
+			$sFA = 'fa-eye-slash object-obsolete';
+			$sHint = Dict::S('ObjectRef:Obsolete');
+		}
 		else
 		{
 			$sSpanClass = '';
@@ -930,7 +938,8 @@ abstract class DBObject implements iDisplay
 	public function GetHyperlink($sUrlMakerClass = null, $bWithNavigationContext = true)
 	{
 		$bArchived = $this->IsArchived();
-		return self::MakeHyperLink(get_class($this), $this->GetKey(), $this->GetName(), $sUrlMakerClass, $bWithNavigationContext, $bArchived);
+		$bObsolete = $this->IsObsolete();
+		return self::MakeHyperLink(get_class($this), $this->GetKey(), $this->GetName(), $sUrlMakerClass, $bWithNavigationContext, $bArchived, $bObsolete);
 	}
 	
 	public static function ComputeStandardUIPage($sClass)
@@ -3625,10 +3634,11 @@ abstract class DBObject implements iDisplay
 		return $bRet;
 	}
 
-	public function IsObsolete()
+	public function IsObsolete($sKeyAttCode = null)
 	{
 		$bRet = false;
-		if (MetaModel::IsValidAttCode(get_class($this), 'obsolescence_flag') && $this->Get('obsolescence_flag'))
+		$sFlagAttCode = is_null($sKeyAttCode) ? 'obsolescence_flag' : $sKeyAttCode.'_obsolescence_flag';
+		if (MetaModel::IsValidAttCode(get_class($this), $sFlagAttCode) && $this->Get($sFlagAttCode))
 		{
 			$bRet = true;
 		}

+ 14 - 6
core/dbobjectsearch.class.php

@@ -1470,6 +1470,7 @@ class DBObjectSearch extends DBSearch
 				$sRawId .= implode(',', $aSelectedClasses); // Unions may alter the list of selected columns
 			}
 			$sRawId .= $oSearch->GetArchiveMode() ? '--arch' : '';
+			$sRawId .= $oSearch->GetShowObsoleteData() ? '--obso' : '';
 			$sOqlId = md5($sRawId);
 		}
 		else
@@ -1613,10 +1614,17 @@ class DBObjectSearch extends DBSearch
 			{
 				if (!$oAttDef->IsScalar()) continue;
 				// keep because it can be used for sorting - if (!$oAttDef->LoadInObject()) continue;
-				
-				foreach ($oAttDef->GetSQLExpressions() as $sColId => $sSQLExpr)
+
+				if ($oAttDef->IsBasedOnOQLExpression())
+				{
+					$oBuild->m_oQBExpressions->AddSelect($sClassAlias.$sAttCode, new FieldExpression($sAttCode, $sClassAlias));
+				}
+				else
 				{
-					$oBuild->m_oQBExpressions->AddSelect($sClassAlias.$sAttCode.$sColId, new FieldExpression($sAttCode.$sColId, $sClassAlias));
+					foreach ($oAttDef->GetSQLExpressions() as $sColId => $sSQLExpr)
+					{
+						$oBuild->m_oQBExpressions->AddSelect($sClassAlias.$sAttCode.$sColId, new FieldExpression($sAttCode.$sColId, $sClassAlias));
+					}
 				}
 			}
 
@@ -2013,10 +2021,10 @@ class DBObjectSearch extends DBSearch
 							$aTranslateNow = array(); // Translation for external fields - must be performed before the join is done (recursion...)
 							foreach($aExtKeys[$sTableClass][$sKeyAttCode] as $sAttCode => $oAtt)
 							{
-								if ($oAtt->IsFriendlyName())
+								$oExtAttDef = $oAtt->GetExtAttDef();
+								if ($oExtAttDef->IsBasedOnOQLExpression())
 								{
-									// Note: for a given ext key, there is one single attribute "friendly name"
-									$aTranslateNow[$sTargetAlias][$sAttCode] = new FieldExpression('friendlyname', $sKeyClassAlias);
+									$aTranslateNow[$sTargetAlias][$sAttCode] = new FieldExpression($oExtAttDef->GetCode(), $sKeyClassAlias);
 								}
 								else
 								{

+ 12 - 0
core/dbobjectset.class.php

@@ -123,6 +123,17 @@ class DBObjectSet
 		$this->m_iCurrRow = 0;
 		$this->m_oSQLResult = null;
 	}
+
+	public function SetShowObsoleteData($bShow)
+	{
+		$this->m_oFilter->SetShowObsoleteData($bShow);
+	}
+
+	public function GetShowObsoleteData()
+	{
+		return $this->m_oFilter->GetShowObsoleteData();
+	}
+
 	/**
 	 * Specify the subset of attributes to load (for each class of objects) before performing the SQL query for retrieving the rows from the DB
 	 * 
@@ -364,6 +375,7 @@ class DBObjectSet
 	{
 		// Make sure that we carry on the parameters of the set with the filter
 		$oFilter = $this->m_oFilter->DeepClone();
+		$oFilter->SetShowObsoleteData(true);
 		// Note: the arguments found within a set can be object (but not in a filter)
 		// That's why PrepareQueryArguments must be invoked there
 		$oFilter->SetInternalParams(array_merge($oFilter->GetInternalParams(), $this->m_aArgs));

+ 10 - 0
core/dbsearch.class.php

@@ -45,6 +45,7 @@ abstract class DBSearch
 	protected $m_bNoContextParameters = false;
 	protected $m_aModifierProperties = array();
 	protected $m_bArchiveMode = false;
+	protected $m_bShowObsoleteData = true;
 
 	public function __construct()
 	{
@@ -71,6 +72,15 @@ abstract class DBSearch
 		return $this->m_bArchiveMode;
 	}
 
+	public function SetShowObsoleteData($bShow)
+	{
+		$this->m_bShowObsoleteData = $bShow;
+	}
+	public function GetShowObsoleteData()
+	{
+		return $this->m_bShowObsoleteData;
+	}
+
 	public function NoContextParameters() {$this->m_bNoContextParameters = true;}
 	public function HasContextParameters() {return $this->m_bNoContextParameters;}
 

+ 18 - 0
core/dbunionsearch.class.php

@@ -71,6 +71,24 @@ class DBUnionSearch extends DBSearch
 		return true;
 	}
 
+	public function SetArchiveMode($bEnable)
+	{
+		foreach ($this->aSearches as $oSearch)
+		{
+			$oSearch->SetArchiveMode($bEnable);
+		}
+		parent::SetArchiveMode($bEnable);
+	}
+
+	public function SetShowObsoleteData($bShow)
+	{
+		foreach ($this->aSearches as $oSearch)
+		{
+			$oSearch->SetShowObsoleteData($bShow);
+		}
+		parent::SetShowObsoleteData($bShow);
+	}
+
 	/**
 	 * Find the lowest common ancestor for each of the selected class
 	 */

+ 33 - 18
core/metamodel.class.php

@@ -1731,6 +1731,7 @@ abstract class MetaModel
 
 		// Initialize the classes (declared attributes, etc.)
 		//
+		$aObsoletableRootClasses = array();
 		foreach(get_declared_classes() as $sPHPClass)
 		{
 			if (is_subclass_of($sPHPClass, 'DBObject'))
@@ -1774,25 +1775,15 @@ abstract class MetaModel
 						{
 							// Defined or overloaded
 							$sObsolescence = self::$m_aClassParams[$sPHPClass]['obsolescence_expression'];
+							$aObsoletableRootClasses[self::$m_aRootClasses[$sPHPClass]] = true;
 						}
-						elseif (@self::$m_aClassParams[$sParent]['obsolescence_expression'])
+						elseif (isset(self::$m_aClassParams[$sParent]['obsolescence_expression']))
 						{
 							// Inherited
 							$sObsolescence = self::$m_aClassParams[$sParent]['obsolescence_expression'];
 						}
 						self::$m_aClassParams[$sPHPClass]['obsolescence_expression'] = $sObsolescence;
 
-						if (@self::$m_aClassParams[$sParent]['obsolescence_expression'])
-						{
-							// Inherited or overloaded
-							self::$m_aClassParams[$sPHPClass]['obsolescence_root_class'] = self::$m_aClassParams[$sParent]['obsolescence_root_class'];
-						}
-						elseif ($sObsolescence)
-						{
-							// Defined
-							self::$m_aClassParams[$sPHPClass]['obsolescence_root_class'] = $sPHPClass;
-						}
-
 						foreach (MetaModel::EnumPlugins('iOnClassInitialization') as $sPluginClass => $oClassInit)
 						{
 							$oClassInit->OnAfterClassInitialization($sPHPClass);
@@ -1826,6 +1817,13 @@ abstract class MetaModel
 			));
 			self::AddMagicAttribute($oClassAtt, $sRootClass);
 
+			$bObsoletable = array_key_exists($sRootClass, $aObsoletableRootClasses);
+			if ($bObsoletable  && is_null(self::$m_aClassParams[$sRootClass]['obsolescence_expression']))
+			{
+				self::$m_aClassParams[$sRootClass]['obsolescence_expression'] = '0';
+			}
+
+
 			foreach(self::EnumChildClasses($sRootClass, ENUM_CHILD_CLASSES_EXCLUDETOP) as $sChildClass)
 			{
 				if (array_key_exists('finalclass', self::$m_aAttribDefs[$sChildClass]))
@@ -1839,6 +1837,11 @@ abstract class MetaModel
 				$oCloned = clone $oClassAtt;
 				$oCloned->SetFixedValue($sChildClass);
 				self::AddMagicAttribute($oCloned, $sChildClass, $sRootClass);
+
+				if ($bObsoletable  && is_null(self::$m_aClassParams[$sChildClass]['obsolescence_expression']))
+				{
+					self::$m_aClassParams[$sChildClass]['obsolescence_expression'] = '0';
+				}
 			}
 		}
 
@@ -1847,6 +1850,8 @@ abstract class MetaModel
 		//
 		foreach (self::GetClasses() as $sClass)
 		{
+			$sRootClass = self::$m_aRootClasses[$sClass];
+
 			// Create the friendly name attribute
 			$sFriendlyNameAttCode = 'friendlyname'; 
 			$oFriendlyName = new AttributeFriendlyName($sFriendlyNameAttCode);
@@ -1879,18 +1884,17 @@ abstract class MetaModel
 				$oObsolescenceFlag = new AttributeObsolescenceFlag('obsolescence_flag');
 				self::AddMagicAttribute($oObsolescenceFlag, $sClass);
 
-				$sObsolescenceRoot = self::$m_aClassParams[$sClass]['obsolescence_root_class'];
-				if ($sClass == $sObsolescenceRoot)
+				if (self::$m_aRootClasses[$sClass] == $sClass)
 				{
 					$oObsolescenceDate = new AttributeDate('obsolescence_date', array('magic' => true, "allowed_values" => null, "sql" => 'obsolescence_date', "default_value" => '', "is_null_allowed" => true, "depends_on" => array()));
 					self::AddMagicAttribute($oObsolescenceDate, $sClass);
 				}
 				else
 				{
-					$oObsolescenceDate = clone self::$m_aAttribDefs[$sObsolescenceRoot]['archive_date'];
+					$oObsolescenceDate = clone self::$m_aAttribDefs[$sRootClass]['obsolescence_date'];
 					$oObsolescenceDate->SetHostClass($sClass);
 					self::$m_aAttribDefs[$sClass]['obsolescence_date'] = $oObsolescenceDate;
-					self::$m_aAttribOrigins[$sClass]['obsolescence_date'] = $sObsolescenceRoot;
+					self::$m_aAttribOrigins[$sClass]['obsolescence_date'] = $sRootClass;
 				}
 			}
 			foreach (self::$m_aAttribDefs[$sClass] as $sAttCode => $oAttDef)
@@ -1993,7 +1997,7 @@ abstract class MetaModel
 					if (self::IsObsoletable($sRemoteClass))
 					{
 						$sObsoleteRemote = $sAttCode.'_obsolescence_flag';
-						$oObsoleteRemote = new AttributeExternalField($sObsoleteRemote, array("allowed_values"=>null, "extkey_attcode"=>$sAttCode, "target_attcode"=>'archive_flag', "depends_on"=>array()));
+						$oObsoleteRemote = new AttributeExternalField($sObsoleteRemote, array("allowed_values"=>null, "extkey_attcode"=>$sAttCode, "target_attcode"=>'obsolescence_flag', "depends_on"=>array()));
 						self::AddMagicAttribute($oObsoleteRemote, $sClass, self::$m_aAttribOrigins[$sClass][$sAttCode]);
 					}
 				}
@@ -4533,7 +4537,10 @@ abstract class MetaModel
 		}
 		return $value;
 	}
-	
+
+	/**
+	 * @return Config
+	 */
 	public static function GetConfig()
 	{
 		return self::$m_oConfig;
@@ -4719,6 +4726,14 @@ abstract class MetaModel
 		return new $sClass($aRow, $sClassAlias, $aAttToLoad, $aExtendedDataSpec);
 	}
 
+	/**
+	 * @param $sClass
+	 * @param $iKey
+	 * @param bool $bMustBeFound
+	 * @param bool $bAllowAllData
+	 * @param null $aModifierProperties
+	 * @return DBObject|null
+	 */
 	public static function GetObject($sClass, $iKey, $bMustBeFound = true, $bAllowAllData = false, $aModifierProperties = null)
 	{
 		self::_check_subclass($sClass);	

+ 10 - 2
core/oql/expression.class.inc.php

@@ -1351,9 +1351,17 @@ class QueryBuilderExpressions
 	protected $m_aJoinFields;
 	protected $m_aClassIds;
 
-	public function __construct($oSearch, $aGroupByExpr = null)
+	public function __construct(DBObjectSearch $oSearch, $aGroupByExpr = null)
 	{
-		$this->m_oConditionExpr = $oSearch->GetCriteria();
+		if ($oSearch->GetShowObsoleteData() || !MetaModel::IsObsoletable($oSearch->GetClass()))
+		{
+			$this->m_oConditionExpr = $oSearch->GetCriteria();
+		}
+		else
+		{
+			$oNotObsolete = new BinaryExpression(new FieldExpression('obsolescence_flag', $oSearch->GetClassAlias()), '=', new ScalarExpression(0));
+			$this->m_oConditionExpr = new BinaryExpression($oSearch->GetCriteria(), 'AND', $oNotObsolete);
+		}
 		$this->m_aSelectExpr = array();
 		$this->m_aGroupByExpr = $aGroupByExpr;
 		$this->m_aJoinFields = array();

+ 16 - 6
core/relationgraph.class.inc.php

@@ -209,8 +209,7 @@ class RelationGraph extends SimpleGraph
 	{
 		if ($sOQL === '') return;
 		
-		$oSearch = DBObjectSearch::FromOQL($sOQL);
-		$oSearch->SetArchiveMode(false); // Exclude archived objects anytime
+		$oSearch = static::MakeSearch($sOQL);
 		$aAliases = $oSearch->GetSelectedClasses();
 		if (count($aAliases) < 2 )
 		{
@@ -394,8 +393,7 @@ class RelationGraph extends SimpleGraph
 	 				$sQuery = $bDown ? $aQueryInfo['sQueryDown'] : $aQueryInfo['sQueryUp'];
 					try
 					{
-						$oFlt = DBObjectSearch::FromOQL($sQuery);
-						$oFlt->SetArchiveMode(false); // Exclude archived objects anytime
+						$oFlt = static::MakeSearch($sQuery);
 						$oObjSet = new DBObjectSet($oFlt, array(), $oObject->ToArgsForQuery());
 						$oRelatedObj = $oObjSet->Fetch();
 					}
@@ -461,8 +459,7 @@ class RelationGraph extends SimpleGraph
 				$sQuery = $aQueryInfo['sQueryUp'];
 				try
 				{
-					$oFlt = DBObjectSearch::FromOQL($sQuery);
-					$oFlt->SetArchiveMode(false); // Exclude archived objects anytime
+					$oFlt = static::MakeSearch($sQuery);
 					$oObjSet = new DBObjectSet($oFlt, array(), $oObject->ToArgsForQuery());
 					$iCount = $oObjSet->Count();
 				}
@@ -580,4 +577,17 @@ class RelationGraph extends SimpleGraph
 		}
 		return $aResults;		
 	}	
+
+	protected static function MakeSearch($sOQL)
+	{
+		$oSearch = DBSearch::FromOQL($sOQL);
+		if (MetaModel::IsObsoletable($oSearch->GetClass()))
+		{
+			// Exclude obsolete objects anytime
+			$oSearch->AddCondition('obsolescence_flag', 0);
+		}
+		// Exclude archived objects anytime
+		$oSearch->SetArchiveMode(false);
+		return $oSearch;
+	}
 }

+ 8 - 1
dictionaries/cs.dictionary.itop.core.php

@@ -60,7 +60,14 @@ Dict::Add('CS CZ', 'Czech', 'Čeština', array(
 	'Core:AttributeArchiveDate/Label' => 'Archive date~~',
 	'Core:AttributeArchiveDate/Label+' => '',
 
-    'Core:AttributeString' => 'Řetězec (string)',
+	'Core:AttributeObsolescenceFlag' => 'Obsolescence flag~~',
+	'Core:AttributeObsolescenceFlag/Value:yes' => 'Yes~~',
+	'Core:AttributeObsolescenceFlag/Value:yes+' => 'This object is excluded from the impact analysis, and hidden from search results~~',
+	'Core:AttributeObsolescenceFlag/Value:no' => 'No~~',
+	'Core:AttributeObsolescenceFlag/Label' => 'Obsolete~~',
+	'Core:AttributeObsolescenceFlag/Label+' => 'Computed dynamically on other attributes~~',
+
+	'Core:AttributeString' => 'Řetězec (string)',
     'Core:AttributeString+' => 'Alfanumerický řetězec',
 
     'Core:AttributeClass' => 'Třída (class)',

+ 3 - 1
dictionaries/cs.dictionary.itop.ui.php

@@ -1078,7 +1078,9 @@ Dict::Add('CS CZ', 'Czech', 'Čeština', array(
     'UI:Favorites:SelectYourLanguage' => 'Preferovaný jazyk:',
     'UI:FavoriteOtherSettings' => 'Další nastavení',
     'UI:Favorites:Default_X_ItemsPerPage' => 'Výchozí délka seznamů: %1$s položek na stránku',
-    'UI:NavigateAwayConfirmationMessage' => 'Všechny úpravy budou zahozeny.',
+	'UI:Favorites:ShowObsoleteData' => 'Show obsolete data~~',
+	'UI:Favorites:ShowObsoleteData+' => 'Show obsolete data in search results and lists of items to select~~',
+	'UI:NavigateAwayConfirmationMessage' => 'Všechny úpravy budou zahozeny.',
     'UI:CancelConfirmationMessage' => 'Přijdete o všechny změny. Přejete si přesto pokračovat?',
     'UI:AutoApplyConfirmationMessage' => 'Některé změny nebyly dosud použity. Chcete aby je iTop zohlednil?',
     'UI:Create_Class_InState' => 'Vytvořit %1$s ve stavu: ',

+ 6 - 0
dictionaries/da.dictionary.itop.core.php

@@ -1408,6 +1408,12 @@ Dict::Add('DA DA', 'Danish', 'Dansk', array(
 	'Core:AttributeArchiveFlag/Label+' => '',
 	'Core:AttributeArchiveDate/Label' => 'Archive date~~',
 	'Core:AttributeArchiveDate/Label+' => '',
+	'Core:AttributeObsolescenceFlag' => 'Obsolescence flag~~',
+	'Core:AttributeObsolescenceFlag/Value:yes' => 'Yes~~',
+	'Core:AttributeObsolescenceFlag/Value:yes+' => 'This object is excluded from the impact analysis, and hidden from search results~~',
+	'Core:AttributeObsolescenceFlag/Value:no' => 'No~~',
+	'Core:AttributeObsolescenceFlag/Label' => 'Obsolete~~',
+	'Core:AttributeObsolescenceFlag/Label+' => 'Computed dynamically on other attributes~~',
 	'Core:AttributeString' => 'String',
 	'Core:AttributeString+' => '',
 	'Core:AttributeClass' => 'Class',

+ 5 - 0
dictionaries/da.dictionary.itop.ui.php

@@ -611,8 +611,11 @@ Dict::Add('DA DA', 'Danish', 'Dansk', array(
 	'UI:ObjectArchived' => 'This object has been archived. Please enable the archive mode or contact your administrator.~~',
 	'Tag:Archived' => 'Archived~~',
 	'Tag:Archived+' => 'Can be accessed only in archive mode~~',
+	'Tag:Obsolete' => 'Obsolete~~',
+	'Tag:Obsolete+' => 'Excluded from the impact analysis and search results~~',
 	'Tag:Synchronized' => 'Synchronized~~',
 	'ObjectRef:Archived' => 'Archived~~',
+	'ObjectRef:Obsolete' => 'Obsolete~~',
 	'UI:SearchResultsPageTitle' => 'iTop - Søge Resultater',
 	'UI:SearchResultsTitle' => 'Søge Resultater',
 	'UI:SearchResultsTitle+' => 'Full-text search results~~',
@@ -872,6 +875,8 @@ Ved tilknytningen til en trigger, bliver hver handling tildelt et "rækkefølge"
 	'UI:Favorites:SelectYourLanguage' => 'Vælg dit foretrukne sprog',
 	'UI:FavoriteOtherSettings' => 'Andre indstillinger',
 	'UI:Favorites:Default_X_ItemsPerPage' => 'Default længde for lister:  %1$s emner per side',
+	'UI:Favorites:ShowObsoleteData' => 'Show obsolete data~~',
+	'UI:Favorites:ShowObsoleteData+' => 'Show obsolete data in search results and lists of items to select~~',
 	'UI:NavigateAwayConfirmationMessage' => 'Enhver ændring vil blive kasseret.',
 	'UI:CancelConfirmationMessage' => 'Du vil miste dine ændringer. Fortsæt alligevel?',
 	'UI:AutoApplyConfirmationMessage' => 'Nogle ændringer er ikke gemt endnu. Ønsker du at itop skal tage hensyn til dem?',

+ 6 - 0
dictionaries/de.dictionary.itop.core.php

@@ -334,6 +334,12 @@ Dict::Add('DE DE', 'German', 'Deutsch', array(
 	'Core:AttributeArchiveFlag/Label+' => '',
 	'Core:AttributeArchiveDate/Label' => 'Archive date~~',
 	'Core:AttributeArchiveDate/Label+' => '',
+	'Core:AttributeObsolescenceFlag' => 'Obsolescence flag~~',
+	'Core:AttributeObsolescenceFlag/Value:yes' => 'Yes~~',
+	'Core:AttributeObsolescenceFlag/Value:yes+' => 'This object is excluded from the impact analysis, and hidden from search results~~',
+	'Core:AttributeObsolescenceFlag/Value:no' => 'No~~',
+	'Core:AttributeObsolescenceFlag/Label' => 'Obsolete~~',
+	'Core:AttributeObsolescenceFlag/Label+' => 'Computed dynamically on other attributes~~',
 	'Core:AttributeString' => 'String',
 	'Core:AttributeString+' => 'Alphanumerischer String',
 	'Core:AttributeClass' => 'Class',

+ 5 - 0
dictionaries/de.dictionary.itop.ui.php

@@ -612,8 +612,11 @@ Dict::Add('DE DE', 'German', 'Deutsch', array(
 	'UI:ObjectArchived' => 'This object has been archived. Please enable the archive mode or contact your administrator.~~',
 	'Tag:Archived' => 'Archived~~',
 	'Tag:Archived+' => 'Can be accessed only in archive mode~~',
+	'Tag:Obsolete' => 'Obsolete~~',
+	'Tag:Obsolete+' => 'Excluded from the impact analysis and search results~~',
 	'Tag:Synchronized' => 'Synchronized~~',
 	'ObjectRef:Archived' => 'Archived~~',
+	'ObjectRef:Obsolete' => 'Obsolete~~',
 	'UI:SearchResultsPageTitle' => 'iTop - Suchergebnisse',
 	'UI:SearchResultsTitle' => 'Suchergebnisse',
 	'UI:SearchResultsTitle+' => 'Full-text search results~~',
@@ -897,6 +900,8 @@ Wenn Aktionen mit Trigger verknüpft sind, bekommt jede Aktion eine Auftragsnumm
 	'UI:Favorites:SelectYourLanguage' => 'Wählen Sie Ihre bevorzugte Sprache aus',
 	'UI:FavoriteOtherSettings' => 'Andere Einstellungen',
 	'UI:Favorites:Default_X_ItemsPerPage' => 'Default-Länge für Listen:  %1$s Elemente pro Seite',
+	'UI:Favorites:ShowObsoleteData' => 'Show obsolete data~~',
+	'UI:Favorites:ShowObsoleteData+' => 'Show obsolete data in search results and lists of items to select~~',
 	'UI:NavigateAwayConfirmationMessage' => 'Jedwede Veränderung wird verworfen.',
 	'UI:CancelConfirmationMessage' => 'Sie werden Ihre Änderungen verlieren. Dennoch fortfahren?',
 	'UI:AutoApplyConfirmationMessage' => 'Einige Änderungen wurden noch nicht angewandt. Möchten Sie, daß iTop diese berüchsichtigt?',

+ 7 - 0
dictionaries/dictionary.itop.core.php

@@ -58,6 +58,13 @@ Dict::Add('EN US', 'English', 'English', array(
 	'Core:AttributeArchiveDate/Label' => 'Archive date',
 	'Core:AttributeArchiveDate/Label+' => '',
 
+	'Core:AttributeObsolescenceFlag' => 'Obsolescence flag',
+	'Core:AttributeObsolescenceFlag/Value:yes' => 'Yes',
+	'Core:AttributeObsolescenceFlag/Value:yes+' => 'This object is excluded from the impact analysis, and hidden from search results',
+	'Core:AttributeObsolescenceFlag/Value:no' => 'No',
+	'Core:AttributeObsolescenceFlag/Label' => 'Obsolete',
+	'Core:AttributeObsolescenceFlag/Label+' => 'Computed dynamically on other attributes',
+
 	'Core:AttributeString' => 'String',
 	'Core:AttributeString+' => 'Alphanumeric string',
 

+ 4 - 0
dictionaries/dictionary.itop.ui.php

@@ -773,6 +773,8 @@ Dict::Add('EN US', 'English', 'English', array(
 	'UI:ObjectArchived' => 'This object has been archived. Please enable the archive mode or contact your administrator.',
 	'Tag:Archived' => 'Archived',
 	'Tag:Archived+' => 'Can be accessed only in archive mode',
+	'Tag:Obsolete' => 'Obsolete',
+	'Tag:Obsolete+' => 'Excluded from the impact analysis and search results',
 	'Tag:Synchronized' => 'Synchronized',
 	'ObjectRef:Archived' => 'Archived',
 	'ObjectRef:Obsolete' => 'Obsolete',
@@ -1091,6 +1093,8 @@ When associated with a trigger, each action is given an "order" number, specifyi
 	'UI:Favorites:SelectYourLanguage' => 'Select your preferred language',
 	'UI:FavoriteOtherSettings' => 'Other Settings',
 	'UI:Favorites:Default_X_ItemsPerPage' => 'Default length for lists:  %1$s items per page',
+	'UI:Favorites:ShowObsoleteData' => 'Show obsolete data',
+	'UI:Favorites:ShowObsoleteData+' => 'Show obsolete data in search results and lists of items to select',
 	'UI:NavigateAwayConfirmationMessage' => 'Any modification will be discarded.',
 	'UI:CancelConfirmationMessage' => 'You will loose your changes. Continue anyway?',
 	'UI:AutoApplyConfirmationMessage' => 'Some changes have not been applied yet. Do you want itop to take them into account?',

+ 7 - 0
dictionaries/es_cr.dictionary.itop.core.php

@@ -58,6 +58,13 @@ Dict::Add('ES CR', 'Spanish', 'Español, Castellano', array(
 	'Core:AttributeArchiveDate/Label' => 'Archive date~~',
 	'Core:AttributeArchiveDate/Label+' => '',
 
+	'Core:AttributeObsolescenceFlag' => 'Obsolescence flag~~',
+	'Core:AttributeObsolescenceFlag/Value:yes' => 'Yes~~',
+	'Core:AttributeObsolescenceFlag/Value:yes+' => 'This object is excluded from the impact analysis, and hidden from search results~~',
+	'Core:AttributeObsolescenceFlag/Value:no' => 'No~~',
+	'Core:AttributeObsolescenceFlag/Label' => 'Obsolete~~',
+	'Core:AttributeObsolescenceFlag/Label+' => 'Computed dynamically on other attributes~~',
+
 	'Core:AttributeString' => 'Cadena de caracteres',
 	'Core:AttributeString+' => 'Cadena de caracteres alfanumerico',
 

+ 5 - 0
dictionaries/es_cr.dictionary.itop.ui.php

@@ -763,8 +763,11 @@ Dict::Add('ES CR', 'Spanish', 'Español, Castellano', array(
 	'UI:ObjectArchived' => 'This object has been archived. Please enable the archive mode or contact your administrator.~~',
 	'Tag:Archived' => 'Archived~~',
 	'Tag:Archived+' => 'Can be accessed only in archive mode~~',
+	'Tag:Obsolete' => 'Obsolete~~',
+	'Tag:Obsolete+' => 'Excluded from the impact analysis and search results~~',
 	'Tag:Synchronized' => 'Synchronized~~',
 	'ObjectRef:Archived' => 'Archived~~',
+	'ObjectRef:Obsolete' => 'Obsolete~~',
 	'UI:SearchResultsPageTitle' => 'iTop - Resultados de la Búsqueda',
 	'UI:SearchResultsTitle' => 'Resultados de la Búsqueda',
 	'UI:SearchResultsTitle+' => 'Full-text search results~~',
@@ -1050,6 +1053,8 @@ Cuando se asocien con un disparador, cada acción recibe un número de "orden",
 	'UI:Favorites:SelectYourLanguage' => 'Seleccione su Idioma Predeterminado',
 	'UI:FavoriteOtherSettings' => 'Otras Configuraciones',
 	'UI:Favorites:Default_X_ItemsPerPage' => 'Tama&ntilde;o Predeterminado de Listas:  %1$s elementos por página',
+	'UI:Favorites:ShowObsoleteData' => 'Show obsolete data~~',
+	'UI:Favorites:ShowObsoleteData+' => 'Show obsolete data in search results and lists of items to select~~',
 	'UI:NavigateAwayConfirmationMessage' => 'Cualquier modificación será descartada.',
 	'UI:CancelConfirmationMessage' => 'Perderá los cambios realizados. ¿Desea Continuar?',
 	'UI:AutoApplyConfirmationMessage' => 'Algunos cambios no han sido aplicados todavía. ¿Quiere que iTop los tome en cuenta?',

+ 8 - 2
dictionaries/fr.dictionary.itop.core.php

@@ -439,10 +439,16 @@ Dict::Add('FR FR', 'French', 'Français', array(
 	'Core:AttributeArchiveFlag/Value:yes' => 'Oui',
 	'Core:AttributeArchiveFlag/Value:yes+' => 'Cet object n\'est visible que dans le mode Archive',
 	'Core:AttributeArchiveFlag/Value:no' => 'Non',
-	'Core:AttributeArchiveFlag/Label' => 'Archivé~~',
+	'Core:AttributeArchiveFlag/Label' => 'Archivé',
 	'Core:AttributeArchiveFlag/Label+' => '',
-	'Core:AttributeArchiveDate/Label' => 'Date archivage~~',
+	'Core:AttributeArchiveDate/Label' => 'Date archivage',
 	'Core:AttributeArchiveDate/Label+' => '',
+	'Core:AttributeObsolescenceFlag' => 'Drapeau Obsolète',
+	'Core:AttributeObsolescenceFlag/Value:yes' => 'Oui',
+	'Core:AttributeObsolescenceFlag/Value:yes+' => 'Cet objet est exclus de l\'analyse d\'impact, et n\'est pas affiché dans les résultats de recherche',
+	'Core:AttributeObsolescenceFlag/Value:no' => 'Non',
+	'Core:AttributeObsolescenceFlag/Label' => 'Obsolète',
+	'Core:AttributeObsolescenceFlag/Label+' => 'Calculé dynamiquement en fonction d\'autres attributs de l\'objet',
 
 	'Core:AttributeString' => 'Chaîne de caractères',
 	'Core:AttributeString+' => 'Chaîne de caractères (limitée à une ligne)',

+ 5 - 0
dictionaries/fr.dictionary.itop.ui.php

@@ -663,8 +663,11 @@ Dict::Add('FR FR', 'French', 'Français', array(
 	'UI:ObjectArchived' => 'Cet objet a été archivé. Veuillez activer le mode Archive, on contactez votre administrateur.',
 	'Tag:Archived' => 'Archivé',
 	'Tag:Archived+' => 'Accessible seulement dans le mode Archive',
+	'Tag:Obsolete' => 'Obsolète',
+	'Tag:Obsolete+' => 'Exclu de l\'analyse d\'impact et des résultats de recherche~~',
 	'Tag:Synchronized' => 'Synchronisé',
 	'ObjectRef:Archived' => 'Archivé',
+	'ObjectRef:Obsolete' => 'Obsolète',
 	'UI:SearchResultsPageTitle' => 'iTop - Résultats de la recherche',
 	'UI:SearchResultsTitle' => 'Recherche globale',
 	'UI:SearchResultsTitle+' => 'Résultat de recherche globale',
@@ -954,6 +957,8 @@ Lors de l\'association à un déclencheur, on attribue à chaque action un numé
 	'UI:Favorites:SelectYourLanguage' => 'Choisissez votre langue préférée',
 	'UI:FavoriteOtherSettings' => 'Autres réglages',
 	'UI:Favorites:Default_X_ItemsPerPage' => 'Longueur par défaut des listes:  %1$s éléments par page',
+	'UI:Favorites:ShowObsoleteData' => 'Voir les données obsolètes',
+	'UI:Favorites:ShowObsoleteData+' => 'Voir les données obsolètes dans les résultats de recherche et dans les listes de choix',
 	'UI:NavigateAwayConfirmationMessage' => 'Toute modification sera perdue.',
 	'UI:CancelConfirmationMessage' => 'Vous allez perdre vos modifications. Voulez-vous continuer ?',
 	'UI:AutoApplyConfirmationMessage' => 'Des modifications n\'ont pas encore été prises en compte. Voulez-vous qu\'elles soient prises en compte automatiquement ?',

+ 6 - 0
dictionaries/hu.dictionary.itop.core.php

@@ -317,6 +317,12 @@ Dict::Add('HU HU', 'Hungarian', 'Magyar', array(
 	'Core:AttributeArchiveFlag/Label+' => '',
 	'Core:AttributeArchiveDate/Label' => 'Archive date~~',
 	'Core:AttributeArchiveDate/Label+' => '',
+	'Core:AttributeObsolescenceFlag' => 'Obsolescence flag~~',
+	'Core:AttributeObsolescenceFlag/Value:yes' => 'Yes~~',
+	'Core:AttributeObsolescenceFlag/Value:yes+' => 'This object is excluded from the impact analysis, and hidden from search results~~',
+	'Core:AttributeObsolescenceFlag/Value:no' => 'No~~',
+	'Core:AttributeObsolescenceFlag/Label' => 'Obsolete~~',
+	'Core:AttributeObsolescenceFlag/Label+' => 'Computed dynamically on other attributes~~',
 	'Core:AttributeString' => 'String',
 	'Core:AttributeString+' => '',
 	'Core:AttributeClass' => 'Class',

+ 5 - 0
dictionaries/hu.dictionary.itop.ui.php

@@ -542,8 +542,11 @@ Dict::Add('HU HU', 'Hungarian', 'Magyar', array(
 	'UI:ObjectArchived' => 'This object has been archived. Please enable the archive mode or contact your administrator.~~',
 	'Tag:Archived' => 'Archived~~',
 	'Tag:Archived+' => 'Can be accessed only in archive mode~~',
+	'Tag:Obsolete' => 'Obsolete~~',
+	'Tag:Obsolete+' => 'Excluded from the impact analysis and search results~~',
 	'Tag:Synchronized' => 'Synchronized~~',
 	'ObjectRef:Archived' => 'Archived~~',
+	'ObjectRef:Obsolete' => 'Obsolete~~',
 	'UI:SearchResultsPageTitle' => 'iTop - Keresés eredményei',
 	'UI:SearchResultsTitle' => 'Keresés eredményei',
 	'UI:SearchResultsTitle+' => 'Full-text search results~~',
@@ -921,6 +924,8 @@ Akció kiváltó okhoz rendelésekor kap egy sorszámot , amely meghatározza az
 	'UI:Favorites:SelectYourLanguage' => 'Select your preferred language~~',
 	'UI:FavoriteOtherSettings' => 'Other Settings~~',
 	'UI:Favorites:Default_X_ItemsPerPage' => 'Default length for lists:  %1$s items per page~~',
+	'UI:Favorites:ShowObsoleteData' => 'Show obsolete data~~',
+	'UI:Favorites:ShowObsoleteData+' => 'Show obsolete data in search results and lists of items to select~~',
 	'UI:NavigateAwayConfirmationMessage' => 'Any modification will be discarded.~~',
 	'UI:CancelConfirmationMessage' => 'You will loose your changes. Continue anyway?~~',
 	'UI:AutoApplyConfirmationMessage' => 'Some changes have not been applied yet. Do you want itop to take them into account?~~',

+ 7 - 0
dictionaries/it.dictionary.itop.core.php

@@ -52,6 +52,13 @@ Dict::Add('IT IT', 'Italian', 'Italiano', array(
 	'Core:AttributeArchiveDate/Label' => 'Archive date~~',
 	'Core:AttributeArchiveDate/Label+' => '',
 
+	'Core:AttributeObsolescenceFlag' => 'Obsolescence flag~~',
+	'Core:AttributeObsolescenceFlag/Value:yes' => 'Yes~~',
+	'Core:AttributeObsolescenceFlag/Value:yes+' => 'This object is excluded from the impact analysis, and hidden from search results~~',
+	'Core:AttributeObsolescenceFlag/Value:no' => 'No~~',
+	'Core:AttributeObsolescenceFlag/Label' => 'Obsolete~~',
+	'Core:AttributeObsolescenceFlag/Label+' => 'Computed dynamically on other attributes~~',
+
 	'Core:AttributeString' => 'Stringa',
 	'Core:AttributeString+' => 'Stringa alfanumerica',
 

+ 5 - 0
dictionaries/it.dictionary.itop.ui.php

@@ -674,8 +674,11 @@ Dict::Add('IT IT', 'Italian', 'Italiano', array(
 	'UI:ObjectArchived' => 'This object has been archived. Please enable the archive mode or contact your administrator.~~',
 	'Tag:Archived' => 'Archived~~',
 	'Tag:Archived+' => 'Can be accessed only in archive mode~~',
+	'Tag:Obsolete' => 'Obsolete~~',
+	'Tag:Obsolete+' => 'Excluded from the impact analysis and search results~~',
 	'Tag:Synchronized' => 'Synchronized~~',
 	'ObjectRef:Archived' => 'Archived~~',
+	'ObjectRef:Obsolete' => 'Obsolete~~',
 	'UI:SearchResultsPageTitle' => 'iTop - Risultati della ricerca',
 	'UI:SearchResultsTitle' => 'Risultati della ricerca',
 	'UI:SearchResultsTitle+' => 'Full-text search results~~',
@@ -1046,6 +1049,8 @@ Quando è associata a un trigger, ad ogni azione è assegnato un numero "ordine"
 	'UI:Favorites:SelectYourLanguage' => 'Select your preferred language~~',
 	'UI:FavoriteOtherSettings' => 'Other Settings~~',
 	'UI:Favorites:Default_X_ItemsPerPage' => 'Default length for lists:  %1$s items per page~~',
+	'UI:Favorites:ShowObsoleteData' => 'Show obsolete data~~',
+	'UI:Favorites:ShowObsoleteData+' => 'Show obsolete data in search results and lists of items to select~~',
 	'UI:NavigateAwayConfirmationMessage' => 'Any modification will be discarded.~~',
 	'UI:CancelConfirmationMessage' => 'You will loose your changes. Continue anyway?~~',
 	'UI:AutoApplyConfirmationMessage' => 'Some changes have not been applied yet. Do you want itop to take them into account?~~',

+ 6 - 0
dictionaries/ja.dictionary.itop.core.php

@@ -336,6 +336,12 @@ Dict::Add('JA JP', 'Japanese', '日本語', array(
 	'Core:AttributeArchiveFlag/Label+' => '',
 	'Core:AttributeArchiveDate/Label' => 'Archive date~~',
 	'Core:AttributeArchiveDate/Label+' => '',
+	'Core:AttributeObsolescenceFlag' => 'Obsolescence flag~~',
+	'Core:AttributeObsolescenceFlag/Value:yes' => 'Yes~~',
+	'Core:AttributeObsolescenceFlag/Value:yes+' => 'This object is excluded from the impact analysis, and hidden from search results~~',
+	'Core:AttributeObsolescenceFlag/Value:no' => 'No~~',
+	'Core:AttributeObsolescenceFlag/Label' => 'Obsolete~~',
+	'Core:AttributeObsolescenceFlag/Label+' => 'Computed dynamically on other attributes~~',
 	'Core:AttributeString' => '文字列',
 	'Core:AttributeString+' => '文字列',
 	'Core:AttributeClass' => 'クラス',

+ 5 - 0
dictionaries/ja.dictionary.itop.ui.php

@@ -611,8 +611,11 @@ Dict::Add('JA JP', 'Japanese', '日本語', array(
 	'UI:ObjectArchived' => 'This object has been archived. Please enable the archive mode or contact your administrator.~~',
 	'Tag:Archived' => 'Archived~~',
 	'Tag:Archived+' => 'Can be accessed only in archive mode~~',
+	'Tag:Obsolete' => 'Obsolete~~',
+	'Tag:Obsolete+' => 'Excluded from the impact analysis and search results~~',
 	'Tag:Synchronized' => 'Synchronized~~',
 	'ObjectRef:Archived' => 'Archived~~',
+	'ObjectRef:Obsolete' => 'Obsolete~~',
 	'UI:SearchResultsPageTitle' => 'iTop - 検索結果',
 	'UI:SearchResultsTitle' => '検索結果',
 	'UI:SearchResultsTitle+' => 'Full-text search results~~',
@@ -871,6 +874,8 @@ Dict::Add('JA JP', 'Japanese', '日本語', array(
 	'UI:Favorites:SelectYourLanguage' => '希望する言語を選択ください。',
 	'UI:FavoriteOtherSettings' => '他のセッティング',
 	'UI:Favorites:Default_X_ItemsPerPage' => 'リストの規定の長さ: %1$s items 毎ページ',
+	'UI:Favorites:ShowObsoleteData' => 'Show obsolete data~~',
+	'UI:Favorites:ShowObsoleteData+' => 'Show obsolete data in search results and lists of items to select~~',
 	'UI:NavigateAwayConfirmationMessage' => '全ての変更を破棄します。',
 	'UI:CancelConfirmationMessage' => '変更内容が失われます。 続けますか?',
 	'UI:AutoApplyConfirmationMessage' => '幾つかの変更は、まだ反映されていません。 それらの変更を反映させますか?。',

+ 7 - 0
dictionaries/nl.dictionary.itop.core.php

@@ -63,6 +63,13 @@ Dict::Add('NL NL', 'Dutch', 'Nederlands', array(
 	'Core:AttributeArchiveDate/Label' => 'Archive date~~',
 	'Core:AttributeArchiveDate/Label+' => '',
 
+	'Core:AttributeObsolescenceFlag' => 'Obsolescence flag~~',
+	'Core:AttributeObsolescenceFlag/Value:yes' => 'Yes~~',
+	'Core:AttributeObsolescenceFlag/Value:yes+' => 'This object is excluded from the impact analysis, and hidden from search results~~',
+	'Core:AttributeObsolescenceFlag/Value:no' => 'No~~',
+	'Core:AttributeObsolescenceFlag/Label' => 'Obsolete~~',
+	'Core:AttributeObsolescenceFlag/Label+' => 'Computed dynamically on other attributes~~',
+
 	'Core:AttributeString' => 'String',
 	'Core:AttributeString+' => 'Alphanumerieke string',
 

+ 5 - 0
dictionaries/nl.dictionary.itop.ui.php

@@ -771,8 +771,11 @@ Dict::Add('NL NL', 'Dutch', 'Nederlands', array(
 	'UI:ObjectArchived' => 'This object has been archived. Please enable the archive mode or contact your administrator.~~',
 	'Tag:Archived' => 'Archived~~',
 	'Tag:Archived+' => 'Can be accessed only in archive mode~~',
+	'Tag:Obsolete' => 'Obsolete~~',
+	'Tag:Obsolete+' => 'Excluded from the impact analysis and search results~~',
 	'Tag:Synchronized' => 'Synchronized~~',
 	'ObjectRef:Archived' => 'Archived~~',
+	'ObjectRef:Obsolete' => 'Obsolete~~',
 	'UI:SearchResultsPageTitle' => 'iTop - Zoekresultaten',
 	'UI:SearchResultsTitle' => 'Zoekresultaten',
 	'UI:SearchResultsTitle+' => 'Full-text search results~~',
@@ -1058,6 +1061,8 @@ Indien gekoppeld aan een Trigger, wordt aan elke actie een "orde" nummer gegeven
 	'UI:Favorites:SelectYourLanguage' => 'Selecteer uw taal',
 	'UI:FavoriteOtherSettings' => 'Overige instellingen',
 	'UI:Favorites:Default_X_ItemsPerPage' => 'Standaard lengte voor lijsten:  %1$s items per pagina',
+	'UI:Favorites:ShowObsoleteData' => 'Show obsolete data~~',
+	'UI:Favorites:ShowObsoleteData+' => 'Show obsolete data in search results and lists of items to select~~',
 	'UI:NavigateAwayConfirmationMessage' => 'Bewerkingen zullen worden genegeerd.',
 	'UI:CancelConfirmationMessage' => 'U zult uw aanpassingen verliezen. Wilt u alsnog doorgaan?',
 	'UI:AutoApplyConfirmationMessage' => 'Sommige veranderingen zijn nog niet doorgevoerd. Wilt u dat iTop deze meeneemt?',

+ 7 - 0
dictionaries/pt_br.dictionary.itop.core.php

@@ -58,6 +58,13 @@ Dict::Add('PT BR', 'Brazilian', 'Brazilian', array(
 	'Core:AttributeArchiveDate/Label' => 'Archive date~~',
 	'Core:AttributeArchiveDate/Label+' => '',
 
+	'Core:AttributeObsolescenceFlag' => 'Obsolescence flag~~',
+	'Core:AttributeObsolescenceFlag/Value:yes' => 'Yes~~',
+	'Core:AttributeObsolescenceFlag/Value:yes+' => 'This object is excluded from the impact analysis, and hidden from search results~~',
+	'Core:AttributeObsolescenceFlag/Value:no' => 'No~~',
+	'Core:AttributeObsolescenceFlag/Label' => 'Obsolete~~',
+	'Core:AttributeObsolescenceFlag/Label+' => 'Computed dynamically on other attributes~~',
+
 	'Core:AttributeString' => 'String',
 	'Core:AttributeString+' => 'Seqüência alfanumérica',
 

+ 5 - 0
dictionaries/pt_br.dictionary.itop.ui.php

@@ -763,8 +763,11 @@ Dict::Add('PT BR', 'Brazilian', 'Brazilian', array(
 	'UI:ObjectArchived' => 'This object has been archived. Please enable the archive mode or contact your administrator.~~',
 	'Tag:Archived' => 'Archived~~',
 	'Tag:Archived+' => 'Can be accessed only in archive mode~~',
+	'Tag:Obsolete' => 'Obsolete~~',
+	'Tag:Obsolete+' => 'Excluded from the impact analysis and search results~~',
 	'Tag:Synchronized' => 'Synchronized~~',
 	'ObjectRef:Archived' => 'Archived~~',
+	'ObjectRef:Obsolete' => 'Obsolete~~',
 	'UI:SearchResultsPageTitle' => 'Resultado da pesquisa',
 	'UI:SearchResultsTitle' => 'Resultado da pesquisa',
 	'UI:SearchResultsTitle+' => 'Full-text search results~~',
@@ -1049,6 +1052,8 @@ When associated with a trigger, each action is given an "order" number, specifyi
 	'UI:Favorites:SelectYourLanguage' => 'Selecione sua linguagem preferida',
 	'UI:FavoriteOtherSettings' => 'Outras configurações',
 	'UI:Favorites:Default_X_ItemsPerPage' => 'Quantidade padrão para listas:  %1$s itens por página',
+	'UI:Favorites:ShowObsoleteData' => 'Show obsolete data~~',
+	'UI:Favorites:ShowObsoleteData+' => 'Show obsolete data in search results and lists of items to select~~',
 	'UI:NavigateAwayConfirmationMessage' => 'Qualquer modificações serão descartados.',
 	'UI:CancelConfirmationMessage' => 'Você vai perder as suas alterações. Continuar mesmo assim?',
 	'UI:AutoApplyConfirmationMessage' => 'Algumas mudanças ainda não foram aplicadas. Você quer levá-los em conta?',

+ 7 - 0
dictionaries/ru.dictionary.itop.core.php

@@ -44,6 +44,13 @@ Dict::Add('RU RU', 'Russian', 'Русский', array(
 	'Core:AttributeArchiveDate/Label' => 'Archive date~~',
 	'Core:AttributeArchiveDate/Label+' => '',
 
+	'Core:AttributeObsolescenceFlag' => 'Obsolescence flag~~',
+	'Core:AttributeObsolescenceFlag/Value:yes' => 'Yes~~',
+	'Core:AttributeObsolescenceFlag/Value:yes+' => 'This object is excluded from the impact analysis, and hidden from search results~~',
+	'Core:AttributeObsolescenceFlag/Value:no' => 'No~~',
+	'Core:AttributeObsolescenceFlag/Label' => 'Obsolete~~',
+	'Core:AttributeObsolescenceFlag/Label+' => 'Computed dynamically on other attributes~~',
+
 	'Core:AttributeString' => 'Строка',
 	'Core:AttributeString+' => 'Alphanumeric string',
 

+ 5 - 0
dictionaries/ru.dictionary.itop.ui.php

@@ -751,8 +751,11 @@ Dict::Add('RU RU', 'Russian', 'Русский', array(
 	'UI:ObjectArchived' => 'This object has been archived. Please enable the archive mode or contact your administrator.~~',
 	'Tag:Archived' => 'Archived~~',
 	'Tag:Archived+' => 'Can be accessed only in archive mode~~',
+	'Tag:Obsolete' => 'Obsolete~~',
+	'Tag:Obsolete+' => 'Excluded from the impact analysis and search results~~',
 	'Tag:Synchronized' => 'Synchronized~~',
 	'ObjectRef:Archived' => 'Archived~~',
+	'ObjectRef:Obsolete' => 'Obsolete~~',
 	'UI:SearchResultsPageTitle' => 'iTop - Результаты поиска',
 	'UI:SearchResultsTitle' => 'Результаты поиска',
 	'UI:SearchResultsTitle+' => 'Результаты полнотекстового поиска',
@@ -1069,6 +1072,8 @@ Dict::Add('RU RU', 'Russian', 'Русский', array(
 	'UI:Favorites:SelectYourLanguage' => 'Выберите Ваш язык',
 	'UI:FavoriteOtherSettings' => 'Другие настройки',
 	'UI:Favorites:Default_X_ItemsPerPage' => 'Длина списка по-умолчанию: %1$s элементов на страницу.',
+	'UI:Favorites:ShowObsoleteData' => 'Show obsolete data~~',
+	'UI:Favorites:ShowObsoleteData+' => 'Show obsolete data in search results and lists of items to select~~',
 	'UI:NavigateAwayConfirmationMessage' => 'Все изменения будут отменены.',
 	'UI:CancelConfirmationMessage' => 'Настройки НЕ будут сохранены. Продолжить?',
 	'UI:AutoApplyConfirmationMessage' => 'Некоторые изменения не вступили в силу. Применить их немедленно?',

+ 6 - 0
dictionaries/tr.dictionary.itop.core.php

@@ -424,6 +424,12 @@ Dict::Add('TR TR', 'Turkish', 'Türkçe', array(
 	'Core:AttributeArchiveFlag/Label+' => '',
 	'Core:AttributeArchiveDate/Label' => 'Archive date~~',
 	'Core:AttributeArchiveDate/Label+' => '',
+	'Core:AttributeObsolescenceFlag' => 'Obsolescence flag~~',
+	'Core:AttributeObsolescenceFlag/Value:yes' => 'Yes~~',
+	'Core:AttributeObsolescenceFlag/Value:yes+' => 'This object is excluded from the impact analysis, and hidden from search results~~',
+	'Core:AttributeObsolescenceFlag/Value:no' => 'No~~',
+	'Core:AttributeObsolescenceFlag/Label' => 'Obsolete~~',
+	'Core:AttributeObsolescenceFlag/Label+' => 'Computed dynamically on other attributes~~',
 	'Core:AttributeString' => 'String~~',
 	'Core:AttributeString+' => 'Alphanumeric string~~',
 	'Core:AttributeClass' => 'Class~~',

+ 5 - 0
dictionaries/tr.dictionary.itop.ui.php

@@ -648,8 +648,11 @@ Dict::Add('TR TR', 'Turkish', 'Türkçe', array(
 	'UI:ObjectArchived' => 'This object has been archived. Please enable the archive mode or contact your administrator.~~',
 	'Tag:Archived' => 'Archived~~',
 	'Tag:Archived+' => 'Can be accessed only in archive mode~~',
+	'Tag:Obsolete' => 'Obsolete~~',
+	'Tag:Obsolete+' => 'Excluded from the impact analysis and search results~~',
 	'Tag:Synchronized' => 'Synchronized~~',
 	'ObjectRef:Archived' => 'Archived~~',
+	'ObjectRef:Obsolete' => 'Obsolete~~',
 	'UI:SearchResultsPageTitle' => 'iTop - Arama Sonuçları',
 	'UI:SearchResultsTitle' => 'Arama Sonuçları',
 	'UI:SearchResultsTitle+' => 'Full-text search results~~',
@@ -1073,6 +1076,8 @@ Tetikleme gerçekleştiriğinde işlemler tanımlanan sıra numarası ile gerçe
 	'UI:Favorites:SelectYourLanguage' => 'Select your preferred language~~',
 	'UI:FavoriteOtherSettings' => 'Other Settings~~',
 	'UI:Favorites:Default_X_ItemsPerPage' => 'Default length for lists:  %1$s items per page~~',
+	'UI:Favorites:ShowObsoleteData' => 'Show obsolete data~~',
+	'UI:Favorites:ShowObsoleteData+' => 'Show obsolete data in search results and lists of items to select~~',
 	'UI:NavigateAwayConfirmationMessage' => 'Any modification will be discarded.~~',
 	'UI:CancelConfirmationMessage' => 'You will loose your changes. Continue anyway?~~',
 	'UI:AutoApplyConfirmationMessage' => 'Some changes have not been applied yet. Do you want itop to take them into account?~~',

+ 6 - 0
dictionaries/zh.dictionary.itop.core.php

@@ -423,6 +423,12 @@ Dict::Add('ZH CN', 'Chinese', '简体中文', array(
 	'Core:AttributeArchiveFlag/Label+' => '',
 	'Core:AttributeArchiveDate/Label' => 'Archive date~~',
 	'Core:AttributeArchiveDate/Label+' => '',
+	'Core:AttributeObsolescenceFlag' => 'Obsolescence flag~~',
+	'Core:AttributeObsolescenceFlag/Value:yes' => 'Yes~~',
+	'Core:AttributeObsolescenceFlag/Value:yes+' => 'This object is excluded from the impact analysis, and hidden from search results~~',
+	'Core:AttributeObsolescenceFlag/Value:no' => 'No~~',
+	'Core:AttributeObsolescenceFlag/Label' => 'Obsolete~~',
+	'Core:AttributeObsolescenceFlag/Label+' => 'Computed dynamically on other attributes~~',
 	'Core:AttributeString' => 'String~~',
 	'Core:AttributeString+' => 'Alphanumeric string~~',
 	'Core:AttributeClass' => 'Class~~',

+ 5 - 0
dictionaries/zh.dictionary.itop.ui.php

@@ -647,8 +647,11 @@ Dict::Add('ZH CN', 'Chinese', '简体中文', array(
 	'UI:ObjectArchived' => 'This object has been archived. Please enable the archive mode or contact your administrator.~~',
 	'Tag:Archived' => 'Archived~~',
 	'Tag:Archived+' => 'Can be accessed only in archive mode~~',
+	'Tag:Obsolete' => 'Obsolete~~',
+	'Tag:Obsolete+' => 'Excluded from the impact analysis and search results~~',
 	'Tag:Synchronized' => 'Synchronized~~',
 	'ObjectRef:Archived' => 'Archived~~',
+	'ObjectRef:Obsolete' => 'Obsolete~~',
 	'UI:SearchResultsPageTitle' => 'iTop - 搜索结果',
 	'UI:SearchResultsTitle' => '搜索结果',
 	'UI:SearchResultsTitle+' => 'Full-text search results~~',
@@ -1072,6 +1075,8 @@ Dict::Add('ZH CN', 'Chinese', '简体中文', array(
 	'UI:Favorites:SelectYourLanguage' => 'Select your preferred language~~',
 	'UI:FavoriteOtherSettings' => 'Other Settings~~',
 	'UI:Favorites:Default_X_ItemsPerPage' => 'Default length for lists:  %1$s items per page~~',
+	'UI:Favorites:ShowObsoleteData' => 'Show obsolete data~~',
+	'UI:Favorites:ShowObsoleteData+' => 'Show obsolete data in search results and lists of items to select~~',
 	'UI:NavigateAwayConfirmationMessage' => 'Any modification will be discarded.~~',
 	'UI:CancelConfirmationMessage' => 'You will loose your changes. Continue anyway?~~',
 	'UI:AutoApplyConfirmationMessage' => 'Some changes have not been applied yet. Do you want itop to take them into account?~~',

+ 14 - 2
pages/preferences.php

@@ -1,5 +1,5 @@
 <?php
-// Copyright (C) 2010-2012 Combodo SARL
+// Copyright (C) 2010-2017 Combodo SARL
 //
 //   This file is part of iTop.
 //
@@ -20,7 +20,7 @@
  * User preferences page
  * Displays / edit some user preferences
  *
- * @copyright   Copyright (C) 2010-2012 Combodo SARL
+ * @copyright   Copyright (C) 2010-2017 Combodo SARL
  * @license     http://opensource.org/licenses/AGPL-3.0
  */
 require_once('../approot.inc.php');
@@ -86,8 +86,18 @@ function DisplayPreferences($oP)
 	
 	$oP->add('<fieldset><legend>'.Dict::S('UI:FavoriteOtherSettings').'</legend>');
 	$oP->add('<form method="post" onsubmit="return ValidateOtherSettings()">');
+
 	$iDefaultPageSize = appUserPreferences::GetPref('default_page_size', MetaModel::GetConfig()->GetMinDisplayLimit());
 	$oP->add('<p>'.Dict::Format('UI:Favorites:Default_X_ItemsPerPage', '<input id="default_page_size" name="default_page_size" type="text" size="3" value="'.$iDefaultPageSize.'"/><span id="v_default_page_size"></span>').'</p>');
+
+	$bDefaultShow = appUserPreferences::GetPref('show_obsolete_data', MetaModel::GetConfig()->Get('show_obsolete_data'));
+	$sSelected = $bDefaultShow ? ' checked="checked"' : '';
+	$oP->add(
+		'<p>'
+		.'<input type="checkbox" id="show_obsolete_data" name="show_obsolete_data" value="1"'.$sSelected.'>'
+		.'<label for="show_obsolete_data" title="'.Dict::S('UI:Favorites:ShowObsoleteData+').'">'.Dict::S('UI:Favorites:ShowObsoleteData').'</label>'
+		.'</p>');
+
 	$oP->add('<input type="hidden" name="operation" value="apply_others"/>');
 	$oP->add($oAppContext->GetForForm());
 	$oP->add('<p><input type="button" onClick="window.location.href=\''.$sURL.'\'" value="'.Dict::S('UI:Button:Cancel').'"/>');
@@ -346,6 +356,8 @@ try
 		{
 			appUserPreferences::SetPref('default_page_size', $iDefaultPageSize);
 		}
+		$bShowObsoleteData = (bool)utils::ReadParam('show_obsolete_data', 0);
+		appUserPreferences::SetPref('show_obsolete_data', $bShowObsoleteData);
 		DisplayPreferences($oPage);
 		break;