Class UserManager

Description

User management

  • todo: Perhaps this class should be merged with the GroupManager class because there is a lot of overlap. Mmmmm.... maybe in a future refactoring operation.

Located in /program/lib/usermanager.class.php (line 40)


	
			
Variable Summary
 object|null $output
 array $users
Method Summary
 UserManager UserManager (object &$output)
 array|bool areas_expand_collapse (array|bool $areas_open, int|null $area_id)
 array a_params ([string|null $task = NULL], [int|null $user_id = NULL], [int|null $module_id = NULL])
 bool|int calc_acl_id (int $user_id)
 bool delete_user_records (int $user_id)
 array get_dialogdef_add_usergroup (int $user_id)
 bool|array get_dialogdef_edit_user (int $user_id)
 string get_fname (array $item)
 string get_icon_delete (int $user_id)
 string get_icon_edit (int $user_id)
 string get_icon_groupdelete (int $user_id,  $group_id)
 int get_num_user_records (int $group_id)
 array get_user_names (int $user_id)
 bool|array get_user_record (int $user_id, [bool $forced = FALSE])
 array|bool get_user_records (int $group_id, int $limit, int $offset)
 bool has_job_permission (int $user_id, int $job)
 void show_breadcrumbs_user (int $user_id)
 void show_menu_overview (int|null $group_id)
 void show_menu_user (int $user_id, [string $current_task = NULL], [int $current_module_id = NULL])
 void users_overview ()
 void user_add ()
 void user_admin ()
 void user_delete ()
 void user_edit ([int $user_id = NULL])
 void user_groupadd ([ $user_id = NULL])
 void user_groups ()
 void user_groupsave ()
 void user_intranet ()
 void user_save ()
 data user_savenew ()
 void user_save_basic (int $user_id)
Variables
object|null $output = NULL (line 42)
  • var: collects the html output
bool $show_parent_menu = FALSE (line 45)
  • var: if TRUE the calling routing is allowed to use the menu area (e.g. show account mgr menu)
array $users = array() (line 48)
  • var: used to cache user records keyed by user_id
Methods
Constructor UserManager (line 57)

construct a UserManager object

This initialises the UserManager and also dispatches the task to do. This also loads the loginlib: we need that in order to manipulate the user password.

UserManager UserManager (object &$output)
  • object &$output: collects the html output
areas_expand_collapse (line 2227)

manipulate the current state if indicator(s) for 'open' and 'closed' areas

this manipulates the current state of 'open' and 'closed' areas in $areas_open. If $area_id is NULL, we don't have to do anything but simply return the current state. If $area_id is 0 (zero), we need to toggle all areas at once (area_id = 0 implies the site level toggle) If $area_id is an integer, it is assumed to be a valid area_id and that area should be toggled.

  • return: new state of indicator(s) for 'open' and 'closed' areas
array|bool areas_expand_collapse (array|bool $areas_open, int|null $area_id)
  • array|bool $areas_open: current state of indicator(s) for 'open' and 'closed' areas
  • int|null $area_id: the area to expand/collapse or NULL if nothing needs to be done
a_params (line 1700)

shorthand for the anchor parameters that lead to the user manager

  • return: ready-to-use array with parameters for constructing a-tag
array a_params ([string|null $task = NULL], [int|null $user_id = NULL], [int|null $module_id = NULL])
  • string|null $task: the next task to do or NULL if none
  • int|null $user_id: the user of interest or NULL if none
  • int|null $module_id: the module of interest or NULL if none
calc_acl_id (line 2172)

determine the acl_id for user user_id

  • return: acl_id on success, FALSE on error
bool|int calc_acl_id (int $user_id)
  • int $user_id: identifies the user record of interest
delete_user_records (line 1401)

remove all records relating to a single acl_id from various acl-tables

this bluntly removes all records from the various user-related tables for user $user_id. Whenever there's an error deleting records, the routine bails out immediately and returns FALSE. If all goes well, TRUE is returned. Any errors are logged, success is logged to DEBUG-log.

Note that the order of deletion is important: we must first get rid of the foreign key constraints.

  • return: TRUE on success, FALSE on failure
bool delete_user_records (int $user_id)
  • int $user_id: the key to the user account to delete
get_dialogdef_add_user (line 1882)

construct the add userdialog

  • return: contains the dialog definition
array get_dialogdef_add_user ()
get_dialogdef_add_usergroup (line 1314)

