Clear up php doc and use of eZRole::fetchByUser in reponse to issue #012602
[tinyz:tinyz.git] / kernel / classes / ezrole.php
1 <?php
2 //
3 // Definition of eZRole class
4 //
5 // Created on: <14-Aug-2002 14:08:46 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-2010 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
31 /*! \file
32 */
33
34 /*! \defgroup eZRole Role based permission system */
35
36 /*!
37   \class eZRole ezrole.php
38   \ingroup eZRole
39   \brief A container for policies in the permission system
40
41   It consists merely of a name() and has a DB id() and a version() number.
42   The actual permissions are stored in policies and policy values
43   which can be fetched with the method policyList().
44
45   To fetch permission access array you can use accessArrayByUserID() and accessArray().
46
47   There are multiple ways to fetch a role,
48   directly from an id() with fetch(), by a role name() with fetchByName(),
49   by a given user with fetchByUser() or the whole list with fetchList() and fetchByOffset().
50
51   Creating roles is done with create(), after which new policies can be added
52   using appendPolicy().
53
54   Remove roles with remove() and its policies with removePolicies().
55
56 */
57 class eZRole extends eZPersistentObject
58 {
59     /*!
60      Constructor
61     */
62     function eZRole( $row = array() )
63     {
64         $this->eZPersistentObject( $row );
65         $this->PolicyArray = 0;
66         $this->LimitIdentifier = false;
67         $this->LimitValue = false;
68         if ( isset( $row['limit_identifier'] ) )
69             $this->LimitIdentifier = $row['limit_identifier'];
70         if ( isset( $row['limit_value'] ) )
71             $this->LimitValue = $row['limit_value'];
72         if ( isset( $row['user_role_id'] ) )
73             $this->UserRoleID = $row['user_role_id'];
74     }
75
76     static function definition()
77     {
78         static $definition = array( "fields" => array( "id" => array( 'name' => 'ID',
79                                                         'datatype' => 'integer',
80                                                         'default' => 0,
81                                                         'required' => true ),
82                                          "version" => array( 'name' => "Version",
83                                                              'datatype' => 'integer',
84                                                              'default' => 0,
85                                                              'required' => true ),
86                                          "name" => array( 'name' => "Name",
87                                                           'datatype' => 'string',
88                                                           'default' => '',
89                                                           'required' => true ),
90                                          "is_new" => array( 'name' => "IsNew",
91                                                             'datatype' => 'integer',
92                                                             'default' => '0',
93                                                             'required' => false ) ),
94                       "function_attributes" => array( "policies" => "policyList",
95                                                       'limit_identifier' => 'limitIdentifier',
96                                                       'limit_value' => 'limitValue',
97                                                       'user_role_id' => 'userRoleID' ),
98                       "keys" => array( "id" ),
99                       "increment_key" => "id",
100                       "sort" => array( "id" => "asc" ),
101                       "class_name" => "eZRole",
102                       "name" => "ezrole" );
103         return $definition;
104     }
105
106     /*!
107      Returns the limit identifier if it is set.
108      \note This will only be available when fetching roles for a specific user
109      \sa limitValue
110     */
111     function limitIdentifier()
112     {
113         return $this->LimitIdentifier;
114     }
115
116     /*!
117      Returns the limit value if it is set.
118      \note This will only be available when fetching roles for a specific user
119      \sa limitIdentifier
120     */
121     function limitValue()
122     {
123         return $this->LimitValue;
124     }
125
126     /*!
127      Returns the user role ID if it is set.
128     \note This will only be available when fetching roles for a specific user
129     \sa userRoleID
130     */
131     function userRoleID()
132     {
133         return $this->UserRoleID;
134     }
135
136     /*!
137      Copies this role, stores it and returns it.
138      \note Transaction unsafe. If you call several transaction unsafe methods you must enclose
139      the calls within a db transaction; thus within db->begin and db->commit.
140     */
141     function copy()
142     {
143         $db = eZDB::instance();
144         $db->begin();
145
146         $newRole = eZRole::createNew();
147         $this->copyPolicies( $newRole->attribute( 'id' ) );
148         $newRole->setAttribute( 'name', ezpI18n::tr( 'kernel/role/edit', 'Copy of %rolename', null,
149                                                 array( '%rolename' => $this->attribute( 'name' ) ) ) );
150         $newRole->store();
151         $db->commit();
152         return $newRole;
153     }
154
155     /*!
156      \note Transaction unsafe. If you call several transaction unsafe methods you must enclose
157      the calls within a db transaction; thus within db->begin and db->commit.
158     */
159     function createTemporaryVersion()
160     {
161         $db = eZDB::instance();
162         $db->begin();
163
164         $newRole = eZRole::createNew();
165         $this->copyPolicies( $newRole->attribute( 'id' ) );
166         $newRole->setAttribute( 'name', $this->attribute( 'name' ) );
167         $newRole->setAttribute( 'version', $this->attribute( 'id' ) );
168         $newRole->store();
169
170         $db->commit();
171         return $newRole;
172     }
173
174     /*!
175      \static
176      Creates a new role with the name 'New role', stores it and returns it.
177      \note Transaction unsafe. If you call several transaction unsafe methods you must enclose
178      the calls within a db transaction; thus within db->begin and db->commit.
179     */
180     static function createNew()
181     {
182         $role = new eZRole( array( 'name' => ezpI18n::tr( 'kernel/role/edit', 'New role' ),
183                                    'is_new' => 1 ) );
184         $role->store();
185         return $role;
186     }
187
188     /*!
189      \static
190      Creates a new role with the name \a $roleName and version \a $version and returns it.
191      \note The role is not stored.
192     */
193     static function create( $roleName, $version = 0 )
194     {
195         $row = array( 'id' => null,
196                       'name' => $roleName,
197                       'version' => 0 );
198         $role = new eZRole( $row );
199         return $role;
200     }
201
202     /*!
203      Appends a new policy to the current role and returns it.
204      \note The policy and it's limitation values will be stored to the database before returning.
205      \param $module Which module to give access to or \c true to give access to all modules.
206      \param $function Which function to give access to or \c true to give access to all functions.
207      \param $limitations An associative array with limitations and their values, use an empty array for no limitations.
208
209      \code
210      // Access to content/read
211      $policy1 = $role->appendPolicy( 'content', 'read' );
212      // Access to content/read in section 1
213      $policy2 = $role->appendPolicy( 'content', 'read', array( 'Section' => 1 ) );
214      // Access to content/read for class 2 and 5
215      $policy3 = $role->appendPolicy( 'content', 'read', array( 'Class' => array( 2, 5 ) ) );
216      \endcode
217
218      \note Transaction unsafe. If you call several transaction unsafe methods you must enclose
219      the calls within a db transaction; thus within db->begin and db->commit.
220     */
221     function appendPolicy( $module, $function, $limitations = array() )
222     {
223         $policy = eZPolicy::create( $this->ID, $module, $function );
224
225         $db = eZDB::instance();
226         $db->begin();
227         $policy->store();
228         if ( count( $limitations ) > 0 )
229         {
230             foreach ( $limitations as $limitationIdentifier => $limitationValues )
231             {
232                 if ( !is_array( $limitationValues ) )
233                     $limitationValues = array( $limitationValues );
234                 $policy->appendLimitation( $limitationIdentifier, $limitationValues );
235             }
236         }
237         $db->commit();
238
239         if ( isset( $this->Policies ) )
240         {
241             $this->Policies[] = $policy;
242         }
243         return $policy;
244     }
245
246     /*!
247      Copies all policies for this role and assigns them to the role identified by ID \a $roleID.
248      \note Transaction unsafe. If you call several transaction unsafe methods you must enclose
249      the calls within a db transaction; thus within db->begin and db->commit.
250     */
251     function copyPolicies( $roleID )
252     {
253         $db = eZDB::instance();
254         $db->begin();
255         foreach ( $this->attribute( 'policies' ) as $policy )
256         {
257             $policy->copy( $roleID );
258         }
259         $db->commit();
260     }
261
262     /*!
263      \note Transaction unsafe. If you call several transaction unsafe methods you must enclose
264      the calls within a db transaction; thus within db->begin and db->commit.
265      */
266     function revertFromTemporaryVersion()
267     {
268         $temporaryVersion = eZRole::fetch( 0, $this->attribute( 'id' ) );
269         if ( $temporaryVersion === null )
270             return 0;
271         $this->removePolicies();
272         $this->setAttribute( 'name', $temporaryVersion->attribute( 'name') );
273         $this->setAttribute( 'is_new', 0 );
274
275         $db = eZDB::instance();
276         $db->begin();
277         $this->store();
278
279         $query = "UPDATE  ezpolicy
280                   SET role_id = " . $this->attribute( 'id' ) . "
281                   WHERE role_id = " . $temporaryVersion->attribute( 'id' );
282         $db->query( $query );
283         $temporaryVersion->removePolicies( false );
284         $temporaryVersion->remove();
285         $db->commit();
286
287         // Expire role cache
288         eZExpiryHandler::registerShutdownFunction();
289         $handler = eZExpiryHandler::instance();
290         $handler->setTimestamp( 'user-access-cache', time() );
291         $handler->setTimestamp( 'user-info-cache', time() );
292         $handler->setTimestamp( 'user-class-cache', time() );
293         $handler->store();
294     }
295
296     /*!
297      \static
298      Removes all temporary roles and roles without policies from the database.
299      \note Transaction unsafe. If you call several transaction unsafe methods you must enclose
300      the calls within a db transaction; thus within db->begin and db->commit.
301     */
302     static function removeTemporary()
303     {
304         $temporaryRoles = eZRole::fetchList( true );
305
306         $db = eZDB::instance();
307         $db->begin();
308         foreach ( $temporaryRoles as $role )
309         {
310             $role->removeThis();
311         }
312         $db->commit();
313     }
314
315     /*!
316      \static
317      \sa removeThis
318     */
319     static function removeRole( $roleID )
320     {
321         if ( !isset( $roleID ) )
322         {
323             return 0;
324         }
325         return eZRole::fetch( $roleID )->removeThis();
326     }
327
328     /*!
329      Removes the role, it's policies and any assignments to users/groups.
330      \param $roleID If this is \c false then the function is not static and the ID is fetched from \c $this.
331      \note Transaction unsafe. If you call several transaction unsafe methods you must enclose
332      the calls within a db transaction; thus within db->begin and db->commit.
333     */
334     function removeThis()
335     {
336         $db = eZDB::instance();
337         $db->begin();
338         foreach ( $this->attribute( 'policies' ) as $policy )
339         {
340             $policy->removeThis();
341         }
342         $db->query( "DELETE FROM ezrole WHERE id='" . $db->escapeString( $this->attribute( 'id' ) ) . "'" );
343         $db->query( "DELETE FROM ezuser_role WHERE role_id = '" . $db->escapeString( $this->attribute( 'id' ) ) . "'" );
344         $db->commit();
345     }
346
347     /*!
348      Removes the policy object list from this role.
349      \param $fromDB If \c true then the policies are removed from database.
350      \note Transaction unsafe. If you call several transaction unsafe methods you must enclose
351      the calls within a db transaction; thus within db->begin and db->commit.
352     */
353     function removePolicies( $fromDB = true )
354     {
355         $db = eZDB::instance();
356         $db->begin();
357         if ( $fromDB )
358         {
359             foreach ( $this->attribute( 'policies' ) as $policy )
360             {
361                 $policy->removeThis();
362             }
363         }
364         $db->commit();
365         unset( $this->Policies );
366     }
367
368     /*!
369      Removes the policy object(s) by specified \a $moduleName and/or \a $functionName.
370      Removes all policies for module \a $moduleName if \a $functionName is \c false.
371      \param $moduleName Module name
372      \param $functionName function name. Default is \c false.
373      \note Transaction unsafe. If you call several transaction unsafe methods you must enclose
374      the calls within a db transaction; thus within db->begin and db->commit.
375     */
376     function removePolicy( $moduleName, $functionName = false )
377     {
378         $policyList = $this->policyList();
379         if ( is_array( $policyList ) && count( $policyList ) > 0 )
380         {
381             $db = eZDB::instance();
382             $db->begin();
383
384             foreach( $policyList as $key => $policy )
385             {
386                 if ( is_object( $policy ) )
387                 {
388                     if ( $policy->attribute( 'module_name' ) == $moduleName )
389                     {
390                         if ( ( $functionName === false ) || ( $policy->attribute( 'function_name' ) == $functionName ) )
391                         {
392                             $policy->removeThis();
393                             unset( $this->Policies[$key] );
394                         }
395                     }
396                 }
397             }
398
399             $db->commit();
400         }
401     }
402
403     /*!
404      \static
405      Cleans up policies and role assignments related to node when this node is removed
406      \note Transaction unsafe. If you call several transaction unsafe methods you must enclose
407      the calls within a db transaction; thus within db->begin and db->commit.
408     */
409     static function cleanupByNode( $node )
410     {
411         // Clean up role assignments with limitations related to this object
412         $db = eZDB::instance();
413         $db->begin();
414         $pathString = $node->attribute( 'path_string' );
415         $nodeID = $node->attribute( 'node_id' );
416         $db->query( "DELETE FROM ezuser_role
417                      WHERE limit_value LIKE '$pathString%' AND limit_identifier='Subtree'" );
418                         // Clean up subtree limitations related to this object
419
420
421         $limitationsToFix = eZPolicyLimitation::findByType( 'SubTree', $node->attribute( 'path_string' ), true, true );
422
423         foreach( $limitationsToFix as $limitation )
424         {
425             $values = $limitation->attribute( 'values' );
426             $valueCount = count( $values );
427             if ( $valueCount > 0 )
428             {
429                 foreach ( $values as $value )
430                 {
431                     if ( strpos( $value->attribute( 'value' ), $node->attribute( 'path_string' ) ) === 0 )
432                     {
433                         $value->remove();
434                         $valueCount--;
435                     }
436                 }
437             }
438             if( $valueCount == 0 )
439             {
440                 $policy = eZPolicy::fetch( $limitation->attribute( 'policy_id' ) );
441                 if ( is_object ( $policy ) )
442                 {
443                     $policy->removeThis();
444                 }
445             }
446         }
447
448         $limitationsToFixNode = eZPolicyLimitation::findByType( 'Node', $node->attribute( 'node_id' ) );
449
450         foreach( $limitationsToFixNode as $limitation )
451         {
452             $values = $limitation->attribute( 'values' );
453             $valueCount = count( $values );
454             if ( $valueCount > 0 )
455             {
456                 foreach ( $values as $value )
457                 {
458                     if ( $value->attribute( 'value' ) == $node->attribute( 'node_id' ) )
459                     {
460                         $value->remove();
461                         $valueCount--;
462                     }
463                 }
464             }
465             if( $valueCount == 0 )
466             {
467                 $policy = eZPolicy::fetch( $limitation->attribute( 'policy_id' ) );
468                 if ( is_object ( $policy ) )
469                 {
470                     $policy->removeThis();
471                 }
472             }
473         }
474
475         eZRole::expireCache();
476
477         $db->commit();
478
479     }
480
481     /**
482      * Returns the roles matching the given users' eZContentObject ID array
483      *
484      * @param array $idArray Array of eZContentObject IDs, either groups + user id or user id's only
485      *                       If only user id's, then remember to set $recursive to true
486      * @param bool $recursive
487      *        If true, roles will be looked up for all nodes of the id's and it's parents
488      *
489      * @return array(eZRole)
490      **/
491     static function fetchByUser( $idArray, $recursive = false )
492     {
493         if ( count( $idArray ) < 1 )
494         {
495             return array();
496         }
497
498         $db = eZDB::instance();
499
500         if ( !$recursive )
501         {
502             $groupINSQL = $db->generateSQLINStatement( $idArray, 'ezuser_role.contentobject_id', false, false, 'int' );
503             $query = "SELECT DISTINCT ezrole.id,
504                                       ezrole.name,
505                                       ezuser_role.limit_identifier,
506                                       ezuser_role.limit_value,
507                                       ezuser_role.id as user_role_id
508                       FROM ezrole,
509                            ezuser_role
510                       WHERE $groupINSQL AND
511                             ezuser_role.role_id = ezrole.id";
512         }
513         else
514         {
515             $userNodeIDArray = array();
516             foreach( $idArray as $id )
517             {
518                 $nodeDefinition = eZContentObjectTreeNode::fetchByContentObjectID( $id );
519                 foreach ( $nodeDefinition as $nodeDefinitionElement )
520                 {
521                     $userNodeIDArray = array_merge( $nodeDefinitionElement->attribute( 'path_array' ), $userNodeIDArray );
522                 }
523             }
524
525             if ( count( $userNodeIDArray ) < 1 )
526             {
527                 return array();
528             }
529
530             $roleTreeINSQL = $db->generateSQLINStatement( $userNodeIDArray, 'role_tree.node_id', false, false, 'int' );
531             $query = "SELECT DISTINCT ezrole.id,
532                                       ezrole.name,
533                                       ezuser_role.limit_identifier,
534                                       ezuser_role.limit_value,
535                                       ezuser_role.id as user_role_id
536                       FROM ezrole,
537                            ezuser_role,
538                            ezcontentobject_tree role_tree
539                       WHERE ezuser_role.contentobject_id = role_tree.contentobject_id AND
540                             ezuser_role.role_id = ezrole.id AND
541                             $roleTreeINSQL";
542         }
543
544         $roleArray = $db->arrayQuery( $query );
545
546         $roles = array();
547         foreach ( $roleArray as $roleRow )
548         {
549             $role = new eZRole( $roleRow );
550             $roles[] = $role;
551         }
552
553         return $roles;
554     }
555
556     /*!
557       Expires all roles, policies and limitations cache.
558     */
559     static function expireCache()
560     {
561         $http = eZHTTPTool::instance();
562
563         $http->removeSessionVariable( 'UserPolicies' );
564         $http->removeSessionVariable( 'UserLimitations' );
565         $http->removeSessionVariable( 'UserLimitationValues' );
566         $http->removeSessionVariable( 'CanInstantiateClassesCachedForUser' );
567         $http->removeSessionVariable( 'CanInstantiateClassList' );
568         $http->removeSessionVariable( 'ClassesCachedForUser' );
569
570         // Expire role cache
571         eZExpiryHandler::registerShutdownFunction();
572         $handler = eZExpiryHandler::instance();
573         $handler->setTimestamp( 'user-access-cache', time() );
574         $handler->store();
575     }
576
577     /**
578      * Return access array by passing in list of groups user belongs to and his user id
579      *
580      * @param array $userIDArray List with user group id's and it's user id
581      * @return array Hash with complete access limitation description
582      */
583     static function accessArrayByUserID( $userIDArray )
584     {
585         $roles = eZRole::fetchByUser( $userIDArray );
586         $userLimitation = false;
587
588         $accessArray = array();
589         foreach ( array_keys ( $roles )  as $roleKey )
590         {
591             $accessArray = array_merge_recursive( $accessArray, $roles[$roleKey]->accessArray() );
592             if ( $roles[$roleKey]->attribute( 'limit_identifier' ) )
593             {
594                 $userLimitation = true;
595             }
596         }
597
598         if ( $userLimitation )
599         {
600             foreach( $accessArray as $moduleKey => $functionList )
601             {
602                 foreach( $functionList as $functionKey => $policyList )
603                 {
604                     foreach( $policyList as $policyKey => $limitationList )
605                     {
606                         if ( is_array( $limitationList ) )
607                         {
608                             foreach( $limitationList as $limitationKey => $limitKeyArray )
609                             {
610                                 if ( is_array( $limitKeyArray ) )
611                                 {
612                                     $accessArray[$moduleKey][$functionKey][$policyKey][$limitationKey] = array_unique( $limitKeyArray );
613                                 }
614                             }
615                         }
616                     }
617                 }
618             }
619         }
620         return $accessArray;
621     }
622
623     /*!
624      Fetch access array of current role
625     */
626     function accessArray( $ignoreLimitIdentifier = false )
627     {
628         $accessArray = array();
629
630         $policies = $this->attribute( 'policies' );
631         foreach ( array_keys( $policies ) as $policyKey )
632         {
633             $accessArray = array_merge_recursive( $accessArray, $policies[$policyKey]->accessArray( $ignoreLimitIdentifier ) );
634         }
635
636         return $accessArray;
637     }
638
639     function policyList()
640     {
641         if ( !isset( $this->Policies ) )
642         {
643             $policies = eZPersistentObject::fetchObjectList( eZPolicy::definition(),
644                                                               null, array( 'role_id' => $this->attribute( 'id') ), null, null,
645                                                               true );
646
647             if ( $this->LimitIdentifier )
648             {
649                 foreach ( array_keys( $policies ) as $policyKey )
650                 {
651                     $policies[$policyKey]->setAttribute( 'limit_identifier', 'User_' . $this->attribute( 'limit_identifier' ) );
652                     $policies[$policyKey]->setAttribute( 'limit_value', $this->attribute( 'limit_value' ) );
653                     $policies[$policyKey]->setAttribute( 'user_role_id', $this->attribute( 'user_role_id' ) );
654                 }
655             }
656             $this->Policies = $policies;
657         }
658
659         return $this->Policies;
660     }
661
662     /**
663      * Fetches the list of roles ID matching an array of eZContentObject IDs
664      * (either users and/or groups IDs)
665      *
666      * @param array(eZContentObjectID) $idArray
667      *
668      * @return array(eZRoleID)
669      **/
670     static function fetchIDListByUser( $idArray )
671     {
672         $db = eZDB::instance();
673
674         $groupINSQL = $db->generateSQLINStatement( $idArray, 'ezuser_role.contentobject_id', false, false, 'int' );
675         $query = "SELECT DISTINCT ezrole.id AS id
676                   FROM ezrole,
677                        ezuser_role
678                   WHERE $groupINSQL AND
679                         ezuser_role.role_id = ezrole.id ORDER BY ezrole.id";
680
681         $retArray = array();
682         foreach( $db->arrayQuery( $query ) as $resultSet )
683         {
684             $retArray[] = $resultSet['id'];
685         }
686         return $retArray;
687     }
688
689     /*!
690      Assigns the current role to the given user or user group identified by the id.
691      \note Transaction unsafe. If you call several transaction unsafe methods you must enclose
692      the calls within a db transaction; thus within db->begin and db->commit.
693      \note WARNING: Roles and content caches need to be cleared after calling this function.
694     */
695     function assignToUser( $userID, $limitIdent = '', $limitValue = '' )
696     {
697         $db = eZDB::instance();
698         $limitIdent = $db->escapeString( $limitIdent );
699         $limitValue = $db->escapeString( $limitValue );
700         $userID =(int) $userID;
701
702         // Who assign which role to whom should be logged.
703         $object = eZContentObject::fetch( $userID );
704         $objectName = $object ? $object->attribute( 'name' ) : 'null';
705
706         eZAudit::writeAudit( 'role-assign', array( 'Role ID' => $this->ID, 'Role name' => $this->attribute( 'name' ),
707                                                    'Assign to content object ID' => $userID,
708                                                    'Content object name' => $objectName,
709                                                    'Comment' => 'Assigned the current role to user or user group identified by the id: eZRole::assignToUser()' ) );
710
711         switch( $limitIdent )
712         {
713             case 'subtree':
714             {
715                 $node = eZContentObjectTreeNode::fetch( $limitValue, false, false );
716                 if ( $node )
717                 {
718                     $limitIdent = 'Subtree';
719                     $limitValue = $node['path_string'];
720                 }
721                 else
722                 {
723                     $limitValue = '';
724                     $limitIdent = '';
725                 }
726             } break;
727             case 'section':
728             {
729                 $limitIdent = 'Section';
730             } break;
731         }
732
733         $query = "SELECT * FROM ezuser_role WHERE role_id='$this->ID' AND contentobject_id='$userID' AND limit_identifier='$limitIdent' AND limit_value='$limitValue'";
734
735         $rows = $db->arrayQuery( $query );
736         if ( count( $rows ) > 0 )
737             return false;
738
739         $db->begin();
740
741         $query = "INSERT INTO ezuser_role ( role_id, contentobject_id, limit_identifier, limit_value ) VALUES ( '$this->ID', '$userID', '$limitIdent', '$limitValue' )";
742         $db->query( $query );
743
744         $db->commit();
745         return true;
746     }
747
748     /*!
749      Fetch user id array which have been assigned to this role.
750     */
751     function fetchUserID()
752     {
753         $db = eZDB::instance();
754
755         $query = "SELECT contentobject_id FROM  ezuser_role WHERE role_id='$this->ID'";
756
757         return $db->arrayQuery( $query );
758     }
759
760     /*!
761      Removes the role assignment
762      \note Transaction unsafe. If you call several transaction unsafe methods you must enclose
763      the calls within a db transaction; thus within db->begin and db->commit.
764      \note WARNING: Roles and content caches need to be cleared after calling this function.
765     */
766     function removeUserAssignment( $userID )
767     {
768         $db = eZDB::instance();
769         $userID =(int) $userID;
770         $query = "DELETE FROM ezuser_role WHERE role_id='$this->ID' AND contentobject_id='$userID'";
771
772         $db->query( $query );
773     }
774
775     /*!
776      Remove ezuser_role by id
777
778      \param ezuser_role id
779      \note Transaction unsafe. If you call several transaction unsafe methods you must enclose
780      the calls within a db transaction; thus within db->begin and db->commit.
781      \note WARNING: Roles and content caches need to be cleared after calling this function.
782     */
783     function removeUserAssignmentByID( $id )
784     {
785         // Remove the assignment.
786         $db = eZDB::instance();
787         $id =(int) $id;
788         $query = "DELETE FROM ezuser_role WHERE id='$id'";
789         $db->query( $query );
790     }
791
792     /*!
793       \return the users and user groups assigned to the current role.
794     */
795     function fetchUserByRole( )
796     {
797         $db = eZDB::instance();
798
799         $query = "SELECT
800                      ezuser_role.contentobject_id as user_id,
801                      ezuser_role.limit_value,
802                      ezuser_role.limit_identifier,
803                      ezuser_role.id
804                   FROM
805                      ezuser_role
806                   WHERE
807                     ezuser_role.role_id = '$this->ID'";
808
809         $userRoleArray = $db->arrayQuery( $query );
810         $userRoles = array();
811         foreach ( $userRoleArray as $userRole )
812         {
813             $role = array();
814             $role['user_object'] = eZContentObject::fetch( $userRole['user_id'] );
815             $role['user_role_id'] = $userRole['id'];
816             $role['limit_ident'] = $userRole['limit_identifier'];
817             $role['limit_value'] = $userRole['limit_value'];
818
819             $userRoles[] = $role;
820         }
821         return $userRoles;
822     }
823
824     static function fetchRolesByLimitation( $limit_identifier, $limit_value )
825     {
826         $db = eZDB::instance();
827         $limit_identifier = $db->escapeString( $limit_identifier );
828         $limit_value = $db->escapeString( $limit_value );
829         $query = "SELECT DISTINCT
830                      ezuser_role.role_id as role_id,
831                      ezuser_role.contentobject_id as user_id
832                   FROM
833                      ezuser_role
834                   WHERE
835                      ezuser_role.limit_value = '$limit_value' AND
836                      ezuser_role.limit_identifier = '$limit_identifier'";
837
838         $userRoleArray = $db->arrayQuery( $query );
839         $userRoles = array();
840         foreach ( $userRoleArray as $userRole )
841         {
842             $role = array();
843             $role['user'] = eZContentObject::fetch( $userRole['user_id'] );
844             $role['role'] = eZRole::fetch( $userRole['role_id'] );
845             $userRoles[] = $role;
846         }
847         return $userRoles;
848     }
849
850     /*!
851      Fetches the role identified by the role ID \a $roleID and returns it.
852      \param $version Which version to fetch, 0 is the published one. Temporary versions get
853       the id of the role.
854     */
855     static function fetch( $roleID, $version = 0 )
856     {
857         if ( $version != 0 )
858         {
859             return eZPersistentObject::fetchObject( eZRole::definition(),
860                                                     null, array( 'version' => $version ), true );
861         }
862         return eZPersistentObject::fetchObject( eZRole::definition(),
863                                                 null, array('id' => $roleID ), true );
864     }
865
866     /*!
867      Fetches the role identified by the role name \a $roleName and returns it.
868      \param $version Which version to fetch, 0 is the published one and 1 is the temporary.
869     */
870     static function fetchByName( $roleName, $version = 0 )
871     {
872         return eZPersistentObject::fetchObject( eZRole::definition(),
873                                                 null, array( 'name' => $roleName,
874                                                              'version' => $version ), true );
875     }
876
877     static function fetchList( $tempVersions = false )
878     {
879         if ( !$tempVersions )
880         {
881             return eZPersistentObject::fetchObjectList( eZRole::definition(),
882                                                         null, array( 'version' => '0'), null,null,
883                                                         true );
884         }
885         else
886         {
887             return eZPersistentObject::fetchObjectList( eZRole::definition(),
888                                                         null, array( 'version' => array( '>', '0') ), null,null,
889                                                         true);
890         }
891     }
892
893     static function fetchByOffset( $offset, $limit, $asObject = true, $ignoreTemp = false, $ignoreNew = true )
894     {
895
896         if ( $ignoreTemp && $ignoreNew )
897             $igTemp = array( 'version' => '0',
898                              'is_new' => '0' );
899         elseif ( $ignoreTemp )
900             $igTemp = array( 'version' => '0' );
901         elseif ( $ignoreNew )
902             $igTemp = array( 'is_new' => '0' );
903         else
904             $igTemp = null;
905
906         return eZPersistentObject::fetchObjectList( eZRole::definition(),
907                                                     null,
908                                                     $igTemp,
909                                                     array( 'name' => 'ASC' ),
910                                                     array( 'offset' => $offset, 'length' => $limit ),
911                                                     $asObject );
912     }
913
914     /*!
915      \static
916      \return the number of roles in the database.
917     */
918     static function roleCount()
919     {
920         $db = eZDB::instance();
921
922         $countArray = $db->arrayQuery(  "SELECT count( * ) AS count FROM ezrole WHERE version=0" );
923         return $countArray[0]['count'];
924     }
925
926     /*!
927      Sets caching of policies to off for this role.
928     */
929     function turnOffCaching()
930     {
931         $this->CachePolicies = false;
932     }
933
934     /*!
935      Sets caching of policies to on for this role.
936     */
937     function turnOnCaching()
938     {
939         $this->CachePolicies = true;
940     }
941
942
943     /// \privatesection
944     public $ID;
945     public $Name;
946     public $Modules;
947     public $Functions;
948     public $LimitValue;
949     public $LimitIdentifier;
950     public $UserRoleID;
951     public $PolicyArray;
952     public $Sets;
953     public $Policies;
954     public $AccessArray;
955     public $CachePolicies = true;
956 }
957
958 ?>