CWIS Developer Documentation
Axis--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 
18 class UserFactory {
19 
20  # ---- PUBLIC INTERFACE --------------------------------------------------
21 
25  function UserFactory()
26  {
27  # create database connection
28  $this->DB = new Database();
29  }
30 
43  function CreateNewUser(
44  $UserName, $Password, $PasswordAgain, $EMail, $EMailAgain,
45  $IgnoreErrorCodes = NULL)
46  {
47  # check incoming values
48  $ErrorCodes = $this->TestNewUserValues(
49  $UserName, $Password, $PasswordAgain, $EMail, $EMailAgain);
50 
51  # discard any errors we are supposed to ignore
52  if ($IgnoreErrorCodes)
53  {
54  $ErrorCodes = array_diff($ErrorCodes, $IgnoreErrorCodes);
55  }
56 
57  # if error found in incoming values return error codes to caller
58  if (count($ErrorCodes)) { return $ErrorCodes; }
59 
60  # add user to database
61  $UserName = User::NormalizeUserName($UserName);
62  $this->DB->Query("INSERT INTO APUsers"
63  ." (UserName, CreationDate)"
64  ." VALUES ('".addslashes($UserName)."', NOW())");
65 
66  # create new user object
67  $UserId = $this->DB->LastInsertId();
68  $User = new User($this->DB, (int)$UserId);
69 
70  # if new user object creation failed return error code to caller
71  if ($User->Status() != U_OKAY) { return array($User->Status()); }
72 
73  # set password and e-mail address
74  $User->SetPassword($Password);
75  $User->Set("EMail", $EMail);
76 
77  # return new user object to caller
78  return $User;
79  }
80 
81  # test new user creation values (returns array of error codes)
83  $UserName, $Password, $PasswordAgain, $EMail, $EMailAgain)
84  {
85  $ErrorCodes = array();
86  if (strlen(User::NormalizeUserName($UserName)) == 0)
87  { $ErrorCodes[] = U_EMPTYUSERNAME; }
88  elseif (!User::IsValidUserName($UserName))
89  { $ErrorCodes[] = U_ILLEGALUSERNAME; }
90  elseif ($this->UserNameExists($UserName))
91  { $ErrorCodes[] = U_DUPLICATEUSERNAME; }
92 
93  if ($this->EMailAddressIsInUse($EMail))
94  { $ErrorCodes[] = U_DUPLICATEEMAIL; }
95 
96  $FoundOtherPasswordError = FALSE;
97  if (strlen(User::NormalizePassword($Password)) == 0)
98  {
99  $ErrorCodes[] = U_EMPTYPASSWORD;
100  $FoundOtherPasswordError = TRUE;
101  }
102  elseif (!User::IsValidPassword($Password))
103  {
104  $ErrorCodes[] = U_ILLEGALPASSWORD;
105  $FoundOtherPasswordError = TRUE;
106  }
107 
108  if (strlen(User::NormalizePassword($PasswordAgain)) == 0)
109  {
110  $ErrorCodes[] = U_EMPTYPASSWORDAGAIN;
111  $FoundOtherPasswordError = TRUE;
112  }
113  elseif (!User::IsValidPassword($PasswordAgain))
114  {
115  $ErrorCodes[] = U_ILLEGALPASSWORDAGAIN;
116  $FoundOtherPasswordError = TRUE;
117  }
118 
119  if ($FoundOtherPasswordError == FALSE)
120  {
121  if (User::NormalizePassword($Password)
122  != User::NormalizePassword($PasswordAgain))
123  {
124  $ErrorCodes[] = U_PASSWORDSDONTMATCH;
125  }
126  }
127 
128  $FoundOtherEMailError = FALSE;
129  if (strlen(User::NormalizeEMailAddress($EMail)) == 0)
130  {
131  $ErrorCodes[] = U_EMPTYEMAIL;
132  $FoundOtherEMailError = TRUE;
133  }
134  elseif (!User::IsValidLookingEMailAddress($EMail))
135  {
136  $ErrorCodes[] = U_ILLEGALEMAIL;
137  $FoundOtherEMailError = TRUE;
138  }
139 
140  if (strlen(User::NormalizeEMailAddress($EMailAgain)) == 0)
141  {
142  $ErrorCodes[] = U_EMPTYEMAILAGAIN;
143  $FoundOtherEMailError = TRUE;
144  }
145  elseif (!User::IsValidLookingEMailAddress($EMailAgain))
146  {
147  $ErrorCodes[] = U_ILLEGALEMAILAGAIN;
148  $FoundOtherEMailError = TRUE;
149  }
150 
151  if ($FoundOtherEMailError == FALSE)
152  {
153  if (User::NormalizeEMailAddress($EMail)
154  != User::NormalizeEMailAddress($EMailAgain))
155  {
156  $ErrorCodes[] = U_EMAILSDONTMATCH;
157  }
158  }
159 
160  return $ErrorCodes;
161  }
162 
168  function GetUserCount($Condition = NULL)
169  {
170  return $this->DB->Query("SELECT COUNT(*) AS UserCount FROM APUsers"
171  .($Condition ? " WHERE ".$Condition : ""), "UserCount");
172  }
173 
174  # return total number of user that matched last GetMatchingUsers call
175  # before the return size was limited
177  {
179  }
180 
187  function GetLoggedInUsers($InactivityTimeout = 60)
188  {
189  # query IDs of logged-in users from database
190  $LoggedInCutoffTime = date("Y-m-d H:i:s",
191  time() - ($InactivityTimeout * 60));
192  $this->DB->Query("SELECT UserId FROM APUsers"
193  ." WHERE LastActiveDate > '".$LoggedInCutoffTime."'"
194  ." AND LoggedIn != '0'");
195  $UserIds = $this->DB->FetchColumn("UserId");
196 
197  # load array of logged in users
198  $ReturnValue = array();
199  foreach ($UserIds as $Id)
200  {
201  $ReturnValue[$Id] = new User(intval($Id));
202  }
203 
204  # return array of user data to caller
205  return $ReturnValue;
206  }
207 
208  # return array of users recently logged in. returns 10 users by default
209  function GetRecentlyLoggedInUsers($Since = NULL, $Limit = 10)
210  {
211  # get users recently logged in during the last 24 hours if no date given
212  if ($Since === NULL)
213  {
214  $Date = date("Y-m-d H:i:s", time() - (24 * 60 * 60));
215  }
216 
217  else
218  {
219  $Date = date("Y-m-d H:i:s", strtotime($Since));
220  }
221 
222  # query for the users who were logged in since the given date
223  $this->DB->Query("SELECT UserId FROM APUsers"
224  ." WHERE LastActiveDate > '".$Date."'"
225  ." AND LoggedIn != '1'"
226  ." ORDER BY LastActiveDate DESC"
227  ." LIMIT ".intval($Limit));
228  $UserIds = $this->DB->FetchColumn("UserId");
229 
230  $ReturnValue = array();
231  foreach ($UserIds as $Id)
232  {
233  $ReturnValue[$Id] = new User(intval($Id));
234  }
235 
236  # return array of user data to caller
237  return $ReturnValue;
238  }
239 
248  {
249  # retrieve privileges
250  $Args = func_get_args();
251  if (is_array(reset($Args))) { $Args = reset($Args); }
252  $Privs = array();
253  foreach ($Args as $Arg)
254  {
255  if (is_array($Args))
256  {
257  $Privs = array_merge($Privs, $Args);
258  }
259  else
260  {
261  $Privs[] = $Arg;
262  }
263  }
264 
265  # start with query string that will return all users
266  $QueryString = "SELECT DISTINCT APUsers.UserId, UserName FROM APUsers"
267  .(count($Privs) ? ", APUserPrivileges" : "");
268 
269  # for each specified privilege
270  foreach ($Privs as $Index => $Priv)
271  {
272  # add condition to query string
273  $QueryString .= ($Index == 0) ? " WHERE (" : " OR";
274  $QueryString .= " APUserPrivileges.Privilege = ".$Priv;
275  }
276 
277  # close privilege condition in query string and add user ID condition
278  $QueryString.= count($Privs)
279  ? ") AND APUsers.UserId = APUserPrivileges.UserId" : "";
280 
281  # add sort by user name to query string
282  $QueryString .= " ORDER BY UserName ASC";
283 
284  # perform query
285  $this->DB->Query($QueryString);
286 
287  # copy query result into user info array
288  $Users = $this->DB->FetchColumn("UserName", "UserId");
289 
290  # return array of users to caller
291  return $Users;
292  }
293 
294  # return array of user objects who have values matching search string
295  # (array indexes are user IDs)
296  function FindUsers($SearchString, $FieldName = "UserName",
297  $SortFieldName = "UserName", $Offset = 0, $Count = 9999999)
298  {
299  # retrieve matching user IDs
300  $UserNames = $this->FindUserNames(
301  $SearchString, $FieldName, $SortFieldName, $Offset, $Count);
302 
303  # create user objects
304  $Users = array();
305  foreach ($UserNames as $UserId => $UserName)
306  {
307  $Users[$UserId] = new User($this->DB, intval($UserId));
308  }
309 
310  # return array of user objects to caller
311  return $Users;
312  }
313 
314  # return array of user names/IDs who have values matching search string
315  # (array indexes are user IDs, array values are user names)
316  function FindUserNames($SearchString, $FieldName = "UserName",
317  $SortFieldName = "UserName", $Offset = 0, $Count = 9999999,
318  $IdExclusions = array(), $ValueExclusions = array())
319  {
320  # Construct a database query:
321  $QueryString = "SELECT UserId, UserName FROM APUsers WHERE";
322 
323  # If the search string is a valid username which is shorter than the
324  # minimum word length indexed by the FTS, just do a normal
325  # equality test instead of using the index.
326  # Otherwise, FTS away.
327  $MinWordLen = $this->DB->Query(
328  "SHOW VARIABLES WHERE variable_name='ft_min_word_len'", "Value");
329  if (User::IsValidUserName($SearchString) &&
330  strlen($SearchString) < $MinWordLen )
331  {
332  $QueryString .= " UserName='".addslashes($SearchString)."'";
333  }
334  else
335  {
336  # massage search string to use AND logic
337  $Words = preg_split("/[\s]+/", trim($SearchString));
338  $NewSearchString = "";
339  $InQuotedString = FALSE;
340  foreach ($Words as $Word)
341  {
342  if ($InQuotedString == FALSE) { $NewSearchString .= "+"; }
343  if (preg_match("/^\"/", $Word)) { $InQuotedString = TRUE; }
344  if (preg_match("/\"$/", $Word)) { $InQuotedString = FALSE; }
345  $NewSearchString .= $Word." ";
346  }
347  $QueryString .= " MATCH (".$FieldName.")"
348  ." AGAINST ('".addslashes(trim($NewSearchString))."'"
349  ." IN BOOLEAN MODE)";
350  }
351 
352  # add each ID exclusion
353  foreach ($IdExclusions as $IdExclusion)
354  {
355  $QueryString .= " AND ".$this->ItemIdFieldName." != '"
356  .addslashes($IdExclusion)."' ";
357  }
358 
359  # add each value exclusion
360  foreach ($ValueExclusions as $ValueExclusion)
361  {
362  $QueryString .= " AND ".$this->ItemNameFieldName." != '"
363  .addslashes($ValueExclusion)."' ";
364  }
365 
366  $QueryString .= " ORDER BY ".$SortFieldName
367  ." LIMIT ".$Offset.", ".$Count;
368 
369  # retrieve matching user IDs
370  $this->DB->Query($QueryString);
371  $UserNames = $this->DB->FetchColumn("UserName", "UserId");
372 
373  # return names/IDs to caller
374  return $UserNames;
375  }
376 
377  # return array of users who have values matching search string (in specific field if requested)
378  # (search string respects POSIX-compatible regular expressions)
379  # optimization: $SearchString = ".*." and $FieldName = NULL will return all
380  # users ordered by $SortFieldName
381  function GetMatchingUsers($SearchString, $FieldName = NULL,
382  $SortFieldName = "UserName",
383  $ResultsStartAt = 0, $ReturnNumber = NULL)
384  {
385  # start with empty array (to prevent array errors)
386  $ReturnValue = array();
387 
388  # if empty search string supplied, return nothing
389  $TrimmedSearchString = trim($SearchString);
390  if (empty($TrimmedSearchString))
391  {
392  return $ReturnValue;
393  }
394 
395  # make sure ordering is done by user name if not specified
396  $SortFieldName = empty($SortFieldName) ? "UserName" : $SortFieldName;
397 
398  # begin constructing the query
399  $Query = "SELECT * FROM APUsers";
400  $QueryOrderBy = " ORDER BY $SortFieldName";
401  $QueryLimit = empty($ReturnNumber) ? "" : " LIMIT $ResultsStartAt, $ReturnNumber";
402 
403  # the Criteria Query will be used to get the total number of results without the
404  # limit clause
405  $CriteriaQuery = $Query;
406 
407  # if specific field comparison requested
408  if (!empty($FieldName))
409  {
410  # append queries with criteria
411  $Query .= " WHERE ".$FieldName." REGEXP '".addslashes($SearchString)."'";
412  $CriteriaQuery = $Query;
413  }
414 
415  # optimize for returning all users
416  else if ($SearchString == ".*.")
417  {
418  # set field name to username - this would be the first field
419  # returned by a field to field search using the above RegExp
420  $FieldName = "UserName";
421  }
422 
423  # add order by and limit to query for optimizing
424  $Query .= $QueryOrderBy.$QueryLimit;
425 
426  # execute query...
427  $this->DB->Query($Query);
428 
429  # ...and process query return
430  while ($Record = $this->DB->FetchRow())
431  {
432  # if specific field or all users requested
433  if (!empty($FieldName))
434  {
435  # add user to return array
436  $ReturnValue[$Record["UserId"]] = $Record;
437 
438  # add matching search field to return array
439  $ReturnValue[$Record["UserId"]]["APMatchingField"] = $FieldName;
440  }
441 
442  else
443  {
444  # for each user data field
445  foreach ($Record as $FName => $FValue)
446  {
447  # if search string appears in data field
448  if (strpos($Record[$FName], $SearchString) !== FALSE)
449  {
450  # add user to return array
451  $ReturnValue[$Record["UserId"]] = $Record;
452 
453  # add matching search field to return array
454  $ReturnValue[$Record["UserId"]]["APMatchingField"] = $FName;
455  }
456  }
457  }
458  }
459 
460  # add matching user count
461  $this->DB->Query($CriteriaQuery);
462  $this->MatchingUserCount = $this->DB->NumRowsSelected();
463 
464  # return array of matching users to caller
465  return $ReturnValue;
466  }
467 
468  # check whether user name currently exists
469  function UserNameExists($UserName)
470  {
471  # normalize user name
472  $UserName = User::NormalizeUserName($UserName);
473 
474  # check whether user name is already in use
475  $NameCount = $this->DB->Query(
476  "SELECT COUNT(*) AS NameCount FROM APUsers"
477  ." WHERE UserName = '".addslashes($UserName)."'",
478  "NameCount");
479 
480  # report to caller whether name exists
481  return ($NameCount > 0);
482  }
483 
484  # check whether e-mail address currently has account associated with it
485  function EMailAddressIsInUse($Address)
486  {
487  # normalize address
488  $UserName = User::NormalizeEMailAddress($Address);
489 
490  # check whether address is already in use
491  $AddressCount = $this->DB->Query(
492  "SELECT COUNT(*) AS AddressCount FROM APUsers"
493  ." WHERE EMail = '".addslashes($Address)."'",
494  "AddressCount");
495 
496  # report to caller whether address is in use
497  return ($AddressCount > 0);
498  }
499 
505  public function GetNewestUsers($Limit = 5)
506  {
507  # assume no users will be found
508  $Users = array();
509 
510  # fetch the newest users
511  $this->DB->Query("SELECT *"
512  ." FROM APUsers"
513  ." ORDER BY CreationDate DESC"
514  ." LIMIT ".intval($Limit));
515  $UserIds = $this->DB->FetchColumn("UserId");
516 
517  # for each user id found
518  foreach ($UserIds as $UserId)
519  {
520  $Users[$UserId] = new SPTUser($UserId);
521  }
522 
523  # return the newest users
524  return $Users;
525  }
526 
527  # ---- PRIVATE INTERFACE -------------------------------------------------
528 
529  var $DB;
532 
533  # callback function for sorting users
534  function CompareUsersForSort($UserA, $UserB)
535  {
536  return strcasecmp($UserA[$this->SortFieldName], $UserB[$this->SortFieldName]);
537  }
538 
539 }
const U_EMPTYEMAIL
Definition: Axis--User.php:34
static NormalizeUserName($UserName)
Definition: Axis--User.php:996
static IsValidLookingEMailAddress($EMail)
Definition: Axis--User.php:984
EMailAddressIsInUse($Address)
const U_ILLEGALUSERNAME
Definition: Axis--User.php:26
SQL database abstraction object with smart query caching.
CreateNewUser($UserName, $Password, $PasswordAgain, $EMail, $EMailAgain, $IgnoreErrorCodes=NULL)
Create new user.
static NormalizePassword($Password)
UserNameExists($UserName)
static IsValidPassword($Password)
Definition: Axis--User.php:977
GetRecentlyLoggedInUsers($Since=NULL, $Limit=10)
UserFactory()
Object constructor.
static IsValidUserName($UserName)
Definition: Axis--User.php:971
GetUsersWithPrivileges()
Return array of user names who have the specified privileges.
const U_DUPLICATEEMAIL
Definition: Axis--User.php:39
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)
const U_DUPLICATEUSERNAME
Definition: Axis--User.php:25
const U_EMPTYUSERNAME
Definition: Axis--User.php:27
FindUsers($SearchString, $FieldName="UserName", $SortFieldName="UserName", $Offset=0, $Count=9999999)
const U_EMPTYEMAILAGAIN
Definition: Axis--User.php:35
const U_PASSWORDSDONTMATCH
Definition: Axis--User.php:23
TestNewUserValues($UserName, $Password, $PasswordAgain, $EMail, $EMailAgain)
static NormalizeEMailAddress($EMailAddress)
Definition: Axis--User.php:990
const U_ILLEGALPASSWORD
Definition: Axis--User.php:28
const U_ILLEGALEMAIL
Definition: Axis--User.php:32
const U_EMPTYPASSWORDAGAIN
Definition: Axis--User.php:31
const U_ILLEGALEMAILAGAIN
Definition: Axis--User.php:33
const U_OKAY
Definition: Axis--User.php:19
GetUserCount($Condition=NULL)
Return number of users in the system.
GetLoggedInUsers($InactivityTimeout=60)
Get users who are currently logged in (i.e.
const U_EMAILSDONTMATCH
Definition: Axis--User.php:24
CompareUsersForSort($UserA, $UserB)
FindUserNames($SearchString, $FieldName="UserName", $SortFieldName="UserName", $Offset=0, $Count=9999999, $IdExclusions=array(), $ValueExclusions=array())
const U_EMPTYPASSWORD
Definition: Axis--User.php:30
const U_ILLEGALPASSWORDAGAIN
Definition: Axis--User.php:29