construct a dialogdef for selecting a group/capacity

  • return: ready-to-use dialog definition
array get_dialogdef_add_usergroup (int $user_id)
  • int $user_id: limit the options to groups this user is NOT already a member of
get_dialogdef_confirm_delete (line 2119)

construct the edit user dialog

  • return: contains dialogdef
array get_dialogdef_confirm_delete ()
get_dialogdef_edit_user (line 1968)

construct the edit user dialog

  • return: FALSE on error or array with dialog definition and existing data from database
  • uses: $LANGUAGE
bool|array get_dialogdef_edit_user (int $user_id)
  • int $user_id: indicates which user to edit
get_fname (line 2185)

shorthand for the first readable name in a dialogdef item

  • return: either the label or the name of the item, without tildes
string get_fname (array $item)
  • array $item: contains definition of a single field in a dialog
get_icon_delete (line 1814)

construct a clickable icon to delete this user

  • return: ready-to-use A-tag
  • uses: $WAS_SCRIPT_NAME
  • uses: $CFG
string get_icon_delete (int $user_id)
  • int $user_id: the user to delete
get_icon_edit (line 1837)

construct a clickable icon to edit the properties of this user

  • return: ready-to-use A-tag
  • uses: $WAS_SCRIPT_NAME
  • uses: $CFG
string get_icon_edit (int $user_id)
  • int $user_id: the user to edit
get_icon_groupdelete (line 1861)

construct a clickable icon to delete a membership from this user

  • return: ready-to-use A-tag
  • uses: $WAS_SCRIPT_NAME
  • uses: $CFG
string get_icon_groupdelete (int $user_id,  $group_id)
  • int $user_id: the group to delete
  • $group_id
get_num_user_records (line 1777)

calculate the total number of users in a specific group

this calculates the total number of users in group $group_id. If $group_id equates to GROUP_SELECT_ALL_USERS, the grand total is returned, if it equates to GROUP_SELECT_NO_GROUP the number of users without a group is calculated.

  • return: the number of users in the specified group (could be 0)
  • uses: $DB
int get_num_user_records (int $group_id)
  • int $group_id: which group needs to be counted
get_options_available_groups_capacities (line 1361)

construct a list of groups still available for this user

this constructs an array with available groups/capacities for the user $user_id If the user is already a member of all available groups or there are no groups at all, the list consists of a single option 'No groups available'.

The values in this list are constructed from the primary key values of the underlying groups_capacities table. These two numbers (group_id and capacity_code) are separated with a colon ':' to make it easier to parse once we are to save the values (in the table users_groups_capacities).

The SQL-statement looks quite complex. What it does is using the table groups_capacities as a starting point for _all_ valid (ie capacity_id != CAPACITY_NONE) combinations of group and capacity. By left-joining the table users_groups_capacities with a very specific ON-clause, and leaving out the column capacity_code, the resulting list consists of all combinations of group and capacity buy without any entries that have a group of which the user is already a member, no matter what capacity. In other words: if a user is already a member of a group with capacity A, this user cannot be member of the same group with capacity B. Finally, the table groups is used to retrieve the group information such as the groupname and the active-flag.

The resulting list is ordered by groupname and subsequently by the sort_order of the capacity_code. However, inactive groups are sorted after the active groups so they appear near the bottom of the list.

  • return: with available groups/capacities ready-to-use in a F_LISTBOX
array get_options_available_groups_capacities (int $user_id)
  • int $user_id: the user to which this list of available groups applies
get_user_names (line 2138)

shortcut to retrieve the username and full name of the selected user

  • return: with ready-to-use information
array get_user_names (int $user_id)
  • int $user_id: identifies the user of interest
get_user_record (line 2197)

retrieve a single user's record possibly from the cache

  • return: FALSE if there were errors, the user record otherwise
bool|array get_user_record (int $user_id, [bool $forced = FALSE])
  • int $user_id: identifies the user record
  • bool $forced: if TRUE unconditionally fetch the record from the database
get_user_records (line 1732)

retrieve (a selection of) all user records from the database

this retrieves a subset of all existing user accounts from the database. The selection depends on the value of $group_id:

  • $group_id == GROUP_SELECT_ALL_USERS (-1): all users ordered by active, username
  • $group_id == GROUP_SELECT_NO_GROUP (0): all users without a group, ordered by active, username
  • otherwise: users in group $group_id, ordered by active, username
Note that in the first two cases there is no capacity, in the third case every user has capacity relating to the specified group.

  • return: FALSE on error or else an array with data of selected users
