Subversion Repositories php_users

Rev

Rev 46 | 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
 
48 rodolico 204
   /**
205
    * getter for user ID
206
    * 
207
    * @return int id
208
    */
209
   public function id() {
210
      return isset( $this->data['id'] ) ? $this->data['id'] : null;
211
   }
7 rodolico 212
 
48 rodolico 213
 
7 rodolico 214
   /**
215
    * Main display function.
216
    * 
217
    * This function should be called to perform the login. It performs all functions
218
    * needed to log in and validate, but once logged in, will return an empty string.
219
    * 
220
    * @param usersDataSource $connection A connection to the data source
221
    * @param string $nextScript The url to be run when logged in
222
    * 
223
    * @return string A (possibly empty) HTML div
224
    */
4 rodolico 225
   public function HTML( $connection, $nextScript = null ) {
226
      if ( isset( $_REQUEST['username'], $_REQUEST['password'] ) ) {
227
         $this->validate( $_REQUEST['username'], $_REQUEST['password'], $connection );
228
      }
229
      if ( isset( $_REQUEST['logout'] ) && $_REQUEST['logout'] == 'Logout' ) {
230
         $this->logOut();
231
      }
232
      if ( ! isset( $this->data['login'], $this->data['id'] ) ) {
233
         return $this->logInScreen();
234
      }
235
   }
236
 
7 rodolico 237
   /**
238
    * Validates a connection and, on success, populates $data
239
    * 
240
    * Function will validate the username and password passed in, using
241
    * data connection $connection. On success, populates class member $data
16 rodolico 242
    * with the values from the database (only those listed in $configuration)
7 rodolico 243
    * 
244
    * On Failure, appends $error with a failure string
245
    * 
246
    * @param string $username The username to be matched in database
247
    * @param string $password The password (unencrypted) the user entered
248
    * @param usersDataSource $connection A connection to the data source
249
    * 
250
    */
16 rodolico 251
   protected function validate( $username, $password, $connection ) {
4 rodolico 252
      $result = $connection->getPassword( $username );
253
      if ( password_verify( $password, $result['pass'] ) ) {
18 rodolico 254
         $result = $connection->getARecord( array( 'login' => $username ) );
4 rodolico 255
         $this->data['id'] = $result['id'];
16 rodolico 256
         foreach ( $this->configuration['tables']['users']['fields'] as $key => $record ) {
4 rodolico 257
            if ( $key != 'pass' )
258
               $this->data[$key] = $result[$key];
259
         }
17 rodolico 260
         return true;
4 rodolico 261
      } else {
7 rodolico 262
         $this->errors[] = 'Login Failed: Unknown username or password';
16 rodolico 263
         foreach ( $this->configuration['tables']['users']['fields'] as $key => $record ) {
4 rodolico 264
            $this->data[$key] = null;
265
         }
17 rodolico 266
         return false;
4 rodolico 267
      }
268
   } // validate
269
 
7 rodolico 270
   /**
271
    * Get all users from data source and put them in an HTML list
272
    * 
273
    * Will retrieve the ID and login name of all users, putting them
274
    * in a list of anchors to allow an admin to select one for editing
275
    * 
276
    * @param  usersDataSource $connection A connection to the data source
277
    * @param string $nextPage The URL of the page to be used in the link
278
    * 
279
    * @return  string   an unordered list (UL) containing links with names
280
    */
4 rodolico 281
   public function allUsersHTML ( $connection, $nextPage = null ) {
282
      $nextPage = self::getNextScript( $nextPage );
283
      $return = '';
284
      $allUsers = $connection->getAllUsers();
285
      foreach ( $allUsers as $row ) {
286
         if ( $row['id'] == $this->data['id'] ) // don't do ourselves
287
            continue;
288
         $return .= sprintf( "<li><a href='$nextPage?doAdmin=1&id=%s'>%s</a></li>\n", $row['id'], $row['login'] );
289
      }
290
      $return .= sprintf( "<li><a href='$nextPage?doAdmin=1&id=%s'>%s</a></li>\n", -1, 'Add New User' );
291
      // wrap in ul, then put a div around it
292
      $return = "<ul class='login_list'>\n$return\n</ul>\n";
293
      $return = "<div class='login_list'>\n$return\n</div>\n";
294
      return $return;
295
   }
296
 
