Location: PHPKode > projects > FiForms Framework > FiForms/FiForms-includes/FiForms_iContainer.inc.php
<?php
/*
*******************************************************************************

    FiForms -- A collection of PHP classes designed 
    to facilitate rapid development of web-database software

    Copyright (C) 2003-2008  Daniel McFeeters

    This library is free software; you can redistribute it and/or
    modify it under the terms of the GNU General Public
    License as published by the Free Software Foundation; either
    version 2 of the License, or (at your option) any later version.

    This library is distributed in the hope that it will be useful,
    but WITHOUT ANY WARRANTY; without even the implied warranty of
    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
    General Public License for more details.

    You should have received a copy of the GNU General Public
    License along with this library; if not, write to the Free Software
    Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA


    The original author of this library can be contacted at the following 
    address:

    Daniel McFeeters
    182 Baker Rd.
    Faubush, KY 42544-6526
    email:databases [at] fiforms [dot] org
    http://www.fiforms.org/


Project Started May 4, 2003
*******************************************************************************
FiForms_iContainer.inc.php

iContainer class Definition

iContainer is a generic iInput which can contain other iInputs and output them 
in an HTML wrapper

*******************************************************************************
*/
    if(!isset($FIFORMS_CONFIG))
    {
        die('No Configuration found. Did you perhaps call an include file' .
                        ' directly instead of calling it as part of the FiForms' .
                        ' application?'); 
    }
    require_once("FiForms_iInput.inc.php");

/* ?><code><?php */

$FIFORM_XML_INPUTS = array('f:code');
$FIFORM_XML_INPUT_NAMESPACES = array(
    'f' => 'http://xml.fiforms.org/FiForms/',
    'html' => 'http://www.w3.org/1999/xhtml'
);

$FIFORM_XML_INPUTS[] = 'f:iContainer';

class iContainer extends iInput
{
    public $inputs;    // objects in the container
    public $formatStr; // array of html code used as a "wrapper" for the 
                    // individual objects.
                    // Contains 3 string elements: head, body, and foot. 
                    // Variables inside %% symbols are substituted.
                    // Special variables are  %drawInput% and %drawCaption%
    public $drawInput; // Special variable used to draw the form.
    public $drawCaption;
                    //Special variable used to draw the form.
    public $resultArray; // results from database
    public $boundForm;   // link to containing form
    public $merge_record;   // array containing the record from the database
                        // to be merged in case of a conflict.

    public $original_record;// array with original record
    public $keyPrefix;      // string prefix for iInput keys



    function iContainer()
    // class constructor
    {
        $this->iInput(func_get_args());
        // assign a generic table wrapper to the format array.
        $this->formatStr->head = "return(\"<table>\");";
        $this->formatStr->body = <<<EOD
            return("\n<tr>\n<th class=\"FiForm\">\$this->drawCaption</th>\n".
            "<td class=\"FiForm\">\$this->drawInput</td>\n</tr>\n");
EOD;
        $this->formatStr->foot = "return(\"</table>\");";
        $this->keyPrefix = '';
    } // function iContainer

    function throwError($errorMessage)
    {
        $this->boundForm->throwError($errorMessage);
    }

    function outputRow($containerForFormat,$needCaption,$type='')
    // Generates output from each contained control
    {
        if(!is_array($this->inputs))
        {
            return(' ');
        }
        $keys = array_keys($this->inputs);
        foreach($keys as $thisKey)
        {  
            if(!is_object($this->inputs[$thisKey]) || !($this->inputs[$thisKey] instanceof iInput))  
            {
                $this->throwError("Unknown input: $thisKey<br />");
                continue;
            }
            if ($this->readOnly == TRUE)
            {
                $this->inputs[$thisKey]->readOnly = TRUE;
                $this->inputs[$thisKey]->checkRO();
            }
            if($needCaption)
            {
                $this->drawCaption = $this->inputs[$thisKey]->drawCaption();
            }
            $this->drawInput = $this->inputs[$thisKey]->drawInput();
            if($this->inputs[$thisKey]->visible)
            {
                //print_r($this); die();
                if(
                    $this->boundForm->sheetView && 
                    ($this->inputs[$thisKey] instanceof iContainer)
                  )
                {
                    $rowOutput .= $this->inputs[$thisKey]->outputRow($containerForFormat,$needCaption,$type);
                }
                else //if($containerForFormat instanceof iInput)
                {
                    $rowOutput .= $containerForFormat->drawBody($type);
                }
            }
        } // while list
        return($rowOutput);
    } // outputRow

