Source for file timefield.php

Documentation is available at timefield.php

  1. <?php
  2. /**
  3. * a textfield widget designed to handle time date
  4. *
  5. @author    Stuart Prescott
  6. @copyright  Copyright Stuart Prescott
  7. @license    http://opensource.org/licenses/gpl-license.php GNU Public License
  8. @version    $Id$
  9. @package    Bumblebee
  10. @subpackage FormsLibrary
  11. */
  12.  
  13. /** Load ancillary functions */
  14. require_once 'inc/typeinfo.php';
  15.  
  16. /** parent object */
  17. require_once 'field.php';
  18.  
  19. /** Time field is in "FIXED" (uneditable) format */
  20. define('TF_FIXED'0);
  21. /** Time field is in "DROP" (dropdown list) format */
  22. define('TF_DROP'1);
  23. /** Time field is in "FREE" (type-in text box) format */
  24. define('TF_FREE'2);
  25. /** Time field is in "FREE" (type-in text box) format always */
  26. define('TF_FREE_ALWAYS'3);
  27. /** Time field is in "AUTO" (any of the above as appropriate) format */
  28. define('TF_AUTO'-1);
  29.  
  30. /**
  31. * a textfield widget designed to handle time date
  32. *
  33. @package    Bumblebee
  34. @subpackage FormsLibrary
  35. */
  36. class TimeField extends Field {
  37.   /** @var SimpleTime    time object for this field */
  38.   var $time;
  39.   /** @var TimeSlotRule  rules for the times that are permitted    */
  40.   var $list;
  41.   /** @var boolean       field is the start time of a slot object    */
  42.   var $isStart=0;
  43.   /** @var SimpleDate    the date on which this time is located     */
  44.   var $slotStart;
  45.   /** @var TimeSlot      the actual time slot to which this time is associated    */
  46.   var $slot;
  47.   /** @var integer       how this field is to be rendered (see TF_* options)  */
  48.   var $representation;
  49.   /** @var integer       force this field to be rendered in a particular way (see TF_* options)    */
  50.   var $_manualRepresentation = TF_AUTO;
  51.   /** @var DropList      DropList object for dropdown list representation of the field    */
  52.   var $droplist;
  53.   /** @var boolean       is the time *really* editable ... ?? FIXME  */
  54.   var $editableOutput=1;
  55.   /** @var integer       maximum number of booking slots to include in the dropdown */
  56.   var $maxSlotsDropDown = 20;
  57.   /** @var boolean       go beyond the end of the slots that are part of a group for booking */
  58.   var $extendDropDown = true;
  59.   /** @var integer       max period to be included in the dropdown in seconds */
  60.   var $maxPeriodDropDown = 86400;
  61.   /** @var SimpleDate    max date for the dropdown to go to */
  62.   var $maxDateDropDown = null;
  63.  
  64.   /**
  65.   *  Create a new field object, designed to be superclasses
  66.   *
  67.   * @param string $name   the name of the field (db name, and html field name
  68.   * @param string $longname  long name to be used in the label of the field in display
  69.   * @param string $description  used in the html title or longdesc for the field
  70.   */
  71.   function TimeField($name$longname=''$description=''{
  72.     parent::Field($name$longname$description);
  73.     $this->time = new SimpleTime(0);
  74.     $this->slotStart = new SimpleDate(0);
  75.     #$this->DEBUG=10;
  76.   }
  77.  
  78.   function displayInTable($cols=3{
  79.     $errorclass ($this->isValid ? '' "class='inputerror'");
  80.     $t "<tr $errorclass><td>$this->longname</td>\n"
  81.         ."<td title='$this->description'>";
  82.     $t .= $this->getdisplay();
  83.     $t .= "</td>\n";
  84.     for ($i=0$i<$cols-2$i++{
  85.       $t .= '<td></td>';
  86.     }
  87.     $t .= '</tr>';
  88.     return $t;
  89.   }
  90.  
  91.   /**
  92.   * render the HTML version of the widget
  93.   *
  94.   * @return string 
  95.   */
  96.   function getDisplay({
  97.     $t '';
  98.     if ($this->editable && $this->editableOutput && $this->hidden{
  99.       $t .= $this->selectable();
  100.     else {
  101.       if (!$this->hidden$t .= xssqw($this->value);
  102.       $t .= $this->hidden();
  103.     }
  104.     if ($this->duplicateName{
  105.       $t .= "<input type='hiddenname='$this->duplicateName"
  106.              ."value='".xssqw($this->value)."' />";
  107.     }
  108.     return $t;
  109.   }
  110.  
  111.   function selectable({
  112.     #echo "TIME=".$this->time->timeString()."\n";
  113.     $this->_determineRepresentation();
  114.     $this->setTime(parent::getValue());
  115.     $t '';
  116.     switch ($this->representation{
  117.       case TF_DROP:
  118.         $this->_prepareDropDown();
  119.         $t .= $this->droplist->selectable();
  120.         break;
  121.       case TF_FREE:
  122.         $fixedname $this->namebase.$this->name.'-fixed';
  123.         $varname   $this->namebase.$this->name.'-var';
  124.         $t .= "<span id='$fixedname'>";
  125.         if ($this->isStart{
  126.           $t .= $this->time->timeString();
  127.           $t .= $this->hidden();
  128.         else {
  129.           $this->_prepareDropDown();
  130.           $t .= $this->droplist->selectable();
  131.         }
  132.         $t .= $this->_makeHiddenSwitch($fixedname$varname);
  133.         $t .= "</span>";
  134.         $t .= "<span id='$varnamestyle='displaynone'>";
  135.         $t .= $this->_prepareFreeField('-varfield');
  136.         $t .= "</span>";
  137.         break;
  138.       case TF_FREE_ALWAYS:
  139.         $t .= $this->_prepareFreeField();
  140.         break;
  141.       case TF_FIXED:
  142.         $t .= $this->time->timeString();
  143.         $t .= $this->hidden();
  144.         break;
  145.     }
  146.     return $t;
  147.   }
  148.  
  149.   /**
  150.    * set the representation of this field
  151.    *
  152.    * @param integer $flag (TF_* types from class TimeField constants)
  153.    */
  154.   function setManualRepresentation($flag{
  155.     $this->log("Manual representation set to $flag",10);
  156.     $this->_manualRepresentation = $flag;
  157.   }
  158.  
  159.   /**
  160.    * Determine what sort of representation is appropriate
  161.    */
  162.   function _determineRepresentation({
  163.     //preDump($this);
  164.     //$this->DEBUG = 10;
  165.     $this->_findExactSlot();
  166.     if (isset($this->slot&& $this->slot != 0{
  167.       $this->log('No slot found, TF_FIXED');
  168.       $this->representation = TF_FIXED;
  169.       return;
  170.     }
  171.     //preDump($this->slot);
  172.     if ($this->_manualRepresentation != TF_AUTO{
  173.       $this->log('Slot manually set');
  174.       $this->representation = $this->_manualRepresentation;
  175.     elseif ($this->editable{
  176.       $this->representation = TF_FIXED;
  177.     elseif ($this->slot->isFreeForm{
  178.       $this->representation = TF_FREE_ALWAYS;
  179. /*    } elseif ($this->isStart || $this->slot->numslotsFollowing < 1) {
  180.       $this->log('Starting slot or none following, TF_FIXED');
  181.       $this->representation = TF_FIXED;*/
  182.     elseif (($duration new SimpleTime($this->getValue()))
  183.               && $this->slot->start->ticks $duration->ticks != $this->slot->stop->ticks{
  184.       //$this->log($this->slot->start->ticks.' + '.$duration->ticks.' != '.$this->slot->stop->ticks);
  185.       $this->log('Not exactly following slots, TF_FIXED');
  186.       $this->representation = TF_FIXED;
  187.     elseif ($this->_fixedTimeSlots()) {
  188.       $this->representation = TF_DROP;
  189.     else {
  190.       $this->representation = TF_FREE_ALWAYS;
  191.     }
  192.     $this->log('Determined representation was '$this->representation10);
  193.   }
  194.  
  195.   /**
  196.    * Calculate data for the dropdown list of permissible times
  197.    *
  198.    * @access private
  199.    */
  200.   function _prepareDropDown({
  201.     $ends $this->slot->allSlotEnds();
  202.     $nextSlot $this->slot;
  203.     $nextStart $ends[count($ends)-1];
  204.     $max clone($this->slot->start);
  205.     $max->addSecs($this->maxPeriodDropDown);
  206.  
  207.     while ($this->extendDropDown && count($ends$this->maxSlotsDropDown && is_object($nextSlot)) {
  208.       #echo "Looking for next start. ";
  209.       #echo $nextStart->dateTimeString()." ";
  210.       #echo "Limit is ". $this->maxDateDropDown->dateTimeString()."<br />";
  211.       $nextSlot $this->list->findSlotByStart($nextStart);
  212.       if (is_object($nextSlot)) {
  213.         // this should never really happen....
  214.         break;
  215.       }
  216.       $nextStart $nextSlot->stop;
  217.       if ($nextSlot->isAvailable{
  218.         #echo "Not available <br />";
  219.         break;
  220.       }
  221.       if ($this->slot->start->ticks $this->maxPeriodDropDown < $nextSlot->stop->ticks{
  222.         #echo "Past max allowable ".$nextSlot->stop->dateTimeString()."<br />";
  223.         break;
  224.       }
  225.       if ($this->maxDateDropDown != null && $this->maxDateDropDown->ticks < $nextSlot->stop->ticks{
  226.         #echo "Conflicting with booking ".$nextSlot->stop->dateTimeString()."<br />";
  227.         break;
  228.       }
  229.  
  230.       $ends[$nextSlot->stop;
  231.       #echo "Got an end: ". $nextSlot->stop->dateTimeString() ." ";
  232.     }
  233.  
  234.     $dropVals array();
  235.  
  236.     foreach($ends as $d{
  237.       $duration new SimpleTime($d->ticks $this->slot->start->ticks);
  238.       #echo $d->datetimeString() . " -- ".$duration->timestring()."<br />";
  239.       $dropVals[$duration->timeString()sprintf(T_("%s (until %s)")$duration->timeString()$d->datetimeString());
  240.     }
  241.     #preDump($dropVals);
  242.  
  243.  
  244.     $this->droplist = new DropList($this->name$this->description);
  245.     $this->droplist->setValuesArray($dropVals'id''iv');
  246.     $this->droplist->setFormat('id''%s'array('iv'));
  247.     //preDump($durations);
  248.     //for ($j = count($durations)-1; $j >=0 && $durations[$j] != $this->value; $j--) {
  249.     //}
  250.     //$this->droplist->setDefault($j);
  251.     $this->droplist->setDefault($this->value);
  252.   }
  253.  
  254.   /**
  255.    * Free-form field entry
  256.    *
  257.    * @access private
  258.    * @param string   $append  append this to the name of the input (optional)
  259.    * @param string   $hidden  show this as hidden by default
  260.    * @return string html for field
  261.    */
  262.   function _prepareFreeField($append=''$hidden=false{
  263.     $t  "<input type='textname='{$this->namebase}{$this->name}$append"
  264.         ."value='".xssqw($this->time->timeString())."' ";
  265.     $t .= (isset($this->attr['size']"size='".$this->attr['size']."' " "");
  266.     $t .= (isset($this->attr['maxlength']"maxlength='".$this->attr['maxlength']."' " "");
  267.     $t .= ($hidden"style='display: none;' " "";
  268.     $t .= "/>";
  269.     return $t;
  270.   }
  271.  
  272.   /**
  273.    * Convert a string into a js link that controls the behaviour of another div
  274.    *
  275.    * @access private
  276.    * @param string $id1 default shown element
  277.    * @param string $id2 default hidden element
  278.    * @return string html for js link
  279.    */
  280.   function _makeHiddenSwitch($id1, $id2) {
  281.     $func = preg_replace('/[^\w]/', '_', "hideunhide$id1");
  282.     $t = "
  283.  
  284.       <input type='hiddenid='{$this->namebase}{$this->name}-switchname='{$this->namebase}{$this->name}-switchvalue='' />
  285.       <script type='text/javascript'>
  286.         function $func() {
  287.           hideDiv('$id1');
  288.           var switchfield = document.getElementById('{$this->namebase}{$this->name}-switch');
  289.           switchfield.value = 'varfield';
  290.           showDiv('$id2');
  291.         }
  292.       </script>
  293.       <a href='javascript:$func();'>".T_('edit times')."</a>
  294.       ";
  295.     return $t;
  296.   }
  297.  
  298.   /**
  299.    * determine if a dropdown list appropriate here?
  300.    *
  301.    * @access private
  302.    */
  303.   function _fixedTimeSlots() {
  304.     return true;
  305.     if ($this->slotStart->ticks == 0{
  306.       $this->fixedTimeSlots false;
  307.     } else {
  308.       $this->fixedTimeSlots $this->slot->numslotsFollowing;
  309.     }
  310.     $this->log('Slot starts at '.$this->slotStart->dateTimeString()
  311.                 .', numFollowing: '.$this->fixedTimeSlots8);
  312.     return $this->fixedTimeSlots;
  313.   }
  314.  
  315.   /**
  316.    * overload the parent's set() method as we need to do some extra processing
  317.    */
  318.   function set($value) {
  319.     parent::set($value);
  320.     if (strpos($value, '-') === false) {
  321.       $this->setTime($value);
  322.     } else {
  323.       $this->setDateTime($value);
  324.     }
  325.   }
  326.  
  327.   /**
  328.    * overload the parent's update method so that local calculations can be performed
  329.    *
  330.    * @param array $data html_name => value pairs
  331.    *
  332.    * @return boolean the value was updated
  333.    */
  334.   function update($data) {
  335.     if (isset($data{$this->namebase.$this->name.'-switch'}) && $data{$this->namebase.$this->name.'-switch'}) {
  336.       $data{$this->namebase.$this->name$data{$this->namebase.$this->name.'-varfield'};
  337.     }
  338.     if (parent::update($data)) {
  339.       $this->setTime($this->value);
  340.     }
  341.     return $this->changed;
  342.   }
  343.  
  344.   /**
  345.    * Set the time (and value) from a Date-Time string
  346.    *
  347.    * @param string $time a date-time string (YYYY-MM-DD HH:MM:SS)
  348.    */
  349.   function setDateTime($time) {
  350.     #echo "SETDATETIME = $time\n";
  351.     $date = new SimpleDate($time);
  352.     $this->date $date;
  353.     $this->setTime($date->timePart());
  354.   }
  355.  
  356.   /**
  357.    * Set the time (and value)
  358.    *
  359.    * @param string $time a time string (HH:MM)
  360.    */
  361.   function setTime($time) {
  362.     #echo "SETTIME = $time\n";
  363.     $this->time = new SimpleTime($time);
  364.     $this->value $this->time->timeString();
  365.   }
  366.  
  367.   /**
  368.    * associate a TimeSlotRule for validation of the times that we are using
  369.    *
  370.    * @param TimeSlotRule $list a valid TimeSlotRule
  371.    */
  372.   function setSlots($list) {
  373.     $this->list = $list;
  374.     //preDump($list);
  375.   }
  376.  
  377.   /**
  378.    * set the appropriate date that we are refering to for the timeslot rule validation
  379.    *
  380.    * @param string $date passed to the TimeSlotRule
  381.    */
  382.   function setSlotStart($date) {
  383.     $this->slotStart new SimpleDate($date);
  384.   }
  385.  
  386.   function _findExactSlot() {
  387.     $this->log('Looking for slot starting at '.$this->slotStart->dateTimeString()10);
  388.     $this->slot = $this->list->findSlotByStart($this->slotStart);
  389.     if ($this->slot{
  390.       $this->slot $this->list->findSlotFromWithin($this->slotStart);
  391.     }
  392.     $this->log('Found slot start '.$this->slot->start->dateTimeString()10);
  393.     $this->log('Found slot stop '.$this->slot->stop->dateTimeString()10);
  394. /*    if ($this->slot == '0') {
  395.       $this->slot = $this->list->findSlotFromWithin($this->slotStart);
  396.     }*/
  397.   }
  398.  
  399.   /**
  400.    *  isValid test (extend Field::isValid), looking at whether the string parsed OK
  401.    */
  402.   function isValid() {
  403.     parent::isValid();
  404.     $this->isValid = $this->isValid && $this->time->isValid;
  405.     return $this->isValid;
  406.   }
  407.  
  408.   /**
  409.    * return a SQL-injection-cleansed string that can be used in an SQL
  410.    * UPDATE or INSERT statement. i.e. "name='Stuart'".
  411.    *
  412.    * @return string  in SQL assignable form
  413.    */
  414.   function sqlSetStr($name='', $force=false) {
  415.     if (empty($name)) {
  416.       $name = $this->name;
  417.     }
  418.     if (! $this->sqlHidden{
  419.       return $name .'='qw($this->time->getHMSstring());
  420.     } else {
  421.       return '';
  422.     }
  423.   }
  424.  
  425.  
  426. } // class TimeField
  427.  

Documentation generated on Tue, 06 Mar 2007 10:02:02 +0000 by phpDocumentor 1.3.0