scopevalidatorhelper.class.inc.php 21 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674
  1. <?php
  2. // Copyright (C) 2010-2015 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. namespace Combodo\iTop\Portal\Helper;
  19. use \Exception;
  20. use \DOMNodeList;
  21. use \DOMFormatException;
  22. use \utils;
  23. use \ProfilesConfig;
  24. use \MetaModel;
  25. use \DBSearch;
  26. use \DBUnionSearch;
  27. use \Combodo\iTop\DesignElement;
  28. class ScopeValidatorHelper
  29. {
  30. const ENUM_MODE_READ = 'r';
  31. const ENUM_MODE_WRITE = 'w';
  32. const ENUM_TYPE_ALLOW = 'allow';
  33. const ENUM_TYPE_RESTRICT = 'restrict';
  34. const DEFAULT_GENERATED_CLASS = 'PortalScopesValues';
  35. const DEFAULT_IGNORE_SILOS = false;
  36. protected $sCachePath;
  37. protected $sFilename;
  38. protected $sInstancePrefix;
  39. protected $sGeneratedClass;
  40. protected $aProfilesMatrix;
  41. public static function EnumTypeValues()
  42. {
  43. return array(static::ENUM_TYPE_ALLOW, static::ENUM_TYPE_RESTRICT);
  44. }
  45. public function __construct($sFilename, $sCachePath = null)
  46. {
  47. $this->sFilename = $sFilename;
  48. $this->sCachePath = $sCachePath;
  49. $this->sInstancePrefix = '';
  50. $this->sGeneratedClass = static::DEFAULT_GENERATED_CLASS;
  51. $this->aProfilesMatrix = array();
  52. }
  53. /**
  54. * Returns the path where to cache the compiled scopes file
  55. *
  56. * @return string
  57. */
  58. public function GetCachePath()
  59. {
  60. return $this->sCachePath;
  61. }
  62. /**
  63. * Returns the name of the compiled scopes file
  64. *
  65. * @return string
  66. */
  67. public function GetFilename()
  68. {
  69. return $this->sFilename;
  70. }
  71. /**
  72. * Returns the instance prefix used for the generated scopes class name
  73. *
  74. * @return string
  75. */
  76. public function GetInstancePrefix()
  77. {
  78. return $this->sInstancePrefix;
  79. }
  80. /**
  81. * Returns the name of the generated scopes class
  82. *
  83. * @return string
  84. */
  85. public function GetGeneratedClass()
  86. {
  87. return $this->sGeneratedClass;
  88. }
  89. /**
  90. * Sets the scope validator instance prefix.
  91. *
  92. * This is used to create a unique scope values class in the cache directory (/data/cache-<ENV>) as there can be several instance of the portal.
  93. *
  94. * @param string $sInstancePrefix
  95. * @return \Combodo\iTop\Portal\Helper\ScopeValidatorHelper
  96. */
  97. public function SetInstancePrefix($sInstancePrefix)
  98. {
  99. $sInstancePrefix = preg_replace('/[-_]/', ' ', $sInstancePrefix);
  100. $sInstancePrefix = ucwords($sInstancePrefix);
  101. $sInstancePrefix = str_replace(' ', '', $sInstancePrefix);
  102. $this->sInstancePrefix = $sInstancePrefix;
  103. $this->sGeneratedClass = $this->sInstancePrefix . static::DEFAULT_GENERATED_CLASS;
  104. return $this;
  105. }
  106. /**
  107. * Initializes the ScopeValidator by generating and caching the scopes compilation in the $this->sCachePath.$this->sFilename file.
  108. *
  109. * @param DOMNodeList $oNodes
  110. * @throws DOMFormatException
  111. * @throws Exception
  112. */
  113. public function Init(DOMNodeList $oNodes)
  114. {
  115. // Checking cache path
  116. if ($this->sCachePath === null)
  117. {
  118. $this->sCachePath = utils::GetCachePath();
  119. }
  120. // Building full pathname for file
  121. $sFilePath = $this->sCachePath . $this->sFilename;
  122. // Creating file if not existing
  123. // Note : This is a temporary cache system, it should soon evolve to a cache provider (fs, apc, memcache, ...)
  124. if (!file_exists($sFilePath))
  125. {
  126. // - Build php array from xml
  127. $aProfiles = array();
  128. // This will be used to know which classes have been set, so we can set the missing ones.
  129. $aProfileClasses = array();
  130. // Iterating over the class nodes
  131. foreach ($oNodes as $oClassNode)
  132. {
  133. // retrieving mandatory class id attribute
  134. $sClass = $oClassNode->getAttribute('id');
  135. if ($sClass === '')
  136. {
  137. throw new DOMFormatException('Class tag must have an id attribute.', null, null, $oClassNode);
  138. }
  139. // Iterating over scope nodes of the class
  140. $oScopesNode = $oClassNode->GetOptionalElement('scopes');
  141. if ($oScopesNode !== null)
  142. {
  143. foreach ($oScopesNode->GetNodes('./scope') as $oScopeNode)
  144. {
  145. // Retrieving mandatory scope id attribute
  146. $sScopeId = $oScopeNode->getAttribute('id');
  147. if ($sScopeId === '')
  148. {
  149. throw new DOMFormatException('Scope tag must have an id attribute.', null, null, $oScopeNode);
  150. }
  151. // Retrieving the type of query
  152. // Note : This has been disabled as we don't want deny rules for now
  153. // $oOqlViewTypeNode = $oClassNode->GetOptionalElement('oql_view_type');
  154. // $sOqlViewType = ($oOqlViewTypeNode !== null && ($oOqlViewTypeNode->GetText() === static::ENUM_TYPE_RESTRICT)) ? static::ENUM_TYPE_RESTRICT : static::ENUM_TYPE_ALLOW;
  155. $sOqlViewType = static::ENUM_TYPE_ALLOW;
  156. // Retrieving the view query
  157. $oOqlViewNode = $oScopeNode->GetUniqueElement('oql_view');
  158. $sOqlView = $oOqlViewNode->GetText();
  159. if ($sOqlView === null)
  160. {
  161. throw new DOMFormatException('Scope tag in class must have a not empty oql_view tag', null, null, $oScopeNode);
  162. }
  163. // Retrieving the edit query
  164. $oOqlEditNode = $oScopeNode->GetOptionalElement('oql_edit');
  165. $sOqlEdit = ( ($oOqlEditNode !== null) && ($oOqlEditNode->GetText() !== null) ) ? $oOqlEditNode->GetText() : null;
  166. // Retrieving ignore allowed org flag
  167. $oIgnoreSilosNode = $oScopeNode->GetOptionalElement('ignore_silos');
  168. $bIgnoreSilos = ( ($oIgnoreSilosNode !== null) && ($oIgnoreSilosNode->GetText() === 'true') ) ? true : static::DEFAULT_IGNORE_SILOS;
  169. // Retrieving profiles for the scope
  170. $oProfilesNode = $oScopeNode->GetOptionalElement('allowed_profiles');
  171. $aProfilesNames = array();
  172. // If no profile is specified, we consider that it's for ALL the profiles
  173. if (($oProfilesNode === null) || ($oProfilesNode->GetNodes('./allowed_profile')->length === 0))
  174. {
  175. foreach (ProfilesConfig::GetProfilesValues() as $iKey => $aValue)
  176. {
  177. $aProfilesNames[] = $aValue['name'];
  178. }
  179. }
  180. else
  181. {
  182. foreach ($oProfilesNode->GetNodes('./allowed_profile') as $oProfileNode)
  183. {
  184. // Retrieving mandatory profile id attribute
  185. $sProfileId = $oProfileNode->getAttribute('id');
  186. if ($sProfileId === '')
  187. {
  188. throw new DOMFormatException('Scope tag must have an id attribute.', null, null, $oProfileNode);
  189. }
  190. $aProfilesNames[] = $sProfileId;
  191. }
  192. }
  193. //
  194. foreach ($aProfilesNames as $sProfileName)
  195. {
  196. // Scope profile id
  197. $iProfileId = $this->GetProfileIdFromProfileName($sProfileName);
  198. // Now that we have the queries infos, we are going to build the queries for that profile / class
  199. $sMatrixPrefix = $iProfileId . '_' . $sClass . '_';
  200. // - View query
  201. $oViewFilter = DBSearch::FromOQL($sOqlView);
  202. // ... We have to union the query if this profile has another scope for that class
  203. if (array_key_exists($sMatrixPrefix . static::ENUM_MODE_READ, $aProfiles) && array_key_exists($sOqlViewType, $aProfiles[$sMatrixPrefix . static::ENUM_MODE_READ]))
  204. {
  205. $oExistingFilter = DBSearch::FromOQL($aProfiles[$sMatrixPrefix . static::ENUM_MODE_READ][$sOqlViewType]);
  206. $aFilters = array($oExistingFilter, $oViewFilter);
  207. $oResFilter = new DBUnionSearch($aFilters);
  208. // Applying ignore_silos flag on result filter if necessary (As the union will remove it if it is not on all sub-queries)
  209. if ($aProfiles[$sMatrixPrefix . static::ENUM_MODE_READ]['ignore_silos'] === true)
  210. {
  211. $bIgnoreSilos = true;
  212. }
  213. }
  214. else
  215. {
  216. $oResFilter = $oViewFilter;
  217. }
  218. $aProfiles[$sMatrixPrefix . static::ENUM_MODE_READ] = array(
  219. $sOqlViewType => $oResFilter->ToOQL(),
  220. 'ignore_silos' => $bIgnoreSilos
  221. );
  222. // - Edit query
  223. if ($sOqlEdit !== null)
  224. {
  225. $oEditFilter = DBSearch::FromOQL($sOqlEdit);
  226. // - If the queries are the same, we don't make an intersect, we just reuse the view query
  227. if ($sOqlEdit === $sOqlView)
  228. {
  229. // Do not intersect, edit query is identical to view query
  230. }
  231. else
  232. {
  233. if (($oEditFilter->GetClass() === $oViewFilter->GetClass()) && $oEditFilter->IsAny())
  234. {
  235. $oEditFilter = $oViewFilter;
  236. // Do not intersect, edit query is identical to view query
  237. }
  238. else
  239. {
  240. // Intersect
  241. $oEditFilter = $oViewFilter->Intersect($oEditFilter);
  242. }
  243. }
  244. // ... We have to union the query if this profile has another scope for that class
  245. if (array_key_exists($sMatrixPrefix . static::ENUM_MODE_WRITE, $aProfiles) && array_key_exists($sOqlViewType, $aProfiles[$sMatrixPrefix . static::ENUM_MODE_WRITE]))
  246. {
  247. $oExistingFilter = DBSearch::FromOQL($aProfiles[$sMatrixPrefix . static::ENUM_MODE_WRITE][$sOqlViewType]);
  248. $aFilters = array($oExistingFilter, $oEditFilter);
  249. $oResFilter = new DBUnionSearch($aFilters);
  250. }
  251. else
  252. {
  253. $oResFilter = $oEditFilter;
  254. }
  255. $aProfiles[$sMatrixPrefix . static::ENUM_MODE_WRITE] = array(
  256. $sOqlViewType => $oResFilter->ToOQL(),
  257. 'ignore_silos' => $bIgnoreSilos
  258. );
  259. }
  260. }
  261. }
  262. $aProfileClasses[] = $sClass;
  263. }
  264. }
  265. // Filling the array with missing classes from MetaModel, so we can have an inheritance principle on the scope
  266. // For each class explicitly given in the scopes, we check if its child classes were also in the scope :
  267. // If not, we add them with the same OQL
  268. foreach ($aProfileClasses as $sProfileClass)
  269. {
  270. foreach (MetaModel::EnumChildClasses($sProfileClass) as $sChildClass)
  271. {
  272. // If the child class is not in the scope, we are going to try to add it
  273. if (!in_array($sChildClass, $aProfileClasses))
  274. {
  275. foreach (ProfilesConfig::GetProfilesValues() as $iKey => $aValue)
  276. {
  277. $iProfileId = $iKey;
  278. foreach (array(static::ENUM_MODE_READ, static::ENUM_MODE_WRITE) as $sAction)
  279. {
  280. // If the current profile has scope for that class in that mode, we duplicate it
  281. if (isset($aProfiles[$iProfileId . '_' . $sProfileClass . '_' . $sAction]))
  282. {
  283. $aTmpProfile = $aProfiles[$iProfileId . '_' . $sProfileClass . '_' . $sAction];
  284. foreach ($aTmpProfile as $sType => $sOql)
  285. {
  286. // IF condition is just to skip the 'ignore_silos' flag
  287. if (in_array($sType, array(static::ENUM_TYPE_ALLOW, static::ENUM_TYPE_RESTRICT)))
  288. {
  289. $oTmpFilter = DBSearch::FromOQL($sOql);
  290. $oTmpFilter->ChangeClass($sChildClass);
  291. $aTmpProfile[$sType] = $oTmpFilter->ToOQL();
  292. }
  293. }
  294. $aProfiles[$iProfileId . '_' . $sChildClass . '_' . $sAction] = $aTmpProfile;
  295. }
  296. }
  297. }
  298. }
  299. }
  300. }
  301. // Iterating over the scope nodes
  302. /* foreach ($oNodes as $oScopeNode)
  303. {
  304. // Retrieving mandatory id attribute
  305. $sProfile = $oScopeNode->getAttribute('id');
  306. if ($sProfile === '')
  307. {
  308. throw new DOMFormatException('Scope tag must have an id attribute.', null, null, $oScopeNode);
  309. }
  310. // Scope profile id
  311. $iProfileId = $this->GetProfileIdFromProfileName($sProfile);
  312. // This will be used to know which classes have been set, so we can set the missing ones.
  313. $aProfileClasses = array();
  314. // Iterating over the class nodes of the scope
  315. foreach ($oScopeNode->GetUniqueElement('classes')->GetNodes('./class') as $oClassNode)
  316. {
  317. // Retrieving mandatory id attribute
  318. $sClass = $oClassNode->getAttribute('id');
  319. if ($sClass === '')
  320. {
  321. throw new DOMFormatException('Class tag must have an id attribute.', null, null, $oClassNode);
  322. }
  323. // Retrieving the type of query
  324. $oOqlViewTypeNode = $oClassNode->GetOptionalElement('oql_view_type');
  325. $sOqlViewType = ($oOqlViewTypeNode !== null && ($oOqlViewTypeNode->GetText() === static::ENUM_TYPE_RESTRICT)) ? static::ENUM_TYPE_RESTRICT : static::ENUM_TYPE_ALLOW;
  326. // Retrieving the view query
  327. $oOqlViewNode = $oClassNode->GetUniqueElement('oql_view');
  328. $sOqlView = $oOqlViewNode->GetText();
  329. if ($sOqlView === null)
  330. {
  331. throw new DOMFormatException('Class tag in scope must have a not empty oql_view tag', null, null, $oClassNode);
  332. }
  333. // Retrieving the edit query
  334. $oOqlEditNode = $oClassNode->GetOptionalElement('oql_edit');
  335. $sOqlEdit = ( ($oOqlEditNode !== null) && ($oOqlEditNode->GetText() !== null) ) ? $oOqlEditNode->GetText() : null;
  336. // Now that we have the queries infos, we are going to build the queries for that profile / class
  337. $sMatrixPrefix = $iProfileId . '_' . $sClass . '_';
  338. // - View query
  339. $oViewFilter = DBSearch::FromOQL($sOqlView);
  340. $aProfiles[$sMatrixPrefix . 'r'] = array(
  341. $sOqlViewType => $oViewFilter->ToOQL()
  342. );
  343. // - Edit query
  344. if ($sOqlEdit !== null)
  345. {
  346. $oEditFilter = DBSearch::FromOQL($sOqlEdit);
  347. // - If the queries are the same, we don't make an intersect, we just reuse the view query
  348. if ($sOqlEdit === $sOqlView)
  349. {
  350. // Do not intersect, edit query is identical to view query
  351. }
  352. else
  353. {
  354. if (($oEditFilter->GetClass() === $oViewFilter->GetClass()) && $oEditFilter->IsAny())
  355. {
  356. $oEditFilter = $oViewFilter;
  357. // Do not intersect, edit query is identical to view query
  358. }
  359. else
  360. {
  361. // Intersect
  362. $oEditFilter = $oViewFilter->Intersect($oEditFilter);
  363. }
  364. }
  365. $aProfiles[$sMatrixPrefix . 'w'] = array(
  366. $sOqlViewType => $oEditFilter->ToOQL()
  367. );
  368. }
  369. $aProfileClasses[] = $sClass;
  370. }
  371. // Filling the array with missing classes from MetaModel, so we can have an inheritance principle on the scope
  372. // For each class explicitly given in the scopes, we check if its child classes were also in the scope :
  373. // If not, we add them with the same OQL
  374. foreach ($aProfileClasses as $sProfileClass)
  375. {
  376. foreach (MetaModel::EnumChildClasses($sProfileClass) as $sChildClass)
  377. {
  378. // If the child class is not in the scope, we are going to try to add it
  379. if (!in_array($sChildClass, $aProfileClasses))
  380. {
  381. foreach (array('r', 'w') as $sAction)
  382. {
  383. // If the current profile has scope for that class in that mode, we duplicate it
  384. if (isset($aProfiles[$iProfileId . '_' . $sProfileClass . '_' . $sAction]))
  385. {
  386. $aTmpProfile = $aProfiles[$iProfileId . '_' . $sProfileClass . '_' . $sAction];
  387. foreach ($aTmpProfile as $sType => $sOql)
  388. {
  389. $oTmpFilter = DBSearch::FromOQL($sOql);
  390. $oTmpFilter->ChangeClass($sChildClass);
  391. $aTmpProfile[$sType] = $oTmpFilter->ToOQL();
  392. }
  393. $aProfiles[$iProfileId . '_' . $sChildClass . '_' . $sAction] = $aTmpProfile;
  394. }
  395. }
  396. }
  397. }
  398. }
  399. } */
  400. // - Build php class
  401. $sPHP = $this->BuildPHPClass($aProfiles);
  402. // - Write file on disk
  403. // - Creating dir if necessary
  404. if (!is_dir($this->sCachePath))
  405. {
  406. mkdir($this->sCachePath, 0777, true);
  407. }
  408. // -- Then creating the file
  409. $ret = file_put_contents($sFilePath, $sPHP);
  410. if ($ret === false)
  411. {
  412. $iLen = strlen($sPHP);
  413. $fFree = @disk_free_space(dirname($sFilePath));
  414. $aErr = error_get_last();
  415. throw new Exception("Failed to write '$sFilePath'. Last error: '{$aErr['message']}', content to write: $iLen bytes, available free space on disk: $fFree.");
  416. }
  417. }
  418. if (!class_exists($this->sGeneratedClass))
  419. {
  420. require_once $this->sCachePath . $this->sFilename;
  421. }
  422. }
  423. /**
  424. * Returns the DBSearch for the $sProfile in $iAction for the class $sClass
  425. *
  426. * @param string $sProfile
  427. * @param string $sClass
  428. * @param integer $iAction
  429. * @return DBSearch
  430. */
  431. public function GetScopeFilterForProfile($sProfile, $sClass, $iAction = null)
  432. {
  433. return $this->GetScopeFilterForProfiles(array($sProfile), $sClass, $iAction);
  434. }
  435. /**
  436. * Returns the DBSearch for the $aProfiles in $iAction for the class $sClass.
  437. * Profiles are a OR condition.
  438. *
  439. * @param array $aProfiles
  440. * @param string $sClass
  441. * @param integer $iAction
  442. * @return DBSearch
  443. */
  444. public function GetScopeFilterForProfiles($aProfiles, $sClass, $iAction = null)
  445. {
  446. $oSearch = null;
  447. $aAllowSearches = array();
  448. $aRestrictSearches = array();
  449. $bIgnoreSilos = static::DEFAULT_IGNORE_SILOS;
  450. // Checking the default mode
  451. if ($iAction === null)
  452. {
  453. $iAction = UR_ACTION_READ;
  454. }
  455. // Iterating on profiles to retrieving the different OQLs parts
  456. foreach ($aProfiles as $sProfile)
  457. {
  458. // Retrieving matrix informtions
  459. $iProfileId = $this->GetProfileIdFromProfileName($sProfile);
  460. $sMode = ($iAction === UR_ACTION_READ) ? static::ENUM_MODE_READ : static::ENUM_MODE_WRITE;
  461. // Retrieving profile OQLs
  462. $sScopeValuesClass = $this->sGeneratedClass;
  463. $aProfileMatrix = $sScopeValuesClass::GetProfileScope($iProfileId, $sClass, $sMode);
  464. if ($aProfileMatrix !== null)
  465. {
  466. if (isset($aProfileMatrix['allow']) && $aProfileMatrix['allow'] !== null)
  467. {
  468. $aAllowSearches[] = DBSearch::FromOQL($aProfileMatrix['allow']);
  469. }
  470. if (isset($aProfileMatrix['restrict']) && $aProfileMatrix['restrict'] !== null)
  471. {
  472. $aRestrictSearches[] = DBSearch::FromOQL($aProfileMatrix['restrict']);
  473. }
  474. // If a profile should ignore allowed org, we set it for all its queries no matter the profile
  475. if (isset($aProfileMatrix['ignore_silos']) && $aProfileMatrix['ignore_silos'] === true)
  476. {
  477. $bIgnoreSilos = true;
  478. }
  479. }
  480. }
  481. // Building the real OQL from all the parts from the differents profiles
  482. for ($i = 0; $i < count($aAllowSearches); $i++)
  483. {
  484. foreach ($aRestrictSearches as $oRestrictSearch)
  485. {
  486. $aAllowSearches[$i] = $aAllowSearches[$i]->Intersect($oRestrictSearch);
  487. }
  488. }
  489. if (count($aAllowSearches) > 0)
  490. {
  491. $oSearch = new DBUnionSearch($aAllowSearches);
  492. $oSearch = $oSearch->RemoveDuplicateQueries();
  493. }
  494. if ($bIgnoreSilos === true)
  495. {
  496. $oSearch->AllowAllData();
  497. }
  498. return $oSearch;
  499. }
  500. /**
  501. * Returns true if at least one of the $aProfiles has the ignore_silos flag set to true for the $sClass.
  502. *
  503. * @param array $aProfiles
  504. * @param string $sClass
  505. * @return boolean
  506. */
  507. public function IsAllDataAllowedForScope($aProfiles, $sClass)
  508. {
  509. $bIgnoreSilos = false;
  510. // Iterating on profiles to retrieving the different OQLs parts
  511. foreach ($aProfiles as $sProfile)
  512. {
  513. // Retrieving matrix informtions
  514. $iProfileId = $this->GetProfileIdFromProfileName($sProfile);
  515. // Retrieving profile OQLs
  516. $sScopeValuesClass = $this->sGeneratedClass;
  517. $aProfileMatrix = $sScopeValuesClass::GetProfileScope($iProfileId, $sClass, static::ENUM_MODE_READ);
  518. if ($aProfileMatrix !== null)
  519. {
  520. // If a profile should ignore allowed org, we set it for all its queries no matter the profile
  521. if (isset($aProfileMatrix['ignore_silos']) && $aProfileMatrix['ignore_silos'] === true)
  522. {
  523. $bIgnoreSilos = true;
  524. }
  525. }
  526. }
  527. return $bIgnoreSilos;
  528. }
  529. /**
  530. * Returns the profile id from a string being either a constant or its name.
  531. *
  532. * @param string $sProfile
  533. * @return integer
  534. * @throws Exception
  535. */
  536. protected function GetProfileIdFromProfileName($sProfile)
  537. {
  538. $iProfileId = null;
  539. // We try to find the profile from its name in order to retrieve it's id
  540. // - If the regular UserRights addon is installed we check the profiles array
  541. if (class_exists('ProfilesConfig'))
  542. {
  543. if (defined($sProfile) && in_array($sProfile, ProfilesConfig::GetProfilesValues()))
  544. {
  545. $iProfileId = constant($sProfile);
  546. }
  547. else
  548. {
  549. foreach (ProfilesConfig::GetProfilesValues() as $iKey => $aValue)
  550. {
  551. if ($aValue['name'] === $sProfile)
  552. {
  553. $iProfileId = $iKey;
  554. break;
  555. }
  556. }
  557. }
  558. }
  559. // - Else, we can't find the id from the name as we don't know the used UserRights addon. It has to be a constant
  560. else
  561. {
  562. throw new Exception('Scope validator : Unknown UserRights addon, scope\'s profile must be a constant');
  563. }
  564. // If profile was not found from its name or from a constant, we throw an exception
  565. if ($iProfileId === null)
  566. {
  567. throw new Exception('Scope validator : Could not find "' . $sProfile . '" in the profiles list');
  568. }
  569. return $iProfileId;
  570. }
  571. /**
  572. * Returns a string containing the generated PHP class for the compiled scopes
  573. *
  574. * @param array $aProfiles
  575. * @return string
  576. */
  577. protected function BuildPHPClass($aProfiles = array())
  578. {
  579. $sProfiles = var_export($aProfiles, true);
  580. $sClassName = $this->sGeneratedClass;
  581. $sPHP = <<<EOF
  582. <?php
  583. // File generated by ScopeValidatorHelperHelper
  584. //
  585. // Please do not edit manually
  586. // List of constant scopes
  587. // - used by the portal ScopeValidatorHelperHelper
  588. //
  589. class $sClassName
  590. {
  591. protected static \$aPROFILES = $sProfiles;
  592. /**
  593. * @param integer \$iProfileId
  594. * @param string \$sClass
  595. * @param string \$sAction 'r'|'w'
  596. */
  597. public static function GetProfileScope(\$iProfileId, \$sClass, \$sAction)
  598. {
  599. \$sQuery = null;
  600. \$sScopeKey = \$iProfileId.'_'.\$sClass.'_'.\$sAction;
  601. if (isset(self::\$aPROFILES[\$sScopeKey]))
  602. {
  603. \$sQuery = self::\$aPROFILES[\$sScopeKey];
  604. }
  605. return \$sQuery;
  606. }
  607. }
  608. EOF;
  609. return $sPHP;
  610. }
  611. }
  612. ?>