    function drawInput()
    {
        if(!$this->visible)
        {
            return '';
        }
        $output = $this->drawHead();
        $output .= $this->outputRow($this,true);
        $output .= $this->drawFoot();
        return($output);

    } // function drawInput

    function buildInsertQuery($describeArray, &$updateQuery, &$valuestring)
    // build one field of the INSERT query
    {
        //print_r($this->inputs);
        foreach($this->inputs as $postInput)
        {
            if($postInput instanceof iContainer && is_array($postInput->inputs))
            {
                //echo('running subclass'.$this->dbField);
                $postInput->buildInsertQuery($describeArray,$updateQuery,$valuestring);
                continue;
            }
            //echo "running field ".$postInput->dbField;
            $descRow =  array_search($postInput->dbField,
                                $describeArray);

            if($descRow === FALSE)
            {
                continue;
            }
            $updateQuery .= "`".$describeArray[$descRow]."`, ";  

            if($postInput->functionToSave)
            {
                $valuestring .= $postInput->functionToSave.", "; 
            }
            elseif($postInput->valueToSave === '' || $postInput->valueToSave === false)
            {
                $valuestring .= "NULL, ";
            }
            elseif($postInput->useHex)
            { 
                if($postInput->valueToSave)
                {
                    $valuestring .=
                        '0x'.bin2hex($postInput->valueToSave).", ";
                }
                else
                {
                    $valuestring .= "'', ";
                }
            }
            else
            {
                if (!get_magic_quotes_gpc())
                {
                    $postInput->valueToSave = addslashes($postInput->valueToSave);
                }
                $valuestring .= "'".$postInput->valueToSave."', ";
            }
            if($postInput->error)
            {
                //$this->wrapper->errorMsg .= $postInput->errorMsg;
                $this->throwError( "Error in input box <i>".$postInput->caption.  "</i>: ".$postInput->errorMsg);
                return(false);
            }
    
        } //foreach in inputs
               return true;

    }  // function buildInsertQueryPart


    function buildUpdateQuery($describeArray,&$updateQuery)
    {
        // Build the SET (Fieldname=x) portion of the UPDATE query
        foreach($this->inputs as $inputName => $postInput)
        {
            if($postInput instanceof iContainer && is_array($postInput->inputs))
            {
                $postInput->buildUpdateQuery($describeArray,$updateQuery);
                continue;
            }

            $descRow =  array_search($postInput->dbField,
                                $describeArray);
            if($descRow === FALSE)
            {
                continue;
            }
            if($postInput->valueToSave !== FALSE || $postInput->functionToSave)
            {
                $updateQuery .= "`".$describeArray[$descRow]."` = ";
                if($postInput->functionToSave)
                {
                    $updateQuery .= $postInput->functionToSave.", ";
                }
                elseif($postInput->valueToSave === '')
                {
                    $updateQuery .= "NULL, ";
                }
                elseif($postInput->useHex)
                {
                    if($postInput->valueToSave)
                    $updateQuery .= '0x'.bin2hex($postInput->valueToSave).", ";
                    else
                    $updateQuery .= "'', ";
                }
                else
                {
                    if (!get_magic_quotes_gpc())
                    {
                        $postInput->valueToSave =
                            addslashes($postInput->valueToSave);
                    }
                    $updateQuery .= "'".$postInput->valueToSave."', ";
                }
            }
            if($postInput->error)
            {
                $this->throwError( "Error in input box <i>".$postInput->caption.  "</i>: ".$postInput->errorMsg);
                return(false);
            }
        } // foreach in inputs
    } // buildUpdateQuery

