CWIS Developer Documentation
UserFactory.php
Go to the documentation of this file.
1 <?PHP
2 
3 #
4 # Axis--UserFactory.php
5 # An Meta-Object for Handling User Information
6 #
7 # Copyright 2003-2012 Axis Data
8 # This code is free software that can be used or redistributed under the
9 # terms of Version 2 of the GNU General Public License, as published by the
10 # Free Software Foundation (http://www.fsf.org).
11 #
12 # Author: Edward Almasy (ealmasy@axisdata.com)
13 #
14 # Part of the AxisPHP library v1.2.4
15 # For more information see http://www.axisdata.com/AxisPHP/
16 #
17 
19 {
20 
21  # ---- PUBLIC INTERFACE --------------------------------------------------
22 
26  public function __construct()
27  {
28  # create database connection
29  $this->DB = new Database();
30 
31  # figure out user class name
32  $this->UserClassName = preg_replace(
33  '/Factory$/', '', get_called_class());
34  }
35 
48  public function CreateNewUser(
49  $UserName, $Password, $PasswordAgain, $EMail, $EMailAgain,
50  $IgnoreErrorCodes = NULL)
51  {
52  # check incoming values
53  $ErrorCodes = $this->TestNewUserValues(
54  $UserName, $Password, $PasswordAgain, $EMail, $EMailAgain);
55 
56  # discard any errors we are supposed to ignore
57  if ($IgnoreErrorCodes)
58  {
59  $ErrorCodes = array_diff($ErrorCodes, $IgnoreErrorCodes);
60  }
61 
62  # if error found in incoming values return error codes to caller
63  if (count($ErrorCodes)) { return $ErrorCodes; }
64 
65  # add user to database
66  $UserClass = $this->UserClassName;
67  $UserName = $UserClass::NormalizeUserName($UserName);
68  $this->DB->Query("INSERT INTO APUsers"
69  ." (UserName, CreationDate)"
70  ." VALUES ('".addslashes($UserName)."', NOW())");
71 
72  # create new user object
73  $UserId = $this->DB->LastInsertId();
74  $User = new User($this->DB, (int)$UserId);
75 
76  # if new user object creation failed return error code to caller
77  if ($User->Status() != U_OKAY) { return array($User->Status()); }
78 
79  # set password and e-mail address
80  $User->SetPassword($Password);
81  $User->Set("EMail", $EMail);
82 
83  # return new user object to caller
84  return $User;
85  }
86 
96  public function TestNewUserValues(
97  $UserName, $Password, $PasswordAgain, $EMail, $EMailAgain)
98  {
99  $UserClass = $this->UserClassName;
100 
101  # normalize incoming values
102  $UserName = $UserClass::NormalizeUserName($UserName);
103  $Password = $UserClass::NormalizePassword($Password);
104  $PasswordAgain = $UserClass::NormalizePassword($PasswordAgain);
105  $EMail = $UserClass::NormalizeEMailAddress($EMail);
106  $EMailAgain = $UserClass::NormalizeEMailAddress($EMailAgain);
107 
108  # start off assuming success
109  $ErrorCodes = array();
110 
111  # check that provided username is valid
112  if (strlen($UserName) == 0)
113  {
114  $ErrorCodes[] = U_EMPTYUSERNAME;
115  }
116  elseif (!$UserClass::IsValidUserName($UserName))
117  {
118  $ErrorCodes[] = U_ILLEGALUSERNAME;
119  }
120  elseif ($this->UserNameExists($UserName))
121  {
122  $ErrorCodes[] = U_DUPLICATEUSERNAME;
123  }
124 
125  # check that email is not already in use
126  if ($this->EMailAddressIsInUse($EMail))
127  {
128  $ErrorCodes[] = U_DUPLICATEEMAIL;
129  }
130 
131  # check for password problems
132  $FoundOtherPasswordError = FALSE;
133  $PasswordErrors = $UserClass::CheckPasswordForErrors(
134  $Password, $UserName, $EMail);
135 
136  # if there were problems, merge those in to our error list
137  if (count($PasswordErrors))
138  {
139  $ErrorCodes = array_merge($ErrorCodes, $PasswordErrors);
140  $FoundOtherPasswordError = TRUE;
141  }
142 
143  # check that PasswordAgain was provided
144  if (strlen($PasswordAgain) == 0)
145  {
146  $ErrorCodes[]= U_EMPTYPASSWORDAGAIN;
147  $FoundOtherPasswordError = TRUE;
148  }
149  # and that PasswordAgain matches Password
150  elseif ($Password != $PasswordAgain)
151  {
152  $ErrorCodes[] = U_PASSWORDSDONTMATCH;
153  }
154 
155  # check that provided email is valid
156  $FoundOtherEMailError = FALSE;
157  if (strlen($EMail) == 0)
158  {
159  $ErrorCodes[] = U_EMPTYEMAIL;
160  $FoundOtherEMailError = TRUE;
161  }
162  elseif (!$UserClass::IsValidLookingEMailAddress($EMail))
163  {
164  $ErrorCodes[] = U_ILLEGALEMAIL;
165  $FoundOtherEMailError = TRUE;
166  }
167 
168  if (strlen($EMailAgain) == 0)
169  {
170  $ErrorCodes[] = U_EMPTYEMAILAGAIN;
171  $FoundOtherEMailError = TRUE;
172  }
173  elseif (!$UserClass::IsValidLookingEMailAddress($EMailAgain))
174  {
175  $ErrorCodes[] = U_ILLEGALEMAILAGAIN;
176  $FoundOtherEMailError = TRUE;
177  }
178 
179  if ($FoundOtherEMailError == FALSE &&
180  $EMail != $EMailAgain)
181  {
182  $ErrorCodes[] = U_EMAILSDONTMATCH;
183  }
184 
185  return $ErrorCodes;
186  }
187 
194  public function GetUserCount($Condition = NULL)
195  {
196  return $this->DB->Query("SELECT COUNT(*) AS UserCount FROM APUsers"
197  .($Condition ? " WHERE ".$Condition : ""), "UserCount");
198  }
199 
205  public function GetMatchingUserCount()
206  {
208  }
209 
214  public function GetUserIds()
215  {
216  $this->DB->Query("SELECT UserId FROM APUsers");
217  return $this->DB->FetchColumn("UserId");
218  }
219 
226  public function GetLoggedInUsers($InactivityTimeout = 60)
227  {
228  # query IDs of logged-in users from database
229  $LoggedInCutoffTime = date("Y-m-d H:i:s",
230  time() - ($InactivityTimeout * 60));
231  $this->DB->Query("SELECT UserId FROM APUsers"
232  ." WHERE LastActiveDate > '".$LoggedInCutoffTime."'"
233  ." AND LoggedIn != '0'");
234  $UserIds = $this->DB->FetchColumn("UserId");
235 
236  # load array of logged in users
237  $ReturnValue = array();
238  foreach ($UserIds as $Id)
239  {
240  $ReturnValue[$Id] = new User(intval($Id));
241  }
242 
243  # return array of user data to caller
244  return $ReturnValue;
245  }
246 
254  public function GetRecentlyLoggedInUsers($Since = NULL, $Limit = 10)
255  {
256  # get users recently logged in during the last 24 hours if no date given
257  if ($Since === NULL)
258  {
259  $Date = date("Y-m-d H:i:s", time() - (24 * 60 * 60));
260  }
261 
262  else
263  {
264  $Date = date("Y-m-d H:i:s", strtotime($Since));
265  }
266 
267  # query for the users who were logged in since the given date
268  $this->DB->Query("SELECT UserId FROM APUsers"
269  ." WHERE LastActiveDate > '".$Date."'"
270  ." AND LoggedIn != '1'"
271  ." ORDER BY LastActiveDate DESC"
272  ." LIMIT ".intval($Limit));
273  $UserIds = $this->DB->FetchColumn("UserId");
274 
275  $ReturnValue = array();
276  foreach ($UserIds as $Id)
277  {
278  $ReturnValue[$Id] = new User(intval($Id));
279  }
280 
281  # return array of user data to caller
282  return $ReturnValue;
283  }
284 
291  public function GetUsersWithPrivileges()
292  {
293  # retrieve privileges
294  $Args = func_get_args();
295  if (is_array(reset($Args))) { $Args = reset($Args); }
296  $Privs = array();
297  foreach ($Args as $Arg)
298  {
299  if (is_array($Args))
300  {
301  $Privs = array_merge($Privs, $Args);
302  }
303  else
304  {
305  $Privs[] = $Arg;
306  }
307  }
308 
309  # start with query string that will return all users
310  $QueryString = "SELECT DISTINCT APUsers.UserId, UserName FROM APUsers"
311  .(count($Privs) ? ", APUserPrivileges" : "");
312 
313  # for each specified privilege
314  foreach ($Privs as $Index => $Priv)
315  {
316  # add condition to query string
317  $QueryString .= ($Index == 0) ? " WHERE (" : " OR";
318  $QueryString .= " APUserPrivileges.Privilege = ".$Priv;
319  }
320 
321  # close privilege condition in query string and add user ID condition
322  $QueryString.= count($Privs)
323  ? ") AND APUsers.UserId = APUserPrivileges.UserId" : "";
324 
325  # add sort by user name to query string
326  $QueryString .= " ORDER BY UserName ASC";
327 
328  # perform query
329  $this->DB->Query($QueryString);
330 
331  # copy query result into user info array
332  $Users = $this->DB->FetchColumn("UserName", "UserId");
333 
334  # return array of users to caller
335  return $Users;
336  }
337 
350  public function FindUsers($SearchString, $FieldName = "UserName",
351  $SortFieldName = "UserName", $Offset = 0, $Count = 9999999)
352  {
353  # retrieve matching user IDs
354  $UserNames = $this->FindUserNames(
355  $SearchString, $FieldName, $SortFieldName, $Offset, $Count);
356 
357  # create user objects
358  $Users = array();
359  foreach ($UserNames as $UserId => $UserName)
360  {
361  $Users[$UserId] = new User($this->DB, intval($UserId));
362  }
363 
364  # return array of user objects to caller
365  return $Users;
366  }
367 
382  public function FindUserNames($SearchString, $FieldName = "UserName",
383  $SortFieldName = "UserName", $Offset = 0, $Count = 9999999,
384  $IdExclusions = array(), $ValueExclusions = array())
385  {
386  $UserClass = $this->UserClassName;
387 
388  # make sure the provided field name is valid
389  if (!$this->DB->FieldExists("APUsers", $FieldName))
390  {
391  throw new Exception(
392  "There is no ".$FieldName." Field in the APUsers table");
393  }
394 
395  # construct a database query
396  $QueryString = "SELECT UserId, UserName FROM APUsers WHERE "
397  .$FieldName." = '".addslashes($SearchString)."'";
398 
399  # add each ID exclusion
400  foreach ($IdExclusions as $IdExclusion)
401  {
402  $QueryString .= " AND ".$this->ItemIdFieldName." != '"
403  .addslashes($IdExclusion)."' ";
404  }
405 
406  # add each value exclusion
407  foreach ($ValueExclusions as $ValueExclusion)
408  {
409  $QueryString .= " AND ".$this->ItemNameFieldName." != '"
410  .addslashes($ValueExclusion)."' ";
411  }
412 
413  $QueryString .= " ORDER BY ".$SortFieldName
414  ." LIMIT ".$Offset.", ".$Count;
415 
416  # retrieve matching user IDs
417  $this->DB->Query($QueryString);
418  $UserNames = $this->DB->FetchColumn("UserName", "UserId");
419 
420  # return names/IDs to caller
421  return $UserNames;
422  }
423 
439  public function GetMatchingUsers($SearchString, $FieldName = NULL,
440  $SortFieldName = "UserName",
441  $ResultsStartAt = 0, $ReturnNumber = NULL)
442  {
443  # start with empty array (to prevent array errors)
444  $ReturnValue = array();
445 
446  # if empty search string supplied, return nothing
447  $TrimmedSearchString = trim($SearchString);
448  if (empty($TrimmedSearchString))
449  {
450  return $ReturnValue;
451  }
452 
453  # make sure ordering is done by user name if not specified
454  $SortFieldName = empty($SortFieldName) ? "UserName" : $SortFieldName;
455 
456  # begin constructing the query
457  $Query = "SELECT * FROM APUsers";
458  $QueryOrderBy = " ORDER BY $SortFieldName";
459  $QueryLimit = empty($ReturnNumber) ? "" : " LIMIT $ResultsStartAt, $ReturnNumber";
460 
461  # the Criteria Query will be used to get the total number of results without the
462  # limit clause
463  $CriteriaQuery = $Query;
464 
465  # if specific field comparison requested
466  if (!empty($FieldName))
467  {
468  # append queries with criteria
469  $Query .= " WHERE ".$FieldName." REGEXP '".addslashes($SearchString)."'";
470  $CriteriaQuery = $Query;
471  }
472 
473  # optimize for returning all users
474  else if ($SearchString == ".*.")
475  {
476  # set field name to username - this would be the first field
477  # returned by a field to field search using the above RegExp
478  $FieldName = "UserName";
479  }
480 
481  # add order by and limit to query for optimizing
482  $Query .= $QueryOrderBy.$QueryLimit;
483 
484  # execute query...
485  $this->DB->Query($Query);
486 
487  # ...and process query return
488  while ($Record = $this->DB->FetchRow())
489  {
490  # if specific field or all users requested
491  if (!empty($FieldName))
492  {
493  # add user to return array
494  $ReturnValue[$Record["UserId"]] = $Record;
495 
496  # add matching search field to return array
497  $ReturnValue[$Record["UserId"]]["APMatchingField"] = $FieldName;
498  }
499 
500  else
501  {
502  # for each user data field
503  foreach ($Record as $FName => $FValue)
504  {
505  # if search string appears in data field
506  if (strpos($Record[$FName], $SearchString) !== FALSE)
507  {
508  # add user to return array
509  $ReturnValue[$Record["UserId"]] = $Record;
510 
511  # add matching search field to return array
512  $ReturnValue[$Record["UserId"]]["APMatchingField"] = $FName;
513  }
514  }
515  }
516  }
517 
518  # add matching user count
519  $this->DB->Query($CriteriaQuery);
520  $this->MatchingUserCount = $this->DB->NumRowsSelected();
521 
522  # return array of matching users to caller
523  return $ReturnValue;
524  }
525 
531  public function UserExists($UserId)
532  {
533  if (!is_numeric($UserId))
534  {
535  return FALSE;
536  }
537  $UserCount = $this->DB->Query("SELECT COUNT(*) AS UserCount"
538  ." FROM APUsers WHERE UserId = ".intval($UserId), "UserCount");
539  return ($UserCount > 0) ? TRUE : FALSE;
540  }
541 
547  public function UserNameExists($UserName)
548  {
549  # normalize user name
550  $UserClass = $this->UserClassName;
551  $UserName = $UserClass::NormalizeUserName($UserName);
552 
553  # check whether user name is already in use
554  $NameCount = $this->DB->Query(
555  "SELECT COUNT(*) AS NameCount FROM APUsers"
556  ." WHERE UserName = '".addslashes($UserName)."'",
557  "NameCount");
558 
559  # report to caller whether name exists
560  return ($NameCount > 0) ? TRUE : FALSE;
561  }
562 
568  public function EMailAddressIsInUse($Address)
569  {
570  # normalize address
571  $UserClass = $this->UserClassName;
572  $UserName = $UserClass::NormalizeEMailAddress($Address);
573 
574  # check whether address is already in use
575  $AddressCount = $this->DB->Query(
576  "SELECT COUNT(*) AS AddressCount FROM APUsers"
577  ." WHERE EMail = '".addslashes($Address)."'",
578  "AddressCount");
579 
580  # report to caller whether address is in use
581  return ($AddressCount > 0) ? TRUE : FALSE;
582  }
583 
589  public function GetNewestUsers($Limit = 5)
590  {
591  $UserClass = $this->UserClassName;
592 
593  # assume no users will be found
594  $Users = array();
595 
596  # fetch the newest users
597  $this->DB->Query("SELECT *"
598  ." FROM APUsers"
599  ." ORDER BY CreationDate DESC"
600  ." LIMIT ".intval($Limit));
601  $UserIds = $this->DB->FetchColumn("UserId");
602 
603  # for each user id found
604  foreach ($UserIds as $UserId)
605  {
606  $Users[$UserId] = new $UserClass($UserId);
607  }
608 
609  # return the newest users
610  return $Users;
611  }
612 
613  # ---- PRIVATE INTERFACE -------------------------------------------------
614 
615  protected $DB;
616  protected $SortFieldName;
618  private $UserClassName;
619 }
const U_EMPTYUSERNAME
Definition: User.php:26
const U_ILLEGALEMAILAGAIN
Definition: User.php:32
EMailAddressIsInUse($Address)
Check whether e-mail address currently has account associated with it.
SQL database abstraction object with smart query caching.
Definition: Database.php:22
CreateNewUser($UserName, $Password, $PasswordAgain, $EMail, $EMailAgain, $IgnoreErrorCodes=NULL)
Create new user.
Definition: UserFactory.php:48
const U_EMAILSDONTMATCH
Definition: User.php:23
UserNameExists($UserName)
Check whether user name currently exists.
GetUserIds()
Get IDs for all users.
GetRecentlyLoggedInUsers($Since=NULL, $Limit=10)
Get users recently logged in.
const U_ILLEGALEMAIL
Definition: User.php:31
Definition: User.php:48
const U_EMPTYPASSWORDAGAIN
Definition: User.php:30
GetUsersWithPrivileges()
Return array of user names who have the specified privileges.
GetNewestUsers($Limit=5)
Get the users sorted by when they signed up, starting with those who signed up most recently...
GetMatchingUsers($SearchString, $FieldName=NULL, $SortFieldName="UserName", $ResultsStartAt=0, $ReturnNumber=NULL)
Return array of users who have values matching search string (in specific field if requested)...
const U_EMPTYEMAIL
Definition: User.php:33
FindUsers($SearchString, $FieldName="UserName", $SortFieldName="UserName", $Offset=0, $Count=9999999)
Get users who have values matching specified string in specified field.
const U_DUPLICATEUSERNAME
Definition: User.php:24
const U_OKAY
Definition: User.php:18
const U_EMPTYEMAILAGAIN
Definition: User.php:34
TestNewUserValues($UserName, $Password, $PasswordAgain, $EMail, $EMailAgain)
Test new user values (usually used before creating new user).
Definition: UserFactory.php:96
const U_DUPLICATEEMAIL
Definition: User.php:38
UserExists($UserId)
Check whether user currently exists with specified ID.
GetUserCount($Condition=NULL)
Return number of users in the system.
GetLoggedInUsers($InactivityTimeout=60)
Get users who are currently logged in (i.e.
const U_ILLEGALUSERNAME
Definition: User.php:25
__construct()
Object constructor.
Definition: UserFactory.php:26
GetMatchingUserCount()
Get total number of user that matched last GetMatchingUsers() call.
FindUserNames($SearchString, $FieldName="UserName", $SortFieldName="UserName", $Offset=0, $Count=9999999, $IdExclusions=array(), $ValueExclusions=array())
Get users who have values matching specified string in specified field.
const U_PASSWORDSDONTMATCH
Definition: User.php:22