Subversion Repositories php_users

Rev

Rev 32 | Go to most recent revision | Details | Compare with Previous | Last modification | View Log | RSS feed

Rev Author Line No. Line
4 rodolico 1
<?php
2
 
7 rodolico 3
/*
4
   Copyright (c) 2021, Daily Data, Inc. Redistribution and use in 
5
   source and binary forms, with or without modification, are permitted
6
   provided that the following conditions are met:
7
 
8
   * Redistributions of source code must retain the above copyright 
9
     notice, this list of conditions and the following disclaimer.
10
   * Redistributions in binary form must reproduce the above copyright 
11
     notice, this list of conditions and the following disclaimer in the 
12
     documentation and/or other materials provided with the distribution.
13
 
14
   THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 
15
   "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
16
   LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
17
   A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
18
   OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
19
   SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT 
20
   LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
21
   DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
22
   THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
23
   (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
24
   OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
25
 
26
*/
27
 
28
/*
29
 * users.class.php
30
 * 
31
 * Authors: R. W. Rodolico
32
 * 
33
 */
34
 
35
/**
36
 * User Login class
37
 * 
38
 * IMPORTANT: Requires a data source. See UsersDataSourceMySQLi.class.php
39
 * for code which provides this for MySQLi
40
 * 
41
 * Users encapsulates a basic login and authentication package. It 
42
 * provides a login screen, authentication, the ability to edit oneself,
43
 * and for users with the admin flag set, the ability to edit others.
44
 * 
45
 * It also allows a user to be disabled.
46
 * 
47
 * Users was designed to be extensible, adding new fields by the calling
48
 * program, modifying the HTML elements, etc...
49
 * 
50
 * @author R. W. Rodolico <rodo@unixservertech.com>
51
 * 
52
 * @version 0.9.0 (beta)
53
 * @copyright 2021 Daily Data, Inc.
54
 * 
55
 */
56
 
