Overview

Packages

  • awl
    • AuthPlugin
    • AwlDatabase
    • Browser
    • classEditor
    • DataEntry
    • DataUpdate
    • EMail
    • iCalendar
    • MenuSet
    • PgQuery
    • Session
    • Translation
    • User
    • Utilities
    • Validation
    • vCalendar
    • vComponent
    • XMLDocument
    • XMLElement
  • None
  • PHP

Classes

  • User
  • Overview
  • Package
  • Class
  • Tree
  • Deprecated
  • Todo
  1: <?php
  2: /**
  3: * A class to handle reading, writing, viewing, editing and validating
  4: * usr records.
  5: *
  6: * @package   awl
  7: * @author Andrew McMillan <andrew@mcmillan.net.nz>
  8: * @copyright Catalyst IT Ltd, Morphoss Ltd <http://www.morphoss.com/>
  9: * @license   http://gnu.org/copyleft/gpl.html GNU GPL v2 or later
 10: */
 11: require_once("AWLUtilities.php");
 12: 
 13: /**
 14: * We need to access some session information.
 15: */
 16: require_once("Session.php");
 17: 
 18: /**
 19: * We use the DataEntry class for data display and updating
 20: */
 21: require_once("DataEntry.php");
 22: 
 23: /**
 24: * We use the DataUpdate class and inherit from DBRecord
 25: */
 26: require_once("DataUpdate.php");
 27: 
 28: /**
 29: * A class to handle reading, writing, viewing, editing and validating
 30: * usr records.
 31: * @package   awl
 32: * @subpackage   User
 33: */
 34: class User extends DBRecord {
 35:   /**#@+
 36:   * @access private
 37:   */
 38:   /**
 39:   * A unique user number that is auto assigned on creation and invariant thereafter
 40:   * @var string
 41:   */
 42:   var $user_no;
 43: 
 44:   /**
 45:   * Something to prefix all field names with before rendering them.
 46:   * @var string
 47:   */
 48:   var $prefix;
 49: 
 50:   /**#@-*/
 51: 
 52:   /**
 53:   * The constructor initialises a new record, potentially reading it from the database.
 54:   * @param int $id The user_no, or 0 if we are creating a new one
 55:   * @param string $prefix The prefix for entry fields
 56:   */
 57:   function User( $id , $prefix = "") {
 58:     global $session;
 59: 
 60:     // Call the parent constructor
 61:     $this->DBRecord();
 62: 
 63:     $this->prefix = $prefix;
 64: 
 65:     $this->user_no = 0;
 66:     $keys = array();
 67: 
 68:     $id = intval("$id");
 69:     if ( $id > 0 ) {
 70:       // Initialise
 71:       $keys['user_no'] = $id;
 72:       $this->user_no = $id;
 73:     }
 74: 
 75:     // Initialise the record, possibly from the file.
 76:     $this->Initialise('usr',$keys);
 77:     $this->Read();
 78:     $this->GetRoles();
 79: 
 80:     $this->EditMode = ( (isset($_GET['edit']) && $_GET['edit'] && $this->AllowedTo($this->WriteType))
 81:                     || (0 == $this->user_no && $this->AllowedTo("insert") ) );
 82: 
 83:     if ( $this->user_no == 0 ) {
 84:       dbg_error_log("User", "Initialising new user values");
 85: 
 86:       // Initialise to standard default values
 87:       $this->active = true;
 88: 
 89:     }
 90:   }
 91: 
 92: 
 93:   /**
 94:   * Can the user do this?
 95:   * @param string $whatever What the user wants to do
 96:   * @return boolean Whether they are allowed to.
 97:   */
 98:   function AllowedTo ( $whatever )
 99:   {
100:     global $session;
101: 
102:     $rc = false;
103: 
104:     /**
105:     * First we globally short-circuit the 'admin can do anything'
106:     */
107:     if ( $session->AllowedTo("Admin") ) {
108:       $rc = true;
109:       dbg_error_log("User",":AllowedTo: Admin is always allowed to %s", $whatever );
110:       return $rc;
111:     }
112: 
113:     switch( strtolower($whatever) ) {
114: 
115:       case 'view':
116:         $rc = ( $this->user_no > 0 && $session->user_no == $this->user_no );
117:         break;
118: 
119:       case 'update':
120:         $rc = ( $this->user_no > 0 && $session->user_no == $this->user_no );
121:         break;
122: 
123:       case 'changepassword':
124:         $rc = ( ($this->user_no > 0 && $session->user_no == $this->user_no)
125:                 || ("insert" == $this->WriteType) );
126:         break;
127: 
128:       case 'changeusername':  // Administrator only
129:       case 'changeactive':    // Administrator only
130:       case 'admin':
131: 
132:       case 'create':
133: 
134:       case 'insert':
135:         $rc = false;
136:         break;
137: 
138:       default:
139:         $rc = ( isset($session->roles[$whatever]) && $session->roles[$whatever] );
140:     }
141:     dbg_error_log("User",":AllowedTo: %s is%s allowed to %s", (isset($this->username)?$this->username:null), ($rc?"":" not"), $whatever );
142:     return $rc;
143:   }
144: 
145: 
146:   /**
147:   * Get the group memberships for the user
148:   */
149:   function GetRoles () {
150:     $this->roles = array();
151:     $qry = new AwlQuery( 'SELECT role_name FROM role_member JOIN roles USING (role_no) WHERE user_no = ? ', $this->user_no );
152:     if ( $qry->Exec("User") && $qry->rows() > 0 ) {
153:       while( $role = $qry->Fetch() ) {
154:         $this->roles[$role->role_name] = 't';
155:       }
156:     }
157:   }
158: 
159: 
160:   /**
161:   * Render the form / viewer as HTML to show the user
162:   * @return string An HTML fragment to display in the page.
163:   */
164:   function Render( ) {
165:     $html = "";
166:     dbg_error_log("User", ":Render: type=$this->WriteType, edit_mode=$this->EditMode" );
167: 
168:     $ef = new EntryForm( $REQUEST_URI, $this->Values, $this->EditMode );
169:     $ef->NoHelp();  // Prefer this style, for the moment
170: 
171:     if ( $ef->EditMode ) {
172:       $html .= $ef->StartForm( array("autocomplete" => "off" ) );
173:       if ( $this->user_no > 0 ) $html .= $ef->HiddenField( "user_no", $this->user_no );
174:     }
175: 
176:     $html .= "<table width=\"100%\" class=\"data\" cellspacing=\"0\" cellpadding=\"0\">\n";
177: 
178:     $html .= $this->RenderFields($ef);
179:     $html .= $this->RenderRoles($ef);
180: 
181:     $html .= "</table>\n";
182:     if ( $ef->EditMode ) {
183:       $html .= '<div id="footer">';
184:       $html .= $ef->SubmitButton( "submit", (("insert" == $this->WriteType) ? translate("Create") : translate("Update")) );
185:       $html .= '</div>';
186:       $html .= $ef->EndForm();
187:     }
188: 
189:     return $html;
190:   }
191: 
192:   /**
193:   * Render the core details to show to the user
194:   * @param object $ef The entry form.
195:   * @param string $title The title to display above the entry fields.
196:   * @return string An HTML fragment to display in the page.
197:   */
198:   function RenderFields($ef , $title = null ) {
199:     global $session, $c;
200: 
201:     if ( $title == null ) $title = i18n("User Details");
202:     $html = ( $title == "" ? "" : $ef->BreakLine(translate($title)) );
203: 
204:     if ( $this->AllowedTo('ChangeUsername') ) {
205:       $html .= $ef->DataEntryLine( translate("User Name"), "%s", "text", "username",
206:               array( "size" => 20, "title" => translate("The name this user can log into the system with.")), $this->prefix );
207:     }
208:     else {
209:       $html .= $ef->DataEntryLine( translate("User Name"), $this->Get('username') );
210:     }
211:     if ( $ef->EditMode && $this->AllowedTo('ChangePassword') ) {
212:       $this->Set('new_password','******');
213:       unset($_POST['new_password']);
214:       $html .= $ef->DataEntryLine( translate("New Password"), "%s", "password", "new_password",
215:                 array( "size" => 20, "title" => translate("The user's password for logging in.")), $this->prefix );
216:       $this->Set('confirm_password', '******');
217:       unset($_POST['confirm_password']);
218:       $html .= $ef->DataEntryLine( translate("Confirm"), "%s", "password", "confirm_password",
219:                 array( "size" => 20, "title" => translate("Confirm the new password.")), $this->prefix );
220:     }
221: 
222:     $html .= $ef->DataEntryLine( translate("Full Name"), "%s", "text", "fullname",
223:               array( "size" => 50, "title" => translate("The user's full name.")), $this->prefix );
224: 
225:     $html .= $ef->DataEntryLine( translate("EMail"), "%s", "text", "email",
226:               array( "size" => 50, "title" => translate("The user's e-mail address.")), $this->prefix );
227: 
228:     if ( $this->AllowedTo('ChangeActive') ) {
229:       $html .= $ef->DataEntryLine( translate("Active"), ($this->Get('active') == 't'? translate('Yes') : translate('No')), "checkbox", "active",
230:                 array( "_label" => translate("User is active"),
231:                       "title" => translate("Is this user active?")), $this->prefix );
232:     }
233:     else {
234:       $html .= $ef->DataEntryLine( translate("Active"), ($this->Get('active') == 't'? translate('Yes') : translate('No')) );
235:     }
236: 
237:     $html .= $ef->DataEntryLine( translate("Date Style"), ($this->Get('date_format_type') == 'E' ? 'European' : ($this->Get('date_format_type') == 'U' ? 'US of A' : 'ISO 8861')),
238:                      "select", "date_format_type",
239:                      array( "title" => translate("The style of dates used for this person."),
240:                        "_E" => translate("European (d/m/y)"), "_U" => translate("United States of America (m/d/y)"), "_I" => translate("ISO Format (YYYY-MM-DD)") ),
241:                      $this->prefix );
242: 
243:     if ( isset($c->default_locale) ) {
244:       if ( $this->Get('locale') == '' ) {
245:         $this->Set('locale',$c->default_locale);
246:       }
247:       $html .= $ef->DataEntryLine( translate("Language"), "%s", "lookup", "locale",
248:                       array( "title" => translate("The preferred language for this person."),
249:                         "_sql" => "SELECT locale, locale_name_locale FROM supported_locales ORDER BY locale ASC;" ),
250:                       $this->prefix );
251:     }
252: 
253:     $html .= $ef->DataEntryLine( translate("EMail OK"), $session->FormattedDate($this->Get('email_ok'),'timestamp'), "timestamp", "email_ok",
254:               array( "title" => translate("When the user's e-mail account was validated.")), $this->prefix );
255: 
256:     $html .= $ef->DataEntryLine( translate("Joined"), $session->FormattedDate($this->Get('joined'),'timestamp') );
257:     $html .= $ef->DataEntryLine( translate("Updated"), $session->FormattedDate($this->Get('updated'),'timestamp') );
258:     $html .= $ef->DataEntryLine( translate("Last used"), $session->FormattedDate($this->Get('last_used'),'timestamp') );
259: 
260:     return $html;
261:   }
262: 
263: 
264:   /**
265:   * Render the user's administrative roles
266:   *
267:   * @return string The string of html to be output
268:   */
269:   function RenderRoles( $ef, $title = null ) {
270:     global $session;
271:     $html = "";
272: 
273:     if ( $title == null ) $title = i18n("User Roles");
274:     $html = ( $title == "" ? "" : $ef->BreakLine(translate($title)) );
275: 
276:     $html .= '<tr><th class="prompt">'.translate("User Roles").'</th><td class="entry">';
277:     if ( $ef->EditMode ) {
278:       $sql = "SELECT role_name FROM roles ";
279:       if ( ! ($session->AllowedTo('Admin') ) ) {
280:         $sql .= "NATURAL JOIN role_member WHERE user_no=$session->user_no ";
281:       }
282:       $sql .= "ORDER BY roles.role_no";
283: 
284:       $ef->record->roles = array();
285: 
286:       // Select the records
287:       $q = new AwlQuery($sql);
288:       if ( $q && $q->Exec("User") && $q->rows() ) {
289:         $i=0;
290:         while( $row = $q->Fetch() ) {
291:           @dbg_error_log("User", ":RenderRoles: Is a member of '%s': %s", $row->role_name, $this->roles[$row->role_name] );
292:           $ef->record->roles[$row->role_name] = ( isset($this->roles[$row->role_name]) ? $this->roles[$row->role_name] : 'f');
293:           $html .= $ef->DataEntryField( "", "checkbox", "roles[$row->role_name]",
294:                           array("title" => translate("Does the user have the right to perform this role?"),
295:                                     "_label" => translate($row->role_name) ) );
296:         }
297:       }
298:     }
299:     else {
300:       $i = 0;
301:       foreach( $this->roles AS $k => $v ) {
302:         if ( $i++ > 0 ) $html .= ", ";
303:         $html .= $k;
304:       }
305:     }
306:     $html .= '</td></tr>'."\n";
307: 
308:     return $html;
309:   }
310: 
311:   /**
312:   * Validate the information the user submitted
313:   * @return boolean Whether the form data validated OK.
314:   */
315:   function Validate( ) {
316:     global $session, $c;
317:     dbg_error_log("User", ":Validate: Validating user");
318: 
319:     $valid = true;
320: 
321:     if ( $this->Get('fullname') == "" ) {
322:       $c->messages[] = i18n('ERROR: The full name may not be blank.');
323:       $valid = false;
324:     }
325: 
326:     // Password changing is a little special...
327:     unset($_POST['password']);
328:     if ( $_POST['new_password'] != "******" && $_POST['new_password'] != ""  ) {
329:       if ( $_POST['new_password'] == $_POST['confirm_password'] ) {
330:         $this->Set('password',$_POST['new_password']);
331:       }
332:       else {
333:         $c->messages[] = i18n('ERROR: The new password must match the confirmed password.');
334:         $valid = false;
335:       }
336:     }
337:     else {
338:       $this->Undefine('password');
339:     }
340: 
341:     dbg_error_log("User", ":Validate: User %s validation", ($valid ? "passed" : "failed"));
342:     return $valid;
343:   }
344: 
345:   /**
346:   * Write the User record.
347:   * @return Success.
348:   */
349:   function Write() {
350:     global $c, $session;
351:     if ( parent::Write() ) {
352:       $c->messages[] = i18n('User record written.');
353:       if ( $this->WriteType == 'insert' ) {
354:         $qry = new AwlQuery( "SELECT currval('usr_user_no_seq');" );
355:         $qry->Exec("User::Write");
356:         $sequence_value = $qry->Fetch(true);  // Fetch as an array
357:         $this->user_no = $sequence_value[0];
358:       }
359:       else {
360:         if ( $this->user_no == $session->user_no && $this->Get("date_format_type") != $session->date_format_type ) {
361:           // Ensure we match the date style setting
362:           $session->date_format_type = $this->Get("date_format_type");
363:           unset($_POST['email_ok']);
364:           $qry = new AwlQuery( "SET DATESTYLE TO ?;", ($this->Get("date_format_type") == 'E' ? 'European,ISO' : ($this->Get("date_format_type") == 'U' ? 'US,ISO' : 'ISO')) );
365:           $qry->Exec();
366:         }
367:       }
368:       return $this->WriteRoles();
369:     }
370:     return false;
371:   }
372: 
373:   /**
374:   * Write the roles associated with the user
375:   * @return Success.
376:   */
377:   function WriteRoles() {
378:     global $c, $session;
379: 
380:     if ( isset($_POST['roles']) && is_array($_POST['roles']) ) {
381:       $roles = "";
382:       $params = array();
383:       foreach( $_POST['roles'] AS $k => $v ) {
384:         if ( $v && $v != "off" ) {
385:           $roles .= ( $roles == '' ? '' : ', ' );
386:           $roles .= AwlQuery::quote($k);
387:         }
388:       }
389:       $qry = new AwlQuery();
390:       if ( $roles == '' )
391:         $succeeded = $qry->QDo('DELETE FROM role_member WHERE user_no = '.$this->user_no);
392:       else {
393:         $succeeded = $qry->Begin();
394:         $sql = 'DELETE FROM role_member WHERE user_no = '.$this->user_no;
395:         $sql .= ' AND role_no NOT IN (SELECT role_no FROM roles WHERE role_name IN ('.$roles.') )';
396:         if ( $succeeded ) $succeeded = $qry->QDo($sql);
397:         $sql = 'INSERT INTO role_member (role_no, user_no)';
398:         $sql .= ' SELECT role_no, '.$this->user_no.' FROM roles WHERE role_name IN ('.$roles.')';
399:         $sql .= ' EXCEPT SELECT role_no, user_no FROM role_member';
400:         if ( $succeeded ) $succeeded = $qry->QDo($sql);
401:         if ( $succeeded )
402:           $qry->Commit();
403:         else
404:           $qry->Rollback();
405:       }
406:       if ( ! $succeeded ) {
407:         $c->messages[] = i18n('ERROR: There was a database error writing the roles information!');
408:         $c->messages[] = i18n('Please note the time and advise the administrator of your system.');
409:         return false;
410:       }
411:     }
412:     return true;
413:   }
414: }
415: 
AWL API documentation generated by ApiGen 2.8.0