array|bool get_user_records (int $group_id, int $limit, int $offset)
  • int $group_id: selection for users
  • int $limit: maximum number of records to retrieve
  • int $offset: number of records to skip in result set
has_job_permission (line 2156)

determine whether a user has permissions for a particular job

this determines whether this user has permissions to access the specified job, e.g. do they have access to the page manager. If so, we can display the menu option, otherwise we can suppress it and keep the menu clean(er).

  • return: TRUE if the group/capacity has the permission, FALSE otherwise
bool has_job_permission (int $user_id, int $job)
  • int $user_id: group to check
  • int $job: job a bitmask indicating a particular job
show_breadcrumbs_adduser (line 1683)

display breadcrumb trail that leads to the add new user dialog

void show_breadcrumbs_adduser ()
show_breadcrumbs_overview (line 1639)

display breadcrumb trail that leads to users overview screen

void show_breadcrumbs_overview ()
show_breadcrumbs_user (line 1666)

display breadcrumb trail that leads to the edit user dialog

void show_breadcrumbs_user (int $user_id)
  • int $user_id: the user of interest
show_menu_overview (line 1559)

display a menu showing groups of users (if any) + corresponding breadcrumb trail

this constructs a list of links allowing for a quick selection of a subset of users This looks a little like this:

All users (66)
No group (5)
faculty (14)
grade12 (7)
...
webmasters (2)

The indication of the current selection in the menu is based on $group_id. Most of the time this is a genuine group_id. However, 'All users' and 'No group' are special cases:

  • The value GROUP_SELECT_ALL_USERS (-1) cannot be a genuine group_id because these are always > 0.
  • The value GROUP_SELECT_NO_GROUP (0) cannot be a genuine group_id because these are always > 0.

  • return: output stored via $this->output.
  • uses: $DB;
  • uses: #AS_SCRIPT_NAME
void show_menu_overview (int|null $group_id)
  • int|null $group_id: identifies the current selection
show_menu_user (line 1454)

show the user menu with current option highlighted

this constructs the user menu. Only the relevant options are displayed (eg. if the user is not an admin, no pagemanager option is displayed).

  • return: output generated in $this->output
void show_menu_user (int $user_id, [string $current_task = NULL], [int $current_module_id = NULL])
  • int $user_id: identifies the user
  • string $current_task: the task to show highlighted
  • int $current_module_id: the current module to show highlighted
show_parent_menu (line 98)
void show_parent_menu ()
users_overview (line 148)

display a list of existing users and an option to add a user

This constructs the heart of the user manager: a link to add a user, followed by a list of links for deleting an modifying selected (see below) users. The list of users is ordered as follows. First the active users are displayed, an after that the inactive users are displayed. The sort order is based on the short name of the user.

Note that a selection is made of all user accounts, based on a choice the user makes from the menu (see show_menu_overview()). This list to show is selected as follows:

  • if the parameter 'group' is NOT set in $_GET[] and this is the 1st time, all users are listed (equivalent with GROUP_SELECT_ALL_USERS). If we are returning, the $_SESSION may contain another default group selectiond
  • if the parameter 'group' is set to GROUP_SELECT_ALL_USERS (-1), all users are listed
  • if the parameter 'group' is set to GROUP_SELECT_NO_GROUP (zero), all users without a group are listed
  • if the parameter 'group' has another value, the users of that group are listed
The list of existing users is paginated, ie. if there are more than a screenfull, an additional paginator is displayed at the end of the list. The screen always starts with an add a user link though.

Note that the list of existing users shows the full name and the username in parenthese. If a 'real' group is selected (ie. not the collection of users without a group or all users), the capacity of that user in that group is also displayed.

Example: Amelia Cackle, a 'Principal' in the 'faculty' group, is displayed like this in the faculty group: Amelia Cackle (acackl) (Principal)

  • return: output is returned in $this->output
void users_overview ()
user_add (line 277)

present 'add user' dialog where the user can enter minimal properties for a new user

this displays a dialog where the user can enter the minimal necessary properties of a new user. These properties are:

  • name (e.g. 'hparkh')
  • full name (e.g. 'Helen Parkhurst')
  • a password
  • an e-mail address
  • the active flag
Other properties will be set to default values and can be edited lateron by editing the user account.

The new user is saved via performing the task TASK_USER_SAVE_NEW

  • return: results are returned as output in $this->output
  • uses: $WAS_SCRIPT_NAME
