'', 'name' => '' ); } /** * Constructor for the UserGroup class * @param array $paramarray an associative array of UserGroup fields **/ public function __construct( $paramarray= array() ) { $this->fields= array_merge( self::default_fields(), $this->fields ); parent::__construct( $paramarray ); $this->exclude_fields('id'); // set up default, empty properties $this->permissions_revoked= array(); $this->db_member_ids= array(); $this->db_permissions_granted= array(); $this->db_permissions_denied= array(); $this->toggle_permission['grant']= array(); $this->toggle_permissions['deny']= array(); // if we have an ID, load this UserGroup's members & permissions if ( $this->id ) { if ( $result= DB::get_column( 'SELECT user_id FROM {users_groups} WHERE group_id= ?', array( $this->id ) ) ) { foreach( $result as $id ) { $this->db_member_ids[ $id ]= $id; } } if ( $result= DB::get_column( 'SELECT permission_id FROM {groups_permissions} WHERE group_id=? AND denied=0 ', array( $this->id ) ) ) { foreach ( $result as $granted ) { $this->db_permissions_granted[ $granted ]= $granted; } } if ( $result= DB::get_column( 'SELECT permission_id FROM {groups_permissions} WHERE group_id=? AND denied=1', array( $this->id ) ) ) { foreach( $result as $denied ) { $this->permissions_denied[ $denied ]= $denied; } } } // set the temporary variables to hold the initial values // as pulled from the DB, if any $this->member_ids= $this->db_member_ids; $this->permissions_granted= $this->db_permissions_granted; $this->permissions_denied= $this->db_permissions_denied; } /** * Create a new UserGroup object and save it to the database * @param array An associative array of UserGroup fields * @return UserGroup the UserGroup that was created **/ public static function create( $paramarray ) { $usergroup= new UserGroup( $paramarray ); if ( $usergroup->insert() ) { return $usergroup; } else { return $false; } } /** * Save a new UserGroup to the UserGroup table **/ public function insert() { $allow= true; // plugins have the opportunity to prevent insertion $allow= Plugins::filter('usergroup_insert_allow', $allow, $this); if ( ! $allow ) { return false; } Plugins::act('usergroup_insert_before', $this); $this->exclude_fields('id'); $result= parent::insertRecord( DB::table('users') ); $this->fields['id']= DB::last_insert_id(); EventLog::log('New group created: ' . $this->name, 'info', 'default', 'habari'); Plugins::act('usergroup_insert_after', $this); return $result; } /** * Updates an existing UserGroup in the DB **/ public function update() { $allow= true; // plugins have the opportunity to prevent modification $allow= Plugins::filter('usergroup_update_allow', $allow, $this); if ( ! $allow ) { return false; } Plugins::act('usergroup_update_before', $this); ` // figure out what needs to be changed // we do this by comparing the various temporary arrays against // the arrays that hold the DB values if ( $this->member_ids != $this->db_member_ids ) { $added= array_diff_assoc( $this->member_ids, $this->db_member_ids); if ( count( $added ) > 0 ) { // one or more members added to this group foreach ( $added as $id ) { DB::query('INSERT INTO {users_groups} (user_id, group_id) VALUES (?, ?)', array( $id, $this->id) ); } } $removed= array_diff_assoc( $this->db_member_ids, $this->member_ids ); if ( count( $removed ) > 0 ) { // one or more members removed from this group foreach ( $removed as $id ) { DB::query('DELETE FROM {users_groups} WHERE user_id=? AND group_id=?', array( $id, $this->id ) ); } } } // were any permissions toggled? We do this to economize hits // to the DB: rather than execute separate DELETE then INSERT // commands, we can execute a single UPDATE if ( ! empty( $this->toggle_permissions['grant'] ) ) { // grant permissions previously denied $ids= implode( ',', $this->toggle_permissions['grant']; $results= DB::query( "UPDATE {groups_permissions} set denied=0 WHERE id IN ($ids)" ); //update DB arrays, to prevent the next set of checks // from trying to insert this permission foreach ( $this->toggle_permissions['grant'] as $id ) { $this->db_permissions_granted[ $id ]= $id; if ( isset( $this->db_permissions_denied[$id] ) ) { // this should make the db array match // its corresponding temp array unset( $this->db_permissions_denied[$id] ); } } } if ( ! empty( $this->toggle_permissions['deny'] ) ) { $ids= implode( ',', $this->toggle_permissions['deny']; $results= DB::query( "UPDATE {groups_permissions} set denied=1 WHERE id IN ($ids)" ); //update DB arrays again foreach ( $this->toggle_permissions['deny'] as $id ) { $this->db_permissions_denied[ $id ]= $id; if ( isset( $this->db_permissions_granted[$id] ) ) { // this should make the db array match // its corresponding temp array unset( $this->db_permissions_granted[$id] ); } } } // now, we compare the current list of granted permissions with // those currently in the DB. If any new ones have been added, // update the DB to reflect this if ( $this->permissions_granted != $this->db_permissions_granted ) { $granted= array_diff_assoc( $this->permissions_granted, $this->db_permissions_granted ); if ( count( $granted ) > 0 ) { // one or more permissions granted foreach( $granted as $perm ) { DB::query('INSERT INTO {groups_permissions} (group_id, permission_id, denied ) VALUES (?, ?, 0)', array( $this->id, $perm) ); } } } // and do the same for the denied permissions if ( $this->permissions_denied != $this->db_permissions_denied ) { $denied= array_diff_assoc( $this->permissions_denied, $this->db_permissions_denied ); if ( count( $denied ) > 0 ) { // one or more permissions denied foreach( $denied as $perm ) { DB::query('INSERT INTO {groups_permissions} (group_id, permission_id, denied) VAlUED (?, ? 1)', array( $this->id, $perm ) ); } } } // finally, were any previously assigned permissions // (granted or denied) removed? If so, take them out of the DB if ( count( $this->permissions_revoked ) > 0 ) { // one or more permissions revoked foreach ( $this->permissions_revoked as $perm ) { DB::query( 'DELETE FROM {users_groups} WHERE group_id=? AND permission_id=?', array( $this->id, $perm ) ); } } Plugins::act('usergroup_update_after', $this); // *whew* We're all done! } /** * Delete a UserGroup **/ public function delete() { $allow= true; // plugins have the opportunity to prevent deletion $allow= Plugins::filter('usergroup_delete_allow', $allow, $this); if ( ! $allow ) { return; } Plugins::act('usergroup_delete_before', $this); // remove all this group's permissions $results= DB::query( 'DELETE FROM {groups_permissions} WHERE group_id=?', array( $this->id ) ); // remove all this group's members $results= DB::query( 'DELETE FROM {users_groups} WHERE group_id=?', array( $this->id ) ); // remove this group $result= parent::deleteRecord( DB::table('groups'), array( 'id' => $this->id ) ); Plugins::act('usergroup_delete_after', $this); return $result; } /** * function members * returns an array of user IDs belogning to this UserGroup * @return array an array of user IDs **/ public function members() { return $this->member_ids; } /** * Add a user to this group * @param mixed a user ID or name **/ public function add( $id ) { if ( ! is_int( $id ) ) { $user= User::get( $id ); $id= $user->id; } if ( isset( $self->member_ids[ $id ] ) ) { // this user is already a member return false; } $self->member_ids[$id]= $id; return true; } /** * Remove a user from this group * @param mixed a user ID or name **/ public function remove( $id ) { if ( ! is_int( $id ) ) { $user= User::get( $id ); $id= $user->id; } if ( ! isset( $self->member_ids[ $id ] ) ) { // this user is not a member of this group return false; } unset($self->member_ids[ $id ]); return true; } /** * Assign a new permission to this group * @param int A permission ID **/ public function grant( $permission ) { // is this permisson currently assigned to this group? if ( isset( $this->permissions_granted[ $permission ] ) ) { // we can short-circuit and stop processing reutrn true; } // is this permission currently denied to ths group? if ( isset( $permission, $this->permissions_denied[ $permission ] ) ) { // we need to toggle the denied bit, which is a single // UPDATE operation, rather than a DELETE + INSERT $this->toggle_permissions['grant']= $permission; // we also need to update the temporary variable // so that the can() method works as expected // even before calls to update() occur unset( $this->permissions_denied[ $permission ] ); } // finally, we grant this permission $this->permissions_granted[ $permission ]= $permission; } /** * Deny a permission to this group * @param int The permission ID to be denied **/ public function deny( $permission ) { // short-circuit: is this permission already denied? if ( isset( $this->permissions_denied[ $permission ] ) ) { return true; } // is this permission currently granted? if ( isset( $this->permissions_granted[ $permission] ) ) { // we need to toggle the denied bit, which is a single // UPDATE operation, rather than a DELETE + INSERT $this->toggle_permissions['deny']= $permission; // we also need to update the temporary variable // so that the can() method works as expected // even before calls to update() occur unset( $this->permissions_granted[ $permission ] ); } // finally, we deny the permission $this->permissions_denied[ $permission ] = $permission; } /** * Remove a permission from a group * @param int a permission ID **/ public function revoke( $permission ) { if ( isset( $this->permissons_granted[ $permission ] ) ) { unset( $this->permissions_granted[ $permission ] ); } if ( isset( $permission, $this->permissions_denied[ $permission ] ) ) { unset( $this->permissions_denied[ $permission] ); } $this->permissions_revoked[ $permission ]= $permission; } /** * Determine whether members of a group can do something * @param string a text description of a permission * @return mixed If a permission is denied to this group, return boolean FALSE; if a permission is granted, return boolean TRUE; if a permission is neither granted nor denied, return an empty string. **/ public function can( $permission ) { if ( isset( $this->permissions_denied[ $permission ] ) ) { return false; } if ( isset( $this->permissions_granted[ $permission ] ) ) { return true; } return ''; } /** * Fetch a group from the database by ID or name. * This is a wrapper for get_by_id() and get_by_name() * @param mixed $group A group ID or name * @return mixed UserGroup object, or boolean FALSE */ public static function get( $group ) { if ( is_int( $group ) ) { return self::get_by_id( $group ); } else { return self::get_by_name( $group ); } } /** * Select a group from the DB by its ID * @param int A group ID * @return mixed A UserGroup object, or boolean FALSE **/ public static function get_by_id( $id ) { if ( 0 == $id ) { return false; } return DB::get_row( 'SELECT * FROM {groups} WHERE id=?', array( $id ), 'UserGroup' ); } /** * Select a group from the DB by its name * @param string A group name * @return mixed A UserGroup object, or boolean FALSE **/ public static function get_by_name( $name ) { if ( '' == $name ) { return false; } return DB::get_row( 'SELECT * FROM {groups} WHERE name=?', array( $name ), 'UserGroup' ); } /** * Determine whether a group exists * @param mixed The name or ID of the group * @return bool Whether the group exists or not **/ public static function exists( $group ) { if ( is_int( $group ) ) { $query= 'id'; } else { $query= 'name'; } return DB::query("SELECT id FROM {groups} WHERE $query=?", array( $group ) ); } } ?>