eZ Publish  [4.0]
ezsubtreenotificationrule.php
Go to the documentation of this file.
00001 <?php
00002 //
00003 // Definition of eZSubtreeNotificationRule class
00004 //
00005 // Created on: <14-May-2003 16:20:24 sp>
00006 //
00007 // ## BEGIN COPYRIGHT, LICENSE AND WARRANTY NOTICE ##
00008 // SOFTWARE NAME: eZ Publish
00009 // SOFTWARE RELEASE: 4.0.x
00010 // COPYRIGHT NOTICE: Copyright (C) 1999-2008 eZ Systems AS
00011 // SOFTWARE LICENSE: GNU General Public License v2.0
00012 // NOTICE: >
00013 //   This program is free software; you can redistribute it and/or
00014 //   modify it under the terms of version 2.0  of the GNU General
00015 //   Public License as published by the Free Software Foundation.
00016 //
00017 //   This program is distributed in the hope that it will be useful,
00018 //   but WITHOUT ANY WARRANTY; without even the implied warranty of
00019 //   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
00020 //   GNU General Public License for more details.
00021 //
00022 //   You should have received a copy of version 2.0 of the GNU General
00023 //   Public License along with this program; if not, write to the Free
00024 //   Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
00025 //   MA 02110-1301, USA.
00026 //
00027 //
00028 // ## END COPYRIGHT, LICENSE AND WARRANTY NOTICE ##
00029 //
00030 
00031 /*! \file ezsubtreenotificationrule.php
00032 */
00033 
00034 /*!
00035   \class eZSubtreeNotificationRule ezsubtreenotificationrule.php
00036   \brief The class eZSubtreeNotificationRule does
00037 
00038 */
00039 //include_once( 'kernel/classes/ezcontentobjecttreenode.php' );
00040 
00041 class eZSubtreeNotificationRule extends eZPersistentObject
00042 {
00043     /*!
00044      Constructor
00045     */
00046     function eZSubtreeNotificationRule( $row )
00047     {
00048         $this->eZPersistentObject( $row );
00049     }
00050 
00051     static function definition()
00052     {
00053         return array( "fields" => array( "id" => array( 'name' => 'ID',
00054                                                         'datatype' => 'integer',
00055                                                         'default' => 0,
00056                                                         'required' => true ),
00057                                          "user_id" => array( 'name' => "UserID",
00058                                                              'datatype' => 'integer',
00059                                                              'default' => '',
00060                                                              'required' => true,
00061                                                              'foreign_class' => 'eZUser',
00062                                                              'foreign_attribute' => 'contentobject_id',
00063                                                              'multiplicity' => '1..*' ),
00064                                          "use_digest" => array( 'name' => "UseDigest",
00065                                                                 'datatype' => 'integer',
00066                                                                 'default' => 0,
00067                                                                 'required' => true ),
00068                                          "node_id" => array( 'name' => "NodeID",
00069                                                              'datatype' => 'integer',
00070                                                              'default' => 0,
00071                                                              'required' => true,
00072                                                              'foreign_class' => 'eZContentObjectTreeNode',
00073                                                              'foreign_attribute' => 'node_id',
00074                                                              'multiplicity' => '1..*' ) ),
00075                       "keys" => array( "id" ),
00076                       "function_attributes" => array( 'node' => 'node' ),
00077                       "increment_key" => "id",
00078                       "sort" => array( "id" => "asc" ),
00079                       "class_name" => "eZSubtreeNotificationRule",
00080                       "name" => "ezsubtree_notification_rule" );
00081     }
00082 
00083 
00084     static function create( $nodeID, $userID, $useDigest = 0 )
00085     {
00086         $rule = new eZSubtreeNotificationRule( array( 'user_id' => $userID,
00087                                                       'use_digest' => $useDigest,
00088                                                       'node_id' => $nodeID ) );
00089         return $rule;
00090     }
00091 
00092     static function fetchNodesForUserID( $userID, $asObject = true )
00093     {
00094         $nodeIDList = eZPersistentObject::fetchObjectList( eZSubtreeNotificationRule::definition(),
00095                                                             array( 'node_id' ), array( 'user_id' => $userID ),
00096                                                             null,null,false );
00097         $nodes = array();
00098         if ( $asObject )
00099         {
00100             foreach ( $nodeIDList as $nodeRow )
00101             {
00102                 $nodes[] = eZContentObjectTreeNode::fetch( $nodeRow['node_id'] );
00103             }
00104         }
00105         else
00106         {
00107             foreach ( $nodeIDList as $nodeRow )
00108             {
00109                 $nodes[] = $nodeRow['node_id'];
00110             }
00111         }
00112         return $nodes;
00113     }
00114 
00115     static function fetchList( $userID, $asObject = true, $offset = false, $limit = false )
00116     {
00117         return eZPersistentObject::fetchObjectList( eZSubtreeNotificationRule::definition(),
00118                                                             null, array( 'user_id' => $userID ),
00119                                                             null, array( 'offset' => $offset,
00120                                                                          'length' => $limit ), $asObject );
00121     }
00122 
00123     static function fetchListCount( $userID )
00124     {
00125         $countRes = eZPersistentObject::fetchObjectList( eZSubtreeNotificationRule::definition(),
00126                                                          array(),
00127                                                          array( 'user_id' => $userID ),
00128                                                          false,
00129                                                          null,
00130                                                          false,
00131                                                          false,
00132                                                          array( array( 'operation' => 'count( id )',
00133                                                                        'name' => 'count' ) ) );
00134         return $countRes[0]['count'];
00135     }
00136 
00137     /**
00138      * Fetch allowed subtreenotification rules based on node_id list and a
00139      * content object
00140      *
00141      * @param array $nodeIDList node id list for notification event
00142      * @param eZContentObject content object to add
00143      *
00144      * @return array matching subtree notification rule data
00145      **/
00146     static function fetchUserList( $nodeIDList, $contentObject )
00147     {
00148         if ( count( $nodeIDList ) == 0 )
00149         {
00150             $retValue = array();
00151             return $retValue;
00152         }
00153 
00154         $db = eZDB::instance();
00155         $concatString = $db->concatString(  array( 'user_tree.path_string', "'%'" ) );
00156 
00157         // Select affected users
00158         $sqlINString = $db->generateSQLINStatement( $nodeIDList, 'subtree_rule.node_id', false, false, 'int' );
00159         $sql = "SELECT DISTINCT subtree_rule.user_id,
00160                                 user_node.node_id
00161                 FROM ezsubtree_notification_rule subtree_rule,
00162                      ezcontentobject_tree user_node,
00163                      ezuser_setting
00164                 WHERE $sqlINString AND
00165                       user_node.contentobject_id = subtree_rule.user_id AND
00166                       ezuser_setting.user_id = subtree_rule.user_id AND
00167                       user_node.is_invisible = 0 AND
00168                       ezuser_setting.is_enabled = 1";
00169         $userPart = $db->arrayQuery( $sql );
00170 
00171         // Remove duplicates
00172         $userNodeIDList = array();
00173         foreach ( $userPart as $row )
00174             $userNodeIDList[] = $row['node_id'];
00175         $userNodeIDList = array_unique( $userNodeIDList );
00176 
00177         if ( count( $userNodeIDList ) == 0 )
00178         {
00179             $retValue = array();
00180             return $retValue;
00181         }
00182 
00183         // Select affected nodes
00184         $sqlINString = $db->generateSQLINstatement( $userNodeIDList, 'user_node.node_id', false, false, 'int' );
00185         $sql = "SELECT DISTINCT user_node.node_id,
00186                                 user_node.path_string,
00187                                 user_tree.contentobject_id
00188                 FROM ezcontentobject_tree user_node,
00189                      ezcontentobject_tree user_tree
00190                 WHERE $sqlINString AND
00191                       user_node.path_string LIKE $concatString";
00192         $nodePart = $db->arrayQuery( $sql );
00193 
00194         // Remove duplicates
00195         $objectIDList = array();
00196         foreach ( $nodePart as $row )
00197             if ( $row['contentobject_id'] != '0' )
00198                 $objectIDList[] = $row['contentobject_id'];
00199         $objectIDList = array_unique( $objectIDList );
00200 
00201         if ( count( $objectIDList ) == 0 )
00202         {
00203             $retValue = array();
00204             return $retValue;
00205         }
00206 
00207         // Select affected roles and policies
00208         $sqlINString = $db->generateSQLINStatement( $objectIDList, 'user_role.contentobject_id', false, false, 'int' );
00209         $sql = "SELECT DISTINCT user_role.contentobject_id,
00210                                 policy.id AS policy_id,
00211                                 user_role.limit_identifier AS limitation,
00212                                 user_role.limit_value AS value
00213                 FROM ezuser_role user_role,
00214                      ezpolicy policy
00215                 WHERE $sqlINString AND
00216                       ( user_role.role_id=policy.role_id AND
00217                         ( policy.module_name='*' OR
00218                           ( policy.module_name='content' AND
00219                             ( policy.function_name='*' OR
00220                               policy.function_name='read'
00221                             )
00222                           )
00223                         )
00224                       )";
00225         $rolePart = $db->arrayQuery( $sql );
00226 
00227         // Build resultArray. Make sure there are no duplicates.
00228         $resultArray = array();
00229         foreach ( $userPart as $up )
00230         {
00231             foreach ( $nodePart as $np )
00232             {
00233                 if ( $up['node_id'] == $np['node_id'] )
00234                 {
00235                     foreach ( $rolePart as $rp )
00236                     {
00237                         if ( $np['contentobject_id'] == $rp['contentobject_id'] )
00238                         {
00239                             $key = $rp['policy_id'] . $up['user_id'] . $rp['limitation'] . $rp['value'];
00240                             $resultArray[$key] = array( 'policy_id' => $rp['policy_id'],
00241                                                         'user_id' => $up['user_id'],
00242                                                         'limitation' => $rp['limitation'],
00243                                                         'value' => $rp['value'] );
00244                         }
00245                     }
00246                 }
00247             }
00248         }
00249 
00250         $policyIDArray = array();
00251         $limitedPolicyIDArray = array();
00252         $userIDArray = array();
00253         foreach( $resultArray as $result )
00254         {
00255             $userIDArray[(string)$result['user_id']] = (int)$result['user_id'];
00256         }
00257 
00258         foreach( $resultArray as $result )
00259         {
00260             if ( $result['limitation'] == '' )
00261             {
00262                 $policyIDArray[(string)$result['policy_id']][] =& $userIDArray[(string)$result['user_id']];
00263             }
00264             else
00265             {
00266                 $limitedPolicyIDArray[] = array( 'user_id' => $userIDArray[(string)$result['user_id']],
00267                                                  'limitation' => $result['limitation'],
00268                                                  'value' => $result['value'],
00269                                                  'policyID' => $result['policy_id'] );
00270             }
00271         }
00272 
00273         //include_once( 'kernel/classes/ezpolicy.php' );
00274         $acceptedUserArray = array();
00275         foreach( array_keys( $policyIDArray ) as $policyID )
00276         {
00277             foreach( array_keys( $policyIDArray[$policyID] ) as $key )
00278             {
00279                 if ( $policyIDArray[$policyID][$key] === false )
00280                 {
00281                     unset( $policyIDArray[$policyID][$key] );
00282                 }
00283             }
00284 
00285             if ( count( $policyIDArray[$policyID] ) == 0 )
00286             {
00287                 continue;
00288             }
00289 
00290             $userArray = eZSubtreeNotificationRule::checkObjectAccess( $contentObject, $policyID, $policyIDArray[$policyID] );
00291             $acceptedUserArray = array_merge( $acceptedUserArray, $userArray );
00292 
00293             foreach ( $userArray as $userID )
00294             {
00295                 $userIDArray[(string)$userID] = false;
00296             }
00297         }
00298 
00299         foreach( $limitedPolicyIDArray as $policyEntry )
00300         {
00301             if ( $policyEntry['user_id'] === false )
00302             {
00303                 continue;
00304             }
00305 
00306             $userArray = eZSubtreeNotificationRule::checkObjectAccess( $contentObject,
00307                                                                        $policyEntry['policyID'],
00308                                                                        array( $policyEntry['user_id'] ),
00309                                                                        array( $policyEntry['limitation'] => $policyEntry['value'] ) );
00310 
00311             $acceptedUserArray = array_merge( $acceptedUserArray, $userArray );
00312             foreach ( $userArray as $userID )
00313             {
00314                 $userIDArray[(string)$userID] = false;
00315             }
00316         }
00317         $acceptedUserArray = array_unique( $acceptedUserArray );
00318 
00319         foreach( array_keys( $acceptedUserArray ) as $key )
00320         {
00321             if ( !is_int( $acceptedUserArray[$key] ) or $acceptedUserArray[$key] == 0 )
00322             {
00323                 unset( $acceptedUserArray[$key] );
00324             }
00325         }
00326 
00327         if ( count( $acceptedUserArray ) == 0 )
00328         {
00329             $retValue = array();
00330             return $retValue;
00331         }
00332 
00333         $nodeIDWhereString = $db->generateSQLINStatement( $nodeIDList, 'rule.node_id', false, false, 'int' );
00334         $userIDWhereString = $db->generateSQLINStatement( $acceptedUserArray, 'rule.user_id', false, false, 'int' );
00335         $rules = $db->arrayQuery( "SELECT rule.user_id, rule.use_digest, ezuser.email as address
00336                                       FROM ezsubtree_notification_rule rule, ezuser
00337                                       WHERE rule.user_id=ezuser.contentobject_id AND
00338                                             $nodeIDWhereString AND
00339                                             $userIDWhereString" );
00340         return $rules;
00341     }
00342 
00343     /*!
00344      \private
00345 
00346      Check access for specified policy on object, and user list.
00347 
00348      \param Content object
00349      \param policyID
00350      \param userID array
00351      \param user limits
00352 
00353      \return array of user ID's which has access to object
00354     */
00355     static function checkObjectAccess( $contentObject, $policyID, $userIDArray, $userLimits = false )
00356     {
00357         $policy = eZPolicy::fetch( $policyID );
00358         if ( $userLimits )
00359         {
00360             reset( $userLimits );
00361             $policy->setAttribute( 'limit_identifier', 'User_' . key( $userLimits ) );
00362             $policy->setAttribute( 'limit_value', current( $userLimits ) );
00363         }
00364 
00365         $limitationArray = $policy->accessArray();
00366         $limitationArray = current( current( $limitationArray ) );
00367         $accessUserIDArray = $userIDArray;
00368 
00369         if ( isset( $limitationArray['*'] ) &&
00370              $limitationArray['*'] == '*' )
00371         {
00372             $returnArray = array();
00373             foreach ( $accessUserIDArray as $userID )
00374             {
00375                 $returnArray[] = $userID;
00376             }
00377             return $returnArray;
00378         }
00379 
00380         $limitationArray = current( $limitationArray );
00381 
00382         $user = eZUser::currentUser();
00383         $classID = $contentObject->attribute( 'contentclass_id' );
00384         $nodeArray = $contentObject->attribute( 'assigned_nodes' );
00385 
00386         if ( isset( $limitationArray['Subtree' ] ) )
00387         {
00388             $checkedSubtree = false;
00389         }
00390         else
00391         {
00392             $checkedSubtree = true;
00393             $nodeSubtree = true;
00394         }
00395         if ( isset( $limitationArray['Node'] ) )
00396         {
00397             $checkedNode = false;
00398         }
00399         else
00400         {
00401             $checkedNode = true;
00402             $nodeLimit = true;
00403         }
00404 
00405         foreach ( array_keys( $limitationArray ) as $key )
00406         {
00407             if ( count( $accessUserIDArray ) == 0 )
00408             {
00409                 return array();
00410             }
00411             switch( $key )
00412             {
00413                 case 'Class':
00414                 {
00415                     if ( !in_array( $contentObject->attribute( 'contentclass_id' ), $limitationArray[$key] )  )
00416                     {
00417                         return array();
00418                     }
00419                 } break;
00420 
00421                 case 'ParentClass':
00422                 {
00423 
00424                     if ( !in_array( $contentObject->attribute( 'contentclass_id' ), $limitationArray[$key]  ) )
00425                     {
00426                         return array();
00427                     }
00428                 } break;
00429 
00430                 case 'Section':
00431                 case 'User_Section':
00432                 {
00433                     if ( !in_array( $contentObject->attribute( 'section_id' ), $limitationArray[$key]  ) )
00434                     {
00435                         return array();
00436                     }
00437                 } break;
00438 
00439                 case 'Owner':
00440                 {
00441                     if ( in_array( $contentObject->attribute( 'owner_id' ), $userIDArray ) )
00442                     {
00443                         $accessUserIDArray = array_intersect( $contentObject->attribute( 'owner_id' ), $accessUserIDArray );
00444                     }
00445                     else if ( in_array( $contentObject->ID, $userIDArray ) )
00446                     {
00447                         $accessUserIDArray = array_intersect( $contentObject->ID, $accessUserIDArray );
00448                     }
00449                     else
00450                     {
00451                         return array();
00452                     }
00453                 } break;
00454 
00455                 case 'Node':
00456                 {
00457                     $nodeLimit = true;
00458                     foreach ( $nodeArray as $node )
00459                     {
00460                         if( in_array( $node->attribute( 'node_id' ), $limitationArray[$key] ) )
00461                         {
00462                             $nodeLimit = false;
00463                             break;
00464                         }
00465                     }
00466                     if ( $nodeLimit && $checkedSubtree && $nodeSubtree )
00467                     {
00468                         return array();
00469                     }
00470                     $checkedNode = true;
00471                 } break;
00472 
00473                 case 'Subtree':
00474                 {
00475                     $nodeSubtree = true;
00476                     foreach ( $nodeArray as $node )
00477                     {
00478                         $path = $node->attribute( 'path_string' );
00479                         $subtreeArray = $limitationArray[$key];
00480                         $validSubstring = false;
00481                         foreach ( $subtreeArray as $subtreeString )
00482                         {
00483                             if ( strstr( $path, $subtreeString ) )
00484                             {
00485                                 $nodeSubtree = false;
00486                                 break;
00487                             }
00488                         }
00489                         if ( !$nodeSubtree )
00490                         {
00491                             break;
00492                         }
00493                     }
00494                     if ( $nodeSubtree && $checkedNode && $nodeLimit )
00495                     {
00496                         return array();
00497                     }
00498                     $checkedSubtree = true;
00499                 } break;
00500 
00501                 case 'User_Subtree':
00502                 {
00503                     $userSubtreeLimit = true;
00504                     foreach ( $nodeArray as $node )
00505                     {
00506                         $path = $node->attribute( 'path_string' );
00507                         $subtreeArray = $limitationArray[$key];
00508                         $validSubstring = false;
00509                         foreach ( $subtreeArray as $subtreeString )
00510                         {
00511                             if ( strstr( $path, $subtreeString ) )
00512                             {
00513                                 $userSubtreeLimit = false;
00514                                 break;
00515                             }
00516                         }
00517                         if ( !$userSubtreeLimit )
00518                         {
00519                             break;
00520                         }
00521                     }
00522                     if ( $userSubtreeLimit )
00523                     {
00524                         return array();
00525                     }
00526                 } break;
00527             }
00528         }
00529 
00530         $returnArray = array();
00531         foreach ( $accessUserIDArray as $userID )
00532         {
00533             $returnArray[] = $userID;
00534         }
00535         return $returnArray;
00536     }
00537 
00538     function node()
00539     {
00540         if ( $this->Node == null )
00541         {
00542             $this->Node = eZContentObjectTreeNode::fetch( $this->attribute( 'node_id' ) );
00543         }
00544         return $this->Node;
00545     }
00546 
00547     static function removeByNodeAndUserID( $userID, $nodeID )
00548     {
00549         eZPersistentObject::removeObject( eZSubtreeNotificationRule::definition(), array( 'user_id' => $userID,
00550                                                                                           'node_id' => $nodeID ) );
00551     }
00552 
00553     /*!
00554      \static
00555 
00556      Remove notifications by user id
00557 
00558      \param userID
00559     */
00560     static function removeByUserID( $userID )
00561     {
00562         eZPersistentObject::removeObject( eZSubtreeNotificationRule::definition(), array( 'user_id' => $userID ) );
00563     }
00564 
00565     /*!
00566      \static
00567      Cleans up all notification rules for all users.
00568     */
00569     static function cleanup()
00570     {
00571         $db = eZDB::instance();
00572         $db->query( "DELETE FROM ezsubtree_notification_rule" );
00573     }
00574 
00575     public $Node = null;
00576 }
00577 
00578 ?>