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

  • EntryField
  • EntryForm
  • Overview
  • Package
  • Class
  • Tree
  • Deprecated
  • Todo
  1: <?php
  2: /**
  3: * Classes to handle entry and viewing of field-based data.
  4: *
  5: * @package   awl
  6: * @subpackage   DataEntry
  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
 10: */
 11: require_once("AWLUtilities.php");
 12: 
 13: /**
 14: * Individual fields used for data entry / viewing.
 15: *
 16: * This object is not really intended to be used directly.  The more normal
 17: * interface is to instantiate an {@link EntryForm} and then issue calls
 18: * to {@link DataEntryLine()} and other {@link EntryForm} methods.
 19: *
 20: * Understanding the operation of this class (and possibly auditing the source
 21: * code, particularly {@link EntryField::Render}) will however convey valuable
 22: * understanding of some of the more
 23: * esoteric features.
 24: *
 25: * @todo This class doesn't really provide a huge amount of utility between construct
 26: * and render, but there must be good things possible there.  Perhaps one EntryField
 27: * is created and used repeatedly as a template (e.g.).  That might be useful to
 28: * support...  Why is this a Class anyway?  Maybe we should have just done half a
 29: * dozen functions (one per major field type) and just used those...  Maybe we should
 30: * build a base class for this and extend it to make EntryField in a better way.
 31: *
 32: * EntryField is only useful at present if you desperately want to use it's simple
 33: * field interface, but want to intimately control the layout (or parts of the layout),
 34: * otherwise you should be using {@link EntryForm} as the main class.
 35: *
 36: * @package awl
 37: */
 38: class EntryField
 39: {
 40:   /**#@+
 41:   * @access private
 42:   */
 43:   /**
 44:   * The name of the field
 45:   * @var string
 46:   */
 47:   var $fname;
 48: 
 49:   /**
 50:   * The type of entry field
 51:   * @var string
 52:   */
 53:   var $ftype;
 54:   /**#@-*/
 55: 
 56:   /**#@+
 57:   * @access public
 58:   */
 59:   /**
 60:   * The current value
 61:   * @var string
 62:   */
 63:   var $current;
 64: 
 65:   /**
 66:   * An array of key value pairs
 67:   * @var string
 68:   */
 69:   var $attributes;
 70: 
 71:   /**
 72:   * Once it actually is...
 73:   * @var string
 74:   */
 75:   var $rendered;
 76:   /**#@-*/
 77: 
 78:   /**
 79:   * Initialise an EntryField, used for data entry.
 80:   *
 81:   * The following types of fields are possible:
 82:   * <ul>
 83:   * <li>select - Will display a select list of the keys/values in $attributes where the
 84:   * key starts with an underscore.  The key will have the '_' removed before being used
 85:   * as the key in the list.  All the $attributes with keys not beginning with '_' will
 86:   * be used in the normal manner as HTML attributes within the &lt;select ...&gt; tag.</li>
 87:   * <li>lookup - Will display a select list of values from the database.
 88:   * If $attributes defines a '_sql' attibute then that will be used to make
 89:   * the list, otherwise the database values will be from the 'codes' table
 90:   * as in "SELECT code_id, code_value FROM codes WHERE code_type = '_type' ORDER BY code_seq, code_id"
 91:   * using the value of $attributes['_type'] as the code_type.</li>
 92:   * <li>date - Will be a text field, expecting a date value which might be
 93:   * javascript validated at some point in the future.</li>
 94:   * <li>checkbox - Will display a checkbox for an on-off value.</li>
 95:   * <li>textarea - Will display an HTML textarea.</li>
 96:   * <li>file - Will display a file browse / enter field.</li>
 97:   * <li>button - Will display a button field.</li>
 98:   * <li>password - Password entry.  This will display entered data as asterisks.</li>
 99:   * </ul>
100:   *
101:   * The $attributes array is useful to set specific HTML attributes within the HTML tag
102:   * used for the entry field however $attribute keys named starting with an underscore ('_')
103:   * affect the field operation rather than the HTML.  For the 'select' field type, these are
104:   * simply used as the keys / values for the selection (with the '_' removed), but other
105:   * cases are more complex:
106:   * <ul>
107:   * <li>_help - While this will be ignored by the EntryField::Render() method the _help
108:   * should be assigned (or will be assigned the same value as the 'title' attribute) and
109:   * will (depending on the data-entry line format in force) be displayed as help for the
110:   * field by the EntryForm::DataEntryLine() method.</li>
111:   * <li>_sql - When used in a 'lookup' field this controls the SQL to return keys/values
112:   * for the list.  The actual SQL should return two columns, the first will be used for
113:   * the key and the second for the displayed value.</li>
114:   * <li>_type - When used in a 'lookup' field this defines the codes type used.</li>
115:   * <li>_null - When used in a 'lookup' field this will control the description for an
116:   * option using a '' key value which will precede the list of values from the database.</li>
117:   * <li>_zero - When used in a 'lookup' field this will control the description for an
118:   * option using a '0' key value which will precede the list of values from the database.</li>
119:   * <li>_label - When used in a 'radio' or 'checkbox' field this will wrap the field
120:   * with an HTML label tag as <label ...><input field...>$attributes['_label']</label></li>
121:   * <li> - </li>
122:   * </ul>
123:   *
124:   * @param text $intype The type of field:
125:   *    select | lookup | date | checkbox | textarea | file | button | password
126:   *    (anything else is dealt with as "text")
127:   *
128:   * @param text $inname The name of the field.
129:   *
130:   * @param text $attributes An associative array of extra attributes to be applied
131:   * to the field.  Optional, but generally important.  Some $attribute keys have
132:   * special meaning, while others are simply added as HTML attributes to the field.
133:   *
134:   * @param text $current_value The current value to use to initialise the
135:   *                     field.   Optional.
136:   */
137:   function EntryField( $intype, $inname, $attributes="", $current_value="" )
138:   {
139:     $this->ftype = $intype;
140:     $this->fname = $inname;
141:     $this->current = $current_value;
142: 
143:     if ( isset($this->{"new_$intype"}) && function_exists($this->{"new_$intype"}) ) {
144:       // Optionally call a function within this object called "new_<intype>" for setup
145:       $this->{"new_$intype"}( $attributes );
146:     }
147:     else if ( is_array($attributes) ) {
148:       $this->attributes = $attributes;
149:     }
150:     else {
151:     }
152: 
153:     $this->rendered = "";
154:   }
155: 
156:   /**
157:   * Render an EntryField into HTML
158:   * @see EntryField::EntryField(), EntryForm::DataEntryLine()
159:   *
160:   * @return text  An HTML fragment for the data-entry field.
161:   */
162:   function Render() {
163:     global $session;
164: 
165:     $r = "<";
166:     dbg_error_log( "EntryField", ":Render: Name: %s, Type: %s, Current: %s", $this->fname, $this->ftype, $this->current );
167:     $size = "";
168:     switch ( $this->ftype ) {
169: 
170:       case "select":
171:         $r .= "select name=\"$this->fname\"%%attributes%%>";
172:         reset( $this->attributes );
173:         while( list($k,$v) = each( $this->attributes ) ) {
174:           if ( substr($k, 0, 1) != '_' ) continue;
175:           if ( $k == '_help' ) continue;
176:           $k = substr($k,1);
177:           $r .= "<option value=\"".htmlspecialchars($k)."\"";
178:           if ( "$this->current" == "$k" ) $r .= " selected";
179:           $r .= ">$v</option>" ;
180:         }
181:         $r .= "</select>";
182:         break;
183: 
184:       case "lookup":
185:         $r .= "select name=\"$this->fname\"%%attributes%%>";
186:         reset( $this->attributes );
187:         while( list($k,$v) = each( $this->attributes ) ) {
188:           if ( substr($k, 0, 1) != '_' ) continue;
189:           $k = substr($k,1);
190:           if ( $k == 'help' || $k == "sql" || $k == "type" ) continue;
191:           if ( $k == "null" ) $k = "";
192:           if ( $k == "zero" ) $k = "0";
193:           $r .= "<option value=\"".htmlspecialchars($k)."\"";
194:           if ( "$this->current" == "$k" ) $r .= " selected";
195:           $r .= ">$v</option>" ;
196:         }
197:         if ( isset($this->attributes["_sql"]) ) {
198:           $qry = new PgQuery( $this->attributes["_sql"] );
199:         }
200:         else {
201:           $qry = new PgQuery( "SELECT code_id, code_value FROM codes WHERE code_type = ? ORDER BY code_seq, code_id", $this->attributes['_type'] );
202:         }
203:         $r .= EntryField::BuildOptionList( $qry, $this->current, "rndr:$this->fname", array('translate'=>1) );
204:         $r .= "</select>";
205:         break;
206: 
207:       case "date":
208:       case "timestamp":
209:         $size = '';
210:         if ( !isset($this->attributes['size']) || $this->attributes['size'] == "" ) $size = " size=" . ($this->ftype == 'date' ? "12" : "18");
211:         $r .= "input type=\"text\" name=\"$this->fname\"$size value=\"".$session->FormattedDate(htmlspecialchars($this->current))."\"%%attributes%%>";
212:         break;
213: 
214:       case "checkbox":
215:         // We send a hidden field with a false value, which will be overridden by the real
216:         // field with a true value (if true) or not overridden (if false).
217:         $r .= "input type=\"hidden\" name=\"$this->fname\" value=\"off\"><";
218:       case "radio":
219:         $checked = "";
220:         if ( $this->current === true || $this->current == 't' || intval($this->current) == 1 || $this->current == 'on'
221:               || (isset($this->attributes['value']) && $this->current == $this->attributes['value'] ) )
222:           $checked = " checked";
223:         $id = "id_$this->fname" . ( $this->ftype == "radio" ? "_".$this->attributes['value'] : "");
224:         if ( isset($this->attributes['_label']) ) {
225:           $r .= "label for=\"$id\"";
226:           if ( isset($this->attributes['class']) )
227:             $r .= ' class="'. $this->attributes['class'] . '"';
228:           $r .= "><";
229:         }
230:         $r .= "input type=\"$this->ftype\" name=\"$this->fname\" id=\"$id\"$checked%%attributes%%>";
231:         if ( isset($this->attributes['_label']) ) {
232:           $r .= " " . $this->attributes['_label'];
233:           $r .= "</label>";
234:         }
235:         break;
236: 
237:       case "button":
238:         $r .= "input type=\"button\" name=\"$this->fname\"%%attributes%%>";
239:         break;
240: 
241:       case "submit":
242:         $r .= "input type=\"submit\" name=\"$this->fname\" value=\"".htmlspecialchars($this->current)."\"%%attributes%%>";
243:         break;
244: 
245:       case "textarea":
246:         $r .= "textarea name=\"$this->fname\"%%attributes%%>$this->current</textarea>";
247:         break;
248: 
249:       case "file":
250:         if ( !isset($this->attributes['size']) || $this->attributes['size'] == "" ) $size = " size=25";
251:         $r .= "input type=\"file\" name=\"$this->fname\"$size value=\"".htmlspecialchars($this->current)."\"%%attributes%%>";
252:         break;
253: 
254:       case "password":
255:         $r .= "input type=\"password\" name=\"$this->fname\" value=\"".htmlspecialchars($this->current)."\"%%attributes%%>";
256:         break;
257: 
258:       default:
259:         $r .= "input type=\"text\" name=\"$this->fname\" value=\"".htmlspecialchars($this->current)."\"%%attributes%%>";
260:         break;
261:     }
262: 
263:     // Now process the generic attributes
264:     reset( $this->attributes );
265:     $attribute_values = "";
266:     while( list($k,$v) = each( $this->attributes ) ) {
267:       if ( $k == '_readonly' ) $attribute_values .= " readonly";
268:       else if ( $k == '_disabled' ) $attribute_values .= " disabled";
269:       if ( substr($k, 0, 1) == '_' ) continue;
270:       $attribute_values .= " $k=\"".htmlspecialchars($v)."\"";
271:     }
272:     $r = str_replace( '%%attributes%%', $attribute_values, $r );
273: 
274:     $this->rendered = $r;
275:     return $r;
276:   }
277: 
278:   /**
279:   * Function called indirectly when a new EntryField of type 'lookup' is created.
280:   * @param array $attributes The attributes array that was passed in to the new EntryField()
281:   * constructor.
282:   */
283:   function new_lookup( $attributes ) {
284:     $this->attributes = $attributes;
285:   }
286: 
287:   /**
288:   * Build an option list from the query.
289:   * @param string $current Default selection of drop down box (optional)
290:   * @param string $location for debugging purposes
291:   * @param array $parameters an array further parameters, including 'maxwidth' => 20 to set a maximum width
292:   * @return string Select box HTML
293:   */
294:   static function BuildOptionList( $qry, $current = '', $location = 'options', $parameters = false ) {
295:     global $debuggroups;
296:     $result = '';
297:     $translate = false;
298: 
299:     if ( isset($maxwidth) ) unset($maxwidth);
300:     if ( is_array($parameters) ) {
301:       if ( isset($parameters['maxwidth']) ) $maxwidth = max(4,intval($parameters['maxwidth']));
302:       if ( isset($parameters['translate']) ) $translate = true;
303:     }
304: 
305:     // The query may not have already been executed
306:     if ( $qry->rows() > 0 || $qry->Exec($location) ) {
307:       while( $row = $qry->Fetch(true) )
308:       {
309:         if (is_array($current)) {
310:           $selected = ( ( in_array($row[0],$current,true) || in_array($row[1],$current,true)) ? ' selected="selected"' : '' );
311:         }
312:         else {
313:           $selected = ( ( "$row[0]" == "$current" || "$row[1]" == "$current" ) ? ' selected="selected"' : '' );
314:         }
315:         $display_value = $row[1];
316:         if ( isset($translate) ) $display_value = translate( $display_value );
317:         if ( isset($maxwidth) ) $display_value = substr( $display_value, 0, $maxwidth);
318:         $nextrow = "<option value=\"".htmlspecialchars($row[0])."\"$selected>".htmlspecialchars($display_value)."</option>";
319:         $result .= $nextrow;
320:       }
321:     }
322:     return $result;
323:    }
324: 
325: }
326: 
327: /**
328: * A class to handle displaying a form on the page (for editing) or a structured
329: * layout of non-editable content (for viewing), with a simple switch to flip from
330: * view mode to edit mode.
331: *
332: * @package awl
333: */
334: class EntryForm
335: {
336:   /**#@+
337:   * @access private
338:   */
339:   /**
340:   * The submit action for the form
341:   * @var string
342:   */
343:   var $action;
344: 
345:   /**
346:   * The record that the form is dealing with
347:   * @var string
348:   */
349:   var $record;
350: 
351:   /**
352:   * Whether we are editing, or not
353:   * @var string
354:   */
355:   var $EditMode;
356: 
357:   /**
358:   * The name of the form
359:   * @var string
360:   */
361:   var $name;
362: 
363:   /**
364:   * The CSS class of the form
365:   * @var string
366:   */
367:   var $class;
368: 
369:   /**
370:   * Format string for lines that are breaks in the data entry field groupings
371:   * @var string
372:   */
373:   var $break_line_format;
374: 
375:   /**
376:   * Format string for normal data entry field lines.
377:   * @var string
378:   */
379:   var $table_line_format;
380: 
381:   /**
382:   * Format string that has been temporarily saved so we can restore it later
383:   * @var string
384:   */
385:   var $saved_line_format;
386:   /**#@-*/
387: 
388:   /**
389:   * Initialise a new data-entry form.
390:   * @param string $action The action when the form is submitted.
391:   * @param objectref $record A reference to the database object we are displaying / editing.
392:   * @param boolean $editmode Whether we are editing.
393:   */
394:   function EntryForm( $action, &$record, $editing=false )
395:   {
396:     $this->action   = $action;
397:     $this->record   = &$record;
398:     $this->EditMode = $editing;
399:     $this->break_line_format = '<tr><th class="ph" colspan="2">%s</th></tr>'."\n";
400:     $this->table_line_format = '<tr><th class="prompt">%s</th><td class="entry">%s<span class="help">%s</span></td></tr>'."\n";
401:   }
402: 
403:   /**
404:   * Initialise some more of the forms fields, possibly with a prefix
405:   * @param objectref $record A reference to the database object we are displaying / editing.
406:   * @param string $prefix A prefix to prepend to the field name.
407:   */
408:   function PopulateForm( &$record, $prefix="" )
409:   {
410:     foreach( $record AS $k => $v ) {
411:       $this->record->{"$prefix$k"} = $v;
412:     }
413:   }
414: 
415:   /**
416:   * Set the line format to have no help display
417:   */
418:   function NoHelp( ) {
419:     $this->break_line_format = '<tr><th class="ph" colspan="2">%s</th></tr>'."\n";
420:     $this->table_line_format = '<tr><th class="prompt">%s</th><td class="entry">%s</td></tr>'."\n";
421:   }
422: 
423:   /**
424:   * Set the line format to have help displayed in the same cell as the entry field.
425:   */
426:   function HelpInLine( ) {
427:     $this->break_line_format = '<tr><th class="ph" colspan="2">%s</th></tr>'."\n";
428:     $this->table_line_format = '<tr><th class="prompt">%s</th><td class="entry">%s<span class="help">%s</span></td></tr>'."\n";
429:   }
430: 
431:   /**
432:   * Set the line format to have help displayed in it's own separate cell
433:   */
434:   function HelpInCell( ) {
435:     $this->break_line_format = '<tr><th class="ph" colspan="3">%s</th></tr>'."\n";
436:     $this->table_line_format = '<tr><th class="prompt">%s</th><td class="entry">%s</td><td class="help">%s</td></tr>'."\n";
437:   }
438: 
439:   /**
440:   * Set the line format to an extremely simple CSS based prompt / field layout.
441:   */
442:   function SimpleForm( $new_format = '<span class="prompt">%s:</span>&nbsp;<span class="entry">%s</span>' ) {
443:     $this->break_line_format = '%s'."\n";
444:     $this->table_line_format = $new_format."\n";
445:   }
446: 
447:   /**
448:   * Set the line format to a temporary one that we can revert from.
449:   * @param string $new_format The (optional) new format we will temporarily use.
450:   */
451:   function TempLineFormat( $new_format = '<span class="prompt">%s:</span>&nbsp;<span class="entry">%s</span>' ) {
452:     $this->saved_line_format = $this->table_line_format;
453:     $this->table_line_format = $new_format ."\n";
454:   }
455: 
456:   /**
457:   * Revert the line format to what was in place before the last TempLineFormat call.
458:   */
459:   function RevertLineFormat( ) {
460:     if ( isset($this->saved_line_format) ) {
461:       $this->table_line_format = $this->saved_line_format;
462:     }
463:   }
464: 
465:   /**
466:   * Start the actual HTML form.  Return the fragment to do this.
467:   * @param array $extra_attributes Extra key/value pairs for the FORM tag.
468:   * @return string The HTML fragment for the start of the form.
469:   */
470:   function StartForm( $extra_attributes='' ) {
471:     if ( !is_array($extra_attributes) && $extra_attributes != '' ) {
472:       list( $k, $v ) = explode( '=', $extra_attributes );
473:       $extra_attributes = array( $k => $v );
474:     }
475:     $extra_attributes['action']  = $this->action;
476:     if ( !isset($extra_attributes['method']) )  $extra_attributes['method']  = 'post';
477:     if ( strtolower($extra_attributes['method']) != 'get' )
478:       if ( !isset($extra_attributes['enctype']) ) $extra_attributes['enctype'] = 'multipart/form-data';
479:     if ( !isset($extra_attributes['name']) )    $extra_attributes['name']    = 'form';
480:     if ( !isset($extra_attributes['class']) )   $extra_attributes['class']   = 'formdata';
481:     if ( !isset($extra_attributes['id']) )      $extra_attributes['id']      = $extra_attributes['name'];
482: 
483:     // Now process the generic attributes
484:     reset( $extra_attributes );
485:     $attribute_values = "";
486:     while( list($k,$v) = each( $extra_attributes ) ) {
487:       $attribute_values .= " $k=\"".htmlspecialchars($v)."\"";
488:     }
489:     return "<form$attribute_values>\n";
490:   }
491: 
492:   /**
493:   * Return the HTML fragment to end the form.
494:   * @return string The HTML fragment to end the form.
495:   */
496:   function EndForm( ) {
497:     return "</form>\n";
498:   }
499: 
500:   /**
501:   * A utility function for a heading line within a data entry table
502:   * @return string The HTML fragment to end the form.
503:   */
504:   function BreakLine( $text = '' )
505:   {
506:     return sprintf( $this->break_line_format, translate($text));
507:   }
508: 
509:   /**
510:   * A utility function for a hidden field within a data entry table
511:   *
512:   * @param string $fname The name of the field.
513:   * @param string $fvalue The value of the field.
514:   * @return string The HTML fragment for the hidden field.
515:   */
516:   function HiddenField($fname,$fvaluei,$fid = null) {
517:     return sprintf( '<input type="hidden" name="%s" value="%s" %s/>%s', $fname,
518:                                htmlspecialchars($fvalue), (isset($id) ? 'id="$id" ' : ''), "\n" );
519:   }
520: 
521:   /**
522:   * Internal function for parsing the type extra on a field.
523:   *
524:   * If the '_help' attribute is not set it will be assigned the value of
525:   * the 'title' attribute, if there is one.
526:   *
527:   * If the 'class' attribute is not set it will be assigned to 'flookup',
528:   * 'fselect', etc, according to the field type.
529:   * @static
530:   * @return string The parsed type extra.
531:   */
532:   function _ParseAttributes( $ftype = '', $attributes = '' )  {
533: 
534:     if ( !is_array($attributes) ) {
535:       if ( strpos( $attributes, '=' ) === false ) {
536:         $attributes = array();
537:       }
538:       else {
539:         list( $k, $v ) = explode( '=', $attributes );
540:         $attributes = array( $k => $v );
541:       }
542:     }
543: 
544:     // Default the help to the title, or to blank
545:     if ( !isset($attributes['_help']) ) {
546:       $attributes['_help'] = "";
547:       if ( isset($attributes['title']) )
548:         $attributes['_help'] = $attributes['title'];
549:     }
550: 
551:     // Default the style to fdate, ftext, fcheckbox etc.
552:     if ( !isset($attributes['class']) ) {
553:       $attributes['class'] = "f$ftype";
554:     }
555: 
556:     return $attributes;
557:   }
558: 
559:   /**
560:   * A utility function for a data entry line within a table
561:   * @return string The HTML fragment to display the data entry field
562:   */
563:   function DataEntryField( $format, $ftype='', $base_fname='', $attributes='', $prefix='' )
564:   {
565:     global $session;
566: 
567:     if ( ($base_fname == '' || $ftype == '') ) {
568:       // Displaying never-editable values
569:       return $format;
570:     }
571:     $fname = $prefix . $base_fname;
572: 
573:     dbg_error_log( "DataEntry", ":DataEntryField: fmt='%s', fname='%s', fvalue='%s'", $format, $fname, (isset($this->record->{$fname})?$this->record->{$fname}:'value not set') );
574:     if ( !$this->EditMode ) {
575:       /** For some forms we prefix the field name with xxxx so it doesn't collide with the real DB field name. */
576:       if ( !isset($this->record->{$fname}) && substr($fname,0,4) == 'xxxx' && isset($this->record->{substr($fname,4)}) )
577:         $fname = substr($fname,4);
578:       if ( !isset($this->record->{$fname}) ) return '';
579:       /** If it is a date, then format it according to the current user's date format type */
580:       if ($ftype == "date" || $ftype == "timestamp")
581:         return sprintf($format, $session->FormattedDate($this->record->{$fname}) );
582:       dbg_error_log( "DataEntry", ":DataEntryField: fmt='%s', fname='%s', fvalue='%s'", $format, $fname, (isset($this->record->{$fname})?$this->record->{$fname}:'value not set') );
583:       return sprintf($format, $this->record->{$fname} );
584:     }
585: 
586:     $currval = '';
587:     // Get the default value, preferably from $_POST
588:     if ( preg_match("/^(.+)\[(.+)\]$/", $fname, $parts) ) {
589:       $p1 = $parts[1];
590:       $p2 = $parts[2];
591:       @dbg_error_log( "DataEntry", ":DataEntryField: fname=%s, p1=%s, p2=%s, POSTVAL=%s, \$this->record->{'%s'}['%s']=%s",
592:                                                   $fname, $p1, $p2, $_POST[$p1][$p2], $p1, $p2, $this->record->{"$p1"}["$p2"] );
593:       // @todo This could be changed to handle more dimensions on submitted variable names
594:       if ( isset($_POST[$p1]) ) {
595:         if ( isset($_POST[$p1][$p2]) ) {
596:           $currval = $_POST[$p1][$p2];
597:         }
598:       }
599:       else if ( isset($this->record) && is_object($this->record)
600:                 && isset($this->record->{"$p1"}["$p2"])
601:               ) {
602:         $currval = $this->record->{"$p1"}["$p2"];
603:       }
604:     }
605:     else {
606:       if ( isset($_POST[$fname]) ) {
607:         $currval = $_POST[$fname];
608:       }
609:       else if ( isset($this->record) && is_object($this->record) && isset($this->record->{"$base_fname"}) ) {
610:         $currval = $this->record->{"$base_fname"};
611:       }
612:       else if ( isset($this->record) && is_object($this->record) && isset($this->record->{"$fname"}) ) {
613:         $currval = $this->record->{"$fname"};
614:       }
615:     }
616:     if ( $ftype == "date" ) $currval = $session->FormattedDate($currval);
617:     else if ( $ftype == "timestamp" ) $currval = $session->FormattedDate($currval, $ftype);
618: 
619:     // Now build the entry field and render it
620:     $field = new EntryField( $ftype, $fname, $this->_ParseAttributes($ftype,$attributes), $currval );
621:     return $field->Render();
622:   }
623: 
624: 
625:   /**
626:   * A utility function for a submit button within a data entry table
627:   * @return string The HTML fragment to display a submit button for the form.
628:   */
629:   function SubmitButton( $fname, $fvalue, $attributes = '' )
630:   {
631:     $field = new EntryField( 'submit', $fname, $this->_ParseAttributes('submit', $attributes), $fvalue );
632:     return $field->Render();
633:   }
634: 
635:   /**
636:   * A utility function for a data entry line within a table
637:   * @return string The HTML fragment to display the prompt and field.
638:   */
639:   function DataEntryLine( $prompt, $field_format, $ftype='', $fname='', $attributes='', $prefix = '' )
640:   {
641:     $attributes = $this->_ParseAttributes( $ftype, $attributes );
642:     return sprintf( $this->table_line_format, $prompt,
643:                 $this->DataEntryField( $field_format, $ftype, $fname, $attributes, $prefix ),
644:                 $attributes['_help'] );
645:   }
646: 
647: 
648:   /**
649:   * A utility function for a data entry line, where the prompt is a drop-down.
650:   * @return string The HTML fragment for the drop-down prompt and associated entry field.
651:   */
652:   function MultiEntryLine( $prompt_options, $prompt_name, $default_prompt, $format, $ftype='', $fname='', $attributes='', $prefix )
653:   {
654: 
655:     $prompt = "<select name=\"$prompt_name\">";
656: 
657:     reset($prompt_options);
658:     while( list($k,$v) = each($prompt_options) ) {
659:       $selected = ( ( $k == $default_prompt ) ? ' selected="selected"' : '' );
660:       $nextrow = "<option value=\"$k\"$selected>$v</option>";
661:       if ( preg_match('/&/', $nextrow) ) $nextrow = preg_replace( '/&/', '&amp;', $nextrow);
662:       $prompt .= $nextrow;
663:     }
664:     $prompt .= "</select>";
665: 
666:     return $this->DataEntryLine( $prompt, $format, $ftype, $fname, $attributes, $prefix );
667:   }
668: 
669: }
670: 
671: 
AWL API documentation generated by ApiGen 2.8.0