57
 class Users {
4 rodolico 58
 
7 rodolico 59
   /**
16 rodolico 60
    * @var string[] $configuration Contains the configuration for the class
7 rodolico 61
    * 
62
    * May be modified by the calling program. Must be replicated in userDataSource class
63
    */
16 rodolico 64
   protected $configuration = array(
4 rodolico 65
      /*
66
       * what to use for html input fields
67
       * These are passed to sprintf, with label, fieldname, title, placeholder and current value, in that order
68
       */
69
      'screens'         => array (
70
         'login form' => "<h1>Login</h1>\n<form class='login_form' action='%s' method='post'>\n%s\n<input type='submit' value='Login'></form>\n",
18 rodolico 71
         'edit form'  => "<form class='login_form' action='%s' method='post'>\n%s\n<input type='submit' name='btnUpdate' value='Update'>\n</form>",
7 rodolico 72
         'loginScreen' => "<div class='login_field'>\n<input class='login_field' type='text' name='username' placeholder='Username' required autofocus>\n</div>\n<div class='login_field'>\n<input class='login_field' type='password' name='password' placeholder='Password' required>\n</div>",
4 rodolico 73
         'adminScreen' => "<input type='hidden' name='doAdmin' value='1'>\n",
74
         'validateScript' => '',
75
         ),
76
      'html input fields' => array(
77
            'text'      => "<div class='login_field'>\n<label>%s\n<input class='login_field' type='text' name='%s' title='%s' placeholder='%s' value='~~%s~~'>\n</label>\n</div>",
78
            'password'  => "<div class='login_field'>\n<label>%s\n<input class='login_field' type='password' name='%s' title='%s' placeholder='%s'>\n</label>\n</div>",
79
            'boolean'   => "<div class='login_field'>\n<label>%s\n<input class='login_field' type='checkbox' name='%s' title='%s' value='1' %s ~~%s~~>\n</label>\n</div>",
80
            'textarea'  => "<div class='login_field'>\n<label>%s\n<textarea class='login_field' name='%s' title='%s' placeholder='%s'>~~%s~~</textarea>\n</label>\n</div>",
81
         ),
82
      'input prefix' => 'admin_', // prefix the name with this in a form
83
      'tables'    => array(
84
         'users'  => array(
85
            'table'     => '_users',   // table name for user records
86
            'id'        => '_user_id', // ID column name
87
            'display'   => array(      // fields which are displayed to select
88
               'login'
89
               ),         
90
            'form test' => 'login',    // field to test if form submitted
91
            'fields' => array(
92
               'login'  => array(
93
                     'label'        => 'Username',       // login name column name
94
                     'html type'    => 'text',
10 rodolico 95
                     'filter'       => '/^[a-zA-Z0-9_]+$/',
4 rodolico 96
                     'instructions' => 'Username can only contain alpha numerics and an underscore',
21 rodolico 97
                     'hint'         => 'Change User Name',
98
                     'unique'       => true
4 rodolico 99
                     ),
100
               'pass'   => array( 
101
                     'label'        => 'Password',    // password column name
102
                     'html type'    => 'password',
103
                     'instructions' => 'Leave blank to keep same password',
104
                     'hint'         => 'Change Password'
105
                     ),
106
               'admin'  => array(
107
                     'label'        => 'isAdmin',
108
                     'html type'    => 'boolean',
109
                     'restrict'     => true,
110
                     'instructions' => 'If checked, user will be able to add/edit users',
111
                     ),
112
               'enabled' => array(
113
                     'label'        => 'Enabled',
114
                     'html type'    => 'boolean',
115
                     'restrict'     => true,
116
                     'instructions' => 'Uncheck to disable log in',
117
                     ),
118
               ) // fields
119
            ) // table users
120
         ) // tables
121
      );
122
 
7 rodolico 123
   /** @var string[] $data Contains the information for the current logged in user */
16 rodolico 124
   protected $data = array();
7 rodolico 125
   /** @var string[] $errors Contains errors that can occur */
16 rodolico 126
   protected $errors = array();
7 rodolico 127
   /** @var string[] $workingOn During administration, contains the record being modified */
16 rodolico 128
   protected $workingOn = array();
7 rodolico 129
 
130
   /**
131
    * constructor for an instance of the class
132
    * 
16 rodolico 133
    * Anything in $customFields will be recursively merged with $configuration, overwriting
7 rodolico 134
    * as necessary.
135
    * 
16 rodolico 136
    * @param string[] $customFields array to merge into $configuration
7 rodolico 137
    */
4 rodolico 138
   public function __construct( $customFields = array() ) {
139
      if ( $customFields ) {
16 rodolico 140
         $this->configuration = array_merge_recursive( $this->configuration, $customFields );
4 rodolico 141
      }
142
   } // constructor
143
 
7 rodolico 144
   /**
32 rodolico 145
    * generic getter to retrieve stuff from $this->data
146
    * 
147
    * Just looks for the key and returns the value, or null if not found
148
    * 
149
    * @param string[] $name key to look up in $this->data
150
    * 
151
    * @return string $this->data[$name], or null if not set
152
    */
153
   public function __get( $name ) {
154
      return isset( $this->data[$name] ) ? $this->data[$name] : null;
155
   }
156
 
157
   /**
158
    * Checks if $name exists in $this->data
159
    * 
160
    * @param string[] $name key to look up in $this->data
161
    * 
162
    * @return bool true if $this->data[$name] is set
163
    */
164
   public function __isset( $name ) {
165
      return isset( $this->data[$name] );
166
   }
167
 
168
 
169
   /**
7 rodolico 170
    * getter for $this->errors
171
    * 
172
    * @return string html div containing one paragraph for every error
173
    */
174
   public function errors() {
175
      $return = "<p>" . implode( "</p>\n<p>", $this->errors ) . "</p>\n";
176
      return "<div class='login_errors'>\n$return</div>\n";
177
   }
178
 
179
   /**
180
    * clears the errors array
181
    */
182
   public function clearErrors() {
183
      $this->errors = array();
184
   }
185
 
186
   /**
187
    * getter for isAdmin
188
    * 
189
    * @return boolean true if user is an admin, false if not
190
    */
4 rodolico 191
   public function isAdmin() {
192
      return $this->data['admin'];
193
   }
194
 
7 rodolico 195
   /**
196
    * getter for login name
197
    * 
198
    * @return string user name 
199
    */
4 rodolico 200
   public function name() {
201
      return isset( $this->data['login'] ) ? $this->data['login'] : null;
202
   }
203
 
7 rodolico 204
 
205
   /**
206
    * Main display function.
207
    * 
208
    * This function should be called to perform the login. It performs all functions
209
    * needed to log in and validate, but once logged in, will return an empty string.
210
    * 
211
    * @param usersDataSource $connection A connection to the data source
212
    * @param string $nextScript The url to be run when logged in
213
    * 
214
    * @return string A (possibly empty) HTML div
215
    */
4 rodolico 216
   public function HTML( $connection, $nextScript = null ) {
217
      if ( isset( $_REQUEST['username'], $_REQUEST['password'] ) ) {
218
         $this->validate( $_REQUEST['username'], $_REQUEST['password'], $connection );
219
      }
220
      if ( isset( $_REQUEST['logout'] ) && $_REQUEST['logout'] == 'Logout' ) {
221
         $this->logOut();
222
      }
223
      if ( ! isset( $this->data['login'], $this->data['id'] ) ) {
224
         return $this->logInScreen();
225
      }
226
   }
227
 
7 rodolico 228
   /**
229
    * Validates a connection and, on success, populates $data
230
    * 
231
    * Function will validate the username and password passed in, using
232
    * data connection $connection. On success, populates class member $data
16 rodolico 233
    * with the values from the database (only those listed in $configuration)
7 rodolico 234
    * 
235
    * On Failure, appends $error with a failure string
236
    * 
237
    * @param string $username The username to be matched in database
238
    * @param string $password The password (unencrypted) the user entered
239
    * @param usersDataSource $connection A connection to the data source
240
    * 
241
    */
16 rodolico 242
   protected function validate( $username, $password, $connection ) {
4 rodolico 243
      $result = $connection->getPassword( $username );
244
      if ( password_verify( $password, $result['pass'] ) ) {
18 rodolico 245
         $result = $connection->getARecord( array( 'login' => $username ) );
4 rodolico 246
         $this->data['id'] = $result['id'];
16 rodolico 247
         foreach ( $this->configuration['tables']['users']['fields'] as $key => $record ) {
4 rodolico 248
            if ( $key != 'pass' )
249
               $this->data[$key] = $result[$key];
250
         }
17 rodolico 251
         return true;
4 rodolico 252
      } else {
7 rodolico 253
         $this->errors[] = 'Login Failed: Unknown username or password';
16 rodolico 254
         foreach ( $this->configuration['tables']['users']['fields'] as $key => $record ) {
4 rodolico 255
            $this->data[$key] = null;
256
         }
17 rodolico 257
         return false;
4 rodolico 258
      }
259
   } // validate
260
 
7 rodolico 261
   /**
262
    * Get all users from data source and put them in an HTML list
263
    * 
264
    * Will retrieve the ID and login name of all users, putting them
265
    * in a list of anchors to allow an admin to select one for editing
266
    * 
267
    * @param  usersDataSource $connection A connection to the data source
268
    * @param string $nextPage The URL of the page to be used in the link
269
    * 
270
    * @return  string   an unordered list (UL) containing links with names
271
    */
4 rodolico 272
   public function allUsersHTML ( $connection, $nextPage = null ) {
273
      $nextPage = self::getNextScript( $nextPage );
274
      $return = '';
275
      $allUsers = $connection->getAllUsers();
276
      foreach ( $allUsers as $row ) {
277
         if ( $row['id'] == $this->data['id'] ) // don't do ourselves
278
            continue;
279
         $return .= sprintf( "<li><a href='$nextPage?doAdmin=1&id=%s'>%s</a></li>\n", $row['id'], $row['login'] );
280
      }
281
      $return .= sprintf( "<li><a href='$nextPage?doAdmin=1&id=%s'>%s</a></li>\n", -1, 'Add New User' );
282
      // wrap in ul, then put a div around it
283
      $return = "<ul class='login_list'>\n$return\n</ul>\n";
284
      $return = "<div class='login_list'>\n$return\n</div>\n";
285
      return $return;
286
   }
287
 
7 rodolico 288
   /**
289
    * Logs user out of system
290
    * 
291
    * destroys itself ($_SESSION['user'], then session, then calls
292
    * $nextScript by doing a header call.
293
    * 
294
    * @param string $nextScript URL of next script to call
295
    */
4 rodolico 296
   public function logOut( $nextScript = null ) {
297
      $nextScript = $this->getNextScript( $nextScript );
298
      $_SESSION['user'] = null;
299
      session_destroy();
300
      header( "Location: $nextScript" );
301
   }
302
 
7 rodolico 303
   /**
304
    * Simple helper script to calculate next script to call
305
    * 
306
    * Returns one of three URL strings, in order of precedence
307
    * $nextScript
16 rodolico 308
    * $configuration['screens']['validateScript']
7 rodolico 309
    * PHP_SELF
310
    * 
311
    * @param string $nextScript URL to call
312
    * @return string URL
313
    */
16 rodolico 314
   protected function getNextScript( $nextScript = null ) {
4 rodolico 315
      if ( ! isset( $nextScript ) ) {
16 rodolico 316
         $nextScript = $this->configuration['screens']['validateScript'] ?:
4 rodolico 317
                           htmlentities($_SERVER["PHP_SELF"]);
318
      }
319
      return $nextScript;
320
   }
321
 
7 rodolico 322
   /**
323
    * Creates the fields needed for a login screen
324
    * 
325
    * Populates %s's in 'login form' with values for $nextScript and
326
    * 'loginScreen'
327
    * 
328
    * @param string $nextScript URL to call form
329
    * 
330
    * @return string HTML code for display
331
    */
16 rodolico 332
   protected function logInScreen( $nextScript = null ) {
7 rodolico 333
      $return =  sprintf( 
16 rodolico 334
         $this->configuration['screens']['login form'],
4 rodolico 335
         $this->getNextScript( $nextScript ),
16 rodolico 336
         $this->configuration['screens']['loginScreen']
4 rodolico 337
      );
7 rodolico 338
      $return .= $this->errors();
339
      $this->clearErrors();
340
      return $return;
4 rodolico 341
   }
342
 
7 rodolico 343
   /**
344
    * Creates an HTML field for display
345
    * 
346
    * Retrieves the template for the record type, then populates it from
347
    * $record, $value and $field. The template MUST have %s's in the 
348
    * following order for an HTML INPUT field
349
    * label=
350
    * name=
351
    * title=
352
    * placeholder=
353
    * value
354
    * 
355
    * Knows how to handle INPUT types TEXT, TEXTAREA, PASSWORD and 
356
    * special html type boolean, which is checkboxes.
357
    * 
358
    * @param string $field name of the field to populate
16 rodolico 359
    * @param string[] $record Record from $configuration[...][fields]
7 rodolico 360
    * @param string $value the current value to put in INPUT
361
    * 
362
    * @return string An HTML INPUT entity
363
    */
16 rodolico 364
   protected function makeHTMLField ( $field, $record, $value ) {
4 rodolico 365
      $return = array();
16 rodolico 366
      $temp = sprintf( $this->configuration['html input fields'][$record['html type']], 
4 rodolico 367
                        $record['label'] ?: $field,
16 rodolico 368
                        $this->configuration['input prefix'] . $field, 
4 rodolico 369
                        !empty($record['instructions']) ? $record['instructions'] : '',
370
                        !empty($record['hint']) ? $record['hint'] : '',
371
                        $field
372
                     );
373
 
374
      switch ($record['html type'] ) {
375
         case 'text':
376
         case 'textarea':
377
                        $temp = preg_replace( "/~~$field~~/", isset( $value ) ? $value : '', $temp );
378
                        break;
379
         case 'password' :
380
                        break;
381
         case 'boolean' :  // boolean is set by checkboxes
382
                        $temp = preg_replace( "/~~$field~~/", $value ? 'checked' : '', $temp );
383
                        break;
384
      } // case
385
      return $temp;
386
 
387
   } // makeHTMLField
388
 
7 rodolico 389
   /**
390
    * Creates an edit screen for display to user
391
    * 
392
    * This function will create an edit screen which, when displayed to
393
    * the user, allows them to edit a users record. The record is stored
394
    * in $this->workingOn
395
    * 
396
    * Function will go through each field in the users table and call makeHTMLField
397
    * for it, unless the field is restricted and the user is editing their own
398
    * entry. It will also create a hidden input field with the users ID
399
    * 
400
    * NOTE: this will not create the form; the form is created someplace else
401
    * 
402
    * @return string HTML containing all of the INPUT records a user can edit
403
    */
17 rodolico 404
   public function editScreen( $connection ) {
4 rodolico 405
      $return = array();
16 rodolico 406
      $return[] = $this->configuration['screens']['adminScreen'];
18 rodolico 407
      $return[] = "<input type='hidden' name='id' value='" . $this->workingOn['id'] . "'>\n";
16 rodolico 408
      foreach ( $this->configuration['tables']['users']['fields'] as $field => $record ) {
4 rodolico 409
         // if this field is restricted and we are not admin, just skip it
410
         // also skip if it is our record
46 rodolico 411
         if ( ! empty( $record['restrict'] ) && ( $this->data['id'] == $this->workingOn['id'] ) )
4 rodolico 412
            continue;
413
         // now process the field
414
         $return[] = $this->makeHTMLField( $field, $record, $this->workingOn[$field] ?? '' );
415
      }
416
      return implode( "\n", $return );
417
   } // editScreen
418
 
7 rodolico 419
   /**
420
    * Creates a variable designed to replace $this->workingOn
421
    * 
422
    * Initializes all fields to something non-null and sets id to -1
423
    * 
424
    * @return string[] An array initialized with all records needed
425
    */
16 rodolico 426
   protected function emptyWorkingOn() {
4 rodolico 427
      $new = array();
428
      $new['id'] = -1;
16 rodolico 429
      foreach ( $this->configuration['tables']['users']['fields'] as $field => $record ) {
4 rodolico 430
         if ( isset( $record['default'] ) ) {
431
            $new[$field] = $record['default'];
432
         } else {
433
            switch ($record['html type']) {
434
               case 'text'    :
435
               case 'blob'    :  $new[$field] = '';
436
                                 break;
437
               case 'boolean' :  $new[$field] = 1;
438
                                 break;
439
               case 'password':  $new[$field] = '';
440
                                 break;
441
            }
442
         } // else
443
      } // foreach
444
      return $new;
445
   }
446
 
17 rodolico 447
   protected function addEdit( $connection ) {
448
      $data = array();
449
      foreach ( $this->configuration['tables']['users']['fields'] as $field => $record ) {
450
         // if this field is restricted it is our record, skip it
451
         if ( isset( $record['restrict'] ) && ( $this->data['id'] == $this->workingOn['id'] ) )
452
            continue;
453
         $htmlFieldName = $this->configuration['input prefix'] . $field;
454
         $temp = '';
455
         switch ( $record['html type'] ) {
456
            case 'password':
457
               if ( ! empty( $_REQUEST[$htmlFieldName] ) ) {
458
                  $data[$field] = password_hash( $_REQUEST[$htmlFieldName], PASSWORD_DEFAULT );
459
                  if ( isset( $this->configuration['tables']['users']['fields']['last password change'] ) ) {
460
                     $data['last password change'] = date("YmdHis");
461
                  }
462
               }
463
               break;
464
            case 'boolean' :
465
               if ( $this->workingOn['id'] == -1 || ( isset( $_REQUEST[$htmlFieldName] ) != $this->workingOn[$field] ) ) {
466
                  $data[$field] = isset( $_REQUEST[$htmlFieldName] ) ? 1 : 0;
467
               }
468
               break;
469
            default : // text, textarea, other things like this
470
               if ( $this->workingOn['id'] == -1 || ( isset( $_REQUEST[$htmlFieldName] ) && $_REQUEST[$htmlFieldName] !== $this->workingOn[$field] ) ) {
471
                  $data[$field] = $_REQUEST[$htmlFieldName];
472
                  if ( isset( $record['filter'] ) && preg_match( $record['filter'], $data[$field] ) !== 1 ) {
473
                     $this->errors[] = sprintf( "Invalid characters in %s, %s", $record['label'], $record['instructions'] );
474
                     unset( $data[$field] );
475
                  }
476
               }
477
               break;
478
         } // switch
479
      } // foreach
480
      if ( count($this->errors) ) { // we have some errors
481
         $this->errors[] = 'Record not updated';
482
         return 'Error';
483
      }
484
      if ( $data ) {
485
         $data['id'] = $this->workingOn['id'];
486
         $return = $connection->update( $data ) ? "Updated" : "Failed";
487
      } else {
488
         $return = "No changes";
489
      }
490
   }
491
 
492
   protected function initWorkingOn( $connection, $id ) {
18 rodolico 493
      if ( ! isset($id) || $id == $this->data['id'] ) { // we're working on ourself
17 rodolico 494
         $this->workingOn = $this->data;
18 rodolico 495
      } elseif ( $id == -1 ) { // a new user
496
         $this->workingOn = $this->emptyWorkingOn();
497
      } else { // this is an existing user
498
         $this->workingOn = $connection->getARecord( array( 'id' => $id ) );
17 rodolico 499
      }
18 rodolico 500
   } // initWorkingOn
17 rodolico 501
 
18 rodolico 502
 
503
 
7 rodolico 504
   /**
505
    * Sets up the admin function which allows users to edit themselves and, optionally, others
506
    * 
507
    * This should be called the first time, then repeatedly called until it is done
508
    * (it returns the string "Updated", "Failed" or "No changes".
509
    * 
510
    * The first iteration returns an edit screen displaying the users
511
    * information for them to edit. It will display an HTML INPUT for
512
    * each field that is not restricted. The user can then edit the
513
    * chosen entries and press the button, which will call the script
514
    * again, and update the record.
515
    * 
516
    * If the user has the admin right, the Edit screen also displays a 
517
    * list of all users as an unsigned list of anchors. If the user 
518
    * clicks on one of those, it will choose that user, load their data
519
    * and allow the user to edit that users record. NOTE: this is the
520
    * only way to edit fields with the restrict flag set.
521
    * 
522
    * @param  usersDataSource $connection A connection to the data source
523
    * @param string $nextPage The URL of the page to be used in the link
524
    * 
525
    * @return string This may be an HTML table or a single screen
526
    */
4 rodolico 527
   public function admin ( $connection, $nextScript = null ) {
18 rodolico 528
      /*
529
       * Entering for first time, 
530
       *    admin=1, $workingOn not set
531
       *    update workingOn
532
       *    display screen
533
       * entering after selecting a user
534
       *    doAdmin=1, id=#, $workingOn[id] <> id
535
       *    update workingOn
536
       *    display screen
537
       * Have pressed update button
538
       *    update
539
       */
540
 
4 rodolico 541
      $nextScript = $this->getNextScript( $nextScript );
18 rodolico 542
      $id = isset($_REQUEST['id']) ? $_REQUEST['id'] : null;
19 rodolico 543
      $return = array();
544
      if ( ! $this->workingOn || $this->workingOn['id'] != $id ) {
545
         // display screen for data entry
546
         //$return[] = 'Initializing $workingOn';
18 rodolico 547
         $this->initWorkingOn( $connection, $id );
19 rodolico 548
         //$return[] = "<pre>WorkingOn\n" . print_r( $this->workingOn, true) . '</pre>';
549
         $screen = $this->editScreen( $connection );
4 rodolico 550
         if ( $this->data['admin'] ) {
19 rodolico 551
            $screen .= $this->allUsersHTML( $connection );
4 rodolico 552
         }
19 rodolico 553
         $return[] = sprintf( $this->configuration['screens']['edit form'],
4 rodolico 554
            $nextScript,
19 rodolico 555
            $screen
4 rodolico 556
            );
18 rodolico 557
      } elseif ( $_SERVER['REQUEST_METHOD'] === 'POST' ) { // they submitted the form
19 rodolico 558
         //$return[] = 'Posting';
559
         $return[] = $this->addEdit( $connection );
18 rodolico 560
         /*
561
          * if ( $this->workingOn['id'] == $this->data['id'] ) // we just updated us, reload record
562
            $this->data = $connection->getARecord( array( 'id' => $this->data['id'] ) );
563
         */
4 rodolico 564
         unset( $this->workingOn );
19 rodolico 565
      } else {
566
         print "<h3>We're in the damned 'else' in admin</h3>";
18 rodolico 567
      }
19 rodolico 568
      return implode( "<br />\n", $return );
4 rodolico 569
   } // admin
570
 
571
} // class Users
572
 
573
?>