Source for file jFormsBase.class.php

Documentation is available at jFormsBase.class.php

  1. <?php
  2. /**
  3. @package     jelix
  4. @subpackage  forms
  5. @author      Laurent Jouanneau
  6. @contributor Dominique Papin
  7. @contributor Christophe Thiriot
  8. @copyright   2006-2007 Laurent Jouanneau, 2007 Dominique Papin
  9. @link        http://www.jelix.org
  10. @licence     http://www.gnu.org/licenses/lgpl.html GNU Lesser General Public Licence, see LICENCE file
  11. */
  12.  
  13. /**
  14.  *
  15.  */
  16. require(JELIX_LIB_FORMS_PATH.'jFormsControl.class.php');
  17. require(JELIX_LIB_FORMS_PATH.'jFormsDatasource.class.php');
  18. require(JELIX_LIB_UTILS_PATH.'jDatatype.class.php');
  19.  
  20. /**
  21.  * exception for jforms
  22.  * @package     jelix
  23.  * @subpackage  forms
  24.  */
  25. class jExceptionForms extends jException {
  26.  
  27. }
  28.  
  29. /**
  30.  * base class of all form classes generated by the jform compiler
  31.  * @package     jelix
  32.  * @subpackage  forms
  33.  */
  34. abstract class jFormsBase {
  35.  
  36.     /**
  37.      * List of all form controls
  38.      * array of jFormsControl objects
  39.      * @var array 
  40.      * @see jFormsControl
  41.      */
  42.     protected $_controls = array();
  43.  
  44.     /**
  45.      * List of submit buttons
  46.      * array of jFormsControl objects
  47.      * @var array 
  48.      * @see jFormsControl
  49.      */
  50.     protected $_submits = array();
  51.  
  52.     /**
  53.      * Reset button
  54.      * @var jFormsControl 
  55.      * @see jFormsControl
  56.      * @since 1.0
  57.      */
  58.     protected $_reset = null;
  59.  
  60.     /**
  61.      * List of uploads controls
  62.      * array of jFormsControl objects
  63.      * @var array 
  64.      * @see jFormsControl
  65.      */
  66.     protected $_uploads = array();
  67.  
  68.     /**
  69.      * the data container
  70.      * @var jFormsDataContainer 
  71.      */
  72.     protected $_container=null;
  73.  
  74.     /**
  75.      * content list of available form builder
  76.      * @var boolean 
  77.      */
  78.     protected $_builders = array();
  79.  
  80.     /**
  81.      * the form selector
  82.      * @var string 
  83.      */
  84.     protected $_sel;
  85.  
  86.     /**
  87.      * @param string $sel the form selector
  88.      * @param jFormsDataContainer $container the data container
  89.      * @param boolean $reset says if the data should be reset
  90.      */
  91.     public function __construct($sel&$container$reset false){
  92.         $this->_container = $container;
  93.         if($reset){
  94.             $this->_container->clear();
  95.         }
  96.         $this->_sel = $sel;
  97.     }
  98.  
  99.     /**
  100.      * set form data from request parameters
  101.      */
  102.     public function initFromRequest(){
  103.         $req $GLOBALS['gJCoord']->request;
  104.         foreach($this->_controls as $name=>$ctrl){
  105.             if($ctrl->readonlycontinue;
  106.             $value $req->getParam($name);
  107.             //@todo à prevoir un meilleur test, pour les formulaires sur plusieurs pages
  108.             if($value === null$value='';
  109.             if($ctrl->type=='checkbox'){
  110.                 if($value){
  111.                     $value $ctrl->valueOnCheck;
  112.                 }else{
  113.                     $value $ctrl->valueOnUncheck;
  114.                 }
  115.             }elseif($ctrl->type=='upload'){
  116.                 if(isset($_FILES[$name])){
  117.                     $value $_FILES[$name]['name'];
  118.                 }else{
  119.                     $value'';
  120.                 }
  121.             }elseif($ctrl->type=='submit' && $value && !$ctrl->standalone{
  122.                 // because IE send the <button> content as value instead of the content of the
  123.                 // "value" attribute, we should verify it and get the real value
  124.                 // or when using <input type="submit">, we have only the label as value (in all browsers...
  125.                 $datas $ctrl->datasource->getDatas();
  126.                 if(!isset($datas[$value])) {
  127.                     $datas=array_flip($datas);
  128.                     if(isset($datas[$value])) {
  129.                         $value $datas[$value];
  130.                     }
  131.                 }
  132.             }
  133.             $this->_container->datas[$name$value;
  134.         }
  135.     }
  136.  
  137.     /**
  138.      * check validity of all data form
  139.      * @return boolean true if all is ok
  140.      */
  141.     public function check(){
  142.         $this->_container->errors = array();
  143.         foreach($this->_controls as $name=>$ctrl){
  144.             $err $ctrl->check($this->_container->datas[$name]$this);
  145.             if($err !== null)
  146.                 $this->_container->errors[$name]$err;
  147.         }
  148.         return count($this->_container->errors== 0;
  149.     }
  150.  
  151.     /**
  152.      * set form data from a DAO
  153.      * @param string $daoSelector the selector of a dao file
  154.      * @param string $key the primary key for the dao. if null, takes the form ID as primary key
  155.      * @param string $dbProfil the jDb profil to use with the dao
  156.      * @see jDao
  157.      */
  158.     public function initFromDao($daoSelector$key null$dbProfil=''){
  159.         if($key === null)
  160.             $key $this->_container->formId;
  161.         $dao jDao::create($daoSelector$dbProfil);
  162.         $daorec $dao->get($key);
  163.         if(!$daorec{
  164.             if(is_array($key))
  165.                 $key var_export($key,true);
  166.             throw new jExceptionForms('jelix~formserr.bad.formid.for.dao',
  167.                                       array($daoSelector$key$this->_sel));
  168.         }
  169.  
  170.         $prop $dao->getProperties();
  171.         foreach($this->_controls as $name=>$ctrl){
  172.             if(isset($prop[$name])) {
  173.                 if($ctrl->datatype instanceof jDatatypeLocaleDateTime
  174.                    && $prop[$name]['datatype'== 'datetime'{
  175.                     if($daorec->$name != ''{
  176.                         $dt new jDateTime();
  177.                         $dt->setFromString($daorec->$namejDateTime::DB_DTFORMAT);
  178.                         $this->_container->datas[$name$dt->toString(jDateTime::LANG_DTFORMAT);
  179.                     else {
  180.                         $this->_container->datas[$name='';
  181.                     }
  182.                 }elseif($ctrl->datatype instanceof jDatatypeLocaleDate
  183.                         && $prop[$name]['datatype'== 'date'{
  184.                     if($daorec->$name != ''{
  185.                         $dt new jDateTime();
  186.                         $dt->setFromString($daorec->$namejDateTime::DB_DFORMAT);
  187.                         $this->_container->datas[$name$dt->toString(jDateTime::LANG_DFORMAT);
  188.                     else {
  189.                         $this->_container->datas[$name='';
  190.                     }
  191.                 }elseif($ctrl->type=='checkbox' && $prop[$name]['datatype'== 'boolean'{
  192.                     if($daorec->$name == 'TRUE'||  $daorec->$name == 't'|| $daorec->$name == '1'||$daorec->$name == true){
  193.                         $this->_container->datas[$name$ctrl->valueOnCheck;
  194.                     }else {
  195.                         $this->_container->datas[$name$ctrl->valueOnUncheck;
  196.                     }
  197.                 }else{
  198.                     $this->_container->datas[$name$daorec->$name;
  199.                 }
  200.             }
  201.         }
  202.     }
  203.  
  204.     /**
  205.      * save data using a dao.
  206.      * it call insert or update depending the value of the formId stored in the container
  207.      * @param string $daoSelector the selector of a dao file
  208.      * @param string $key the primary key for the dao. if null, takes the form ID as primary key
  209.      * @param string $dbProfil the jDb profil to use with the dao
  210.      * @return mixed  the primary key of the new record in a case of inserting
  211.      * @see jDao
  212.      */
  213.     public function saveToDao($daoSelector$key null$dbProfil=''){
  214.         $dao jDao::get($daoSelector$dbProfil);
  215.  
  216.         if($key === null)
  217.             $key $this->_container->formId;
  218.  
  219.         if($key != null && ($daorec $dao->get($key))) {
  220.             $toInsertfalse;
  221.         }else{
  222.             $daorec jDao::createRecord($daoSelector$dbProfil);
  223.             if($key != null)
  224.                 $daorec->setPk($key);
  225.             $toInserttrue;
  226.         }
  227.  
  228.         $prop $dao->getProperties();
  229.         foreach($this->_controls as $name=>$ctrl){
  230.             if(!isset($prop[$name]))
  231.                 continue;
  232.  
  233.             if(is_array($this->_container->datas[$name])){
  234.                 ifcount ($this->_container->datas[$name]==1){
  235.                     $daorec->$name $this->_container->datas[$name][0];
  236.                 }else{
  237.                     // do nothing for arrays ?
  238.                     continue;
  239.                 }
  240.             }else{
  241.                 $daorec->$name $this->_container->datas[$name];
  242.             }
  243.  
  244.             if($daorec->$name == '' && !$prop[$name]['required']{
  245.                 // if no value and if the property is not required, we set null to it
  246.                 $daorec->$name null;
  247.             }else if($daorec->$name == '' && $prop[$name]['defaultValue'!== null
  248.                     && in_array($prop[$name]['datatype'],
  249.                                 array('int','integer','double','float'))) {
  250.                 $daorec->$name $prop[$name]['defaultValue'];
  251.  
  252.             }else if$prop[$name]['datatype'== 'boolean'){
  253.                 $daorec->$name ($daorec->$name == '1'|| $daorec->$name == 'true'
  254.                                   || $daorec->$name == 't');
  255.  
  256.             }else if($ctrl->datatype instanceof jDatatypeLocaleDateTime
  257.                      && $prop[$name]['datatype'== 'datetime'{
  258.                 $dt new jDateTime();
  259.                 $dt->setFromString($daorec->$namejDateTime::LANG_DTFORMAT);
  260.                 $daorec->$name $dt->toString(jDateTime::DB_DTFORMAT);
  261.  
  262.             }elseif($ctrl->datatype instanceof jDatatypeLocaleDate
  263.                     && $prop[$name]['datatype'== 'date'{
  264.                 $dt new jDateTime();
  265.                 $dt->setFromString($daorec->$namejDateTime::LANG_DFORMAT);
  266.                 $daorec->$name $dt->toString(jDateTime::DB_DFORMAT);
  267.             }
  268.         }
  269.         if($toInsert){
  270.             // todo : what about updating the formId with the Pk ?
  271.             $dao->insert($daorec);
  272.         }else{
  273.             $dao->update($daorec);
  274.         }
  275.         return $daorec->getPk();
  276.     }
  277.  
  278.     /**
  279.      * set data from a DAO, in a control
  280.      *
  281.      * The control must be a container like checkboxes or listbox with multiple attribute.
  282.      * The form should contain a formId
  283.      *
  284.      * The Dao should map to an "association table" : its primary key should be composed by
  285.      * the primary key stored in the formId (or the given primarykey) + the field which will contain one of
  286.      * the values of the control. If this order is not the same as defined into the dao,
  287.      * you should provide the list of property names which corresponds to the primary key
  288.      * in this order : properties for the formId, followed by the property which contains
  289.      * the value.
  290.      * @param string $controlName  the name of the control
  291.      * @param string $daoSelector the selector of a dao file
  292.      * @param mixed  $primaryKey the primary key if the form have no id. (optional)
  293.      * @param mixed  $primaryKeyNames list of field corresponding to primary keys (optional)
  294.      * @param string $dbProfil the jDb profil to use with the dao
  295.      * @see jDao
  296.      */
  297.     public function initControlFromDao($controlName$daoSelector$primaryKey null$primaryKeyNames=null$dbProfil=''){
  298.  
  299.         if(!$this->_controls[$controlName]->isContainer()){
  300.             throw new jExceptionForms('jelix~formserr.control.not.container'array($controlName$this->_sel));
  301.         }
  302.  
  303.         if(!$this->_container->formId)
  304.             throw new jExceptionForms('jelix~formserr.formid.undefined.for.dao'array($controlName$this->_sel));
  305.  
  306.         if($primaryKey === null)
  307.             $primaryKey $this->_container->formId;
  308.  
  309.         if(!is_array($primaryKey))
  310.             $primaryKey =array($primaryKey);
  311.  
  312.         $dao jDao::create($daoSelector$dbProfil);
  313.  
  314.         $conditions jDao::createConditions();
  315.         if($primaryKeyNames)
  316.             $pkNamelist $primaryKeyNames;
  317.         else
  318.             $pkNamelist $dao->getPrimaryKeyNames();
  319.  
  320.         foreach($primaryKey as $k=>$pk){
  321.             $conditions->addCondition ($pkNamelist[$k]'='$pk);
  322.         }
  323.  
  324.         $results $dao->findBy($conditions);
  325.         $valuefield $pkNamelist[$k+1];
  326.         $val array();
  327.         foreach($results as $res){
  328.             $val[]=$res->$valuefield;
  329.         }
  330.         $this->_container->datas[$controlName]=$val;
  331.     }
  332.  
  333.  
  334.     /**
  335.      * save data of a control using a dao.
  336.      *
  337.      * The control must be a container like checkboxes or listbox with multiple attribute.
  338.      * If the form contain a new record (no formId), you should call saveToDao before
  339.      * in order to get a new id (the primary key of the new record), or you should get a new id
  340.      * by an other way. then you must pass this primary key in the third argument.
  341.      * If the form has already a formId, then it will be used as a primary key, unless
  342.      * you give one in the third argument.
  343.      *
  344.      * The Dao should map to an "association table" : its primary key should be
  345.      * the primary key stored in the formId + the field which will contain one of
  346.      * the values of the control. If this order is not the same as defined into the dao,
  347.      * you should provide the list of property names which corresponds to the primary key
  348.      * in this order : properties for the formId, followed by the property which contains
  349.      * the value.
  350.      * All existing records which have the formid in their keys are deleted
  351.      * before to insert new values.
  352.      *
  353.      * @param string $controlName  the name of the control
  354.      * @param string $daoSelector the selector of a dao file
  355.      * @param mixed  $primaryKey the primary key if the form have no id. (optional)
  356.      * @param mixed  $primaryKeyNames list of field corresponding to primary keys (optional)
  357.      * @param string $dbProfil the jDb profil to use with the dao
  358.      * @see jDao
  359.      */
  360.     public function saveControlToDao($controlName$daoSelector$primaryKey null$primaryKeyNames=null$dbProfil=''){
  361.  
  362.         if(!$this->_controls[$controlName]->isContainer()){
  363.             throw new jExceptionForms('jelix~formserr.control.not.container'array($controlName$this->_sel));
  364.         }
  365.  
  366.         $values $this->_container->datas[$controlName];
  367.         if(!is_array($values&& $values != '')
  368.             throw new jExceptionForms('jelix~formserr.value.not.array'array($controlName$this->_sel));
  369.  
  370.         if(!$this->_container->formId && !$primaryKey)
  371.             throw new jExceptionForms('jelix~formserr.formid.undefined.for.dao'array($controlName$this->_sel));
  372.  
  373.         if($primaryKey === null)
  374.             $primaryKey $this->_container->formId;
  375.  
  376.         if(!is_array($primaryKey))
  377.             $primaryKey =array($primaryKey);
  378.  
  379.         $dao jDao::create($daoSelector$dbProfil);
  380.         $daorec jDao::createRecord($daoSelector$dbProfil);
  381.  
  382.         $conditions jDao::createConditions();
  383.         if($primaryKeyNames)
  384.             $pkNamelist $primaryKeyNames;
  385.         else
  386.             $pkNamelist $dao->getPrimaryKeyNames();
  387.  
  388.         foreach($primaryKey as $k=>$pk){
  389.             $conditions->addCondition ($pkNamelist[$k]'='$pk);
  390.             $daorec->{$pkNamelist[$k]$pk;
  391.         }
  392.  
  393.         $dao->deleteBy($conditions);
  394.         if (is_array($values)) {
  395.             $valuefield $pkNamelist[$k+1];
  396.             foreach($values as $value){
  397.                 $daorec->$valuefield $value;
  398.                 $dao->insert($daorec);
  399.             }
  400.         }
  401.     }
  402.  
  403.     /**
  404.      * method not implemented...
  405.      * @param boolean $r 
  406.      * @deprecated since 1.0.4
  407.      */
  408.     public function setReadOnly($r true){   }
  409.  
  410.     /**
  411.      * return list of errors found during the check
  412.      * @return array 
  413.      * @see jFormsBase::check
  414.      */
  415.     public function getErrors(){  return $this->_container->errors;  }
  416.  
  417.     /**
  418.      * set an error message on a specific field
  419.      * @param string $field the field name
  420.      * @param string $mesg  the error message string
  421.      */
  422.     public function setErrorOn($field$mesg){
  423.         $this->_container->errors[$field]=$mesg;
  424.     }
  425.  
  426.     /**
  427.      *
  428.      * @param string $name the name of the control/data
  429.      * @param string $value the data value
  430.      */
  431.     public function setData($name,$value){
  432.         if($this->_controls[$name]->type == 'checkbox'{
  433.             if($value != $this->_controls[$name]->valueOnCheck){
  434.                 if($value =='on')
  435.                     $value $this->_controls[$name]->valueOnCheck;
  436.                 else
  437.                     $value $this->_controls[$name]->valueOnUncheck;
  438.             }
  439.         }
  440.         $this->_container->datas[$name]=$value;
  441.     }
  442.     /**
  443.      *
  444.      * @param string $name the name of the control/data
  445.      * @return string the data value
  446.      */
  447.     public function getData($name){
  448.         if(isset($this->_container->datas[$name]))
  449.             return $this->_container->datas[$name];
  450.         else return null;
  451.     }
  452.  
  453.     /**
  454.      * @return array form data
  455.      */
  456.     public function getDatas()return $this->_container->datas}
  457.     /**
  458.      * @return jFormsDataContainer 
  459.      */
  460.     public function getContainer()return $this->_container}
  461.  
  462.     /**
  463.      * @return array of jFormsControl objects
  464.      */
  465.     public function getControls()return $this->_controls}
  466.  
  467.     /**
  468.      * @param string $name the control name you want to get
  469.      * @return jFormsControl 
  470.      * @since jelix 1.0
  471.      */
  472.     public function getControl($name)return $this->_controls[$name]}
  473.  
  474.     /**
  475.      * @return array of jFormsControl objects
  476.      */
  477.     public function getSubmits()return $this->_submits}
  478.  
  479.     /**
  480.      * @return array of jFormsControl objects
  481.      */
  482.     public function getReset()return $this->_reset}
  483.  
  484.     /**
  485.      * @return string the formId
  486.      */
  487.     public function id()return $this->_container->formId}
  488.  
  489.     /**
  490.      * @return boolean 
  491.      */
  492.     public function hasUpload(return count($this->_uploads)>0}
  493.  
  494.     /**
  495.      * @param string $buildertype  the type name of a form builder
  496.      * @param string $action action selector where form will be submit
  497.      * @param array $actionParams  parameters for the action
  498.      * @return jFormsBuilderBase 
  499.      */
  500.     public function getBuilder($buildertype$action$actionParams){
  501.         if(isset($this->_builders[$buildertype])){
  502.             include_once(JELIX_LIB_FORMS_PATH.'jFormsBuilderBase.class.php');
  503.             include_once ($this->_builders[$buildertype][0]);
  504.             $c =  $this->_builders[$buildertype][1];
  505.             return new $c($this$action$actionParams);
  506.         }else{
  507.             throw new jExceptionForms('jelix~formserr.invalid.form.builder'array($buildertype$this->_sel));
  508.         }
  509.     }
  510.  
  511.     /**
  512.      * save an uploaded file in the given directory. the given control must be
  513.      * an upload control of course.
  514.      * @param string $controlName the name of the upload control
  515.      * @param string $path path of the directory where to store the file. If it is not given,
  516.      *                      it will be stored under the var/uploads/_modulename~formname_/ directory
  517.      * @param string $alternateName a new name for the file. If it is not given, the file
  518.      *                               while be stored with the original name
  519.      * @return boolean true if the file has been saved correctly
  520.      */
  521.     public function saveFile($controlName$path=''$alternateName=''{
  522.         if ($path == ''{
  523.             $path JELIX_APP_VAR_PATH.'uploads/'.$this->_sel.'/';
  524.         else if (substr($path-11!= '/'{
  525.             $path.='/';
  526.         }
  527.  
  528.         if(!isset($this->_controls[$controlName]|| $this->_controls[$controlName]->type != 'upload')
  529.             throw new jExceptionForms('jelix~formserr.invalid.upload.control.name'array($controlName$this->_sel));
  530.  
  531.         if(!isset($_FILES[$controlName]|| $_FILES[$controlName]['error']!= UPLOAD_ERR_OK)
  532.             return false;
  533.  
  534.         if($this->_controls[$controlName]->maxsize && $_FILES[$controlName]['size'$this->_controls[$controlName]->maxsize){
  535.             return false;
  536.         }
  537.         jFile::createDir($path);
  538.         if ($alternateName == ''{
  539.             $path.= $_FILES[$controlName]['name'];
  540.         else {
  541.             $path.= $alternateName;
  542.         }
  543.         return move_uploaded_file($_FILES[$controlName]['tmp_name']$path);
  544.     }
  545.  
  546.     /**
  547.      * save all uploaded file in the given directory
  548.      * @param string $path path of the directory where to store the file. If it is not given,
  549.      *                      it will be stored under the var/uploads/_modulename~formname_/ directory
  550.      */
  551.     public function saveAllFiles($path=''{
  552.         if ($path == ''{
  553.             $path JELIX_APP_VAR_PATH.'uploads/'.$this->_sel.'/';
  554.         else if (substr($path-11!= '/'{
  555.             $path.='/';
  556.         }
  557.  
  558.         if(count($this->_uploads))
  559.             jFile::createDir($path);
  560.  
  561.         foreach($this->_uploads as $ref=>$ctrl){
  562.  
  563.             if(!isset($_FILES[$ref]|| $_FILES[$ref]['error']!= UPLOAD_ERR_OK)
  564.                 continue;
  565.             if($ctrl->maxsize && $_FILES[$ref]['size'$ctrl->maxsize)
  566.                 continue;
  567.  
  568.             move_uploaded_file($_FILES[$ref]['tmp_name']$path.$_FILES[$ref]['name']);
  569.         }
  570.     }
  571.  
  572.  
  573.     /**
  574.     * add a control to the form
  575.     * @param $control jFormsControl
  576.     */
  577.     protected function addControl($control){
  578.         $this->_controls [$control->ref$control;
  579.         if($control->type =='submit')
  580.             $this->_submits [$control->ref$control;
  581.         else if($control->type =='reset')
  582.             $this->_reset $control;
  583.         else if($control->type =='upload')
  584.             $this->_uploads [$control->ref$control;
  585.  
  586.         if(!isset($this->_container->datas[$control->ref])){
  587.             if $control->datatype instanceof jDatatypeDateTime && $control->defaultValue == 'now'{
  588.                 $dt new jDateTime();
  589.                 $dt->now();
  590.                 $this->_container->datas[$control->ref$dt->toString($control->datatype->getFormat());
  591.             }
  592.             else {
  593.                 $this->_container->datas[$control->ref$control->defaultValue;
  594.             }
  595.         }
  596.     }
  597. }
  598.  
  599. ?>

Documentation generated on Wed, 07 Sep 2011 13:47:22 +0200 by phpDocumentor 1.4.3