Search:

# CWIS Developers Documentation

- Main Page
- Classes
- Files

- File List
- File Members

# Axis--UserFactory.php

Go to the documentation of this file.

    00001 <?PHP
    00002
    00003 #
    00004 #   Axis--UserFactory.php
    00005 #   An Meta-Object for Handling User Information
    00006 #
    00007 #   Copyright 2003 Axis Data
    00008 #   This code is free software that can be used or redistributed under the
    00009 #   terms of Version 2 of the GNU General Public License, as published by the
    00010 #   Free Software Foundation (http://www.fsf.org).
    00011 #
    00012 #   Author:  Edward Almasy (almasy@axisdata.com)
    00013 #
    00014 #   Part of the AxisPHP library v1.2.4
    00015 #   For more information see http://www.axisdata.com/AxisPHP/
    00016 #
    00017
    00018 class UserFactory {
    00019
    00020     # ---- PUBLIC INTERFACE --------------------------------------------------
    00021
    00022     # object constructor
    00023     function UserFactory($SessionOrDb)
    00024     {
    00025         # if a session was passed in
    00026         if (is_object($SessionOrDb) && method_exists($SessionOrDb, "Session"))
    00027         {
    00028             # swipe database handle from session
    00029             $this->DB = $SessionOrDb->DB;
    00030
    00031             # save session
    00032             $this->Session = $SessionOrDb;
    00033         }
    00034         # else if database handle was passed in
    00035         elseif (is_object($SessionOrDb) && method_exists($SessionOrDb, "Database"))
    00036         {
    00037             # save database handle
    00038             $this->DB = $SessionOrDb;
    00039
    00040             # create session
    00041             $this->Session = new Session($this->DB);
    00042         }
    00043         else
    00044         {
    00045             # error out
    00046             $this->Result = U_ERROR;
    00047             exit(1);
    00048         }
    00049     }
    00050
    00063     function CreateNewUser(
    00064             $UserName, $Password, $PasswordAgain, $EMail, $EMailAgain,
    00065             $IgnoreErrorCodes = NULL)
    00066     {
    00067         # check incoming values
    00068         $ErrorCodes = $this->TestNewUserValues(
    00069             $UserName, $Password, $PasswordAgain, $EMail, $EMailAgain);
    00070
    00071         # discard any errors we are supposed to ignore
    00072         if ($IgnoreErrorCodes)
    00073         {
    00074             $ErrorCodes = array_diff($ErrorCodes, $IgnoreErrorCodes);
    00075         }
    00076
    00077         # if error found in incoming values return error codes to caller
    00078         if (count($ErrorCodes)) {  return $ErrorCodes;  }
    00079
    00080         # add user to database
    00081         $UserName = User::NormalizeUserName($UserName);
    00082         $this->DB->Query("INSERT INTO APUsers"
    00083                 ." (UserName, CreationDate)"
    00084                 ." VALUES ('".addslashes($UserName)."', NOW())");
    00085
    00086         # create new user object
    00087         $UserId = $this->DB->LastInsertId("APUsers");
    00088         $User = new User($this->DB, (int)$UserId);
    00089
    00090         # if new user object creation failed return error code to caller
    00091         if ($User->Status() != U_OKAY) {  return array($User->Status());  }
    00092
    00093         # set password and e-mail address
    00094         $User->SetPassword($Password);
    00095         $User->Set("EMail", $EMail);
    00096
    00097         # return new user object to caller
    00098         return $User;
    00099     }
    00100
    00101     # test new user creation values (returns array of error codes)
    00102     function TestNewUserValues(
    00103             $UserName, $Password, $PasswordAgain, $EMail, $EMailAgain)
    00104     {
    00105         $ErrorCodes = array();
    00106         if (strlen(User::NormalizeUserName($UserName)) == 0)
    00107             {  $ErrorCodes[] = U_EMPTYUSERNAME;  }
    00108         elseif (!User::IsValidUserName($UserName))
    00109             {  $ErrorCodes[] = U_ILLEGALUSERNAME;  }
    00110         elseif ($this->UserNameExists($UserName))
    00111             {  $ErrorCodes[] = U_DUPLICATEUSERNAME;  }
    00112
    00113         if ($this->EMailAddressIsInUse($EMail))
    00114             {  $ErrorCodes[] = U_DUPLICATEEMAIL;  }
    00115
    00116         $FoundOtherPasswordError = FALSE;
    00117         if (strlen(User::NormalizePassword($Password)) == 0)
    00118         {
    00119             $ErrorCodes[] = U_EMPTYPASSWORD;
    00120             $FoundOtherPasswordError = TRUE;
    00121         }
    00122         elseif (!User::IsValidPassword($Password))
    00123         {
    00124             $ErrorCodes[] = U_ILLEGALPASSWORD;
    00125             $FoundOtherPasswordError = TRUE;
    00126         }
    00127
    00128         if (strlen(User::NormalizePassword($PasswordAgain)) == 0)
    00129         {
    00130             $ErrorCodes[] = U_EMPTYPASSWORDAGAIN;
    00131             $FoundOtherPasswordError = TRUE;
    00132         }
    00133         elseif (!User::IsValidPassword($PasswordAgain))
    00134         {
    00135             $ErrorCodes[] = U_ILLEGALPASSWORDAGAIN;
    00136             $FoundOtherPasswordError = TRUE;
    00137         }
    00138
    00139         if ($FoundOtherPasswordError == FALSE)
    00140         {
    00141             if (User::NormalizePassword($Password)
    00142                     != User::NormalizePassword($PasswordAgain))
    00143             {
    00144                 $ErrorCodes[] = U_PASSWORDSDONTMATCH;
    00145             }
    00146         }
    00147
    00148         $FoundOtherEMailError = FALSE;
    00149         if (strlen(User::NormalizeEMailAddress($EMail)) == 0)
    00150         {
    00151             $ErrorCodes[] = U_EMPTYEMAIL;
    00152             $FoundOtherEMailError = TRUE;
    00153         }
    00154         elseif (!User::IsValidLookingEMailAddress($EMail))
    00155         {
    00156             $ErrorCodes[] = U_ILLEGALEMAIL;
    00157             $FoundOtherEMailError = TRUE;
    00158         }
    00159
    00160         if (strlen(User::NormalizeEMailAddress($EMailAgain)) == 0)
    00161         {
    00162             $ErrorCodes[] = U_EMPTYEMAILAGAIN;
    00163             $FoundOtherEMailError = TRUE;
    00164         }
    00165         elseif (!User::IsValidLookingEMailAddress($EMailAgain))
    00166         {
    00167             $ErrorCodes[] = U_ILLEGALEMAILAGAIN;
    00168             $FoundOtherEMailError = TRUE;
    00169         }
    00170
    00171         if ($FoundOtherEMailError == FALSE)
    00172         {
    00173             if (User::NormalizeEMailAddress($EMail)
    00174                     != User::NormalizeEMailAddress($EMailAgain))
    00175             {
    00176                 $ErrorCodes[] = U_EMAILSDONTMATCH;
    00177             }
    00178         }
    00179
    00180         return $ErrorCodes;
    00181     }
    00182
    00188     function GetUserCount($Condition = NULL)
    00189     {
    00190         return $this->DB->Query("SELECT COUNT(*) AS UserCount FROM APUsers"
    00191                 .($Condition ? " WHERE ".$Condition : ""), "UserCount");
    00192     }
    00193
    00194     # return total number of user that matched last GetMatchingUsers call
    00195     # before the return size was limited
    00196     function GetMatchingUserCount()
    00197     {
    00198         return $this->MatchingUserCount;
    00199     }
    00200
    00201     # return array of users currently logged in
    00202     function GetLoggedInUsers()
    00203     {
    00204         # start with empty array (to prevent array errors)
    00205         $ReturnValue = array();
    00206
    00207         # load array of logged in user
    00208         $UserIds = $this->Session->GetFromAllSessions("APUserId");
    00209
    00210         # for each logged in user
    00211         foreach ($UserIds as $UserId)
    00212         {
    00213             # load all data values for user
    00214             $this->DB->Query("SELECT * FROM APUsers WHERE UserId = '".$UserId."'");
    00215             $ReturnValue[$UserId] = $this->DB->FetchRow();
    00216         }
    00217
    00218         # return array of user data to caller
    00219         return $ReturnValue;
    00220     }
    00221
    00222     # return array of users recently logged in. returns 10 users by default
    00223     function GetRecentlyLoggedInUsers($Since = NULL, $Limit = 10)
    00224     {
    00225         # start with empty array (to prevent array errors)
    00226         $ReturnValue = array();
    00227
    00228         # get users recently logged in during the last 24 hours if no date given
    00229         if (is_null($Since))
    00230         {
    00231             $Date = date("Y-m-d H:i:s", time()-86400);
    00232         }
    00233
    00234         else
    00235         {
    00236             $Date = date("Y-m-d H:i:s", strtotime($Since));
    00237         }
    00238
    00239         # query for the users who were logged in since the given date
    00240         $this->DB->Query("
    00241             SELECT U.*
    00242             FROM APUsers U
    00243             LEFT JOIN
    00244             -- the dummy table is an optimization. see the comment by Vimal
    00245             -- Gupta in the MySQL docs:
    00246             -- http://dev.mysql.com/doc/refman/5.0/en/in-subquery-optimization.html
    00247             (SELECT DataValue
    00248              FROM APSessionData
    00249              WHERE DataName = 'APUserId'
    00250              -- allows fetching distinct DataValue values but with GROUP BY
    00251              -- optimizations
    00252              GROUP BY DataValue) as Dummy
    00253             -- using this convoluted method because DataValue is an integer
    00254             -- (UserId) serialized by PHP to a string
    00255             ON CONCAT('s:', CHAR_LENGTH(CAST(U.UserId AS CHAR)),
    00256             ':\"', U.UserId,'\";') = Dummy.DataValue
    00257             WHERE U.LastActiveDate >= '".$Date."'
    00258             AND Dummy.DataValue IS NULL
    00259             ORDER BY U.LastActiveDate DESC
    00260             LIMIT ".intval($Limit));
    00261
    00262         while (FALSE !== ($Row = $this->DB->FetchRow()))
    00263         {
    00264             $ReturnValue[$Row["UserId"]] = $Row;
    00265         }
    00266
    00267         # return array of user data to caller
    00268         return $ReturnValue;
    00269     }
    00270
    00271     # return array of user names who have the specified privileges
    00272     # (array index is user IDs)
    00273     function GetUsersWithPrivileges()
    00274     {
    00275         # start with query string that will return all users
    00276         $QueryString = "SELECT DISTINCT APUsers.UserId, UserName FROM APUsers, APUserPrivileges";
    00277
    00278         # for each specified privilege
    00279         $Args = func_get_args();
    00280         foreach ($Args as $Index => $Arg)
    00281         {
    00282             # add condition to query string
    00283             $QueryString .= ($Index == 0) ? " WHERE (" : " OR";
    00284             $QueryString .= " APUserPrivileges.Privilege = ".$Arg;
    00285         }
    00286
    00287         # close privilege condition in query string and add user ID condition
    00288         $QueryString.= count($Args) ? ") AND APUsers.UserId = APUserPrivileges.UserId" : "";
    00289
    00290         # perform query
    00291         $this->DB->Query($QueryString);
    00292
    00293         # copy query result into user info array
    00294         $Users = $this->DB->FetchColumn("UserName", "UserId");
    00295
    00296         # return array of users to caller
    00297         return $Users;
    00298     }
    00299
    00300     # return array of user objects who have values matching search string
    00301     # (array indexes are user IDs)
    00302     function FindUsers($SearchString, $FieldName = "UserName",
    00303             $SortFieldName = "UserName", $Offset = 0, $Count = 9999999)
    00304     {
    00305         # retrieve matching user IDs
    00306         $UserNames = $this->FindUserNames(
    00307                 $SearchString, $FieldName, $SortFieldName, $Offset, $Count);
    00308
    00309         # create user objects
    00310         $Users = array();
    00311         foreach ($UserNames as $UserId => $UserName)
    00312         {
    00313             $Users[$UserId] = new User($this->DB, intval($UserId));
    00314         }
    00315
    00316         # return array of user objects to caller
    00317         return $Users;
    00318     }
    00319
    00320     # return array of user names/IDs who have values matching search string
    00321     # (array indexes are user IDs, array values are user names)
    00322     function FindUserNames($SearchString, $FieldName = "UserName",
    00323             $SortFieldName = "UserName", $Offset = 0, $Count = 9999999)
    00324     {
    00325         # Construct a database query:
    00326         $QueryString = "SELECT UserId, UserName FROM APUsers WHERE";
    00327
    00328         # If the search string is a valid username which is shorter than the
    00329         # minimum word length indexed by the FTS, just do a normal
    00330         # equality test instead of using the index.
    00331         # Otherwise, FTS away.
    00332         $MinWordLen = $this->DB->Query(
    00333             "SHOW VARIABLES WHERE variable_name='ft_min_word_len'", "Value");
    00334         if (User::IsValidUserName($SearchString) &&
    00335             strlen($SearchString) < $MinWordLen )
    00336         {
    00337             $QueryString .= " UserName='".addslashes($SearchString)."'";
    00338         }
    00339         else
    00340         {
    00341             # massage search string to use AND logic
    00342             $Words = preg_split("/[\s]+/", trim($SearchString));
    00343             $NewSearchString = "";
    00344             $InQuotedString = FALSE;
    00345             foreach ($Words as $Word)
    00346             {
    00347                 if ($InQuotedString == FALSE) {  $NewSearchString .= "+";  }
    00348                 if (preg_match("/^\"/", $Word)) {  $InQuotedString = TRUE;  }
    00349                 if (preg_match("/\"$/", $Word)) {  $InQuotedString = FALSE;  }
    00350                 $NewSearchString .= $Word." ";
    00351             }
    00352             $QueryString .= " MATCH (".$FieldName.")"
    00353                 ." AGAINST ('".addslashes(trim($NewSearchString))."'"
    00354                 ." IN BOOLEAN MODE)";
    00355         }
    00356         $QueryString .= " ORDER BY ".$SortFieldName
    00357             ." LIMIT ".$Offset.", ".$Count;
    00358
    00359         # retrieve matching user IDs
    00360         $this->DB->Query($QueryString);
    00361         $UserNames = $this->DB->FetchColumn("UserName", "UserId");
    00362
    00363         # return names/IDs to caller
    00364         return $UserNames;
    00365     }
    00366
    00367     # return array of users who have values matching search string (in specific field if requested)
    00368     # (search string respects POSIX-compatible regular expressions)
    00369     # optimization: $SearchString = ".*." and $FieldName = NULL will return all
    00370     #   users ordered by $SortFieldName
    00371     function GetMatchingUsers($SearchString, $FieldName = NULL,
    00372                               $SortFieldName = "UserName",
    00373                               $ResultsStartAt = 0, $ReturnNumber = NULL)
    00374     {
    00375         # start with empty array (to prevent array errors)
    00376         $ReturnValue = array();
    00377
    00378         # if search string supplied
    00379         if (strlen(trim($SearchString)) > 0)
    00380         {
    00381             # build the sorting clause
    00382             $QueryOrderBy = " ORDER BY $SortFieldName";
    00383
    00384             if ($ReturnNumber)
    00385             {
    00386                 $QueryLimit = " LIMIT ";
    00387                 if ($ResultsStartAt)
    00388                 {
    00389                     $QueryLimit .= "$ResultsStartAt, $ReturnNumber";
    00390                 }
    00391                 else
    00392                     $QueryLimit .= $ReturnNumber;
    00393             }
    00394             else
    00395             {
    00396                 $QueryLimit = "";
    00397             }
    00398
    00399             $Query = "SELECT * FROM APUsers";
    00400
    00401             # the Criteria Query will be used to get the total number
    00402             # of results without the limit clause
    00403             $CriteriaQuery = $Query;
    00404
    00405
    00406             # if specific field comparison requested
    00407             if ($FieldName != NULL)
    00408             {
    00409                 # append queries with criteria
    00410                 $Query .= " WHERE ".$FieldName." REGEXP '".addslashes($SearchString)."'";
    00411
    00412                 $CriteriaQuery = $Query;
    00413
    00414                 # tack on ordering and limiting
    00415                 $Query .= $QueryOrderBy.$QueryLimit;
    00416
    00417             }
    00418             # optimize for returning all users
    00419             elseif (strcasecmp($SearchString, ".*.") == 0)
    00420             {
    00421                 $Query .= $QueryOrderBy.$QueryLimit;
    00422
    00423                 # set field name to username - this would be the first field
    00424                 # returned by a field to field search using the above RegExp
    00425                 $FieldName = "UserName";
    00426             }
    00427             else
    00428             {
    00429                 # search all fields - can't limit here, but we can order by
    00430                 $Query .= $QueryOrderBy;
    00431             }
    00432
    00433             # execute query
    00434             $this->DB->Query($Query);
    00435
    00436             # process query return
    00437             while ($Record = $this->DB->FetchRow())
    00438             {
    00439
    00440                 # if specific field or all users requested
    00441                 if ($FieldName != NULL)
    00442                 {
    00443                     # add user to return array
    00444                     $ReturnValue[$Record["UserId"]] = $Record;
    00445
    00446                     # add matching search field to return array
    00447                     $ReturnValue[$Record["UserId"]]["APMatchingField"] = $FieldName;
    00448                 }
    00449                 else
    00450                 {
    00451                     # for each user data field
    00452                     foreach ($Record as $FName => $FValue)
    00453                     {
    00454                         # if search string appears in data field
    00455                         if (ereg($SearchString, $Record[$FName]))
    00456                         {
    00457                             # add user to return array
    00458                             $ReturnValue[$Record["UserId"]] = $Record;
    00459
    00460                             # add matching search field to return array
    00461                             $ReturnValue[$Record["UserId"]]["APMatchingField"] = $FName;
    00462
    00463                             # move on to next user
    00464                             continue;
    00465                         }
    00466                     }
    00467
    00468                     # cut return array down to requested size
    00469                     if (isset($ReturnNumber))
    00470                     {
    00471                         $ReturnValue = array_slice($ReturnValue, $ResultsStartAt, $ReturnNumber, true);
    00472                     }
    00473                 }
    00474             }
    00475
    00476             if (!isset($this->MatchingUserCount))
    00477             {
    00478                 $this->DB->Query($CriteriaQuery);
    00479                 $this->MatchingUserCount = $this->DB->NumRowsSelected();
    00480             }
    00481
    00482         }
    00483
    00484         # return array of matching users to caller
    00485         return $ReturnValue;
    00486     }
    00487
    00488     # check whether user name currently exists
    00489     function UserNameExists($UserName)
    00490     {
    00491         # normalize user name
    00492         $UserName = User::NormalizeUserName($UserName);
    00493
    00494         # check whether user name is already in use
    00495         $NameCount = $this->DB->Query(
    00496                 "SELECT COUNT(*) AS NameCount FROM APUsers"
    00497                     ." WHERE UserName = '".addslashes($UserName)."'",
    00498                 "NameCount");
    00499
    00500         # report to caller whether name exists
    00501         return ($NameCount > 0);
    00502     }
    00503
    00504     # check whether e-mail address currently has account associated with it
    00505     function EMailAddressIsInUse($Address)
    00506     {
    00507         # normalize address
    00508         $UserName = User::NormalizeEMailAddress($Address);
    00509
    00510         # check whether address is already in use
    00511         $AddressCount = $this->DB->Query(
    00512                 "SELECT COUNT(*) AS AddressCount FROM APUsers"
    00513                     ." WHERE EMail = '".addslashes($Address)."'",
    00514                 "AddressCount");
    00515
    00516         # report to caller whether address is in use
    00517         return ($AddressCount > 0);
    00518     }
    00519
    00525     public function GetNewestUsers($Limit = 5)
    00526     {
    00527         # assume no users will be found
    00528         $Users = array();
    00529
    00530         # fetch the newest users
    00531         $this->DB->Query("SELECT *"
    00532                 ." FROM APUsers"
    00533                 ." ORDER BY CreationDate DESC"
    00534                 ." LIMIT ".intval($Limit));
    00535         $UserIds = $this->DB->FetchColumn("UserId");
    00536
    00537         # for each user id found
    00538         foreach ($UserIds as $UserId)
    00539         {
    00540             $Users[$UserId] = new SPTUser($UserId);
    00541         }
    00542
    00543         # return the newest users
    00544         return $Users;
    00545     }
    00546
    00547     # ---- PRIVATE INTERFACE -------------------------------------------------
    00548
    00549     var $DB;
    00550     var $Session;
    00551     var $SortFieldName;
    00552     var $MatchingUserCount;
    00553
    00554     # callback function for sorting users
    00555     function CompareUsersForSort($UserA, $UserB)
    00556     {
    00557         return strcasecmp($UserA[$this->SortFieldName], $UserB[$this->SortFieldName]);
    00558     }
    00559 };
    00560
    00561
    00562 ?>