    function fillInputs()
    // called by getNextRecord to fill $this->inputs 
    // with data from $this->resultArray
    {
        if(!is_array($this->inputs))
        {
            return false;
        }
        $keys = array_keys($this->inputs);
        foreach($keys as $thiskey)
        // loop through all the controls on the form.
        {
            if($this->inputs[$thiskey] instanceof iContainer)
            // this is a container, so call recursive function
            {
                $this->inputs[$thiskey]->resultArray = &$this->resultArray;
                $this->inputs[$thiskey]->primaryKeyFilter =
                     &$this->primaryKeyFilter;
                $this->inputs[$thiskey]->recNum = &$this->recNum;
                $this->inputs[$thiskey]->fillInputs();
                continue;
            }

            if(array_key_exists($this->inputs[$thiskey]->dbField,
                 $this->resultArray))
            // this is a data-bound field, so fill it with data
            {
                $this->inputs[$thiskey]->setValue(
                $this->resultArray[$this->inputs[$thiskey]->dbField]);
                // Disable user sort if field name and 
                // array index are different.
                if($thiskey != $this->inputs[$thiskey]->dbField)
                {
                    $this->inputs[$thiskey]->allowUserSort = FALSE;
                }
            }
            else
            // this is not a data-bound field
            {
                // Disable user sort on non data-bound fields
                $this->inputs[$thiskey]->allowUserSort = FALSE;
            }
            if($this->inputs[$thiskey]->multiField)
            {
                $this->inputs[$thiskey]->fieldList = &$this->resultArray;
                $this->inputs[$thiskey]->primaryKeyFilter =
                     &$this->primaryKeyFilter;
                $this->inputs[$thiskey]->recNum = &$this->recNum;
            }
        } // foreach input
    }  // function fillInputs


/******************************************************************************
                                ADD INPUT 
******************************************************************************/

    public function &addIn()
    // Add a new iInput to the form. First argument is class of input.
    // Remaining arguments are passed to constructor. 
    {
        $theArgs = func_get_args();
        $inputType = &$theArgs[0];
        if($inputType == "")
        {
            $inputType = "iText";
        }

        $inputField = $theArgs[1];

        $inputName = $theArgs[2];
        if($inputName == "")
        {
            $inputName = $inputField;
        }

        $params = '';
        for($count=1; $count < func_num_args(); $count++)
        {
            $params .= '$theArgs['.$count.'],';
        }       
        $params = substr($params, 0,strlen($params)-1);

        $createFunction = '$tmp'." = new $inputType($params);".
                          'return($tmp);';
        if($inputField == '')
        {
            $inputField = '1';
        }
        $inputField = $this->keyPrefix.$inputField;
        while(isset($this->inputs[$inputField]))
        {
                $inputField .= "1";
        }
        $this->inputs[$inputField] = eval($createFunction);
        if($this->inputs[$inputField] instanceof iContainer)
        {
            $this->inputs[$inputField]->boundForm = &$this->boundForm;
            $this->inputs[$inputField]->allowedParameters =
                 &$this->allowedParameters;
            $this->inputs[$inputField]->keyPrefix = $inputField.'_';
        }
        return $this->inputs[$inputField];
    } // function addIn

