PageRenderTime 55ms CodeModel.GetById 24ms RepoModel.GetById 0ms app.codeStats 1ms

/kernel/classes/notification/handler/ezsubtree/ezsubtreenotificationrule.php

https://github.com/granitegreg/ezpublish
PHP | 575 lines | 448 code | 51 blank | 76 comment | 50 complexity | b2322fea49bb89fd56e936eaabc2bcb0 MD5 | raw file
Possible License(s): GPL-2.0
  1. <?php
  2. //
  3. // Definition of eZSubtreeNotificationRule class
  4. //
  5. // Created on: <14-May-2003 16:20:24 sp>
  6. //
  7. // ## BEGIN COPYRIGHT, LICENSE AND WARRANTY NOTICE ##
  8. // SOFTWARE NAME: eZ Publish
  9. // SOFTWARE RELEASE: 4.1.x
  10. // COPYRIGHT NOTICE: Copyright (C) 1999-2011 eZ Systems AS
  11. // SOFTWARE LICENSE: GNU General Public License v2.0
  12. // NOTICE: >
  13. // This program is free software; you can redistribute it and/or
  14. // modify it under the terms of version 2.0 of the GNU General
  15. // Public License as published by the Free Software Foundation.
  16. //
  17. // This program is distributed in the hope that it will be useful,
  18. // but WITHOUT ANY WARRANTY; without even the implied warranty of
  19. // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  20. // GNU General Public License for more details.
  21. //
  22. // You should have received a copy of version 2.0 of the GNU General
  23. // Public License along with this program; if not, write to the Free
  24. // Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
  25. // MA 02110-1301, USA.
  26. //
  27. //
  28. // ## END COPYRIGHT, LICENSE AND WARRANTY NOTICE ##
  29. //
  30. /*! \file
  31. */
  32. /*!
  33. \class eZSubtreeNotificationRule ezsubtreenotificationrule.php
  34. \brief The class eZSubtreeNotificationRule does
  35. */
  36. class eZSubtreeNotificationRule extends eZPersistentObject
  37. {
  38. /*!
  39. Constructor
  40. */
  41. function eZSubtreeNotificationRule( $row )
  42. {
  43. $this->eZPersistentObject( $row );
  44. }
  45. static function definition()
  46. {
  47. return array( "fields" => array( "id" => array( 'name' => 'ID',
  48. 'datatype' => 'integer',
  49. 'default' => 0,
  50. 'required' => true ),
  51. "user_id" => array( 'name' => "UserID",
  52. 'datatype' => 'integer',
  53. 'default' => '',
  54. 'required' => true,
  55. 'foreign_class' => 'eZUser',
  56. 'foreign_attribute' => 'contentobject_id',
  57. 'multiplicity' => '1..*' ),
  58. "use_digest" => array( 'name' => "UseDigest",
  59. 'datatype' => 'integer',
  60. 'default' => 0,
  61. 'required' => true ),
  62. "node_id" => array( 'name' => "NodeID",
  63. 'datatype' => 'integer',
  64. 'default' => 0,
  65. 'required' => true,
  66. 'foreign_class' => 'eZContentObjectTreeNode',
  67. 'foreign_attribute' => 'node_id',
  68. 'multiplicity' => '1..*' ) ),
  69. "keys" => array( "id" ),
  70. "function_attributes" => array( 'node' => 'node' ),
  71. "increment_key" => "id",
  72. "sort" => array( "id" => "asc" ),
  73. "class_name" => "eZSubtreeNotificationRule",
  74. "name" => "ezsubtree_notification_rule" );
  75. }
  76. static function create( $nodeID, $userID, $useDigest = 0 )
  77. {
  78. $rule = new eZSubtreeNotificationRule( array( 'user_id' => $userID,
  79. 'use_digest' => $useDigest,
  80. 'node_id' => $nodeID ) );
  81. return $rule;
  82. }
  83. static function fetchNodesForUserID( $userID, $asObject = true )
  84. {
  85. $nodeIDList = eZPersistentObject::fetchObjectList( eZSubtreeNotificationRule::definition(),
  86. array( 'node_id' ), array( 'user_id' => $userID ),
  87. null,null,false );
  88. $nodes = array();
  89. if ( $asObject )
  90. {
  91. foreach ( $nodeIDList as $nodeRow )
  92. {
  93. $nodes[] = eZContentObjectTreeNode::fetch( $nodeRow['node_id'] );
  94. }
  95. }
  96. else
  97. {
  98. foreach ( $nodeIDList as $nodeRow )
  99. {
  100. $nodes[] = $nodeRow['node_id'];
  101. }
  102. }
  103. return $nodes;
  104. }
  105. static function fetchList( $userID, $asObject = true, $offset = false, $limit = false )
  106. {
  107. return eZPersistentObject::fetchObjectList( eZSubtreeNotificationRule::definition(),
  108. null, array( 'user_id' => $userID ),
  109. null, array( 'offset' => $offset,
  110. 'length' => $limit ), $asObject );
  111. }
  112. static function fetchListCount( $userID )
  113. {
  114. $countRes = eZPersistentObject::fetchObjectList( eZSubtreeNotificationRule::definition(),
  115. array(),
  116. array( 'user_id' => $userID ),
  117. false,
  118. null,
  119. false,
  120. false,
  121. array( array( 'operation' => 'count( id )',
  122. 'name' => 'count' ) ) );
  123. return $countRes[0]['count'];
  124. }
  125. /**
  126. * Fetch allowed subtreenotification rules based on node_id list and a
  127. * content object
  128. *
  129. * @param array $nodeIDList node id list for notification event
  130. * @param eZContentObject content object to add
  131. *
  132. * @return array matching subtree notification rule data
  133. */
  134. static function fetchUserList( $nodeIDList, $contentObject )
  135. {
  136. if ( count( $nodeIDList ) == 0 )
  137. {
  138. $retValue = array();
  139. return $retValue;
  140. }
  141. $db = eZDB::instance();
  142. $concatString = $db->concatString( array( 'user_tree.path_string', "'%'" ) );
  143. // Select affected users
  144. $sqlINString = $db->generateSQLINStatement( $nodeIDList, 'subtree_rule.node_id', false, false, 'int' );
  145. $sql = "SELECT DISTINCT subtree_rule.user_id,
  146. user_node.node_id
  147. FROM ezsubtree_notification_rule subtree_rule,
  148. ezcontentobject_tree user_node,
  149. ezuser_setting
  150. WHERE $sqlINString AND
  151. user_node.contentobject_id = subtree_rule.user_id AND
  152. ezuser_setting.user_id = subtree_rule.user_id AND
  153. user_node.is_invisible = 0 AND
  154. ezuser_setting.is_enabled = 1";
  155. $userPart = $db->arrayQuery( $sql );
  156. // Remove duplicates
  157. $userNodeIDList = array();
  158. foreach ( $userPart as $row )
  159. $userNodeIDList[] = $row['node_id'];
  160. $userNodeIDList = array_unique( $userNodeIDList );
  161. if ( count( $userNodeIDList ) == 0 )
  162. {
  163. $retValue = array();
  164. return $retValue;
  165. }
  166. // Select affected nodes
  167. $sqlINString = $db->generateSQLINStatement( $userNodeIDList, 'user_node.node_id', false, false, 'int' );
  168. $sql = "SELECT DISTINCT user_node.node_id,
  169. user_node.path_string,
  170. user_tree.contentobject_id
  171. FROM ezcontentobject_tree user_node,
  172. ezcontentobject_tree user_tree
  173. WHERE $sqlINString AND
  174. user_node.path_string LIKE $concatString";
  175. $nodePart = $db->arrayQuery( $sql );
  176. // Remove duplicates
  177. $objectIDList = array();
  178. foreach ( $nodePart as $row )
  179. if ( $row['contentobject_id'] != '0' )
  180. $objectIDList[] = $row['contentobject_id'];
  181. $objectIDList = array_unique( $objectIDList );
  182. if ( count( $objectIDList ) == 0 )
  183. {
  184. $retValue = array();
  185. return $retValue;
  186. }
  187. // Select affected roles and policies
  188. $sqlINString = $db->generateSQLINStatement( $objectIDList, 'user_role.contentobject_id', false, false, 'int' );
  189. $sql = "SELECT DISTINCT user_role.contentobject_id,
  190. policy.id AS policy_id,
  191. user_role.limit_identifier AS limitation,
  192. user_role.limit_value AS value
  193. FROM ezuser_role user_role,
  194. ezpolicy policy
  195. WHERE $sqlINString AND
  196. ( user_role.role_id=policy.role_id AND
  197. ( policy.module_name='*' OR
  198. ( policy.module_name='content' AND
  199. ( policy.function_name='*' OR
  200. policy.function_name='read'
  201. )
  202. )
  203. )
  204. )";
  205. $rolePart = $db->arrayQuery( $sql );
  206. // Build resultArray. Make sure there are no duplicates.
  207. $resultArray = array();
  208. foreach ( $userPart as $up )
  209. {
  210. foreach ( $nodePart as $np )
  211. {
  212. if ( $up['node_id'] == $np['node_id'] )
  213. {
  214. foreach ( $rolePart as $rp )
  215. {
  216. if ( $np['contentobject_id'] == $rp['contentobject_id'] )
  217. {
  218. $key = $rp['policy_id'] . $up['user_id'] . $rp['limitation'] . $rp['value'];
  219. $resultArray[$key] = array( 'policy_id' => $rp['policy_id'],
  220. 'user_id' => $up['user_id'],
  221. 'limitation' => $rp['limitation'],
  222. 'value' => $rp['value'] );
  223. }
  224. }
  225. }
  226. }
  227. }
  228. $policyIDArray = array();
  229. $limitedPolicyIDArray = array();
  230. $userIDArray = array();
  231. foreach( $resultArray as $result )
  232. {
  233. $userIDArray[(string)$result['user_id']] = (int)$result['user_id'];
  234. }
  235. foreach( $resultArray as $result )
  236. {
  237. if ( $result['limitation'] == '' )
  238. {
  239. $policyIDArray[(string)$result['policy_id']][] =& $userIDArray[(string)$result['user_id']];
  240. }
  241. else
  242. {
  243. $limitedPolicyIDArray[] = array( 'user_id' => $userIDArray[(string)$result['user_id']],
  244. 'limitation' => $result['limitation'],
  245. 'value' => $result['value'],
  246. 'policyID' => $result['policy_id'] );
  247. }
  248. }
  249. $acceptedUserArray = array();
  250. foreach( array_keys( $policyIDArray ) as $policyID )
  251. {
  252. foreach( array_keys( $policyIDArray[$policyID] ) as $key )
  253. {
  254. if ( $policyIDArray[$policyID][$key] === false )
  255. {
  256. unset( $policyIDArray[$policyID][$key] );
  257. }
  258. }
  259. if ( count( $policyIDArray[$policyID] ) == 0 )
  260. {
  261. continue;
  262. }
  263. $userArray = eZSubtreeNotificationRule::checkObjectAccess( $contentObject, $policyID, $policyIDArray[$policyID] );
  264. $acceptedUserArray = array_merge( $acceptedUserArray, $userArray );
  265. foreach ( $userArray as $userID )
  266. {
  267. $userIDArray[(string)$userID] = false;
  268. }
  269. }
  270. foreach( $limitedPolicyIDArray as $policyEntry )
  271. {
  272. if ( $policyEntry['user_id'] === false )
  273. {
  274. continue;
  275. }
  276. $userArray = eZSubtreeNotificationRule::checkObjectAccess( $contentObject,
  277. $policyEntry['policyID'],
  278. array( $policyEntry['user_id'] ),
  279. array( $policyEntry['limitation'] => $policyEntry['value'] ) );
  280. $acceptedUserArray = array_merge( $acceptedUserArray, $userArray );
  281. foreach ( $userArray as $userID )
  282. {
  283. $userIDArray[(string)$userID] = false;
  284. }
  285. }
  286. $acceptedUserArray = array_unique( $acceptedUserArray );
  287. foreach( array_keys( $acceptedUserArray ) as $key )
  288. {
  289. if ( !is_int( $acceptedUserArray[$key] ) or $acceptedUserArray[$key] == 0 )
  290. {
  291. unset( $acceptedUserArray[$key] );
  292. }
  293. }
  294. if ( count( $acceptedUserArray ) == 0 )
  295. {
  296. $retValue = array();
  297. return $retValue;
  298. }
  299. $nodeIDWhereString = $db->generateSQLINStatement( $nodeIDList, 'rule.node_id', false, false, 'int' );
  300. $userIDWhereString = $db->generateSQLINStatement( $acceptedUserArray, 'rule.user_id', false, false, 'int' );
  301. $rules = $db->arrayQuery( "SELECT rule.user_id, rule.use_digest, ezuser.email as address
  302. FROM ezsubtree_notification_rule rule, ezuser
  303. WHERE rule.user_id=ezuser.contentobject_id AND
  304. $nodeIDWhereString AND
  305. $userIDWhereString" );
  306. return $rules;
  307. }
  308. /*!
  309. \private
  310. Check access for specified policy on object, and user list.
  311. \param Content object
  312. \param policyID
  313. \param userID array
  314. \param user limits
  315. \return array of user ID's which has access to object
  316. */
  317. static function checkObjectAccess( $contentObject, $policyID, $userIDArray, $userLimits = false )
  318. {
  319. $policy = eZPolicy::fetch( $policyID );
  320. if ( $userLimits )
  321. {
  322. reset( $userLimits );
  323. $policy->setAttribute( 'limit_identifier', 'User_' . key( $userLimits ) );
  324. $policy->setAttribute( 'limit_value', current( $userLimits ) );
  325. }
  326. $limitationArray = $policy->accessArray();
  327. $limitationArray = current( current( $limitationArray ) );
  328. $accessUserIDArray = $userIDArray;
  329. if ( isset( $limitationArray['*'] ) &&
  330. $limitationArray['*'] == '*' )
  331. {
  332. $returnArray = array();
  333. foreach ( $accessUserIDArray as $userID )
  334. {
  335. $returnArray[] = $userID;
  336. }
  337. return $returnArray;
  338. }
  339. $limitationArray = current( $limitationArray );
  340. $user = eZUser::currentUser();
  341. $classID = $contentObject->attribute( 'contentclass_id' );
  342. $nodeArray = $contentObject->attribute( 'assigned_nodes' );
  343. if ( isset( $limitationArray['Subtree' ] ) )
  344. {
  345. $checkedSubtree = false;
  346. }
  347. else
  348. {
  349. $checkedSubtree = true;
  350. $nodeSubtree = true;
  351. }
  352. if ( isset( $limitationArray['Node'] ) )
  353. {
  354. $checkedNode = false;
  355. }
  356. else
  357. {
  358. $checkedNode = true;
  359. $nodeLimit = true;
  360. }
  361. foreach ( array_keys( $limitationArray ) as $key )
  362. {
  363. if ( count( $accessUserIDArray ) == 0 )
  364. {
  365. return array();
  366. }
  367. switch( $key )
  368. {
  369. case 'Class':
  370. {
  371. if ( !in_array( $contentObject->attribute( 'contentclass_id' ), $limitationArray[$key] ) )
  372. {
  373. return array();
  374. }
  375. } break;
  376. case 'ParentClass':
  377. {
  378. if ( !in_array( $contentObject->attribute( 'contentclass_id' ), $limitationArray[$key] ) )
  379. {
  380. return array();
  381. }
  382. } break;
  383. case 'Section':
  384. case 'User_Section':
  385. {
  386. if ( !in_array( $contentObject->attribute( 'section_id' ), $limitationArray[$key] ) )
  387. {
  388. return array();
  389. }
  390. } break;
  391. case 'Owner':
  392. {
  393. if ( in_array( $contentObject->attribute( 'owner_id' ), $userIDArray ) )
  394. {
  395. $accessUserIDArray = array( $contentObject->attribute( 'owner_id' ) );
  396. }
  397. else if ( in_array( $contentObject->attribute( 'id' ), $userIDArray ) )
  398. {
  399. $accessUserIDArray = array( $contentObject->attribute( 'id' ) );
  400. }
  401. else
  402. {
  403. return array();
  404. }
  405. } break;
  406. case 'Node':
  407. {
  408. $nodeLimit = true;
  409. foreach ( $nodeArray as $node )
  410. {
  411. if( in_array( $node->attribute( 'node_id' ), $limitationArray[$key] ) )
  412. {
  413. $nodeLimit = false;
  414. break;
  415. }
  416. }
  417. if ( $nodeLimit && $checkedSubtree && $nodeSubtree )
  418. {
  419. return array();
  420. }
  421. $checkedNode = true;
  422. } break;
  423. case 'Subtree':
  424. {
  425. $nodeSubtree = true;
  426. foreach ( $nodeArray as $node )
  427. {
  428. $path = $node->attribute( 'path_string' );
  429. $subtreeArray = $limitationArray[$key];
  430. $validSubstring = false;
  431. foreach ( $subtreeArray as $subtreeString )
  432. {
  433. if ( strstr( $path, $subtreeString ) )
  434. {
  435. $nodeSubtree = false;
  436. break;
  437. }
  438. }
  439. if ( !$nodeSubtree )
  440. {
  441. break;
  442. }
  443. }
  444. if ( $nodeSubtree && $checkedNode && $nodeLimit )
  445. {
  446. return array();
  447. }
  448. $checkedSubtree = true;
  449. } break;
  450. case 'User_Subtree':
  451. {
  452. $userSubtreeLimit = true;
  453. foreach ( $nodeArray as $node )
  454. {
  455. $path = $node->attribute( 'path_string' );
  456. $subtreeArray = $limitationArray[$key];
  457. $validSubstring = false;
  458. foreach ( $subtreeArray as $subtreeString )
  459. {
  460. if ( strstr( $path, $subtreeString ) )
  461. {
  462. $userSubtreeLimit = false;
  463. break;
  464. }
  465. }
  466. if ( !$userSubtreeLimit )
  467. {
  468. break;
  469. }
  470. }
  471. if ( $userSubtreeLimit )
  472. {
  473. return array();
  474. }
  475. } break;
  476. }
  477. }
  478. $returnArray = array();
  479. foreach ( $accessUserIDArray as $userID )
  480. {
  481. $returnArray[] = $userID;
  482. }
  483. return $returnArray;
  484. }
  485. function node()
  486. {
  487. if ( $this->Node == null )
  488. {
  489. $this->Node = eZContentObjectTreeNode::fetch( $this->attribute( 'node_id' ) );
  490. }
  491. return $this->Node;
  492. }
  493. static function removeByNodeAndUserID( $userID, $nodeID )
  494. {
  495. eZPersistentObject::removeObject( eZSubtreeNotificationRule::definition(), array( 'user_id' => $userID,
  496. 'node_id' => $nodeID ) );
  497. }
  498. /*!
  499. \static
  500. Remove notifications by user id
  501. \param userID
  502. */
  503. static function removeByUserID( $userID )
  504. {
  505. eZPersistentObject::removeObject( eZSubtreeNotificationRule::definition(), array( 'user_id' => $userID ) );
  506. }
  507. /*!
  508. \static
  509. Cleans up all notification rules for all users.
  510. */
  511. static function cleanup()
  512. {
  513. $db = eZDB::instance();
  514. $db->query( "DELETE FROM ezsubtree_notification_rule" );
  515. }
  516. public $Node = null;
  517. }
  518. ?>