void user_add ()
user_admin (line 1197)

show a dialog for modifying admin permissions for a user

  • return: results are returned as output in $this->output
  • uses: $WAS_SCRIPT_NAME
  • uses: $CFG
void user_admin ()
user_delete (line 771)

delete a user after confirmation

after some basic tests this either presents a confirmation dialog to the user OR deletes a user with associated acls and other records.

Note that this routine could have been split into two routines, with the first one displaying the confirmation dialog and the second one 'saving the changes'. However, I think it is counter-intuitive to perform a deletion of data under the name of 'saving'. So, I decided to use the same routine for both displaying the dialog and acting on the dialog.

Note that the (user)files should be removed before the account can be removed, see userdir_is_empty(). It is up to the user or the admin to remove those files.

A special test is performed to prevent users from killing their own account (which would immediately kick them out of admin.php never to be seen again).

  • return: results are returned as output in $this->output
  • todo: since multiple tables are involved, shouldn't we use transaction/rollback/commit? Q: How well is MySQL suited for transactions? A: Mmmmm.... Which version? Which storage engine?
void user_delete ()
user_edit (line 479)

present an 'edit user' dialog filled with existing data

this prepares the basic user properties dialog, based on the parameter $user_id. If that is not specified, we read the $user_id from $_GET. (Currently only user_savenew() and user_save_basic() call us with $user_id set).

void user_edit ([int $user_id = NULL])
  • int $user_id: indicates which user to edit
user_groupadd (line 972)

present 'add membership' dialog

this displays a simple dialog where the user can add a membership to a user account, one at a time. Basically we show a picklist with all available group/capacity-combinations. Here "available" means:

  • only groups of which the user is currently NOT a member
  • only non-0 group/capacity-combinations that occur in the groups_capacities_table (capacity 0 implies: no capacity)
An additional feature is that the user can become member of inactive groups. However, these groups are sorted at the end of the picklist.

$param int $user_id identifies the user to edit

  • return: data written to output object
void user_groupadd ([ $user_id = NULL])
  • $user_id
user_groupdelete (line 1109)

end the group membership for the selected user

  • uses: $DB
void user_groupdelete ()
user_groups (line 895)

present an overview of group memberships for the specified user

this constructs a link to add a membership to the user account and a list of existing memberships, if any, including a delete button per membership.

The SQL-query retrieves the list of existing memberships from the database, ordered by the short groupname. The data is validated by joining to the table groups_capacities. If for some reason there exists an invalid combination of group_id and capacity_code in users_groups_capacities table, it will not show up in the list here.

Note that it is currently not possible to change a users' group membership, i.e. you cannot promote a user from 'Member' to 'Chair' for a group: you have to delete the group membership first, and subsequently add it again with the correct capacity.

  • return: results are returned as output in $this->output
void user_groups ()
user_groupsave (line 1010)

save the new group/capacity for the selected user

this adds a record to the users_groups_capacities table, indicating the group membership and the corresponding capacity for the user.

  • return: output written to browser via $this->output
  • uses: $WAS_SCRIPT_NAME
void user_groupsave ()
user_intranet (line 1155)

show a dialog for modifying intranet permissions for a user

  • return: results are returned as output in $this->output
  • uses: $WAS_SCRIPT_NAME
  • uses: $CFG
void user_intranet ()
user_pagemanager (line 1238)

show a dialog for modifying page manager permissions for a user

  • return: results are returned as output in $this->output
  • uses: $WAS_SCRIPT_NAME
  • uses: $CFG
void user_pagemanager ()
user_save (line 508)

save edited user data to the database

void user_save ()
user_savenew (line 301)

save a new user to the database

this saves a new user to the database. This involves at least two tables: a record in the users table with basic information and also a record with access control in the acls table.

  • return: saved to the database, directory created, output created via users_overview()
  • todo: shouldn't we end with the edit-user dialog rather than the users overview? that might make more sense...
  • todo: maybe we should find a more elegant way to check a field for uniqueness
  • uses: $WAS_SCRIPT_NAME
  • uses: $CFG
data user_savenew ()
user_save_basic (line 635)

save basic properties of user account

  • uses: $WAS_SCRIPT_NAME
void user_save_basic (int $user_id)
  • int $user_id: the account to save (pkey in users table)

Documentation generated on Tue, 28 Jun 2016 19:12:33 +0200 by phpDocumentor 1.4.0