7 rodolico 297
   /**
298
    * Logs user out of system
299
    * 
300
    * destroys itself ($_SESSION['user'], then session, then calls
301
    * $nextScript by doing a header call.
302
    * 
303
    * @param string $nextScript URL of next script to call
304
    */
4 rodolico 305
   public function logOut( $nextScript = null ) {
306
      $nextScript = $this->getNextScript( $nextScript );
307
      $_SESSION['user'] = null;
308
      session_destroy();
309
      header( "Location: $nextScript" );
310
   }
311
 
7 rodolico 312
   /**
313
    * Simple helper script to calculate next script to call
314
    * 
315
    * Returns one of three URL strings, in order of precedence
316
    * $nextScript
16 rodolico 317
    * $configuration['screens']['validateScript']
7 rodolico 318
    * PHP_SELF
319
    * 
320
    * @param string $nextScript URL to call
321
    * @return string URL
322
    */
16 rodolico 323
   protected function getNextScript( $nextScript = null ) {
4 rodolico 324
      if ( ! isset( $nextScript ) ) {
16 rodolico 325
         $nextScript = $this->configuration['screens']['validateScript'] ?:
4 rodolico 326
                           htmlentities($_SERVER["PHP_SELF"]);
327
      }
328
      return $nextScript;
329
   }
330
 
7 rodolico 331
   /**
332
    * Creates the fields needed for a login screen
333
    * 
334
    * Populates %s's in 'login form' with values for $nextScript and
335
    * 'loginScreen'
336
    * 
337
    * @param string $nextScript URL to call form
338
    * 
339
    * @return string HTML code for display
340
    */
16 rodolico 341
   protected function logInScreen( $nextScript = null ) {
7 rodolico 342
      $return =  sprintf( 
16 rodolico 343
         $this->configuration['screens']['login form'],
4 rodolico 344
         $this->getNextScript( $nextScript ),
16 rodolico 345
         $this->configuration['screens']['loginScreen']
4 rodolico 346
      );
7 rodolico 347
      $return .= $this->errors();
348
      $this->clearErrors();
349
      return $return;
4 rodolico 350
   }
351
 
7 rodolico 352
   /**
353
    * Creates an HTML field for display
354
    * 
355
    * Retrieves the template for the record type, then populates it from
356
    * $record, $value and $field. The template MUST have %s's in the 
357
    * following order for an HTML INPUT field
358
    * label=
359
    * name=
360
    * title=
361
    * placeholder=
362
    * value
363
    * 
364
    * Knows how to handle INPUT types TEXT, TEXTAREA, PASSWORD and 
365
    * special html type boolean, which is checkboxes.
366
    * 
367
    * @param string $field name of the field to populate
16 rodolico 368
    * @param string[] $record Record from $configuration[...][fields]
7 rodolico 369
    * @param string $value the current value to put in INPUT
370
    * 
371
    * @return string An HTML INPUT entity
372
    */
16 rodolico 373
   protected function makeHTMLField ( $field, $record, $value ) {
4 rodolico 374
      $return = array();
16 rodolico 375
      $temp = sprintf( $this->configuration['html input fields'][$record['html type']], 
4 rodolico 376
                        $record['label'] ?: $field,
16 rodolico 377
                        $this->configuration['input prefix'] . $field, 
4 rodolico 378
                        !empty($record['instructions']) ? $record['instructions'] : '',
379
                        !empty($record['hint']) ? $record['hint'] : '',
380
                        $field
381
                     );
382
 
383
      switch ($record['html type'] ) {
384
         case 'text':
385
         case 'textarea':
386
                        $temp = preg_replace( "/~~$field~~/", isset( $value ) ? $value : '', $temp );
387
                        break;
388
         case 'password' :
389
                        break;
390
         case 'boolean' :  // boolean is set by checkboxes
391
                        $temp = preg_replace( "/~~$field~~/", $value ? 'checked' : '', $temp );
392
                        break;
393
      } // case
394
      return $temp;
395
 
396
   } // makeHTMLField
397
 
