Main Page | Class Hierarchy | Class List | File List | Class Members | File Members

formcontrols/controls.php

Go to the documentation of this file.
00001 <?php
00002 
00009 // EVENT CONSTANTS
00010 
00012 define('FC_EVENT_UPDATE', 1);
00014 define('FC_EVENT_CLICK', 2);
00016 define('FC_EVENT_SELECT', 4);
00018 define('FC_EVENT_DESELECT', 8);
00019 
00020 
00029 function gen_control_name($as_array = false) 
00030 {
00031     $control_name = md5(uniqid(mt_rand(), true));
00032     if ($as_array)
00033         $control_name .= '[]';
00034     
00035     return $control_name;
00036 }
00037 
00044 function is_valid_control_name($name, $multiple = false) 
00045 {
00046     if (!$multiple)
00047         return preg_match('#^\w+$#', $name);
00048     else
00049         return preg_match('#^\w+\[\]$#', $name);
00050 }
00051 
00058 function is_subclass($child, $parent) {
00059     if(is_string($child)) {
00060         $child = strtolower($child);
00061         $parent = strtolower($parent);
00062         do {
00063             if (!$child = get_parent_class($child))
00064                 return false;
00065         } while ($child != $parent);
00066         return true;
00067     }
00068 
00069     return is_subclass_of($child, $parent);
00070 }
00071 
00081 function check_class($unknown, $base) 
00082 {
00083     if (!class_exists($unknown))
00084         trigger_error("The class '$unknown' has not been declared", E_USER_ERROR);
00085     if (!is_subclass($unknown, $base))
00086         if ($unknown != $base)
00087             trigger_error("'$unknown' is not a '$base' or subclass thereof", E_USER_ERROR);
00088 }
00089 
00101 class XHTMLElement
00102 {
00104     var $dom_document;
00106     var $node;
00108     var $serialise;
00109 
00114     function XHTMLElement($name) 
00115         {
00116             $this->dom_document = domxml_new_doc("1.0");
00117             $element = $this->dom_document->create_element($name);
00118             $this->node = $this->dom_document->append_child($element);            
00119         }
00120 
00125     function getElementName() 
00126         {
00127             return $this->node->node_name();
00128         }
00129 
00135     function getAttribute($name) 
00136         {
00137             return $this->node->get_attribute($name);
00138         }
00139 
00146     function setAttribute($name, $value)
00147         {
00148             $this->node->set_attribute($name, $value);
00149         }
00150 
00157     function setBooleanAttribute($name, $state) 
00158         {
00159             if ($state)
00160                 $this->node->set_attribute($name, $name);
00161             else
00162                 $this->removeAttribute($name);
00163         }
00164 
00170     function hasAttribute($name) 
00171         {
00172             return $this->node->has_attribute($name);
00173         }
00174 
00180     function removeAttribute($name) 
00181         {
00182             return $this->node->remove_attribute($name);
00183         }
00184 
00189     function toXHTML() 
00190         {
00191             return $this->dom_document->dump_node($this->node);
00192         }
00193 
00194     /***************************************************
00195      * Printable INTERFACE
00196      ***************************************************/
00197 
00203     function toString() 
00204         {
00205             return $this->toXHTML();
00206         }
00207 
00208     /***************************************************
00209      * Serialisation INTERFACE
00210      ***************************************************/
00211     
00221     function __sleep() 
00222         {
00223             $this->serialise = $this->toXHTML();
00224             return array('serialise');
00225         }
00226 
00236     function __wakeup() 
00237         {
00238             $this->dom_document = domxml_open_mem($this->serialise);
00239             $this->node = $this->dom_document->document_element();
00240             $this->serialise = null;
00241         }
00242 }
00243 
00261 class ControlElement extends XHTMLElement 
00262 {
00264     var $actions;
00266     var $events;
00268     var $display;
00269     
00275     function ControlElement($name, $control_name = null) 
00276         {
00277             $this->XHTMLElement($name);
00278 
00279             $control_name = gen_control_name($this->submitsMultipleValues());
00280             
00281             $this->setControlName($control_name);
00282             $this->setDisplay(true);
00283             $this->actions = array();
00284             $this->events = array();
00285 
00286             $this->addEvent(FC_EVENT_UPDATE);
00287         }    
00288 
00289     /***************************************************
00290      * Control INTERFACE
00291      ***************************************************/
00292 
00297     function getId() 
00298         {
00299             return $this->getAttribute('id');
00300         }
00301 
00306     function setId($id) 
00307         {
00308             $this->setAttribute('id', $id);
00309         }
00310     
00317     function isSimpleControl() 
00318         {
00319             return true;
00320         }
00321     
00328     function submitsMultipleValues() 
00329         {
00330             return false;
00331         }
00332 
00337     function display() 
00338         {
00339             return $this->display;
00340         }
00341 
00347     function setDisplay($display) 
00348         {
00349             if ($display)
00350                 $this->display = true;
00351             else
00352                 $this->display = false;
00353         }
00354 
00359     function disabled() 
00360         {
00361             return $this->hasAttribute('disabled');
00362         }
00363 
00369     function setDisabled($disabled) 
00370         {
00371             $this->setBooleanAttribute('disabled', $disabled);
00372         }
00373     
00379     function updated() 
00380         {
00381             return $this->eventHasOccurred(FC_EVENT_UPDATE);
00382         }
00383 
00390     function setUpdated($updated) 
00391         {
00392             if ($updated)
00393                 $this->setEventHasOccurred(FC_EVENT_UPDATE, true);
00394             else
00395                 $this->setEventHasOccurred(FC_EVENT_UPDATE, false);
00396         }
00397 
00404     function checkControlName($name) 
00405         {
00406             if (!is_valid_control_name($name, $this->submitsMultipleValues())) // ensure it's a valid name
00407                 trigger_error("The name '$name' is not a valid control name", E_USER_ERROR);
00408         }
00409 
00414     function getControlName() 
00415         {
00416             return $this->getAttribute('name');
00417         }
00418 
00424     function setControlName($name) 
00425         {
00426             $this->checkControlName($name);
00427             $this->setAttribute('name', $name);
00428         }
00429 
00436     function getValue() 
00437         {
00438         }
00439     
00446     function setValue($value) 
00447         {
00448             $this->setUpdated(true);
00449         }    
00450 
00451     // ACTION HANDLING METHODS
00452 
00463     function addAction($event, $name, $callback) 
00464         {
00465             if ($this->actionExists($name))
00466                 trigger_error("The action '$name' already exists", E_USER_ERROR);
00467 
00468             if (!is_callable($callback))
00469                 trigger_error("The callback function to associate with the action '$name' is not valid", E_USER_ERROR);
00470 
00471             if (!$this->isValidEvent($event))
00472                 trigger_error("The event to associate with the action '$name' is not valid", E_USER_ERROR);
00473             
00474             $this->actions[$name] = array($callback, $event, false);
00475         }
00476 
00483     function setActionTriggered($name, $state) 
00484         {
00485             if (!$this->actionExists($name))
00486                 trigger_error("The action '$name' does not exist", E_USER_ERROR);
00487 
00488             $this->actions[$name][2] = ($state) ? true : false;
00489         }
00490     
00496     function actionTriggered($name) 
00497         {
00498             if ($this->actionExists($name))
00499                 return $this->actions[$name][2];
00500 
00501             return false;
00502         }
00503 
00508     function &getAction($name) 
00509         {
00510             if ($this->actionExists($name))
00511                 return $this->actions[$name][0];
00512 
00513             return false;
00514         }
00515 
00523     function getEvent($name) 
00524         {
00525             if ($this->actionExists($name))
00526                 return $this->actions[$name][1];
00527 
00528             return false;
00529         }
00530 
00541     function getActionNames($event = 0) 
00542         {
00543             if (!$event)
00544                 return array_keys($this->actions);
00545 
00546             if (!$this->isValidEvent($event))
00547                 trigger_error("The event is not valid", E_USER_ERROR);
00548 
00549             $names = array();
00550             foreach (array_keys($this->actions) as $name) 
00551                 {
00552                     if (($event ^ $this->getEvent($name)) !== 0)
00553                         $names[] = $name;
00554                 }
00555             return $names;
00556         }
00557 
00568     function getActions($event = 0) 
00569         {
00570             $names = $this->getActionNames($event);
00571             $actions = array();
00572             foreach ($names as $name) 
00573                 {
00574                     $actions[] =& $this->getAction($name);
00575                 }
00576             
00577             return $actions;
00578         }
00579     
00585     function actionExists($name) 
00586         {
00587             return isset($this->actions[$name]);
00588         }
00589 
00598     function triggerAction($name) 
00599         {
00600             if (!$this->actionExists($name))
00601                 trigger_error("The action '$name' does not exist", E_USER_ERROR);
00602 
00603             if ($this->actionTriggered($name))
00604                 return false;
00605             
00606             $event = $this->getEvent($name);
00607 
00608             if (!$this->eventHasOccurred($event))
00609                 return false;
00610 
00611             $this->setActionTriggered($name, true);
00612 
00613             $callback =& $this->getAction($name);
00614             return call_user_func($callback, &$this);
00615         }
00616     
00623     function removeAction($name) 
00624         {
00625             unset($this->actions[$name]);
00626         }
00627 
00634     function triggerActions() 
00635         {
00636             foreach ($this->getActionNames() as $action) 
00637                 {
00638                     $this->triggerAction($action);
00639                 }
00640         }
00641 
00642     // EVENT MANIPULATIONS
00643 
00651     function addEvent($event) 
00652         {
00653             if ($this->isValidEvent($event))
00654                 trigger_error("The event is not valid", E_USER_ERROR);
00655 
00656             $this->events[$event] = false;
00657         }
00658     
00663     function eventHasOccurred($event) 
00664         {
00665             return $this->events[$event];
00666         }
00667 
00674     function setEventHasOccurred($event, $state) 
00675         {
00676             if (!$this->isValidEvent($event))
00677                 trigger_error("The event is not supported", E_USER_ERROR);
00678 
00679             $this->events[$event] = ($state) ? true : false;
00680 
00681             // reset all the triggered state of all actions
00682             foreach ($this->getActionNames($event) as $action) 
00683                 {
00684                     $this->setActionTriggered($action, false);
00685                 }
00686         }
00687     
00692     function supportedEvents() 
00693         {
00694             $events = array_keys($this->events);
00695             $bits = 0;
00696 
00697             foreach ($events as $event) 
00698                 {
00699                     $bits = $bits ^ $event;
00700                 }
00701             
00702             return $bits;
00703         }
00704     
00710     function isValidEvent($event) 
00711         {
00712             return ($event & $this->supportedEvents()) !== 0;
00713         }
00714 
00721     function resetEvents() 
00722         {
00723             // reset the events to false
00724             $events = array_keys($this->events);
00725             
00726             foreach ($events as $event) 
00727                 {
00728                     $this->setEventHasOccurred($event, false);
00729                 }
00730 
00731             // reset the actions trigger state to false
00732             foreach ($this->getActionNames() as $action) 
00733                 {
00734                     $this->setActionTriggered($action, false);
00735                 }
00736         }
00737 
00738     /***************************************************
00739      * Serialisation INTERFACE
00740      ***************************************************/
00741 
00749     function _processPOSTED($post) 
00750         {
00751             if ($post === null)    // catch common case
00752                 return;
00753 
00754             if (!$this->submitsMultipleValues() and get_magic_quotes_gpc())
00755                 $post = stripslashes($post);
00756             
00757             if ($post != $this->getValue()) {
00758                 //debugVar($post);
00759                 $this->setValue($post);
00760             }
00761         }
00762     
00769     function __wakeup() 
00770         {
00771             parent::__wakeup();
00772             
00773             $this->resetEvents();
00774 
00775             $name = $this->getControlName();
00776 
00777             if (substr($name, -2) == '[]') // get rid of the [] if there is one in the control name
00778                 $name = substr($name, 0, -2);
00779 
00780             if (isset($_POST[$name]))
00781                 $this->_processPOSTED($_POST[$name]);
00782             else
00783                 $this->_processPOSTED(null);
00784         }
00785 
00786     function __sleep() 
00787         {
00788             $sleep_vars = parent::__sleep();
00789             array_push($sleep_vars, 'actions', 'display', 'events');
00790             return $sleep_vars;
00791         }
00792 }
00793 
00798 class TextArea extends ControlElement 
00799 {
00804     function TextArea($value = '') 
00805         {
00806             $this->ControlElement('textarea');
00807             $this->setValue($value);
00808         }
00809 
00810     /***************************************************
00811      * Control INTERFACE
00812      ***************************************************/
00813     
00814     function getValue() 
00815         {
00816             return $this->node->get_content();
00817         }
00818 
00819     function setValue($value) 
00820         {
00821             $this->setUpdated(true);
00822             
00823             if ($this->node->has_child_nodes()) {
00824                 $text_node = $this->node->first_child();
00825                 return $text_node->set_content($value);
00826             }
00827             return $this->node->set_content($value);
00828         }
00829 }
00830 
00835 class Input extends ControlElement
00836 {
00842     function Input($type, $control_name = null)
00843         {
00844             $this->ControlElement('input', $control_name);
00845             $this->setAttribute('type', $type);
00846         }
00847 }
00848 
00854 class ValueInput extends Input 
00855 {
00859     function ValueInput($type, $control_name = null) 
00860         {
00861             $this->Input($type, $control_name);
00862         }
00863 
00864     /***************************************************
00865      * Control INTERFACE
00866      ***************************************************/
00867 
00868     function getValue() 
00869         {
00870             return $this->getAttribute('value');
00871         }
00872 
00873     function setValue($value) 
00874         {
00875             $this->setUpdated(true);
00876 
00877             $this->setAttribute('value', $value);
00878         }
00879 }
00880 
00883 class TextInput extends ValueInput
00884 {
00889     function TextInput($value = null) 
00890         {
00891             $this->ValueInput('text');
00892             $this->SetValue($value);
00893         }
00894 }
00895 
00898 class PasswordInput extends ValueInput 
00899 {
00904     function PasswordInput($value = null) 
00905         {
00906             $this->ValueInput('password');
00907             $this->SetValue($value);
00908         }
00909 }
00910 
00913 class HiddenInput extends ValueInput
00914 {
00919     function HiddenInput($value = null) 
00920         {
00921             $this->ValueInput('hidden');
00922             $this->setValue($value);
00923         }
00924 
00925     /***************************************************
00926      * Control INTERFACE
00927      ***************************************************/
00928 
00935     function setDisabled($disabled)
00936         {
00937         }
00938 }
00939 
00945 class ClickedInput extends ValueInput 
00946 {
00952     function ClickedInput($type, $value, $control_name = null) 
00953         {
00954             $this->ValueInput($type, $control_name);
00955             $this->setValue($value);
00956 
00957             $this->addEvent(FC_EVENT_CLICK);
00958         }
00959 
00966     function clicked() 
00967         {
00968             return $this->eventHasOccurred(FC_EVENT_CLICK);
00969         }
00970 
00971     /***************************************************
00972      * Serialisation INTERFACE
00973      ***************************************************/
00974 
00975     function _processPOSTED($post) 
00976         {
00977             if ($post !== null) {
00978                 $this->setEventHasOccurred(FC_EVENT_CLICK, true); // it's been clicked
00979                 parent::_processPOSTED($post);
00980             } else {
00981                 $this->setEventHasOccurred(FC_EVENT_CLICK, false);
00982             }
00983         }    
00984 }
00985 
00988 class SubmitInput extends ClickedInput 
00989 {
00994     function SubmitInput($value) 
00995         {
00996             $this->ClickedInput('submit', $value);
00997         }
00998 }
00999 
01002 class ImageInput extends ClickedInput
01003 {
01005     var $value;
01006     
01012     function ImageInput($src = null, $control_name = null) 
01013         {
01014             $this->ClickedInput('image', null);
01015             if ($src !== null)
01016                 $this->setSrc($src);
01017         }
01018 
01023     function getXY() 
01024         {
01025             return array('x' => $this->value[0],
01026                          'y' => $this->value[1]);
01027         }
01028 
01033     function getX() 
01034         {
01035             return $this->value[0];
01036         }
01037 
01042     function getY() 
01043         {
01044             return $this->value[1];
01045         }
01046 
01047     /***************************************************
01048      * Image INTERFACE
01049      ***************************************************/
01050 
01055     function getSrc() 
01056         {
01057             return $this->getAttribute('src');
01058         }
01059     
01065     function setSrc($src) 
01066         {
01067             $this->setAttribute('src', $src);
01068         }
01069 
01070     
01071     /***************************************************
01072      * Control INTERFACE
01073      ***************************************************/
01074 
01075     function submitsMultipleValues() 
01076         {
01077             return true;
01078         }
01079 
01080     function getValue() 
01081         {
01082             return $this->value;
01083         }
01084 
01085     function setValue($value) 
01086         {
01087             if (!is_array($value)) {
01088                 $this->value = array();
01089                 return;
01090             }
01091             if (sizeof($value) != 2)
01092                 trigger_error("The value array must consist of two elements", E_USER_ERROR);
01093             if (!is_numeric($value[0]) or !is_numeric($value[0]))
01094                 trigger_error("The value elements must be numeric", E_USER_ERROR);
01095 
01096             $this->setUpdated(true);
01097 
01098             $this->value = $value;
01099         }
01100 }
01101 
01108 class EnhancedImageInput extends ImageInput 
01109 {
01111     var $enabled_src;
01113     var $disabled_src;
01114     
01121     function EnhancedImageInput($enabled_src, $disabled_src, $control_name = null)
01122         {
01123             $this->ImageInput($enabled_src, $control_name = null) ;
01124             $this->enabled_src = $enabled_src;
01125             $this->disabled_src = $disabled_src;
01126         }
01127 
01128     /***************************************************
01129      * Control INTERFACE
01130      ***************************************************/
01131 
01132     function setDisabled($disabled)
01133         {
01134             parent::setDisabled($disabled);
01135 
01136             $this->setSrc((!$this->disabled()) ? $this->enabled_src : $this->disabled_src);    
01137         }
01138     
01139     /***************************************************
01140      * Serialisation INTERFACE
01141      ***************************************************/
01142     
01143     function __sleep() 
01144         {
01145             $sleep_vars = parent::__sleep();
01146             array_push($sleep_vars,
01147                        'enabled_src',
01148                        'disabled_src');
01149             return $sleep_vars;
01150         }
01151     
01152 }
01153 
01156 class ResetInput extends ValueInput
01157 {
01161     function ResetInput($value) 
01162         {
01163             $this->ValueInput('reset');
01164             $this->setValue($value);
01165         }
01166 }
01167 
01177 class Option extends ControlElement 
01178 {
01180     var $control_name;
01181 
01188     function Option($value, $label = null, $control_name = null) 
01189         {
01190             $this->ControlElement('option', $control_name);
01191             $this->setLabel($label);
01192             $this->setValue($value);
01193 
01194             $this->addEvent(FC_EVENT_SELECT);
01195             $this->addEvent(FC_EVENT_DESELECT);
01196         }
01197 
01198     /***************************************************
01199      * Control INTERFACE
01200      ***************************************************/
01201 
01202     function getValue() 
01203         {
01204             return $this->getAttribute('value');
01205         }
01206 
01207     function setValue($value) 
01208         {
01209             $this->setUpdated(true);
01210 
01211             $this->setAttribute('value', $value);
01212         }
01213 
01214     // OVERRIDDEN Control ELEMENT METHODS
01215     
01216     function getControlName() 
01217         {
01218             return $this->control_name;
01219         }
01220 
01221     function setControlName($name) 
01222         {
01223             $this->checkControlName($name);
01224             $this->control_name = $name;
01225         }
01226     
01227     /***************************************************
01228      * SelectableControl INTERFACE
01229      ***************************************************/
01230 
01235     function getLabel() 
01236         {
01237             return $this->node->get_content();
01238         }
01239 
01245     function setLabel($label) 
01246         {
01247             if ($this->node->has_child_nodes()) {
01248                 $text_node = $this->node->first_child();
01249                 return $text_node->set_content($label);
01250             }
01251             return $this->node->set_content($label);
01252         }
01253 
01258     function selected() 
01259         {
01260             return $this->hasAttribute('selected');
01261         }
01262     
01267     function select() 
01268         {
01269             $this->setBooleanAttribute('selected', true);
01270             $this->setEventHasOccurred(FC_EVENT_SELECT, true);
01271             $this->setEventHasOccurred(FC_EVENT_DESELECT, false);
01272         }
01273     
01278     function deselect() 
01279         {
01280             $this->setBooleanAttribute('selected', false);
01281             $this->setEventHasOccurred(FC_EVENT_DESELECT, true);
01282             $this->setEventHasOccurred(FC_EVENT_SELECT, false);
01283         }
01284 
01285     /***************************************************
01286      * Serialisation INTERFACE
01287      ***************************************************/
01288     
01289     function __sleep() 
01290         {
01291             $sleep_vars = parent::__sleep();
01292             array_push($sleep_vars, 'control_name');
01293             return $sleep_vars;
01294         }
01295 }
01296 
01302 class SingleOption extends Option 
01303 {
01307     function SingleOption($value, $label = null, $control_name = null) 
01308         {
01309             $this->Option($value, $label, $control_name);
01310         }
01311 
01312     /***************************************************
01313      * Serialisation INTERFACE
01314      ***************************************************/
01315 
01316     function _processPOSTED($post) 
01317         {
01318             //debugVar($post);
01319 
01320             // don't alter the state if there isn't any post
01321             if ($post === null)
01322                 return;
01323 
01324             // update the selection state
01325             if ($post == $this->getValue()) {
01326                 if (!$this->selected())
01327                     $this->select();
01328             } elseif ($this->selected()) {
01329                 $this->deselect();
01330             }
01331         }
01332 }
01333 
01339 class MultipleOption extends Option 
01340 {
01344     function MultipleOption($value, $label = null, $control_name = null) 
01345         {
01346             $this->Option($value, $label, $control_name);
01347         }
01348 
01349     /***************************************************
01350      * Control INTERFACE
01351      ***************************************************/
01352     
01353     function submitsMultipleValues() 
01354         {
01355             return true;
01356         }
01357 
01358     /***************************************************
01359      * Serialisation INTERFACE
01360      ***************************************************/
01361 
01362     function _processPOSTED($post) 
01363         {
01364             //debugVar($post);
01365 
01366             if ($post === null) // catch the common case
01367                 return;
01368 
01369             if (is_array($post)) {
01370                 if (in_array($this->getValue(), $post)) {
01371                     if (!$this->selected()) {
01372                         $this->select();
01373                     }
01374                     return;
01375                 }
01376             }
01377 
01378             $this->deselect();            
01379         }
01380 }
01381 
01389 class CheckedInput extends ValueInput
01390 {
01392     var $label;
01393     
01399     function CheckedInput($type, $label = null, $control_name = null) 
01400         {
01401             $this->ValueInput($type, $control_name);
01402             $this->setLabel($label);
01403 
01404             $this->addEvent(FC_EVENT_SELECT);
01405             $this->addEvent(FC_EVENT_DESELECT);
01406         }
01407     
01408     /***************************************************
01409      * SelectableControl INTERFACE
01410      ***************************************************/
01411 
01416     function getLabel() 
01417         {
01418             return $this->label;
01419         }
01420 
01425     function setLabel($label) 
01426         {
01427             $this->label = $label;
01428         }
01429     
01434     function selected() 
01435         {
01436             return $this->hasAttribute('checked');
01437         }
01438     
01443     function select()
01444         {
01445             $this->setBooleanAttribute('checked', true);
01446             $this->setEventHasOccurred(FC_EVENT_SELECT, true);
01447             $this->setEventHasOccurred(FC_EVENT_DESELECT, false);
01448         }
01449     
01454     function deselect() 
01455         {
01456             $this->setBooleanAttribute('checked', false);
01457             $this->setEventHasOccurred(FC_EVENT_DESELECT, true);
01458             $this->setEventHasOccurred(FC_EVENT_SELECT, false);
01459         }
01460 
01461     /***************************************************
01462      * Printable INTERFACE
01463      ***************************************************/
01464 
01465     function toString() 
01466         {
01467             $xhtml = $this->toXHTML();
01468             $label = $this->getLabel();
01469             $id = $this->getId();
01470             
01471             return sprintf('%s&nbsp;<label for="%s">%s</label>', $xhtml, $id, $label);
01472         }
01473     
01474     /***************************************************
01475      * Serialisation INTERFACE
01476      ***************************************************/
01477 
01478     function __sleep() 
01479         {
01480             $sleep_vars = parent::__sleep();
01481             array_push($sleep_vars, 'label');
01482             return $sleep_vars;
01483         }
01484 }
01485 
01486 
01489 class RadioInput extends CheckedInput
01490 {
01494     function RadioInput($value, $label = null, $control_name = null) 
01495         {
01496             $this->CheckedInput('radio', $label, $control_name);
01497             $this->setValue($value);
01498         }
01499 
01500     /***************************************************
01501      * Serialisation INTERFACE
01502      ***************************************************/
01503 
01504     function _processPOSTED($post) 
01505         {
01506             //debugVar($post);
01507 
01508             // don't alter the state if there isn't any post
01509             if ($post === null)
01510                 return;
01511 
01512             // update the selection state
01513             if ($post == $this->getValue()) {
01514                 if (!$this->selected())
01515                     $this->select();
01516             } elseif ($this->selected()) {
01517                 $this->deselect();
01518             }
01519         }
01520 }
01521 
01524 class CheckboxInput extends CheckedInput 
01525 {
01532     function CheckboxInput($value, $label = null, $control_name = null) 
01533         {
01534             $this->CheckedInput('checkbox', $label, $control_name, true);
01535             $this->setValue($value);
01536         }
01537 
01538     /***************************************************
01539      * Control INTERFACE
01540      ***************************************************/
01541 
01542     function submitsMultipleValues() 
01543         {
01544             return true;
01545         }
01546 
01547     /***************************************************
01548      * Printable INTERFACE
01549      ***************************************************/
01550 
01551     function toString() 
01552         {
01553             $string = parent::toString();
01554             return $string .= sprintf('<input type="hidden" name="%s" value="">', $this->getControlName());    // this is required so that a value is posted even if all checkboxes with this name are deselected
01555         }    
01556     
01557     /***************************************************
01558      * Serialisation INTERFACE
01559      ***************************************************/
01560 
01561     function _processPOSTED($post) 
01562         {
01563             //debugVar($post);
01564 
01565             if ($post === null) // catch the common case
01566                 return;
01567 
01568             if (is_array($post)) {
01569                 if (in_array($this->getValue(), $post)) {
01570                     if (!$this->selected()) {
01571                         $this->select();
01572                     }
01573                     return;
01574                 }
01575             }
01576 
01577             $this->deselect();            
01578         }
01579 
01580 }
01581 
01584 class FileInput extends Input 
01585 {
01587     var $filename;
01588     
01589     function FileInput() 
01590         {
01591             $this->Input('file');
01592         }
01593 
01594     /***************************************************
01595      * Control INTERFACE
01596      ***************************************************/
01597 
01602     function getValue() 
01603         {
01604             return $this->filename;
01605         }
01606 
01613     function setValue($value) 
01614         {
01615             $this->setUpdated(true);
01616 
01617             $this->filename = $value;
01618         }
01619 
01620     /***************************************************
01621      * Serialisation INTERFACE
01622      ***************************************************/
01623     
01624     function __wakeup() 
01625         {
01626             parent::__wakeup();
01627 
01628             $name = $this->getControlName();
01629             $matches = preg_split('#\[(\w+|\d+)\]#', $name, -1, PREG_SPLIT_DELIM_CAPTURE | PREG_SPLIT_NO_EMPTY);
01630             if (sizeof($matches) == 0)
01631                 return;
01632             
01633             //debugVar($matches);
01634             $root_name = array_shift($matches);
01635             if (!isset($_FILES[$root_name]))
01636                 return;
01637             
01638             $files =& $_FILES[$root_name];
01639             $upload_data = array();
01640 
01641             foreach ($files as $info => $content) 
01642                 {
01643                     if (!is_array($content)) {
01644                         $upload_data[$info] = $content;
01645                         continue;
01646                     }
01647                         
01648                     $final_val =& $content;
01649                     foreach ($matches as $value) {
01650                         //debugVar($post);
01651                         if (isset($final_val[$value])) {
01652                             $final_val =& $final_val[$value];
01653                         }
01654                     }
01655                     $upload_data[$info] = $final_val;
01656                 }
01657 
01658             $filename = $upload_data['tmp_name'].'/'.$upload_data['name'];
01659             if (is_uploaded_file($upload_data['tmp_name']))
01660                 $this->setValue($filename);
01661         }
01662 }
01663 
01669 class ControlContainer 
01670 {
01672     var $controls;
01674     var $trigger_order;
01675 
01676     function ControlContainer() 
01677         {
01678             $this->controls = array();
01679             $this->trigger_order = array();
01680         }
01681 
01682     /***************************************************
01683      * Container INTERFACE
01684      ***************************************************/
01685 
01691     function &get($id)
01692         {
01693             if (!$this->exists($id))
01694                 trigger_error("The id '$id' does not exist", E_USER_ERROR);
01695             return $this->controls[$id];
01696         }
01697 
01705     function &getByValue($value) 
01706         {
01707             foreach ($this->getAllControls() as $control) 
01708                 {
01709                     if ($control->submitsMultipleValues()) {
01710                         if (in_array($value, $control->getValue()))
01711                             return $control->getByValue($value);
01712                     } elseif ($control->getValue() == $value) {
01713                         return $control;
01714                     }
01715                 }
01716             return null;
01717         }
01718     
01724     function add(&$control) 
01725         {
01726             $id = $control->getId();
01727             if (!strlen($id))
01728                 trigger_error("The control does not have an id", E_USER_ERROR);
01729 
01730             if ($this->exists($id))
01731                 trigger_error("The id '$id' already exists", E_USER_ERROR);
01732 
01733             $this->controls[$id] =& $control;            
01734 
01735             $this->trigger_order[] = $control->getId();
01736         }    
01737 
01743     function exists($id) 
01744         {
01745             return isset($this->controls[$id]);
01746         }
01747 
01752     function count() 
01753         {
01754             return sizeof($this->controls);
01755         }
01756 
01762     function &remove($id) 
01763         {
01764             if (!$this->exists($id))
01765                 return false;
01766             $control =& $this->get($id);
01767             unset($this->controls[$id]);
01768 
01769             $trigger_count = sizeof($this->trigger_order);
01770             for ($i = 0; $i < $trigger_count; $i++) {
01771                 if ($this->trigger_order[$i] == $id) {
01772                     if ($i == 0)
01773                         array_shift($this->trigger_order);
01774                     elseif ($i == $trigger_count - 1)
01775                         array_pop($this->trigger_order);
01776                     else {
01777                         $this->trigger_order = array_merge(array_slice($this->trigger_order, 0, $i), array_slice($this->trigger_order, $i+1));
01778                     }
01779                 }
01780             }
01781 
01782             return $control;
01783         }
01784 
01789     function getAllIds() 
01790         {
01791             return array_keys($this->controls);
01792         }
01793 
01798     function getAllControls() 
01799         {
01800             $controls = array();
01801 
01802             foreach ($this->getAllIds() as $id) 
01803                 {
01804                     $controls[] =& $this->controls[$id];
01805                 }
01806             
01807             return $controls;
01808         }    
01809 
01814     function getDisplayableIds() 
01815         {
01816             $displayable = array();
01817             
01818             foreach ($this->getAllIds() as $id) 
01819                 {
01820                     if ($this->childDisplay($id))
01821                         $displayable[] = $id;
01822                 }
01823 
01824             return $displayable;
01825         }
01826     
01831     function getDisplayableControls() 
01832         {
01833             $displayable = array();
01834 
01835             foreach ($this->getDisplayableIds() as $id) 
01836                 {
01837                     $displayable[] =& $this->get($id);
01838                 }
01839 
01840             return $displayable;
01841         }
01842 
01843     // UTILITY METHODS
01844 
01850     function childDisplay($id) 
01851         {
01852             $control =& $this->get($id);
01853             return $control->display();            
01854         }
01855     
01861     function childToString($id) 
01862         {
01863             $control =& $this->get($id);
01864             return $control->toString();
01865         }
01866 
01872     function childUpdated($id) 
01873         {
01874             $control =& $this->get($id);
01875             return $control->updated();
01876         }
01877     
01878     // ACTION MANIPULATIONS
01879     
01884     function triggerChildActions() 
01885         {
01886             foreach ($this->getTriggerOrder() as $id) 
01887                 {
01888                     $control =& $this->get($id);
01889                     $control->triggerActions();
01890                 }
01891         }
01892     
01897     function getTriggerOrder() 
01898         {
01899             return $this->trigger_order;
01900         }
01901 
01907     function setTriggerOrder($order) 
01908         {
01909             $control_count = $this->count();
01910             
01911             if (sizeof($order) != $control_count)
01912                 trigger_error('the action order does not contain the same number of elements as there are controls');
01913 
01914             if (sizeof(array_unique($order)) != $control_count)
01915                 trigger_error("The action order does not consist of unique values", E_USER_ERROR);
01916             
01917             $new_order = array();
01918             foreach ($order as $id) 
01919                 {
01920                     if (!$this->exists($id))
01921                         trigger_error("A control with id '$id' does not exist", E_USER_ERROR);
01922                     
01923                     $new_order[] = $id;
01924                 }
01925             $this->order = $new_order;
01926         }
01927 
01928     /***************************************************
01929      * Serialisation INTERFACE
01930      ***************************************************/
01931 
01932     function __sleep() 
01933         {
01934             return array('controls', 'trigger_order');            
01935         }
01936 }
01937 
01946 class ControlChoice extends ControlContainer
01947 {
01949     var $control_name;
01951     var $id;
01953     var $control_class;
01955     var $actions;
01957     var $selected;
01959     var $display;
01961     var $events;
01962 
01968     function ControlChoice($control_class, $choice) 
01969         {            
01970             $this->ControlContainer();
01971             $control_name = gen_control_name($this->submitsMultipleValues());
01972             $this->setControlName($control_name);
01973             $this->setDisplay(true);
01974             $this->actions = array();
01975             $this->selected = array();
01976             $this->events = array();
01977 
01978             $this->addEvent(FC_EVENT_UPDATE);
01979 
01980             $this->setControlClass($control_class);
01981             
01982             if (is_array($choice)) {
01983                 $values = array();
01984 
01985                 foreach ($choice as $id => $object)
01986                     {
01987 
01988                         $label = $value = null;
01989                         if (is_array($object)) {
01990                             if (sizeof($object) > 1) {
01991                                 $label = $object[0];
01992                                 $value = $object[1];
01993                             } else {
01994                                 $label = $id;
01995                                 $value = $object[0];
01996                             }
01997                         } else {
01998                             $label = $object;
01999                             $value = $id;
02000                         }
02001 
02002                         if (in_array($value, $values))
02003                             trigger_error("Bad value for id '$id'; the value is not unique", E_USER_ERROR);
02004 
02005                         array_push($values, $value);
02006                         
02007                         $control =& new $control_class($value, $label, $control_name);
02008                         $control->setId($id);
02009                         $this->add($control);        
02010                     }
02011             }
02012 
02013         }
02014     
02015     /***************************************************
02016      * Control INTERFACE
02017      ***************************************************/
02018 
02023     function isSimpleControl() 
02024         {
02025             return false;
02026         }
02027 
02032     function submitsMultipleValues() 
02033         {
02034             return false;
02035         }
02036 
02041     function display() 
02042         {
02043             return $this->display;
02044         }
02045 
02050     function setDisplay($display) 
02051         {
02052             if ($display)
02053                 $this->display = true;
02054             else
02055                 $this->display = false;
02056         }
02057     
02062     function checkControlName($name) 
02063         {
02064             if (!is_valid_control_name($name, $this->submitsMultipleValues())) // ensure it's a valid name
02065                 trigger_error("The name '$name' is not a valid control name", E_USER_ERROR);
02066         }
02067 
02072     function setControlName($name) 
02073         {
02074             $this->checkControlName($name);
02075             $this->control_name = $name;
02076 
02077             foreach ($this->getAllIds() as $id) 
02078                 {
02079                     $control =& $this->get($id);
02080                     $control->setControlName($name);
02081                 }
02082         }
02083 
02088     function getControlName() 
02089         {
02090             return $this->control_name;
02091         }
02092     
02097     function updated() 
02098         {
02099             return $this->eventHasOccurred(FC_EVENT_UPDATE);
02100         }
02101     
02106     function getId() 
02107         {
02108             return $this->id;
02109         }
02110 
02115     function setId($id) 
02116         {
02117             $this->id = $id;
02118         }    
02119 
02124     function getValue() 
02125         {
02126         }
02127 
02132     function setValue($value) 
02133         {
02134         }
02135     
02136     // ACTION HANDLING METHODS
02137 
02142     function addAction($event, $name, $callback) 
02143         {
02144             if ($this->actionExists($name))
02145                 trigger_error("The action '$name' already exists", E_USER_ERROR);
02146 
02147             if (!is_callable($callback))
02148                 trigger_error("The callback function to associate with the action '$name' is not valid", E_USER_ERROR);
02149 
02150             if (!$this->isValidEvent($event))
02151                 trigger_error("The event to associate with the action '$name' is not valid", E_USER_ERROR);
02152             
02153             $this->actions[$name] = array($callback, $event, false);
02154         }
02155 
02160     function setActionTriggered($name, $state) 
02161         {
02162             if (!$this->actionExists($name))
02163                 trigger_error("The action '$name' does not exist", E_USER_ERROR);
02164 
02165             $this->actions[$name][2] = ($state) ? true : false;
02166         }
02167     
02172     function actionTriggered($name) 
02173         {
02174             if ($this->actionExists($name))
02175                 return $this->actions[$name][2];
02176 
02177             return false;
02178         }
02179 
02184     function &getAction($name) 
02185         {
02186             return $this->actions[$name][0];
02187         }
02188 
02193     function getEvent($name) 
02194         {
02195             return $this->actions[$name][1];
02196         }
02197 
02202     function getActionNames($event = 0) 
02203         {
02204             if (!$event)
02205                 return array_keys($this->actions);
02206 
02207             if (!$this->isValidEvent($event))
02208                 trigger_error("The event is not valid", E_USER_ERROR);
02209 
02210             $names = array();
02211             foreach (array_keys($this->actions) as $name) 
02212                 {
02213                     if (($event ^ $this->getEvent($name)) !== 0)
02214                         $names[] = $name;
02215                 }
02216             return $names;
02217         }
02218 
02223     function getActions($event = 0) 
02224         {
02225             $names = $this->getActionNames($event);
02226             $actions = array();
02227             foreach ($names as $name) 
02228                 {
02229                     $actions[] =& $this->getAction($name);
02230                 }
02231             
02232             return $actions;
02233         }
02234     
02239     function actionExists($name) 
02240         {
02241             return isset($this->actions[$name]);
02242         }
02243 
02248     function triggerAction($name) 
02249         {
02250             if (!$this->actionExists($name))
02251                 trigger_error("The action '$name' does not exist", E_USER_ERROR);
02252 
02253             if ($this->actionTriggered($name))
02254                 return false;
02255             
02256             $event = $this->getEvent($name);
02257 
02258             if (!$this->eventHasOccurred($event))
02259                 return false;
02260 
02261             $this->setActionTriggered($name, true);
02262 
02263             $callback =& $this->getAction($name);
02264             return call_user_func($callback, &$this);
02265         }
02266     
02271     function removeAction($name) 
02272         {
02273             unset($this->actions[$name]);
02274         }
02275 
02280     function triggerActions() 
02281         {
02282             foreach ($this->getActionNames() as $action) 
02283                 {
02284                     $this->triggerAction($action);
02285                 }
02286 
02287             $this->triggerChildActions();
02288         }
02289 
02290     // EVENT MANIPULATIONS
02291 
02296     function addEvent($event) 
02297         {
02298             if ($this->isValidEvent($event))
02299                 trigger_error("The event is already exists", E_USER_ERROR);
02300 
02301             $this->events[$event] = false;
02302         }
02303 
02308     function eventHasOccurred($event) 
02309         {
02310             if ($event & FC_EVENT_UPDATE) {
02311                 $current_selected = $this->getSelectedIds();
02312 
02313                 // if the array lengths are different then an update has occurred
02314                 if (sizeof($current_selected) != sizeof($this->selected))
02315                     $this->setEventHasOccurred(FC_EVENT_UPDATE, true);
02316 
02317                 // are the contents different?
02318                 if (sizeof(array_diff($current_selected, $this->selected)))
02319                     $this->setEventHasOccurred(FC_EVENT_UPDATE, true);
02320             }
02321 
02322             return $this->events[$event];
02323         }
02324 
02329     function setEventHasOccurred($event, $state) 
02330         {
02331             if (!$this->isValidEvent($event))
02332                 trigger_error("The event is not supported", E_USER_ERROR);
02333 
02334             $this->events[$event] = ($state) ? true : false;
02335 
02336             // reset all the triggered state of all actions
02337             foreach ($this->getActionNames($event) as $action) 
02338                 {
02339                     $this->setActionTriggered($action, false);
02340                 }
02341         }
02342     
02347     function supportedEvents() 
02348         {
02349             $events = array_keys($this->events);
02350             $bits = 0;
02351 
02352             foreach ($events as $event) 
02353                 {
02354                     $bits = $bits ^ $event;
02355                 }
02356             
02357             return $bits;
02358         }
02359     
02364     function isValidEvent($event) 
02365         {
02366             return ($event & $this->supportedEvents()) !== 0;
02367         }
02368 
02373     function resetEvents() 
02374         {
02375             // reset the events to false
02376             $events = array_keys($this->events);
02377             
02378             foreach ($events as $event) 
02379                 {
02380                     $this->setEventHasOccurred($event, false);
02381                 }
02382 
02383             // reset the actions trigger state to false
02384             foreach ($this->getActionNames() as $action) 
02385                 {
02386                     $this->setActionTriggered($action, false);
02387                 }
02388         }
02389 
02390     /***************************************************
02391      * Container INTERFACE
02392      ***************************************************/
02393 
02394     function add(&$control) 
02395         {
02396             parent::add($control);
02397             $control->setControlName($this->getControlName());
02398         }
02399 
02400     /***************************************************
02401      * Choice INTERFACE
02402      ***************************************************/
02403     
02409     function setControlClass($control_class) 
02410         {
02411             $this->control_class = $control_class;
02412         }
02413     
02414     
02419     function getControlClass() 
02420         {
02421             return $this->control_class;
02422         }
02423     
02431     function &addChoice($value, $label = null, $selected = false) 
02432         {
02433             $control_class = $this->getControlClass();
02434             $choice =& new $control_class($value, $label, $this->getControlName());
02435             $choice->setId($value);
02436 
02437             if ($selected)
02438                 $choice->select();
02439 
02440             $this->add($choice);
02441             return $choice;
02442         }    
02443     
02448     function getSelectedIds() 
02449         {
02450             $selected_ids = array();
02451             foreach ($this->getAllIds() as $id) 
02452                 {
02453                     if ($this->selected($id))
02454                         array_push($selected_ids, $id);
02455                 }
02456             return $selected_ids;
02457         }
02458 
02463     function getSelectedControls() 
02464         {
02465             $selected_controls = array();
02466             foreach ($this->getSelectedIds() as $id) 
02467                 {
02468                     $selected_controls[] =& $this->get($id);
02469                 }
02470             return $selected_controls;
02471         }
02472     
02477     function selectedCount() 
02478         {
02479             return sizeof($this->getSelectedIds());
02480         }
02481     
02487     function select($id) 
02488         {
02489             $control =& $this->get($id);
02490             return $control->select();
02491         }
02492 
02498     function selected($id) 
02499         {
02500             $control =& $this->get($id);
02501             return $control->selected();
02502         }
02503     
02509     function deselect($id) 
02510         {
02511             $control =& $this->get($id);
02512             return $control->deselect();
02513         }
02514 
02515 
02516     /***************************************************
02517      * Printable INTERFACE
02518      ***************************************************/
02519 
02521     function toString() 
02522         {
02523             $strings = array();
02524 
02525             foreach ($this->getDisplayableControls() as $control) 
02526                 {
02527                     array_push($strings, $control->toString());
02528                 }
02529 
02530             return implode('<br/>', $strings);
02531         }
02532 
02533 
02534     /***************************************************
02535      * Serialisation INTERFACE
02536      ***************************************************/
02537 
02542     function __wakeup() 
02543         {
02544             $this->resetEvents();
02545         }
02546     
02551     function __sleep() 
02552         {
02553             $this->selected = $this->getSelectedIds();
02554 
02555             $sleep_vars = parent::__sleep();
02556             array_push($sleep_vars, 'control_name', 'id', 'control_class', 'actions', 'selected', 'display', 'events');
02557             return $sleep_vars;
02558         }
02559 }
02560 
02563 class SingleChoice extends ControlChoice 
02564 {
02565     
02570     function SingleChoice($control_class, $choice) 
02571         {
02572             $this->ControlChoice($control_class, $choice);
02573         }
02574 
02575     /***************************************************
02576      * Control INTERFACE
02577      ***************************************************/
02578 
02579     function getValue() 
02580         {
02581             $selected = $this->getSelectedControls();
02582             if (sizeof($selected) == 1)
02583                 return $selected[0]->getValue();
02584             return null;
02585         }
02586     
02587     /***************************************************
02588      * Choice INTERFACE
02589      ***************************************************/
02590 
02591     function select($id) 
02592         {
02593             parent::select($id);
02594 
02595             foreach ($this->getSelectedIds() as $selected_id) 
02596                 {
02597                     if ($id != $selected_id)
02598                         $this->deselect($selected_id);
02599                 }
02600         }
02601 }
02602 
02609 class RadioChoice extends SingleChoice 
02610 {
02616     function RadioChoice($choice, $radio_class = 'RadioInput') 
02617         {
02618             check_class($radio_class, 'RadioInput');
02619             
02620             $this->SingleChoice($radio_class, $choice);
02621         }    
02622 }
02623 
02626 class MultipleChoice extends ControlChoice 
02627 {
02632     function MultipleChoice($control_class, $choice) 
02633         {
02634             $this->ControlChoice($control_class, $choice);
02635         }
02636 
02637     /***************************************************
02638      * Control INTERFACE
02639      ***************************************************/
02640     
02641     function submitsMultipleValues() 
02642         {
02643             return true;
02644         }
02645 
02646     function getValue() 
02647         {
02648             $selected = array();
02649             foreach ($this->getSelectedControls() as $control) 
02650                 {
02651                     $selected[] = $control->getValue();
02652                 }
02653             return $selected;
02654         }
02655     
02656 }
02657 
02664 class CheckboxChoice extends MultipleChoice 
02665 {
02671     function CheckboxChoice($choice, $checkbox_class = 'CheckboxInput') 
02672         {
02673             check_class($checkbox_class, 'CheckboxInput');
02674 
02675             $this->MultipleChoice($checkbox_class, $choice);
02676         }
02677 }
02678 
02679 
02692 class SelectElement extends ControlElement
02693 {
02695     var $controlchoice;
02696     
02701     function SelectElement($choice = null) 
02702         {
02703             if ($this->submitsMultipleValues())
02704                 $this->controlchoice = new MultipleChoice('MultipleOption', $choice);
02705             else
02706                 $this->controlchoice = new SingleChoice('SingleOption', $choice);
02707             
02708             $this->ControlElement('select', $this->controlchoice->getControlName());
02709         }
02710 
02711     function setAttribute($name, $value)
02712         {
02713             if ($name == 'multiple') {
02714                 if ($this->submitsMultipleValues() and $this->hasAttribute('multiple')) // check to see if we can set the attribute. Can only be set once, in the constructor.
02715                     trigger_error("The 'multiple' attribute cannot be changed", E_USER_ERROR);
02716             }
02717 
02718             parent::setAttribute($name, $value);
02719         }
02720 
02721     function toXHTML() 
02722         {
02723             $dom_document = $this->dom_document->clone_node(true);
02724             $root = $dom_document->document_element();
02725             foreach ($this->getDisplayableControls() as $option) 
02726                 {
02727                     $node = $option->node->clone_node(true);
02728                     $root->append_child($node);
02729                 }
02730             
02731             return $dom_document->dump_node($root);            
02732         }
02733 
02734     /***************************************************
02735      * Control INTERFACE
02736      ***************************************************/
02737     
02738     function isSimpleControl() 
02739         {
02740             return false;
02741         }
02742 
02743     function submitsMultipleValues() 
02744         {
02745             return false;
02746         }
02747     
02748     function setId($id) 
02749         {
02750             parent::setId($id);
02751             $this->controlchoice->setId($id);
02752         }
02753 
02754     function getValue() 
02755         {
02756             return $this->controlchoice->getValue();
02757         }
02758     
02759     function setControlName($name) 
02760         {
02761             parent::setControlName($name);
02762             if ($this->controlchoice)
02763                 $this->controlchoice->setControlName($name);
02764         }    
02765 
02766     function triggerActions() 
02767         {
02768             parent::triggerActions();
02769             $this->triggerChildActions();
02770         }
02771 
02772     function eventHasOccurred($event) 
02773         {
02774             if ($event == FC_EVENT_UPDATE) {
02775                 $this->setEventHasOccurred(FC_EVENT_UPDATE, $this->controlchoice->eventHasOccurred(FC_EVENT_UPDATE));
02776             }
02777             
02778             return parent::eventHasOccurred($event);
02779         }
02780     
02781     /***************************************************
02782      * Choice INTERFACE
02783      ***************************************************/
02784 
02789     function setControlClass($control_class) 
02790         {
02791             $this->controlchoice->setControlClass($control_class);
02792         }
02793     
02794     
02799     function getControlClass() 
02800         {
02801             return $this->controlchoice->getControlClass();
02802         }
02803     
02804     
02809     function &addChoice($value, $label = null, $selected = false) 
02810         {
02811             return $this->controlchoice->addChoice($value, $label, $selected);
02812         }
02813 
02818     function selectedCount() 
02819         {
02820             return $this->controlchoice->selectedCount();
02821         }
02822 
02827     function getSelectedIds() 
02828         {
02829             return $this->controlchoice->getSelectedIds();
02830         }
02831 
02836     function getSelectedControls() 
02837         {
02838             return $this->controlchoice->getSelectedControls();
02839         }
02840 
02845     function select($id)
02846         {
02847             return $this->controlchoice->select($id);
02848         }
02849 
02854     function selected($id) 
02855         {
02856             return $this->controlchoice->selected($id);
02857         }
02858 
02863     function deselect($id)
02864         {
02865             return $this->controlchoice->deselect($id);
02866         }
02867 
02868     /***************************************************
02869      * Container INTERFACE
02870      ***************************************************/
02871 
02876     function triggerChildActions() 
02877         {
02878             $this->controlchoice->triggerChildActions();
02879         }
02880     
02885     function &getByValue($value) 
02886         {
02887             return $this->controlchoice->getByValue($value);
02888         }
02889     
02894     function &get($id) 
02895         {
02896             return $this->controlchoice->get($id);
02897         }
02898 
02903     function add(&$control) 
02904         {
02905             return $this->controlchoice->add($control);
02906         }
02907 
02912     function exists($id) 
02913         {
02914             return $this->controlchoice->exists($id);
02915         }
02916 
02921     function &remove($id) 
02922         {
02923             return $this->controlchoice->remove($id);
02924         }
02925 
02930     function getAllIds() 
02931         {
02932             return $this->controlchoice->getAllIds();
02933         }
02934 
02939     function getAllControls() 
02940         {
02941             return $this->controlchoice->getAllControls();
02942         }
02943 
02948     function getDisplayableIds() 
02949         {
02950             return $this->controlchoice->getDisplayableIds();
02951         }
02952 
02957     function getDisplayableControls() 
02958         {
02959             return $this->controlchoice->getDisplayableControls();
02960         }
02961 
02966     function childDisplay($id) 
02967         {
02968             return $this->controlchoice->display();            
02969         }
02970     
02975     function childToString($id) 
02976         {
02977             return $this->controlchoice->toString();
02978         }
02979 
02984     function childUpdated($id) 
02985         {
02986             return $this->controlchoice->updated();
02987         }    
02988     
02989     /***************************************************
02990      * Serialisation INTERFACE
02991      ***************************************************/
02992 
02993     function __wakeup() 
02994         {
02995             parent::__wakeup();
02996 
02997             // remove serialised options
02998             foreach ($this->node->child_nodes() as $node) 
02999                 {
03000                     $node->unlink_node($node);
03001                 }
03002         }
03003     
03004     function __sleep() 
03005         {
03006             $sleep_vars = parent::__sleep();
03007             array_push($sleep_vars, 'controlchoice');
03008             return $sleep_vars;
03009         }
03010 }
03011 
03015 class SingleSelect extends SelectElement 
03016 {
03021     function SingleSelect($choice = null) 
03022         {
03023             $this->SelectElement($choice);
03024         }
03025 }
03026 
03030 class MultipleSelect extends SelectElement 
03031 {
03036     function MultipleSelect($choice = null) 
03037         {
03038             $this->SelectElement($choice);
03039             $this->setBooleanAttribute('multiple', true);
03040         }
03041 
03042     /***************************************************
03043      * Control INTERFACE
03044      ***************************************************/
03045 
03046     function submitsMultipleValues() 
03047         {
03048             return true;
03049         }    
03050 
03051     /***************************************************
03052      * Printable INTERFACE
03053      ***************************************************/
03054 
03055     function toString() 
03056         {
03057             $string = parent::toString();
03058             return $string .= sprintf('<input type="hidden" name="%s" value="">', $this->getControlName());    // this is required so that a value is posted even if all options are deselected
03059         }
03060 }
03061 
03062 ?>

Generated on Mon Feb 14 11:39:50 2005 for FormControls by doxygen 1.3.5