mirror of
https://github.com/Combodo/iTop.git
synced 2026-04-24 11:08:45 +02:00
Implemented the capability to implemented a separate module for sharing objects between the silos:
+ possibility for a plugin to alter the definition of a class (add an attribute) + fixed a bug (low exposure) in the cache for MetaModel::GetObject() + possibility to have computed fields on links (list of fields in the form now based on the ZList 'list') SVN:1.2[1853]
This commit is contained in:
@@ -17,6 +17,7 @@
|
||||
require_once(APPROOT.'core/modulehandler.class.inc.php');
|
||||
require_once(APPROOT.'core/querybuildercontext.class.inc.php');
|
||||
require_once(APPROOT.'core/querymodifier.class.inc.php');
|
||||
require_once(APPROOT.'core/metamodelmodifier.inc.php');
|
||||
|
||||
/**
|
||||
* Metamodel
|
||||
@@ -1172,6 +1173,33 @@ if (!array_key_exists($sAttCode, self::$m_aAttribDefs[$sClass]))
|
||||
|
||||
self::$m_sTablePrefix = $sTablePrefix;
|
||||
|
||||
// Build the list of available extensions
|
||||
//
|
||||
$aInterfaces = array('iApplicationUIExtension', 'iApplicationObjectExtension', 'iQueryModifier', 'iOnClassInitialization');
|
||||
foreach($aInterfaces as $sInterface)
|
||||
{
|
||||
self::$m_aExtensionClasses[$sInterface] = array();
|
||||
}
|
||||
|
||||
foreach(get_declared_classes() as $sPHPClass)
|
||||
{
|
||||
$oRefClass = new ReflectionClass($sPHPClass);
|
||||
$oExtensionInstance = null;
|
||||
foreach($aInterfaces as $sInterface)
|
||||
{
|
||||
if ($oRefClass->implementsInterface($sInterface))
|
||||
{
|
||||
if (is_null($oExtensionInstance))
|
||||
{
|
||||
$oExtensionInstance = new $sPHPClass;
|
||||
}
|
||||
self::$m_aExtensionClasses[$sInterface][$sPHPClass] = $oExtensionInstance;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Initialize the classes (declared attributes, etc.)
|
||||
//
|
||||
foreach(get_declared_classes() as $sPHPClass) {
|
||||
if (is_subclass_of($sPHPClass, 'DBObject'))
|
||||
{
|
||||
@@ -1184,6 +1212,10 @@ if (!array_key_exists($sAttCode, self::$m_aAttribDefs[$sClass]))
|
||||
if (method_exists($sPHPClass, 'Init'))
|
||||
{
|
||||
call_user_func(array($sPHPClass, 'Init'));
|
||||
foreach (MetaModel::EnumPlugins('iOnClassInitialization') as $sPluginClass => $oClassInit)
|
||||
{
|
||||
$oClassInit->OnAfterClassInitialization($sPHPClass);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1401,31 +1433,6 @@ if (!array_key_exists($sAttCode, self::$m_aAttribDefs[$sClass]))
|
||||
// }
|
||||
//}
|
||||
}
|
||||
|
||||
// Build the list of available extensions
|
||||
//
|
||||
$aInterfaces = array('iApplicationUIExtension', 'iApplicationObjectExtension', 'iQueryModifier');
|
||||
foreach($aInterfaces as $sInterface)
|
||||
{
|
||||
self::$m_aExtensionClasses[$sInterface] = array();
|
||||
}
|
||||
|
||||
foreach(get_declared_classes() as $sPHPClass)
|
||||
{
|
||||
$oRefClass = new ReflectionClass($sPHPClass);
|
||||
$oExtensionInstance = null;
|
||||
foreach($aInterfaces as $sInterface)
|
||||
{
|
||||
if ($oRefClass->implementsInterface($sInterface))
|
||||
{
|
||||
if (is_null($oExtensionInstance))
|
||||
{
|
||||
$oExtensionInstance = new $sPHPClass;
|
||||
}
|
||||
self::$m_aExtensionClasses[$sInterface][$sPHPClass] = $oExtensionInstance;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// To be overriden, must be called for any object class (optimization)
|
||||
@@ -1562,9 +1569,12 @@ if (!array_key_exists($sAttCode, self::$m_aAttribDefs[$sClass]))
|
||||
return true;
|
||||
}
|
||||
|
||||
public static function Init_AddAttribute(AttributeDefinition $oAtt)
|
||||
public static function Init_AddAttribute(AttributeDefinition $oAtt, $sTargetClass = null)
|
||||
{
|
||||
$sTargetClass = self::GetCallersPHPClass("Init");
|
||||
if (!$sTargetClass)
|
||||
{
|
||||
$sTargetClass = self::GetCallersPHPClass("Init");
|
||||
}
|
||||
|
||||
$sAttCode = $oAtt->GetCode();
|
||||
if ($sAttCode == 'finalclass')
|
||||
@@ -1625,11 +1635,14 @@ if (!array_key_exists($sAttCode, self::$m_aAttribDefs[$sClass]))
|
||||
// Note: it looks redundant to put targetclass there, but a mix occurs when inheritance is used
|
||||
}
|
||||
|
||||
public static function Init_SetZListItems($sListCode, $aItems)
|
||||
public static function Init_SetZListItems($sListCode, $aItems, $sTargetClass = null)
|
||||
{
|
||||
MyHelpers::CheckKeyInArray('list code', $sListCode, self::$m_aListInfos);
|
||||
|
||||
$sTargetClass = self::GetCallersPHPClass("Init");
|
||||
if (!$sTargetClass)
|
||||
{
|
||||
$sTargetClass = self::GetCallersPHPClass("Init");
|
||||
}
|
||||
|
||||
// Discard attributes that do not make sense
|
||||
// (missing classes in the current module combination, resulting in irrelevant ext key or link set)
|
||||
@@ -1916,7 +1929,7 @@ if (!array_key_exists($sAttCode, self::$m_aAttribDefs[$sClass]))
|
||||
//
|
||||
if (!$oFilter->IsAllDataAllowed() && !$oFilter->IsDataFiltered())
|
||||
{
|
||||
$oVisibleObjects = UserRights::GetSelectFilter($oFilter->GetClass());
|
||||
$oVisibleObjects = UserRights::GetSelectFilter($oFilter->GetClass(), $oFilter->GetModifierProperties('UserRightsGetSelectFilter'));
|
||||
if ($oVisibleObjects === false)
|
||||
{
|
||||
// Make sure this is a valid search object, saying NO for all
|
||||
@@ -4359,17 +4372,31 @@ if (!array_key_exists($sAttCode, self::$m_aAttribDefs[$sClass]))
|
||||
{
|
||||
$aRes = array();
|
||||
$iTotalHits = 0;
|
||||
foreach(self::$aQueryCacheGetObjectHits as $sClass => $iHits)
|
||||
foreach(self::$aQueryCacheGetObjectHits as $sClassSign => $iHits)
|
||||
{
|
||||
$aRes[] = "$sClass: $iHits";
|
||||
$aRes[] = "$sClassSign: $iHits";
|
||||
$iTotalHits += $iHits;
|
||||
}
|
||||
return $iTotalHits.' ('.implode(', ', $aRes).')';
|
||||
}
|
||||
|
||||
public static function MakeSingleRow($sClass, $iKey, $bMustBeFound = true, $bAllowAllData = false)
|
||||
public static function MakeSingleRow($sClass, $iKey, $bMustBeFound = true, $bAllowAllData = false, $aModifierProperties = null)
|
||||
{
|
||||
if (!array_key_exists($sClass, self::$aQueryCacheGetObject))
|
||||
// Build the query cache signature
|
||||
//
|
||||
$sQuerySign = $sClass;
|
||||
if($bAllowAllData)
|
||||
{
|
||||
$sQuerySign .= '_all_';
|
||||
}
|
||||
if (count($aModifierProperties))
|
||||
{
|
||||
array_multisort($aModifierProperties);
|
||||
$sModifierProperties = json_encode($aModifierProperties);
|
||||
$sQuerySign .= '_all_'.md5($sModifierProperties);
|
||||
}
|
||||
|
||||
if (!array_key_exists($sQuerySign, self::$aQueryCacheGetObject))
|
||||
{
|
||||
// NOTE: Quick and VERY dirty caching mechanism which relies on
|
||||
// the fact that the string '987654321' will never appear in the
|
||||
@@ -4378,20 +4405,30 @@ if (!array_key_exists($sAttCode, self::$m_aAttribDefs[$sClass]))
|
||||
// but this would slow down -by how much time?- the application
|
||||
$oFilter = new DBObjectSearch($sClass);
|
||||
$oFilter->AddCondition('id', 987654321, '=');
|
||||
if ($aModifierProperties)
|
||||
{
|
||||
foreach ($aModifierProperties as $sPluginClass => $aProperties)
|
||||
{
|
||||
foreach ($aProperties as $sProperty => $value)
|
||||
{
|
||||
$oFilter->SetModifierProperty($sPluginClass, $sProperty, $value);
|
||||
}
|
||||
}
|
||||
}
|
||||
if ($bAllowAllData)
|
||||
{
|
||||
$oFilter->AllowAllData();
|
||||
}
|
||||
|
||||
$sSQL = self::MakeSelectQuery($oFilter);
|
||||
self::$aQueryCacheGetObject[$sClass] = $sSQL;
|
||||
self::$aQueryCacheGetObjectHits[$sClass] = 0;
|
||||
self::$aQueryCacheGetObject[$sQuerySign] = $sSQL;
|
||||
self::$aQueryCacheGetObjectHits[$sQuerySign] = 0;
|
||||
}
|
||||
else
|
||||
{
|
||||
$sSQL = self::$aQueryCacheGetObject[$sClass];
|
||||
self::$aQueryCacheGetObjectHits[$sClass] += 1;
|
||||
// echo " -load $sClass/$iKey- ".self::$aQueryCacheGetObjectHits[$sClass]."<br/>\n";
|
||||
$sSQL = self::$aQueryCacheGetObject[$sQuerySign];
|
||||
self::$aQueryCacheGetObjectHits[$sQuerySign] += 1;
|
||||
// echo " -load $sClass/$iKey- ".self::$aQueryCacheGetObjectHits[$sQuerySign]."<br/>\n";
|
||||
}
|
||||
$sSQL = str_replace(CMDBSource::Quote(987654321), CMDBSource::Quote($iKey), $sSQL);
|
||||
$res = CMDBSource::Query($sSQL);
|
||||
@@ -4437,10 +4474,10 @@ if (!array_key_exists($sAttCode, self::$m_aAttribDefs[$sClass]))
|
||||
return new $sClass($aRow, $sClassAlias, $aAttToLoad, $aExtendedDataSpec);
|
||||
}
|
||||
|
||||
public static function GetObject($sClass, $iKey, $bMustBeFound = true, $bAllowAllData = false)
|
||||
public static function GetObject($sClass, $iKey, $bMustBeFound = true, $bAllowAllData = false, $aModifierProperties = null)
|
||||
{
|
||||
self::_check_subclass($sClass);
|
||||
$aRow = self::MakeSingleRow($sClass, $iKey, $bMustBeFound, $bAllowAllData);
|
||||
$aRow = self::MakeSingleRow($sClass, $iKey, $bMustBeFound, $bAllowAllData, $aModifierProperties);
|
||||
if (empty($aRow))
|
||||
{
|
||||
return null;
|
||||
|
||||
Reference in New Issue
Block a user