7 rodolico 398
   /**
399
    * Creates an edit screen for display to user
400
    * 
401
    * This function will create an edit screen which, when displayed to
402
    * the user, allows them to edit a users record. The record is stored
403
    * in $this->workingOn
404
    * 
405
    * Function will go through each field in the users table and call makeHTMLField
406
    * for it, unless the field is restricted and the user is editing their own
407
    * entry. It will also create a hidden input field with the users ID
408
    * 
409
    * NOTE: this will not create the form; the form is created someplace else
410
    * 
411
    * @return string HTML containing all of the INPUT records a user can edit
412
    */
17 rodolico 413
   public function editScreen( $connection ) {
4 rodolico 414
      $return = array();
16 rodolico 415
      $return[] = $this->configuration['screens']['adminScreen'];
18 rodolico 416
      $return[] = "<input type='hidden' name='id' value='" . $this->workingOn['id'] . "'>\n";
16 rodolico 417
      foreach ( $this->configuration['tables']['users']['fields'] as $field => $record ) {
4 rodolico 418
         // if this field is restricted and we are not admin, just skip it
419
         // also skip if it is our record
46 rodolico 420
         if ( ! empty( $record['restrict'] ) && ( $this->data['id'] == $this->workingOn['id'] ) )
4 rodolico 421
            continue;
422
         // now process the field
423
         $return[] = $this->makeHTMLField( $field, $record, $this->workingOn[$field] ?? '' );
424
      }
425
      return implode( "\n", $return );
426
   } // editScreen
427
 
7 rodolico 428
   /**
429
    * Creates a variable designed to replace $this->workingOn
430
    * 
431
    * Initializes all fields to something non-null and sets id to -1
432
    * 
433
    * @return string[] An array initialized with all records needed
434
    */
16 rodolico 435
   protected function emptyWorkingOn() {
4 rodolico 436
      $new = array();
437
      $new['id'] = -1;
16 rodolico 438
      foreach ( $this->configuration['tables']['users']['fields'] as $field => $record ) {
4 rodolico 439
         if ( isset( $record['default'] ) ) {
440
            $new[$field] = $record['default'];
441
         } else {
442
            switch ($record['html type']) {
443
               case 'text'    :
444
               case 'blob'    :  $new[$field] = '';
445
                                 break;
446
               case 'boolean' :  $new[$field] = 1;
447
                                 break;
448
               case 'password':  $new[$field] = '';
449
                                 break;
450
            }
451
         } // else
452
      } // foreach
453
      return $new;
454
   }
455
 
17 rodolico 456
   protected function addEdit( $connection ) {
457
      $data = array();
458
      foreach ( $this->configuration['tables']['users']['fields'] as $field => $record ) {
459
         // if this field is restricted it is our record, skip it
460
         if ( isset( $record['restrict'] ) && ( $this->data['id'] == $this->workingOn['id'] ) )
461
            continue;
462
         $htmlFieldName = $this->configuration['input prefix'] . $field;
463
         $temp = '';
464
         switch ( $record['html type'] ) {
465
            case 'password':
466
               if ( ! empty( $_REQUEST[$htmlFieldName] ) ) {
467
                  $data[$field] = password_hash( $_REQUEST[$htmlFieldName], PASSWORD_DEFAULT );
468
                  if ( isset( $this->configuration['tables']['users']['fields']['last password change'] ) ) {
469
                     $data['last password change'] = date("YmdHis");
470
                  }
471
               }
472
               break;
473
            case 'boolean' :
474
               if ( $this->workingOn['id'] == -1 || ( isset( $_REQUEST[$htmlFieldName] ) != $this->workingOn[$field] ) ) {
475
                  $data[$field] = isset( $_REQUEST[$htmlFieldName] ) ? 1 : 0;
476
               }
477
               break;
478
            default : // text, textarea, other things like this
479
               if ( $this->workingOn['id'] == -1 || ( isset( $_REQUEST[$htmlFieldName] ) && $_REQUEST[$htmlFieldName] !== $this->workingOn[$field] ) ) {
480
                  $data[$field] = $_REQUEST[$htmlFieldName];
481
                  if ( isset( $record['filter'] ) && preg_match( $record['filter'], $data[$field] ) !== 1 ) {
482
                     $this->errors[] = sprintf( "Invalid characters in %s, %s", $record['label'], $record['instructions'] );
483
                     unset( $data[$field] );
484
                  }
485
               }
486
               break;
487
         } // switch
488
      } // foreach
489
      if ( count($this->errors) ) { // we have some errors
490
         $this->errors[] = 'Record not updated';
491
         return 'Error';
492
      }
493
      if ( $data ) {
494
         $data['id'] = $this->workingOn['id'];
495
         $return = $connection->update( $data ) ? "Updated" : "Failed";
496
      } else {
497
         $return = "No changes";
498
      }
499
   }