    function loadInputFromXML($input)
    {
        $type = $input->localName;
        if($type == "code")
        {
            eval($input->nodeValue);
            return 0;
        } // if code

        // The $field property of each class comes from a different
        // XML attribute, so each must be tested for. 
        if($type == "iLink")
        {
            $field = $input->attributes->getNamedItem('href')->nodeValue;
        }
        else if($type == "iSubform")
        {
            // Always ignore subforms in sheetView
            if(array_key_exists('sheetView',$_GET) && 
                $_GET['sheetView'] == 'YES')
            {
                return 0;
            }
            $field = 'viewform.php?app='.
                urlencode($GLOBALS['FIFORMS_CONFIG']['APP_NAME']).
                '&formname='.
                $input->attributes->getNamedItem('href')->nodeValue;

        } // if iSubform

        else if($type == "iCustomInput")
        {
            // in iCustomInput, this is called "expression"
            $field = $input->attributes->getNamedItem('expression')->nodeValue;
        }
        else
        {
            // default case (all others) it is called "field"
            $field = $input->attributes->getNamedItem('field')->nodeValue;
        }
        $caption = "";
        if($input->attributes->getNamedItem('caption'))
        {
            $caption = $input->attributes->getNamedItem('caption')->nodeValue;
        }
        if($caption == "" && $type == "iLink")
        {
            $caption = " ";
        }

        $displayWhen = "";
        foreach($input->attributes as $attr)
        {
            $name = $attr->nodeName;
            if($name == 'display')
            {
                $displayWhen = $attr->nodeValue;
                break;
            }
        }  // foreach

        if($displayWhen !== "none" && 
            ($displayWhen !== "sheet" || $this->sheetView) && 
            ($displayWhen !== "form" || !$this->sheetView))
            // check that this control is not disabled
        {
            // create the input object
            $thisinput = &$this->addIn($type,
                            $field,
                            $caption,'','','');

            if(in_array($field,$this->allowedParameters))
            {
                $thisinput->autoFilter = TRUE;
            }

            // call the input-specific function to load its own config
            // from the xml object
            $thisinput->buildFromXML($input);
        }  // if control is not disabled
    } // function loadInputsFromXML

    function buildFromXML($input)
    {
        foreach($input->childNodes as $thisElement)
        {
            if($thisElement->nodeType == 1)
            {
                $this->loadInputFromXML($thisElement);
            }
        }
    }  // function buildFromXML

    function restoreMerge($merge_mode)
    {
        foreach($this->inputs as $thiskey => $thisinput)
        {
            if($this->inputs[$thiskey] instanceof iContainer && is_array($this->inputs[$thiskey]->inputs))
            {
                $this->inputs[$thiskey]->original_record =
                     &$this->original_record;
                $this->inputs[$thiskey]->merge_record =
                     &$this->merge_record;
                $this->inputs[$thiskey]->restoreMerge($merge_mode);
                continue;
            }
            $postedValue = stripslashes(
                $this->inputs[$thiskey]->valueToSave);
            $fieldName = $this->inputs[$thiskey]->dbField;
            if($merge_mode &&
                array_key_exists($fieldName,$this->original_record))
            {
                $originalValue = $this->original_record[$fieldName];
                $dbValue = $this->merge_record[$fieldName];
                // The following conditions detect if and where 
                // a field was changed
                if($originalValue == $postedValue)  // no change on this form
                {
                    $newValue = $dbValue;
                }
                else if($originalValue == $dbValue)  // no change in database
                {
                    $newValue = $postedValue;
                }
                else if($dbValue == $postedValue)  
                // same change was made in both places
                {
                    $newValue = $postedValue;
                }
                else // There is a conflict in the merge.
                {
                    $newValue = $postedValue;
                    $this->throwError("<b>Conflict while merging ".
                        $this->inputs[$thiskey]->caption.
                        "</b><br /><b>Original Value:</b> ".
                        htmlentities($originalValue).
                        "  <br /><b>Value in Database:</b>".
                        htmlentities($dbValue).
                        "  <br /><b>New Value:</b>".
                        htmlentities($postedValue)."<br />");
                } // if else change detection
            }
            else
            {
                $newValue = $postedValue;
            }
            if(is_a($this->inputs[$thiskey],'iInput'))
            {
                $this->inputs[$thiskey]->setValue($newValue);
            }
            if($thisinput->multiField == TRUE)
            {
                foreach($_POST as $fieldName => $fieldValue)
                {
                    $this->inputs[$thiskey]->fieldList[$fieldName] =
                    $fieldValue;
                } // foreach 
            } // if
        } // foreach

    } // function restoreMerge

} // class iContainer

/* ?></code><?php */

?>
Return current item: FiForms Framework