valuesetdef.class.inc.php 11 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428
  1. <?php
  2. // Copyright (C) 2010-2017 Combodo SARL
  3. //
  4. // This file is part of iTop.
  5. //
  6. // iTop is free software; you can redistribute it and/or modify
  7. // it under the terms of the GNU Affero General Public License as published by
  8. // the Free Software Foundation, either version 3 of the License, or
  9. // (at your option) any later version.
  10. //
  11. // iTop is distributed in the hope that it will be useful,
  12. // but WITHOUT ANY WARRANTY; without even the implied warranty of
  13. // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  14. // GNU Affero General Public License for more details.
  15. //
  16. // You should have received a copy of the GNU Affero General Public License
  17. // along with iTop. If not, see <http://www.gnu.org/licenses/>
  18. /**
  19. * Value set definitions (from a fixed list or from a query, etc.)
  20. *
  21. * @copyright Copyright (C) 2010-2017 Combodo SARL
  22. * @license http://opensource.org/licenses/AGPL-3.0
  23. */
  24. require_once('MyHelpers.class.inc.php');
  25. /**
  26. * ValueSetDefinition
  27. * value sets API and implementations
  28. *
  29. * @package iTopORM
  30. */
  31. abstract class ValueSetDefinition
  32. {
  33. protected $m_bIsLoaded = false;
  34. protected $m_aValues = array();
  35. // Displayable description that could be computed out of the std usage context
  36. public function GetValuesDescription()
  37. {
  38. $aValues = $this->GetValues(array(), '');
  39. $aDisplayedValues = array();
  40. foreach($aValues as $key => $value)
  41. {
  42. $aDisplayedValues[] = "$key => $value";
  43. }
  44. $sAllowedValues = implode(', ', $aDisplayedValues);
  45. return $sAllowedValues;
  46. }
  47. public function GetValues($aArgs, $sContains = '')
  48. {
  49. if (!$this->m_bIsLoaded)
  50. {
  51. $this->LoadValues($aArgs);
  52. $this->m_bIsLoaded = true;
  53. }
  54. if (strlen($sContains) == 0)
  55. {
  56. // No filtering
  57. $aRet = $this->m_aValues;
  58. }
  59. else
  60. {
  61. // Filter on results containing the needle <sContain>
  62. $aRet = array();
  63. foreach ($this->m_aValues as $sKey=>$sValue)
  64. {
  65. if (stripos($sValue, $sContains) !== false)
  66. {
  67. $aRet[$sKey] = $sValue;
  68. }
  69. }
  70. }
  71. // Sort on the display value
  72. asort($aRet);
  73. return $aRet;
  74. }
  75. abstract protected function LoadValues($aArgs);
  76. }
  77. /**
  78. * Set of existing values for an attribute, given a search filter
  79. *
  80. * @package iTopORM
  81. */
  82. class ValueSetObjects extends ValueSetDefinition
  83. {
  84. protected $m_sContains;
  85. protected $m_sFilterExpr; // in OQL
  86. protected $m_sValueAttCode;
  87. protected $m_aOrderBy;
  88. protected $m_aExtraConditions;
  89. private $m_bAllowAllData;
  90. private $m_aModifierProperties;
  91. /**
  92. * @param hash $aOrderBy Array of '[<classalias>.]attcode' => bAscending
  93. */
  94. public function __construct($sFilterExp, $sValueAttCode = '', $aOrderBy = array(), $bAllowAllData = false, $aModifierProperties = array())
  95. {
  96. $this->m_sContains = '';
  97. $this->m_sFilterExpr = $sFilterExp;
  98. $this->m_sValueAttCode = $sValueAttCode;
  99. $this->m_aOrderBy = $aOrderBy;
  100. $this->m_bAllowAllData = $bAllowAllData;
  101. $this->m_aModifierProperties = $aModifierProperties;
  102. $this->m_aExtraConditions = array();
  103. }
  104. public function SetModifierProperty($sPluginClass, $sProperty, $value)
  105. {
  106. $this->m_aModifierProperties[$sPluginClass][$sProperty] = $value;
  107. }
  108. public function AddCondition(DBSearch $oFilter)
  109. {
  110. $this->m_aExtraConditions[] = $oFilter;
  111. }
  112. public function ToObjectSet($aArgs = array(), $sContains = '', $iAdditionalValue = null)
  113. {
  114. if ($this->m_bAllowAllData)
  115. {
  116. $oFilter = DBObjectSearch::FromOQL_AllData($this->m_sFilterExpr);
  117. }
  118. else
  119. {
  120. $oFilter = DBObjectSearch::FromOQL($this->m_sFilterExpr);
  121. }
  122. foreach($this->m_aExtraConditions as $oExtraFilter)
  123. {
  124. $oFilter = $oFilter->Intersect($oExtraFilter);
  125. }
  126. foreach($this->m_aModifierProperties as $sPluginClass => $aProperties)
  127. {
  128. foreach ($aProperties as $sProperty => $value)
  129. {
  130. $oFilter->SetModifierProperty($sPluginClass, $sProperty, $value);
  131. }
  132. }
  133. if ($iAdditionalValue > 0)
  134. {
  135. $oSearchAdditionalValue = new DBObjectSearch($oFilter->GetClass());
  136. $oSearchAdditionalValue->AddCondition('id', $iAdditionalValue);
  137. $oSearchAdditionalValue->AllowAllData();
  138. $oSearchAdditionalValue->SetArchiveMode(true);
  139. $oFilter = new DBUnionSearch(array($oFilter, $oSearchAdditionalValue));
  140. }
  141. return new DBObjectSet($oFilter, $this->m_aOrderBy, $aArgs);
  142. }
  143. public function GetValues($aArgs, $sContains = '')
  144. {
  145. if (!$this->m_bIsLoaded || ($sContains != $this->m_sContains))
  146. {
  147. $this->LoadValues($aArgs, $sContains);
  148. $this->m_bIsLoaded = true;
  149. }
  150. // The results are already filtered and sorted (on friendly name)
  151. $aRet = $this->m_aValues;
  152. return $aRet;
  153. }
  154. protected function LoadValues($aArgs, $sContains = '')
  155. {
  156. $this->m_sContains = $sContains;
  157. $this->m_aValues = array();
  158. if ($this->m_bAllowAllData)
  159. {
  160. $oFilter = DBObjectSearch::FromOQL_AllData($this->m_sFilterExpr);
  161. }
  162. else
  163. {
  164. $oFilter = DBObjectSearch::FromOQL($this->m_sFilterExpr);
  165. }
  166. if (!$oFilter) return false;
  167. foreach($this->m_aExtraConditions as $oExtraFilter)
  168. {
  169. $oFilter = $oFilter->Intersect($oExtraFilter);
  170. }
  171. foreach($this->m_aModifierProperties as $sPluginClass => $aProperties)
  172. {
  173. foreach ($aProperties as $sProperty => $value)
  174. {
  175. $oFilter->SetModifierProperty($sPluginClass, $sProperty, $value);
  176. }
  177. }
  178. $oValueExpr = new ScalarExpression('%'.$sContains.'%');
  179. $oNameExpr = new FieldExpression('friendlyname', $oFilter->GetClassAlias());
  180. $oNewCondition = new BinaryExpression($oNameExpr, 'LIKE', $oValueExpr);
  181. $oFilter->AddConditionExpression($oNewCondition);
  182. $oObjects = new DBObjectSet($oFilter, $this->m_aOrderBy, $aArgs);
  183. while ($oObject = $oObjects->Fetch())
  184. {
  185. if (empty($this->m_sValueAttCode))
  186. {
  187. $this->m_aValues[$oObject->GetKey()] = $oObject->GetName();
  188. }
  189. else
  190. {
  191. $this->m_aValues[$oObject->GetKey()] = $oObject->Get($this->m_sValueAttCode);
  192. }
  193. }
  194. return true;
  195. }
  196. public function GetValuesDescription()
  197. {
  198. return 'Filter: '.$this->m_sFilterExpr;
  199. }
  200. public function GetFilterExpression()
  201. {
  202. return $this->m_sFilterExpr;
  203. }
  204. }
  205. /**
  206. * Set of existing values for a link set attribute, given a relation code
  207. *
  208. * @package iTopORM
  209. */
  210. class ValueSetRelatedObjectsFromLinkSet extends ValueSetDefinition
  211. {
  212. protected $m_sLinkSetAttCode;
  213. protected $m_sExtKeyToRemote;
  214. protected $m_sRelationCode;
  215. protected $m_iMaxDepth;
  216. protected $m_sTargetClass;
  217. protected $m_sTargetExtKey;
  218. // protected $m_aOrderBy;
  219. public function __construct($sLinkSetAttCode, $sExtKeyToRemote, $sRelationCode, $iMaxDepth, $sTargetClass, $sTargetLinkClass, $sTargetExtKey)
  220. {
  221. $this->m_sLinkSetAttCode = $sLinkSetAttCode;
  222. $this->m_sExtKeyToRemote = $sExtKeyToRemote;
  223. $this->m_sRelationCode = $sRelationCode;
  224. $this->m_iMaxDepth = $iMaxDepth;
  225. $this->m_sTargetClass = $sTargetClass;
  226. $this->m_sTargetLinkClass = $sTargetLinkClass;
  227. $this->m_sTargetExtKey = $sTargetExtKey;
  228. // $this->m_aOrderBy = $aOrderBy;
  229. }
  230. protected function LoadValues($aArgs)
  231. {
  232. $this->m_aValues = array();
  233. if (!array_key_exists('this', $aArgs))
  234. {
  235. throw new CoreException("Missing 'this' in arguments", array('args' => $aArgs));
  236. }
  237. $oTarget = $aArgs['this->object()'];
  238. // Nodes from which we will start the search for neighbourhood
  239. $oNodes = DBObjectSet::FromLinkSet($oTarget, $this->m_sLinkSetAttCode, $this->m_sExtKeyToRemote);
  240. // Neighbours, whatever their class
  241. $aRelated = $oNodes->GetRelatedObjects($this->m_sRelationCode, $this->m_iMaxDepth);
  242. $sRootClass = MetaModel::GetRootClass($this->m_sTargetClass);
  243. if (array_key_exists($sRootClass, $aRelated))
  244. {
  245. $aLinksToCreate = array();
  246. foreach($aRelated[$sRootClass] as $iKey => $oObject)
  247. {
  248. if (MetaModel::IsParentClass($this->m_sTargetClass, get_class($oObject)))
  249. {
  250. $oNewLink = MetaModel::NewObject($this->m_sTargetLinkClass);
  251. $oNewLink->Set($this->m_sTargetExtKey, $iKey);
  252. //$oNewLink->Set('role', 'concerned by an impacted CI');
  253. $aLinksToCreate[] = $oNewLink;
  254. }
  255. }
  256. // #@# or AddObjectArray($aObjects) ?
  257. $oSetToCreate = DBObjectSet::FromArray($this->m_sTargetLinkClass, $aLinksToCreate);
  258. $this->m_aValues[$oObject->GetKey()] = $oObject->GetName();
  259. }
  260. return true;
  261. }
  262. public function GetValuesDescription()
  263. {
  264. return 'Filter: '.$this->m_sFilterExpr;
  265. }
  266. }
  267. /**
  268. * Fixed set values (could be hardcoded in the business model)
  269. *
  270. * @package iTopORM
  271. */
  272. class ValueSetEnum extends ValueSetDefinition
  273. {
  274. protected $m_values;
  275. public function __construct($Values)
  276. {
  277. $this->m_values = $Values;
  278. }
  279. // Helper to export the datat model
  280. public function GetValueList()
  281. {
  282. $this->LoadValues($aArgs = array());
  283. return $this->m_aValues;
  284. }
  285. protected function LoadValues($aArgs)
  286. {
  287. if (is_array($this->m_values))
  288. {
  289. $aValues = $this->m_values;
  290. }
  291. elseif (is_string($this->m_values) && strlen($this->m_values) > 0)
  292. {
  293. $aValues = array();
  294. foreach (explode(",", $this->m_values) as $sVal)
  295. {
  296. $sVal = trim($sVal);
  297. $sKey = $sVal;
  298. $aValues[$sKey] = $sVal;
  299. }
  300. }
  301. else
  302. {
  303. $aValues = array();
  304. }
  305. $this->m_aValues = $aValues;
  306. return true;
  307. }
  308. }
  309. /**
  310. * Fixed set values, defined as a range: 0..59 (with an optional increment)
  311. *
  312. * @package iTopORM
  313. */
  314. class ValueSetRange extends ValueSetDefinition
  315. {
  316. protected $m_iStart;
  317. protected $m_iEnd;
  318. public function __construct($iStart, $iEnd, $iStep = 1)
  319. {
  320. $this->m_iStart = $iStart;
  321. $this->m_iEnd = $iEnd;
  322. $this->m_iStep = $iStep;
  323. }
  324. protected function LoadValues($aArgs)
  325. {
  326. $iValue = $this->m_iStart;
  327. for($iValue = $this->m_iStart; $iValue <= $this->m_iEnd; $iValue += $this->m_iStep)
  328. {
  329. $this->m_aValues[$iValue] = $iValue;
  330. }
  331. return true;
  332. }
  333. }
  334. /**
  335. * Data model classes
  336. *
  337. * @package iTopORM
  338. */
  339. class ValueSetEnumClasses extends ValueSetEnum
  340. {
  341. protected $m_sCategories;
  342. public function __construct($sCategories = '', $sAdditionalValues = '')
  343. {
  344. $this->m_sCategories = $sCategories;
  345. parent::__construct($sAdditionalValues);
  346. }
  347. protected function LoadValues($aArgs)
  348. {
  349. // Call the parent to parse the additional values...
  350. parent::LoadValues($aArgs);
  351. // Translate the labels of the additional values
  352. foreach($this->m_aValues as $sClass => $void)
  353. {
  354. if (MetaModel::IsValidClass($sClass))
  355. {
  356. $this->m_aValues[$sClass] = MetaModel::GetName($sClass);
  357. }
  358. else
  359. {
  360. unset($this->m_aValues[$sClass]);
  361. }
  362. }
  363. // Then, add the classes from the category definition
  364. foreach (MetaModel::GetClasses($this->m_sCategories) as $sClass)
  365. {
  366. if (MetaModel::IsValidClass($sClass))
  367. {
  368. $this->m_aValues[$sClass] = MetaModel::GetName($sClass);
  369. }
  370. else
  371. {
  372. unset($this->m_aValues[$sClass]);
  373. }
  374. }
  375. return true;
  376. }
  377. }