500
 
501
   protected function initWorkingOn( $connection, $id ) {
18 rodolico 502
      if ( ! isset($id) || $id == $this->data['id'] ) { // we're working on ourself
17 rodolico 503
         $this->workingOn = $this->data;
18 rodolico 504
      } elseif ( $id == -1 ) { // a new user
505
         $this->workingOn = $this->emptyWorkingOn();
506
      } else { // this is an existing user
507
         $this->workingOn = $connection->getARecord( array( 'id' => $id ) );
17 rodolico 508
      }
18 rodolico 509
   } // initWorkingOn
17 rodolico 510
 
18 rodolico 511
 
512
 
7 rodolico 513
   /**
514
    * Sets up the admin function which allows users to edit themselves and, optionally, others
515
    * 
516
    * This should be called the first time, then repeatedly called until it is done
517
    * (it returns the string "Updated", "Failed" or "No changes".
518
    * 
519
    * The first iteration returns an edit screen displaying the users
520
    * information for them to edit. It will display an HTML INPUT for
521
    * each field that is not restricted. The user can then edit the
522
    * chosen entries and press the button, which will call the script
523
    * again, and update the record.
524
    * 
525
    * If the user has the admin right, the Edit screen also displays a 
526
    * list of all users as an unsigned list of anchors. If the user 
527
    * clicks on one of those, it will choose that user, load their data
528
    * and allow the user to edit that users record. NOTE: this is the
529
    * only way to edit fields with the restrict flag set.
530
    * 
531
    * @param  usersDataSource $connection A connection to the data source
532
    * @param string $nextPage The URL of the page to be used in the link
533
    * 
534
    * @return string This may be an HTML table or a single screen
535
    */
4 rodolico 536
   public function admin ( $connection, $nextScript = null ) {
18 rodolico 537
      /*
538
       * Entering for first time, 
539
       *    admin=1, $workingOn not set
540
       *    update workingOn
541
       *    display screen
542
       * entering after selecting a user
543
       *    doAdmin=1, id=#, $workingOn[id] <> id
544
       *    update workingOn
545
       *    display screen
546
       * Have pressed update button
547
       *    update
548
       */
549
 
4 rodolico 550
      $nextScript = $this->getNextScript( $nextScript );
18 rodolico 551
      $id = isset($_REQUEST['id']) ? $_REQUEST['id'] : null;
19 rodolico 552
      $return = array();
553
      if ( ! $this->workingOn || $this->workingOn['id'] != $id ) {
554
         // display screen for data entry
555
         //$return[] = 'Initializing $workingOn';
18 rodolico 556
         $this->initWorkingOn( $connection, $id );
19 rodolico 557
         //$return[] = "<pre>WorkingOn\n" . print_r( $this->workingOn, true) . '</pre>';
558
         $screen = $this->editScreen( $connection );
4 rodolico 559
         if ( $this->data['admin'] ) {
19 rodolico 560
            $screen .= $this->allUsersHTML( $connection );
4 rodolico 561
         }
19 rodolico 562
         $return[] = sprintf( $this->configuration['screens']['edit form'],
4 rodolico 563
            $nextScript,
19 rodolico 564
            $screen
4 rodolico 565
            );
18 rodolico 566
      } elseif ( $_SERVER['REQUEST_METHOD'] === 'POST' ) { // they submitted the form
19 rodolico 567
         //$return[] = 'Posting';
568
         $return[] = $this->addEdit( $connection );
18 rodolico 569
         /*
570
          * if ( $this->workingOn['id'] == $this->data['id'] ) // we just updated us, reload record
571
            $this->data = $connection->getARecord( array( 'id' => $this->data['id'] ) );
572
         */
4 rodolico 573
         unset( $this->workingOn );
19 rodolico 574
      } else {
575
         print "<h3>We're in the damned 'else' in admin</h3>";
18 rodolico 576
      }
19 rodolico 577
      return implode( "<br />\n", $return );
4 rodolico 578
   } // admin
579
 
580
} // class Users
581
 
582
?>