<?php

use ProcessMaker\Core\System;
use ProcessMaker\Plugins\PluginRegistry;

/**
 * Class XmlFormField
 *
 * @package gulliver.system
 * @access public
 */
class XmlFormField
{
    public $name = '';
    public $type = 'field';
    public $label = '';
    public $pmLabel = '';
    public $owner;
    public $language;
    public $group = 0;
    public $mode = '';
    public $defaultValue = null;
    public $gridFieldType = '';
    public $gridLabel = '';
    /* Hint value generic declaration */
    public $hint = '';
    /*to change the presentation*/
    public $enableHtml = false;
    public $style = '';
    public $withoutLabel = false;
    public $className = '';
    /*attributes for paged table*/
    public $colWidth = 140;
    public $colAlign = 'left';
    public $colClassName = '';
    public $titleAlign = '';
    public $align = '';
    public $showInTable = '';
    /*Events*/
    public $onclick = '';
    /*attributes for data filtering*/
    /*dataCompareField = field to be compared with*/
    public $dataCompareField = '';
    /* $dataCompareType : '=' ,'<>' , 'like', ... , 'contains'(== ' like "%value%"')
    */
    public $dataCompareType = '=';
    public $sql = '';
    public $sqlConnection = '';
    //Attributes for PM Tables integration (only ProcessMaker for now)
    public $pmtable = '';
    public $keys = '';
    public $pmconnection = '';
    public $pmfield = '';

    // For mode cases Grid
    public $modeGrid = '';
    public $modeForGrid = '';

    /**
     * Function XmlFormField
     *
     * @access public
     * @param string xmlNode
     * @param string lang
     * @param string home
     * @return string
     */
    public function __construct($xmlNode, $lang = 'en', $home = '', $owner = null)
    {
        //Loads any attribute that were defined in the xmlNode
        //except name and label.
        $myAttributes = get_class_vars(get_class($this));
        foreach ($myAttributes as $k => $v) {
            $myAttributes[$k] = strtoupper($k);
        }
        //$data: Includes labels and options.
        $data = &$xmlNode->findNode($lang);
        if (!isset($data->value)) {
            //It seems that in the actual language there are no value for the current field, so get the value in English
            $data = &$xmlNode->findNode("en");
            if (!isset($data->value)) {
                //It seems that in the actual language there are no value for the current field, so get the value in First language
                if (isset($xmlNode->children[0])) {
                    //Lets find first child
                    if ((isset($xmlNode->children[0]->name)) && (strlen($xmlNode->children[0]->name) == 2)) {
                        //Just to be sure that the node ocrresponds to a valid lang
                        $data = &$xmlNode->findNode($xmlNode->children[0]->name);
                    }
                }
            }
        }
        @$this->label = $this->pmLabel = $data->value;

        /*Loads the field attributes*/
        foreach ($xmlNode->attributes as $k => $v) {
            $key = array_search(strtoupper($k), $myAttributes);
            if ($key) {
                eval('$this->' . $key . '=$v;');
            }
        }
        //Loads the main attributes
        $this->name = $xmlNode->name;
        $this->type = strtolower($xmlNode->attributes['type']);
        preg_match('/\s*([^\s][\w\W]*)?/m', $xmlNode->value, $matches);
        $this->sql = (isset($matches[1])) ? $matches[1] : '';
        //List Options
        if (isset($data->children)) {
            foreach ($data->children as $k => $v) {
                if ($v->type !== 'cdata') {
                    if (isset($v->name) && isset($v->attributes["name"])) {
                        $this->{$v->name}[$v->attributes["name"]] = $v->value;
                    }
                }
            }
        }
        $this->options = (isset($this->option)) ? $this->option : [];
        //Sql Options : cause warning because values are not setted yet.
        if (isset($owner)) {
            if (isset($owner->mode)) {
                $ownerMode = $owner->mode;
            } else {
                $ownerMode = '';
            }
        } else {
            $ownerMode = '';
        }
        if ($ownerMode != '') {
            $this->mode = $ownerMode;
        }
        if ($this->mode == '') {
            $this->mode = 'edit';
        }
        $this->modeForGrid = $this->mode;
    }

    /**
     * validate if a value is setted
     *
     * @param $value
     * @return boolean true/false
     */
    public function validateValue($value)
    {
        return isset($value);
    }

    /**
     * execute a xml query
     *
     * @param &$owner reference of owner
     * @param $row
     * @return $result array of results
     */
    private function executeXmlDB(&$owner, $row = -1)
    {
        if (!$this->sqlConnection) {
            $dbc = new DBConnection();
        } else {
            if (defined('DB_' . $this->sqlConnection . '_USER')) {
                if (defined('DB_' . $this->sqlConnection . '_HOST')) {
                    eval('$res[\'DBC_SERVER\'] = DB_' . $this->sqlConnection . '_HOST;');
                } else {
                    $res['DBC_SERVER'] = DB_HOST;
                }
                if (defined('DB_' . $this->sqlConnection . '_USER')) {
                    eval('$res[\'DBC_USERNAME\'] = DB_' . $this->sqlConnection . '_USER;');
                }
                if (defined('DB_' . $this->sqlConnection . '_PASS')) {
                    eval('$res[\'DBC_PASSWORD\'] = DB_' . $this->sqlConnection . '_PASS;');
                } else {
                    $res['DBC_PASSWORD'] = DB_PASS;
                }
                if (defined('DB_' . $this->sqlConnection . '_NAME')) {
                    eval('$res[\'DBC_DATABASE\'] = DB_' . $this->sqlConnection . '_NAME;');
                } else {
                    $res['DBC_DATABASE'] = DB_NAME;
                }
                if (defined('DB_' . $this->sqlConnection . '_TYPE')) {
                    eval('$res[\'DBC_TYPE\'] = DB_' . $this->sqlConnection . '_TYPE;');
                } else {
                    $res['DBC_TYPE'] = defined('DB_TYPE') ? DB_TYPE : 'mysql';
                }
                $dbc = new DBConnection($res['DBC_SERVER'], $res['DBC_USERNAME'], $res['DBC_PASSWORD'], $res['DBC_DATABASE'], $res['DBC_TYPE']);
            } else {
                $dbc0 = new DBConnection();
                $dbs0 = new DBSession($dbc0);
                $res = $dbs0->execute("select * from  DB_CONNECTION WHERE DBC_UID=" . $this->sqlConnection);
                $res = $res->read();
                $dbc = new DBConnection($res['DBC_SERVER'], $res['DBC_USERNAME'], $res['DBC_PASSWORD'], $res['DBC_DATABASE']);
            }
        }
        $query = G::replaceDataField($this->sql, $owner->values);
        $dbs = new DBSession($dbc);
        $res = $dbs->execute($query);
        $result = [];
        while ($row = $res->Read()) {
            $result[] = $row;
        }
        return $result;
    }

    /**
     * Execute a propel query
     *
     * @param &$owner reference
     * @param $row
     * @return $result array of
     */
    private function executePropel(&$owner, $row = -1)
    {
        //g::pr($row);
        if (!isset($owner->values[$this->name])) {
            if ($row > -1) {
                $owner->values[$this->name] = [];
            } else {
                $owner->values[$this->name] = '';
            }
        }
        if (!is_array($owner->values[$this->name])) {
            //echo '1';
            $query = G::replaceDataField($this->sql, $owner->values);
        } else {
            $aAux = [];
            foreach ($owner->values as $key => $data) {
                if (is_array($data)) {
                    //echo '3:'.$key.' ';
                    if (isset($data[$row])) {
                        $qValue = $data[$row];
                    } else {
                        if (isset($owner->fields[$key]->selectedValue)) {
                            $qValue = $owner->fields[$key]->selectedValue;
                        } else {
                            $qValue = '';
                        }
                    }
                    $aAux[$key] = $qValue;
                    //$aAux [$key] = isset ( $data [$row] ) ? $data [$row] : '';
                } else {
                    //echo '4'.$key.' ';
                    $aAux[$key] = $data;
                }
            }

            //echo '2';
            //g::pr($aAux);
            $query = G::replaceDataField($this->sql, $aAux);
        }
        //echo $query;

        $result = [];
        if ($this->sqlConnection == 'dbarray') {
            try {
                $con = Propel::getConnection($this->sqlConnection);
                $stmt = $con->createStatement();
                $rs = $con->executeQuery($query, ResultSet::FETCHMODE_NUM);
            } catch (Exception $e) {
                //dismiss error because dbarray shouldnt be defined in some contexts.
                $workspace = !empty(config("system.workspace")) ? config("system.workspace") : "Undefined Workspace";
                G::log($workspace . " | ip: | " . G::getIpAddress() . " | type error: | " . $e->getMessage() . " | query: " . $query, PATH_DATA, "queriesWithErrors.log");

                return $result;
            }
        } else {
            try {
                $con = Propel::getConnection($this->sqlConnection);
                $stmt = $con->createStatement();
                $rs = $stmt->executeQuery($query, ResultSet::FETCHMODE_NUM);
            } catch (Exception $e) {
                //dismiss error because dbarray shouldnt be defined in some contexts.
                $workspace = !empty(config("system.workspace")) ? config("system.workspace") : "Undefined Workspace";
                G::log($workspace . " | ip: | " . G::getIpAddress() . " | type error: | " . $e->getMessage() . " | query: " . $query, PATH_DATA, "queriesWithErrors.log");

                return $result;
            }
        }

        $rs->next();
        $row = $rs->getRow();
        while (is_array($row)) {
            $result[] = $row;
            $rs->next();
            $row = $rs->getRow();
        }
        return $result;
    }

    /**
     * Function executeSQL
     *
     * @access public
     * @param string owner
     * @return string
     */
    public function executeSQL(&$owner, $row = -1)
    {
        if (!isset($this->sql)) {
            return 1;
        }
        if ($this->sql === '') {
            return 1;
        }

        if (isset($this->mode) && $this->mode == "edit" && (isset($this->owner->values[$this->name]) && $this->owner->values[$this->name] !== "") && ($this->type == "text" || $this->type == "currency" || $this->type == "percentage" || $this->type == "textarea" || $this->type == "hidden" || $this->type == "suggest")) {
            return 1;
        }

        if (isset($this->mode) && $this->mode == "view" && ($this->type == "text" || $this->type == "currency" || $this->type == "percentage" || $this->type == "textarea" || $this->type == "hidden" || $this->type == "suggest")) {
            return 1;
        }

        if (!$this->sqlConnection) {
            $this->sqlConnection = 'workflow';
        }

        //Read the result of the query
        if ($this->sqlConnection === "XMLDB") {
            $result = $this->executeXmlDB($owner, $row);
        } else {
            $result = $this->executePropel($owner, $row);
        }
        $this->sqlOption = [];
        $this->options = [];
        if (isset($this->option)) {
            foreach ($this->option as $k => $v) {
                $this->options[$k] = $v;
            }
        }
        for ($r = 0; $r < sizeof($result); $r++) {
            $key = reset($result[$r]);
            $this->sqlOption[$key] = next($result[$r]);
            $this->options[$key] = $this->sqlOption[$key];
        }

        if ($this->type != 'listbox') {
            if (isset($this->options) && isset($this->owner) && isset($this->owner->values[$this->name])) {
                if ((!is_array($this->owner->values[$this->name])) && !((is_string($this->owner->values[$this->name]) || is_int($this->owner->values[$this->name])) && array_key_exists($this->owner->values[$this->name], $this->options))) {
                    reset($this->options);
                    $firstElement = key($this->options);
                    if (isset($firstElement)) {
                        $this->owner->values[$this->name] = $firstElement;
                    } else {
                        $this->owner->values[$this->name] = '';
                    }
                }
            }
        }
        return 0;
    }

    /**
     * return the html entities of a value
     *
     * @param <any> $value
     * @param <type> $flags
     * @param <String> $encoding
     * @return <any>
     */

    public function htmlentities($value, $flags = ENT_QUOTES, $encoding = 'utf-8')
    {
        if ($this->enableHtml) {
            return $value;
        } else {
            return htmlentities($value, $flags, $encoding);
        }
    }

    /**
     * Function render
     *
     * @access public
     * @param string value
     * @return string
     */
    public function render($value = null, $paramDummy2 = null)
    {
        //this is an unknown field type.
        return $this->htmlentities($value != '' ? $value : $this->name, ENT_COMPAT, 'utf-8');
    }

    /**
     * Function renderGrid
     *
     * @access public
     * @param string values
     * @return string
     */
    public function renderGrid($values = null, $owner = null, $onlyValue = false, $therow = -1)
    {
        if ($values === null) {
            $values = [];
        }
        $result = [];
        $r = 1;
        foreach ($values as $v) {
            $result[] = $this->render($v, $owner, '[' . $owner->name . '][' . $r . ']', $onlyValue, $r, $therow);
            $r++;
        }
        return $result;
    }

    /**
     * render the field in a table
     *
     * @param $values
     * @param $owner
     * @param <Boolean> $onlyValue
     * @return <String> $result
     */
    public function renderTable($values = '', $owner = null, $onlyValue = false)
    {
        $r = 1;
        $result = $this->render($values, $owner, '[' . $owner->name . '][' . $r . ']', $onlyValue);
        return $result;
    }

    /**
     * Function dependentOf
     *
     * @access public
     * @return array
     */
    public function dependentOf()
    {
        $fields = [];
        if (isset($this->formula)) {
            preg_match_all("/\b[a-zA-Z][a-zA-Z_0-9]*\b/", $this->formula, $matches, PREG_PATTERN_ORDER);
            foreach ($matches[0] as $field) {
                $fields[] = $field;
            }
        }
        return $fields;
    }

    /**
     * Function mask
     *
     * @access public
     * @param string format
     * @param string value
     * @return string
     */
    public function mask($format, $value)
    {
        $value = explode('', $value);
        for ($j = 0; $j < strlen($format); $j++) {
            $result = '';
            $correct = true;
            for ($i = $j; $i < strlen($format); $i++) {
                $a = substr($format, $i, 1);
                $e = $i < strlen($value) ? substr($value, $i, 1) : '';
                //$e=$i<strlen($format)?substr($format, $i+1,1):'';
                switch ($a) {
                    case '0':
                        if ($e === '') {
                            $e = '0';
                        }
                    // no break
                    case '#':
                        if ($e === '') {
                            break 3;
                        }
                        if (strpos('0123456789', $e) !== false) {
                            $result .= $e;
                        } else {
                            $correct = false;
                            break 3;
                        }
                        break;
                    case '.':
                        if ($e === '') {
                            break 3;
                        }
                        if ($e === $a) {
                            break 1;
                        }
                        if ($e !== $a) {
                            break 2;
                        }
                    // no break
                    default:
                        if ($e === '') {
                            break 3;
                        }
                        $result .= $e;
                }
            }
        }
        if ($e !== '') {
            $correct = false;
        }
        //##,###.##   --> ^...$ no parece pero no, o mejor si, donde # es \d?, en general todos
        // es valida cuando no encuentra un caracter que no deberia estar, puede no terminar la mascara
        // pero si sobran caracteres en el value entonces no se cumple la mascara.
        return $correct ? $result : $correct;
    }

    /**
     * Function getAttributes
     *
     * @access public
     * @return string
     */
    public function getAttributes()
    {
        $attributes = [];
        foreach ($this as $attribute => $value) {
            switch ($attribute) {
                case 'sql':
                case 'sqlConnection':
                case 'name':
                case 'type':
                case 'owner':
                    break;
                default:
                    if (substr($attribute, 0, 2) !== 'on') {
                        $attributes[$attribute] = $value;
                    }
            }
        }
        if (sizeof($attributes) < 1) {
            return '{}';
        }
        //$json = new Services_JSON();
        //return $json->encode( $attributes );
        return G::json_encode($attributes);
    }

    /**
     * Function getEvents
     *
     * @access public
     * @return string
     */
    public function getEvents()
    {
        $events = [];
        foreach ($this as $attribute => $value) {
            if (substr($attribute, 0, 2) === 'on') {
                $events[$attribute] = $value;
            }
        }
        if (sizeof($events) < 1) {
            return '{}';
        }
        //$json = new Services_JSON();
        //return $json->encode( $events );
        return G::json_encode($events);
    }

    /**
     * Function attachEvents: Attaches events to a control using
     * leimnud.event.add
     *
     * @param $elementRef
     * @access public
     */
    public function attachEvents($elementRef)
    {
        $events = '';
        foreach ($this as $attribute => $value) {
            if (substr($attribute, 0, 2) == 'on') {
                $events = 'if (' . $elementRef . ') leimnud.event.add(' . $elementRef . ',"' . substr($attribute, 2) . '",function(){' . $value . '});' . "\n";
            }
        }
    }

    /**
     * Function createXmlNode: Creates an Xml_Node object storing
     * the data of $this Xml_Field.
     *
     * @access public
     * @return Xml_Node
     */
    public function createXmlNode($includeDefaultValues = false)
    {
        /* Start Comment: Creates the corresponding XML Tag for $this
        *    object.
        */
        $attributesList = $this->getXmlAttributes($includeDefaultValues);
        $node = new Xml_Node($this->name, 'open', $this->sql, $attributesList);
        /* End Comment */
        /* Start Comment: Creates the languages nodes and options
        *   if exist.
        */
        $node->addChildNode(new Xml_Node('', 'cdata', "\n"));
        $node->addChildNode(new Xml_Node($this->language, 'open', $this->label));
        if (isset($this->option)) {
            foreach ($this->option as $k => $v) {
                $node->children[1]->addChildNode(new Xml_Node('option', 'open', $v, array('name' => $k
                )));
            }
        }
        /* End Comment */
        return $node;
    }

    /**
     * Function updateXmlNode: Updates and existing Xml_Node
     * with the data of $this Xml_Field.
     *
     * @access public
     * @param string value
     * @return Xml_Node
     */
    public function &updateXmlNode(&$node, $includeDefaultValues = false)
    {
        /* Start Comment: Modify the node's attributes and value.
        */
        $attributesList = $this->getXmlAttributes($includeDefaultValues);
        $node->name = $this->name;
        $node->value = $this->sql;
        $node->attributes = $attributesList;
        /* End Comment */
        /* Start Comment: Modifies the languages nodes
        */
        $langNode = &$node->findNode($this->language);
        $langNode->value = $this->label;
        if (isset($this->option)) {
            $langNode->children = [];
            foreach ($this->option as $k => $v) {
                $langNode->addChildNode(new Xml_Node('option', 'open', $v, array('name' => $k
                )));
            }
        }
        /* End Comment */
        return $node;
    }

    /**
     * Function getXmlAttributes: Returns an associative array
     * with the attributes of $this Xml_field (only the modified ones).
     *
     * @access public
     * @param boolean includeDefaultValues Includes attributes
     * with default values.
     * @return Xml_Node
     */
    public function getXmlAttributes($includeDefaultValues = false)
    {
        $attributesList = [];
        $class = get_class($this);
        $default = new $class(new Xml_Node('DEFAULT', 'open', '', array('type' => $this->type
        )));
        foreach ($this as $k => $v) {
            switch ($k) {
                case 'owner':
                case 'name':
                case 'type':
                case 'language':
                case 'sql':
                    break;
                default:
                    if (($v !== $default->{$k}) || $includeDefaultValues) {
                        $attributesList[$k] = $v;
                    }
            }
        }
        return $attributesList;
    }

    /**
     * Used in Form::validatePost
     *
     * @param $value
     * @param &$owner
     * @return $value
     */
    public function maskValue($value, &$owner)
    {
        return $value;
    }
    /*Close this object*/
    /**
     * clone the current object
     *
     * @return <Object>
     */
    public function cloneObject()
    {
        //return unserialize( serialize( $this ) );//con este cambio los formularios ya no funcionan en php4
        return clone ($this);
    }

    /**
     * get a value from a PM Table
     *
     * @param <Object> $oOwner
     * @return <String> $sValue
     */
    public function getPMTableValue($oOwner)
    {
        $sValue = '';
        if (isset($oOwner->fields[$this->pmconnection])) {
            if (defined('PATH_CORE')) {
                if (file_exists(PATH_CORE . 'classes' . PATH_SEP . 'model' . PATH_SEP . 'AdditionalTables.php')) {
                    $oAdditionalTables = new AdditionalTables();
                    try {
                        $aData = $oAdditionalTables->load($oOwner->fields[$this->pmconnection]->pmtable, true);
                    } catch (Exception $oError) {
                        $aData = array('FIELDS' => array());
                    }
                    $aKeys = [];
                    $aValues = explode('|', $oOwner->fields[$this->pmconnection]->keys);
                    $i = 0;
                    if ($aData == "" || count($aData['FIELDS']) < 1) {
                        $message = G::LoadTranslation('ID_PMTABLE_NOT_FOUND');
                        G::SendMessageText($message, "WARNING");
                        $sValue = "";
                    } else {
                        foreach ($aData['FIELDS'] as $aField) {
                            if ($aField['FLD_KEY'] == '1') {
                                // note added by gustavo cruz gustavo[at]colosa[dot]com
                                // this additional [if] checks if a case variable has been set
                                // in the keys attribute, so it can be parsed and replaced for
                                // their respective value.
                                if (preg_match("/@#/", $aValues[$i])) {
                                    // check if a case are running in order to prevent that preview is
                                    // erroneous rendered.
                                    if (isset($_SESSION['APPLICATION'])) {
                                        $oApp = new Cases();
                                        if ($oApp->loadCase($_SESSION['APPLICATION']) != null) {
                                            $aFields = $oApp->loadCase($_SESSION['APPLICATION']);
                                            $formVariable = substr($aValues[$i], 2);
                                            if (isset($aFields['APP_DATA'][$formVariable])) {
                                                $formVariableValue = $aFields['APP_DATA'][$formVariable];
                                                $aKeys[$aField['FLD_NAME']] = (isset($formVariableValue) ? G::replaceDataField($formVariableValue, $oOwner->values) : '');
                                            } else {
                                                $aKeys[$aField['FLD_NAME']] = '';
                                            }
                                        } else {
                                            $aKeys[$aField['FLD_NAME']] = '';
                                        }
                                    } else {
                                        $aKeys[$aField['FLD_NAME']] = '';
                                    }
                                } else {
                                    $aKeys[$aField['FLD_NAME']] = (isset($aValues[$i]) ? G::replaceDataField($aValues[$i], $oOwner->values) : '');
                                }
                                $i++;
                            }
                        }
                        try {
                            $aData = $oAdditionalTables->getDataTable($oOwner->fields[$this->pmconnection]->pmtable, $aKeys);
                        } catch (Exception $oError) {
                            $aData = [];
                        }
                        if (isset($aData[$this->pmfield])) {
                            $sValue = $aData[$this->pmfield];
                        }
                    }
                }
            }
        }
        return $sValue;
    }

    /**
     * Prepares NS Required Value
     *
     * @author Enrique Ponce de Leon <enrique@colosa.com>
     * @param boolean optional (true = always show, false = show only if not empty)
     * @return string
     */

    public function NSRequiredValue($show = false)
    {
        if (isset($this->required)) {
            $req = ($this->required) ? '1' : '0';
        } else {
            $req = '0';
        }
        $idv = 'pm:required="' . $req . '"';
        if ($show) {
            return $idv;
        } else {
            return ($req != '0') ? $idv : '';
        }
    }

    /**
     * Prepares NS Required Value
     *
     * @author Enrique Ponce de Leon <enrique@colosa.com>
     * @param boolean optional (true = always show, false = show only if not empty)
     * @return string
     */

    public function NSGridLabel($show = false)
    {
        $idv = 'pm:label="' . htmlentities($this->pmLabel, ENT_COMPAT, 'utf-8') . '"';
        if ($show) {
            return $idv;
        } else {
            return ($this->pmLabel != '') ? $idv : '';
        }
    }

    /**
     * Prepares NS Default Text
     *
     * @author Enrique Ponce de Leon <enrique@colosa.com>
     * @param boolean optional (true = always show, false = show only if not empty)
     * @return string
     */
    public function NSDefaultValue($show = false)
    {
        $idv = 'pm:defaultvalue="' . $this->defaultValue . '"';
        if ($show) {
            return $idv;
        } else {
            return ($this->defaultValue != '') ? $idv : '';
        }
    }

    /**
     * Prepares NS Field Type
     *
     * @author Julio Cesar Laura <contact@julio-laura.com>
     * @return string
     */
    public function NSFieldType()
    {
        return 'pmfieldtype="' . $this->type . '"';
    }

    /**
     * Prepares NS Grid Type
     *
     * @author Enrique Ponce de Leon <enrique@colosa.com>
     * @param boolean optional (true = always show, false = show only if not empty)
     * @return string
     */
    public function NSGridType($show = false)
    {
        $igt = 'pmgridtype="' . $this->gridFieldType . '"';

        if ($show) {
            return $igt;
        } else {
            return ($this->gridFieldType != '') ? $igt : '';
        }
    }

    /**
     * Prepares NS Grid Type
     *
     * @author Enrique Ponce de Leon <enrique@colosa.com>
     * @param boolean optional (true = always show, false = show only if not empty)
     * @return string
     */
    public function NSDependentFields($show = false)
    {
        $idf = 'pm:dependent="' . (($this->dependentFields != '') ? '1' : '0') . '"';
        if ($show) {
            return $idf;
        } else {
            return ($this->dependentFields != '') ? $idf : '';
        }
    }

    /**
     * Prepares Hint HTML if hint value is defined
     *
     * @author Enrique Ponce de Leon <enrique@colosa.com>
     * @param void
     * @return string
     *
     */

    public function renderHint()
    {
        $_outHint = '';
        if ($this->hint != '' && $this->mode == 'edit') {
            $_outHint = '<a href="#" onclick="return false;" onmouseout="hideTooltip()" onmouseover="showTooltip(event, \'' . $this->hint . '\');return false;">
                     <image src="/images/help4.gif" width="13" height="13" border="0"/>
                   </a>';
        }
        return $_outHint;
    }
}

/**
 * Class XmlFormFieldTitle
 *
 * @package gulliver.system
 * @access public
 */
class XmlFormFieldTitle extends XmlFormField
{

    /**
     * Function render
     *
     * @access public
     * @param string value
     * @return string
     */
    public function render($value = null, $owner = null)
    {
        $this->label = G::replaceDataField($this->label, $owner->values);
        return '<span id=\'form[' . $this->name . ']\' name=\'form[' . $this->name . ']\' ' . $this->NSFieldType() . ' >' . $this->htmlentities($this->label) . '</span>';
    }

    /**
     * A title node has no value
     *
     * @param $value
     * @return false
     */
    public function validateValue($value)
    {
        return false;
    }
}

/**
 * Class XmlFormFieldSubtitle
 *
 * @package gulliver.system
 * @access public
 */
class XmlFormFieldSubtitle extends XmlFormField
{

    /**
     * Function render
     *
     * @access public
     * @param string value
     * @return string
     */
    public function render($value = null, $paramDummy2 = null)
    {
        return '<span id=\'form[' . $this->name . ']\' name=\'form[' . $this->name . ']\' ' . $this->NSFieldType() . ' >' . $this->htmlentities($this->label) . '</span>';
    }

    /**
     * A subtitle node has no value
     *
     * @param $value
     * @return false
     */
    public function validateValue($value)
    {
        return false;
    }
}

/**
 * Class XmlFormFieldSimpleText
 *
 * @package gulliver.system
 * @access public
 */
class XmlFormFieldSimpleText extends XmlFormField
{
    public $size = 15;
    public $maxLength = '';
    public $validate = 'Any';
    public $mask = '';
    /* Additional events */
    public $onkeypress = '';
    public $renderMode = '';

    /**
     * Function render
     *
     * @access public
     * @param string value
     * @return string
     */
    public function render($value = null, $owner = null)
    {
        if (($this->pmconnection != '') && ($this->pmfield != '') && $value == null) {
            $value = $this->getPMTableValue($owner);
        }
        $onkeypress = G::replaceDataField($this->onkeypress, $owner->values);
        if ($this->mode === 'edit') {
            if ($this->readOnly) {
                return '<input class="module_app_input___gray" id="form[' . $this->name . ']" name="form[' . $this->name . ']" type ="text" size="' . $this->size . '" ' . (isset($this->maxLength) ? ' maxlength="' . $this->maxLength . '"' : '') . ' value=\'' . htmlentities($value, ENT_COMPAT, 'utf-8') . '\' ' . $this->NSRequiredValue() . ' ' . $this->NSFieldType() . ' readOnly="readOnly" style="' . htmlentities($this->style, ENT_COMPAT, 'utf-8') . '" onkeypress="' . htmlentities($onkeypress, ENT_COMPAT, 'utf-8') . '"/>';
            } else {
                return '<input class="module_app_input___gray" id="form[' . $this->name . ']" name="form[' . $this->name . ']" type ="text" size="' . $this->size . '" ' . (isset($this->maxLength) ? ' maxlength="' . $this->maxLength . '"' : '') . ' value=\'' . htmlentities($value, ENT_COMPAT, 'utf-8') . '\' ' . $this->NSRequiredValue() . ' ' . $this->NSFieldType() . ' style="' . htmlentities($this->style, ENT_COMPAT, 'utf-8') . '" onkeypress="' . htmlentities($onkeypress, ENT_COMPAT, 'utf-8') . '"/>';
            }
        } elseif ($this->mode === 'view') {
            return '<input class="module_app_input___gray" id="form[' . $this->name . ']" name="form[' . $this->name . ']" type ="text" size="' . $this->size . '" ' . (isset($this->maxLength) ? ' maxlength="' . $this->maxLength . '"' : '') . ' value=\'' . htmlentities($value, ENT_COMPAT, 'utf-8') . '\' ' . $this->NSRequiredValue() . ' ' . $this->NSFieldType() . ' style="display:none;' . htmlentities($this->style, ENT_COMPAT, 'utf-8') . '" onkeypress="' . htmlentities($onkeypress, ENT_COMPAT, 'utf-8') . '"/>' . htmlentities($value, ENT_COMPAT, 'utf-8');
        } else {
            return $this->htmlentities($value, ENT_COMPAT, 'utf-8');
        }
    }

    /**
     * Function renderGrid
     *
     * @access public
     * @param string values
     * @param string owner
     * @return string
     */
    public function renderGrid($values = array(), $owner = null, $paramDummy3 = null, $paramDummy4 = null)
    {
        $result = [];
        $r = 1;
        if ($owner->mode != 'view') {
            $this->renderMode = $this->modeForGrid;
        }

        foreach ($values as $v) {
            $html = '';
            if ($this->renderMode === 'edit') {
                //EDIT MODE
                $readOnlyText = ($this->readOnly == 1 || $this->readOnly == '1') ? 'readOnly="readOnly"' : '';
                $html .= '<input ' . $readOnlyText . ' class="module_app_input___gray" ';
                $html .= 'id="form[' . $owner->name . '][' . $r . '][' . $this->name . ']" ';
                $html .= 'name="form[' . $owner->name . '][' . $r . '][' . $this->name . ']" ';
                $html .= 'type="text" size="' . $this->size . '" maxlength="' . $this->maxLength . '" ';
                $html .= 'value="' . $this->htmlentities($v, ENT_QUOTES, 'utf-8') . '" ';
                $html .= 'style="' . $this->htmlentities($this->style, ENT_COMPAT, 'utf-8') . '" ';
                $html .= $this->NSDefaultValue() . ' ';
                $html .= $this->NSRequiredValue() . ' ';
                $html .= $this->NSGridType() . ' ';
                $html .= $this->NSGridLabel() . ' ';
                $html .= '/>';
            } else {
                //VIEW MODE
                $html .= $this->htmlentities($v, ENT_QUOTES, 'utf-8');
                $html .= '<input ';
                $html .= 'id="form[' . $owner->name . '][' . $r . '][' . $this->name . ']" ';
                $html .= 'name="form[' . $owner->name . '][' . $r . '][' . $this->name . ']" ';
                $html .= 'type="hidden" value="' . $this->htmlentities($v, ENT_QUOTES, 'utf-8') . '" />';
            }
            $result[] = $html;
            $r++;
        }
        return $result;
    }
}

/**
 * Class XmlFormFieldText
 *
 * @package gulliver.system
 * @access public
 */
class XmlFormFieldText extends XmlFormFieldSimpleText
{
    public $size = 15;
    public $maxLength = 64;
    public $validate = 'Any';
    public $mask = '';
    public $defaultValue = '';
    public $required = false;
    public $dependentFields = '';
    public $linkField = '';
    //Possible values:(-|UPPER|LOWER|CAPITALIZE)
    public $strTo = '';
    public $readOnly = false;
    public $sqlConnection = 0;
    public $sql = '';
    public $sqlOption = [];
    //Attributes only for grids
    public $gridFieldType = 'text';
    public $formula = '';
    public $function = '';
    public $replaceTags = 0;
    public $renderMode = '';
    public $comma_separator = '.';
    public $autocomplete = "on";

    /**
     * Function render
     *
     * @access public
     * @param string value
     * @param string owner
     * @return string
     */
    public function render($value = null, $owner = null)
    {
        if ($this->autocomplete === '1') {
            $this->autocomplete = "on";
        } else {
            if ($this->autocomplete === '0') {
                $this->autocomplete = "off";
            }
        }
        if ($this->renderMode == '') {
            $this->renderMode = $this->mode;
        }
        if (($this->pmconnection != '') && ($this->pmfield != '') && $value == null) {
            $value = $this->getPMTableValue($owner);
        } else {
            $this->executeSQL($owner);
            $firstElement = key($this->sqlOption);
            if (isset($firstElement)) {
                $value = $firstElement;
            }
        }

        //NOTE: string functions must be in G class
        if ($this->strTo === 'UPPER') {
            $value = strtoupper($value);
        }
        if ($this->strTo === 'LOWER') {
            $value = strtolower($value);
        }
        if ($this->strTo === 'TITLE') {
            $value = strtolower($value);
            $value = ucwords($value);
        }
        if ($this->strTo === 'PHRASE') {
            //$value = strtolower( $value );

            $title = explode(" ", $value);

            $title[0] = ucwords($title[0]);

            $value = implode(" ", $title);
        }
        //if ($this->strTo==='CAPITALIZE') $value = strtocapitalize($value);
        $onkeypress = G::replaceDataField($this->onkeypress, $owner->values);
        if ($this->replaceTags == 1) {
            $value = G::replaceDataField($value, $owner->values);
        }

        $html = '';
        if ($this->renderMode == 'edit') {
            //EDIT MODE
            $readOnlyText = ($this->readOnly == 1 || $this->readOnly == '1') ? 'readOnly="readOnly"' : '';
            $html .= '<input ' . $readOnlyText . ' class="module_app_input___gray" ';
            $html .= 'id="form[' . $this->name . ']" ';
            $html .= 'name="form[' . $this->name . ']" ';
            $html .= 'type="text" size="' . $this->size . '" maxlength="' . $this->maxLength . '" ';
            $html .= 'autocomplete="' . $this->autocomplete . '" ';
            $html .= 'value="' . $this->htmlentities($value, ENT_QUOTES, 'utf-8') . '" ';
            $html .= 'style="' . $this->htmlentities($this->style, ENT_COMPAT, 'utf-8') . '" ';
            $html .= 'onkeypress="' . $this->htmlentities($onkeypress, ENT_COMPAT, 'utf-8') . '" ';
            $html .= $this->NSDefaultValue() . ' ';
            $html .= $this->NSRequiredValue() . ' ';
            $html .= $this->NSFieldType() . ' ';
            $html .= 'pm:decimal_separator="' . $this->comma_separator . '" ';
            $html .= '/>';
        } else {
            //VIEW MODE
            $html .= $this->htmlentities($value, ENT_QUOTES, 'utf-8');
            $html .= '<input ';
            $html .= 'id="form[' . $this->name . ']" ';
            $html .= 'name="form[' . $this->name . ']" ';
            $html .= $this->NSFieldType() . ' ';
            $this->enableHtml = false;
            $html .= 'type="hidden" value="' . $this->htmlentities($value, ENT_QUOTES, 'utf-8') . '" />';
        }

        $html .= $this->renderHint();
        if (($this->readOnly == 1) && ($this->renderMode == 'edit')) {
            $html = str_replace("class=\"module_app_input___gray\"", "class=\"module_app_input___gray_readOnly\"", $html);
        }

        return $html;
    }

    /**
     * Function renderGrid
     *
     * @access public
     * @param string values
     * @param string owner
     * @return string
     */
    public function renderGrid($values = array(), $owner = null, $paramDummy3 = null, $paramDummy4 = null)
    {
        $result = $aux = [];
        $r = 1;
        if ($owner->mode != 'view') {
            $this->renderMode = $this->modeForGrid;
        }

        foreach ($values as $v) {
            $this->executeSQL($owner, $r);
            $firstElement = key($this->sqlOption);
            if (isset($firstElement)) {
                $v = $firstElement;
            }
            if ($this->replaceTags == 1) {
                $v = G::replaceDataField($v, $owner->values);
            }
            $aux[$r] = $v;

            $html = '';
            if ($this->renderMode == 'edit') {
                //EDIT MODE
                $readOnlyText = ($this->readOnly == 1 || $this->readOnly == '1') ? 'readOnly="readOnly"' : '';
                $html .= '<input ' . $readOnlyText . ' class="module_app_input___gray" ';
                $html .= 'id="form[' . $owner->name . '][' . $r . '][' . $this->name . ']" ';
                $html .= 'name="form[' . $owner->name . '][' . $r . '][' . $this->name . ']" ';
                $html .= 'type="text" size="' . $this->size . '" maxlength="' . $this->maxLength . '" ';
                $html .= 'value="' . $this->htmlentities($v, ENT_QUOTES, 'utf-8') . '" ';
                $html .= 'style="' . $this->htmlentities($this->style, ENT_COMPAT, 'utf-8') . '" ';
                $html .= $this->NSDefaultValue() . ' ';
                $html .= $this->NSRequiredValue() . ' ';
                $html .= $this->NSGridLabel() . ' ';
                $html .= $this->NSGridType() . ' ';
                $html .= $this->NSDependentFields() . ' ';
                $html .= '/>';
            } else {
                //VIEW MODE
                $html .= $this->htmlentities($v, ENT_QUOTES, 'utf-8');
                $html .= '<input ';
                $html .= 'id="form[' . $owner->name . '][' . $r . '][' . $this->name . ']" ';
                $html .= 'name="form[' . $owner->name . '][' . $r . '][' . $this->name . ']" ';
                $html .= $this->NSDefaultValue() . ' ';
                $html .= $this->NSGridType() . ' ';
                $html .= 'type="hidden" value="' . $this->htmlentities($v, ENT_QUOTES, 'utf-8') . '" />';
            }

            $result[] = $html;
            $r++;
        }
        $this->options = $aux;
        return $result;
    }

    public function renderTable($values = "", $owner = null, $paramDummy3 = null)
    {
        $result = $this->htmlentities($values, ENT_COMPAT, 'utf-8');
        return $result;
    }
}

/**
 * Class XmlFormFieldSuggest
 *
 * @package gulliver.system
 * @access public
 */
class XmlFormFieldSuggest extends XmlFormFieldSimpleText
{
    public $size = 15;
    public $maxLength = 64;
    public $validate = 'Any';
    public $mask = '';
    public $defaultValue = '';
    public $required = false;
    public $dependentFields = '';
    public $linkField = '';
    //Possible values:(-|UPPER|LOWER|CAPITALIZE)
    public $strTo = '';
    public $readOnly = false;
    public $sqlConnection = 0;
    public $sql = '';
    public $sqlOption = [];
    public $searchType = "*searchtext*";
    //Atributes only for grids
    public $gridFieldType = 'suggest';
    public $formula = '';
    public $function = '';
    public $replaceTags = 0;

    public $ajaxServer = '../gulliver/genericAjax';
    public $maxresults = '6';
    public $savelabel = 1;
    public $shownoresults;
    public $callback = '';

    public $store_new_entry = '';
    public $table = '';
    public $table_data = '';
    public $primary_key = '';
    public $primary_key_data = '';
    public $primary_key_type = '';
    public $primary_key_type_data = '';

    public $field = '';

    /**
     * Function render
     *
     * @author Erik A. Ortiz.
     * @param $value
     * @param $owner
     * @return <String>
     */
    public function render($value = null, $owner = null)
    {
        if (!$this->sqlConnection) {
            $this->sqlConnection = 'workflow';
        }

        //NOTE: string functions must be in G class
        if ($this->strTo === 'UPPER') {
            $value = strtoupper($value);
        }
        if ($this->strTo === 'LOWER') {
            $value = strtolower($value);
        }

        //if ($this->strTo==='CAPITALIZE') $value = strtocapitalize($value);
        $onkeypress = G::replaceDataField($this->onkeypress, $owner->values);

        if ($this->replaceTags == 1) {
            $value = G::replaceDataField($value, $owner->values);
        }

        $aProperties = array('value' => '""', 'size' => '"' . $this->size . '"');

        $storeEntry = null;
        $storeEntryData = ", storeEntryData: [0]";

        if ($this->store_new_entry) {
            $storeEntry = ' title="' . G::LoadTranslation("ID_FIELD_DYNAFORM_SUGGEST_INPUT_TITLE") . '"';
            $storeEntryData = ", storeEntryData: [1, \"form[" . $this->name . "_label]\", \"" . $this->sqlConnection . "\", \"" . $this->table . "\", \"" . $this->primary_key . "\", \"" . $this->primary_key_type . "\", \"" . $this->field . "\"]";
        }

        $formVariableValue = '';
        $formVariableKeyValue = '';

        $oApp = new Cases();
        if (isset($_SESSION['APPLICATION']) && ($_SESSION['APPLICATION'] != null && $oApp->loadCase($_SESSION['APPLICATION']) != null)) {
            $aFields = $oApp->loadCase($_SESSION['APPLICATION']);
            if (isset($aFields['APP_DATA'][$this->name . '_label'])) {
                $formVariableValue = $aFields['APP_DATA'][$this->name . '_label'];
                $formVariableKeyValue = $aFields['APP_DATA'][$this->name];
            }
        }

        if ($this->mode === 'edit') {
            if ($this->readOnly) {
                return '<input class="module_app_input___gray" id="form[' . $this->name . ']" name="form[' . $this->name . ']" type ="text" size="' . $this->size . '" maxlength="' . $this->maxLength . '" value=\'' . $this->htmlentities($value, ENT_COMPAT, 'utf-8') . '\' ' . $this->NSFieldType() . ' readOnly="readOnly" style="' . htmlentities($this->style, ENT_COMPAT, 'utf-8') . '" onkeypress="' . htmlentities($onkeypress, ENT_COMPAT, 'utf-8') . '"/>';
            } else {
                //        $str = '<textarea '.$storeEntry.' class="module_app_input___gray" style="height:16px" rows=1 cols="'.$this->size.'" id="form[' . $this->name . ']" name="form[' . $this->name . ']" >'.$this->htmlentities($value, ENT_COMPAT, 'utf-8').'</textarea>';
                if (strlen(trim($formVariableValue)) > 0) {
                    $value = $formVariableValue;
                }
                $name = "'" . $this->name . "'";
                $str = '<input type="text" ' . $storeEntry . ' class="module_app_input___gray" size="' . $this->size . '" id="form[' . $this->name . '_label]" name="form[' . $this->name . '_label]" value="' . $this->htmlentities($value, ENT_COMPAT, 'utf-8') . '" onblur="idSet(' . $name . ');" ';
                $str .= $this->NSDependentFields(true) . ' ';
                $str .= '/>';
                $str .= '<input ';
                $str .= 'id="form[' . $this->name . ']" ';
                $str .= 'name="form[' . $this->name . ']" ';
                $str .= $this->NSFieldType() . ' ';
                $str .= 'value="' . $this->htmlentities($formVariableKeyValue, ENT_COMPAT, 'utf-8') . '" ';
                $str .= 'type="hidden" />';

                $str .= $this->renderHint();
                if (trim($this->callback) != '') {
                    $sCallBack = 'try{' . $this->callback . '}catch(e){alert("Suggest Widget call back error: "+e)}';
                } else {
                    $sCallBack = '';
                }

                $sSQL = $this->sql;
                $nCount = preg_match_all('/\@(?:([\@\%\#\!Qq])([a-zA-Z\_]\w*)|([a-zA-Z\_][\w\-\>\:]*)\(((?:[^\\\\\)]*?)*)\))/', $sSQL, $match, PREG_PATTERN_ORDER | PREG_OFFSET_CAPTURE);

                $aResult = [];
                if ($nCount) {
                    for ($i = 0; $i < $nCount; $i++) {
                        if (isset($match[0][$i][0]) && isset($match[2][$i][0])) {
                            $aResult[$match[0][$i][0]] = $match[2][$i][0];
                        }
                    }
                }

                $depValues = '';
                $i = 1;
                if (isset($aResult) && $aResult) {
                    $sResult = '"' . implode('","', $aResult) . '"';
                    $aResultKeys = array_keys($aResult);
                    $sResultKeys = str_rot13(base64_encode(implode('|', $aResultKeys)));

                    foreach ($aResult as $key => $field) {
                        $depValues .= 'getField(\'' . $field . '\').value';
                        if ($i++ < count($aResult)) {
                            $depValues .= '+"|"+';
                        }
                    }
                    $depValues = '+' . $depValues . '+';
                } else {
                    $sResult = '';
                    $sResultKeys = '';
                    $depValues = '+';
                }

                $aDepFields = [];
                $count = 0;
                if ($this->dependentFields !== '') {
                    $dependentFields = explode(",", $this->dependentFields);
                    foreach ($dependentFields as $keyDependent => $valueDependent) {
                        $sqlDepField = $owner->fields[$valueDependent]->sql;
                        $count = preg_match_all('/\@(?:([\@\%\#\=\!Qq])([a-zA-Z\_]\w*)|([a-zA-Z\_][\w\-\>\:]*)\(((?:[^\\\\\)]*?)*)\))/', $sqlDepField, $match, PREG_PATTERN_ORDER | PREG_OFFSET_CAPTURE);
                        for ($cnt = 0; $cnt < $count; $cnt++) {
                            $aDepFields[$cnt] = $match[2][$cnt][0];
                        }
                    }
                }

                $sOptions = 'script: function (input) { ';
                $sOptions .= '  var inputValue = base64_encode(getField(\'' . $this->name . '_label\').value); ';

                $sOptions .= '  return "' . $this->ajaxServer . '?request=suggest&type=form&form=' . $owner->id . '&variable=' . $this->name . '&json=true&limit=' . $this->maxresults;
                $sOptions .= '&dependentFieldsKeys=' . $sResultKeys . '&dependentFieldsValue="';

                $sOptions .= $depValues . '"&input="+inputValue+"&inputEnconde64=enable&searchType=' . $this->searchType . '";';

                $sOptions .= '},';
                $sOptions .= 'json: true,';
                $sOptions .= 'limit: ' . $this->maxresults . ',';

                $sOptions .= 'shownoresults: ' . ($this->shownoresults ? 'true' : 'false') . ',';
                $sOptions .= 'maxresults: ' . $this->maxresults . ',';
                $sOptions .= 'chache: true,';

                $setValue = ($this->savelabel == '1') ? 'obj.value' : 'obj.id';

                $sOptions .= 'callback: function (obj) { ';
                $sOptions .= 'if (typeof obj != "undefined") { ';
                $sOptions .= ' var jField = { };';
                $sOptions .= ' var sField = "[]"; ';

                if ($count > 0) {
                    for ($cnt = 0; $cnt < $count; $cnt++) {
                        if ($this->name == $aDepFields[$cnt]) {
                            $sOptions .= '  jField[\'' . $aDepFields[$cnt] . '\'] = obj.id;';
                        } else {
                            $sOptions .= '  jField[\'' . $aDepFields[$cnt] . '\'] = getField(\'' . $aDepFields[$cnt] . '\').value; ';
                        }
                    }
                }

                $sOptions .= ' var sField = "["+ encodeURIComponent(jField.toJSONString()) + "]"; ';

                $sOptions .= $sCallBack . '; getField("' . $this->name . '").value = obj.id;';
                $sOptions .= 'var response = ajax_function("../gulliver/defaultAjaxDynaform", "reloadField", ';
                $sOptions .= '               "form=' . $owner->id . '&fields=" + sField, "POST"); ';

                $sOptions .= 'if (response.substr(0,1) === \'[\') { ';
                $sOptions .= '  var newcont; ';
                $sOptions .= '  eval(\'newcont=\' + response + \';\'); ';
                $sOptions .= '  for(var i = 0; i<newcont.length; i++) { ';
                //$sOptions .= '    var j = getField(newcont[i].name); ';
                $sOptions .= '    getField(newcont[i].name).value = newcont[i].value; ';
                $sOptions .= '
                                  switch (newcont[i].content.type) {
                                      case "dropdown":
                                          dropDownSetOption({element: getField(newcont[i].name), name: newcont[i].name}, newcont[i].content);
                                          break;
                                      case "text":
                                          getField(newcont[i].name).value = "";

                                          if (newcont[i].content.options) {
                                              if (newcont[i].content.options[0]) {
                                                  getField(newcont[i].name).value = newcont[i].content.options[0].value;
                                              }
                                          }
                                          break;
                                  }
                ';
                $sOptions .= '  } ';
                $sOptions .= '} else { ';
                $sOptions .= '  alert(\'Invalid response: \' + response); ';
                $sOptions .= '} ';
                $sOptions .= '} ';
                $sOptions .= 'return false; ';
                $sOptions .= '}';

                $str .= '<script type="text/javascript">';
                $str .= 'var as_json = new bsn.AutoSuggest(\'form[' . $this->name . '_label]\', {' . $sOptions . $storeEntryData . '}, "' . $this->searchType . '");';
                $str .= '</script>';

                return $str;
            }
        } else {
            $html = '<span id="form[' . $this->name . ']" name="form[' . $this->name . ']" ' . $this->NSFieldType() . ' >';
            $html .= $this->htmlentities($formVariableValue, ENT_COMPAT, 'utf-8');
            $html .= '</span>';
            return $html;
        }
    }

    /**
     * render Field Grid
     *
     * @param type $value
     * @param type $owner
     * @param type $rowId
     * @param type $ownerName Grid Name
     * @param type $index Index on the grid
     * @return string
     */
    public function renderFieldGrid($value = null, $owner = null, $rowId = '', $ownerName = '', $index = 0)
    {
        $rowIdField = substr($rowId, 1);
        if (!$this->sqlConnection) {
            $this->sqlConnection = 'workflow';
        }

        if ($this->strTo === 'UPPER') {
            $value = strtoupper($value);
        }
        if ($this->strTo === 'LOWER') {
            $value = strtolower($value);
        }
        $onkeypress = G::replaceDataField($this->onkeypress, $owner->values);

        if ($this->replaceTags == 1) {
            $value = G::replaceDataField($value, $owner->values);
        }

        $storeEntry = null;
        $storeEntryData = ", storeEntryData: [0]";
        if ($this->store_new_entry) {
            $storeEntry = ' title="' . G::LoadTranslation("ID_FIELD_DYNAFORM_SUGGEST_INPUT_TITLE") . '"';
            $storeEntryData = ", storeEntryData: [1, \"form" . $rowId . "[" . $this->name . "_label]\", \"" . $this->sqlConnection . "\", \"" . $this->table . "\", \"" . $this->primary_key . "\", \"" . $this->primary_key_type . "\", \"" . $this->field . "\"]";
        }

        $formVariableValue = '';
        $formVariableKeyValue = '';

        $oApp = new Cases();
        if (isset($_SESSION['APPLICATION']) && ($_SESSION['APPLICATION'] != null && $oApp->loadCase($_SESSION['APPLICATION']) != null)) {
            $aFields = $oApp->loadCase($_SESSION['APPLICATION']);
            if (isset($aFields['APP_DATA'][$ownerName][$index][$this->name . '_label'])) {
                $formVariableValue = $aFields['APP_DATA'][$ownerName][$index][$this->name . '_label'];
                $formVariableKeyValue = $aFields['APP_DATA'][$ownerName][$index][$this->name];
            }
        }

        if ($this->mode === 'edit') {
            if ($this->readOnly) {
                return '<input class="module_app_input___gray" id="form' . $rowId . '[' . $this->name . ']" name="form' . $rowId . '[' . $this->name . ']" type ="text" size="' . $this->size . '" maxlength="' . $this->maxLength . '" value=\'' . $this->htmlentities($value, ENT_COMPAT, 'utf-8') . '\' ' . $this->NSGridType() . ' readOnly="readOnly" style="' . htmlentities($this->style, ENT_COMPAT, 'utf-8') . '" onkeypress="' . htmlentities($onkeypress, ENT_COMPAT, 'utf-8') . '"/>';
            } else {
                if (strlen(trim($formVariableValue)) > 0) {
                    $value = $formVariableValue;
                }

                $str = '<input type="text" ' . $storeEntry . ' class="module_app_input___gray" size="' . $this->size . '" id="form' . $rowId . '[' . $this->name . '_label]" name="form' . $rowId . '[' . $this->name . '_label]" value="' . $this->htmlentities($value, ENT_COMPAT, 'utf-8') . '" onblur="idSet(\'' . $this->name . '\');" ';
                $str .= $this->NSDependentFields(true) . ' ';
                $str .= $this->NSRequiredValue() . ' ';
                $str .= $this->NSGridLabel() . ' ';
                $str .= '/>';
                $str .= '<input ';
                $str .= 'id="form' . $rowId . '[' . $this->name . ']" ';
                $str .= 'name="form' . $rowId . '[' . $this->name . ']" ';
                $str .= $this->NSGridType() . ' ';
                $str .= 'value="' . $this->htmlentities($formVariableKeyValue, ENT_COMPAT, 'utf-8') . '" ';
                $str .= 'type="hidden" />';

                //$str .= $this->renderHint();
                if (trim($this->callback) != '') {
                    $sCallBack = 'try{' . $this->callback . '}catch(e){alert("Suggest Widget call back error: "+e)}';
                } else {
                    $sCallBack = '';
                }

                $sSQL = $this->sql;
                $nCount = preg_match_all('/\@(?:([\@\%\#\!Qq])([a-zA-Z\_]\w*)|([a-zA-Z\_][\w\-\>\:]*)\(((?:[^\\\\\)]*?)*)\))/', $sSQL, $match, PREG_PATTERN_ORDER | PREG_OFFSET_CAPTURE);

                $aResult = [];
                if ($nCount) {
                    for ($i = 0; $i < $nCount; $i++) {
                        if (isset($match[0][$i][0]) && isset($match[2][$i][0])) {
                            $aResult[$match[0][$i][0]] = $match[2][$i][0];
                        }
                    }
                }

                $depValues = '';
                $depFieldsLast = '';
                $i = 1;
                if (isset($aResult) && $aResult) {
                    $sResult = '"' . implode('","', $aResult) . '"';
                    $aResultKeys = array_keys($aResult);
                    $sResultKeys = str_rot13(base64_encode(implode('|', $aResultKeys)));

                    foreach ($aResult as $key => $field) {
                        $depValues .= 'getField(\'' . $rowIdField . '[' . $field . '\').value';

                        if ($i++ < count($aResult)) {
                            $depValues .= '+"|"+';
                        }
                    }
                    $depFieldsLast = 'getField(\'' . $rowIdField . '[' . $field . '\').value';
                    $depValues = '+' . $depValues . '+';
                } else {
                    $sResult = '';
                    $sResultKeys = '';
                    $depValues = '+';
                }

                $sOptions = 'script: function (input) { ';

                $sOptions .= '  var inputValue = base64_encode(getField(\'' . $rowIdField . '[' . $this->name . '_label\').value); ';

                $sOptions .= '  return "' . $this->ajaxServer . '?request=suggest&type=grid&form=' . $owner->id . '&grid=' . $owner->name . '&variable=' . $this->name . '&json=true&limit=' . $this->maxresults;
                $sOptions .= '&dependentFieldsKeys=' . $sResultKeys . '&dependentFieldsValue="';
                $sOptions .= $depValues . '"&input="+inputValue+"&inputEnconde64=enable&searchType=' . $this->searchType . '";';

                $sOptions .= '},';
                $sOptions .= 'json: true,';
                $sOptions .= 'limit: ' . $this->maxresults . ',';

                $sOptions .= 'shownoresults: ' . ($this->shownoresults ? 'true' : 'false') . ',';
                $sOptions .= 'maxresults: ' . $this->maxresults . ',';
                $sOptions .= 'chache: true,';

                $sOptions .= 'callback: function (obj) { ';

                $sOptions .= 'if (typeof obj != "undefined") { ';
                $sOptions .= ' var aFieldCurrent = {};';
                $sOptions .= ' aFieldCurrent[\'' . $this->name . '\'] = obj.id;';
                $sOptions .= ' var sFieldCurrent = "["+ encodeURIComponent(aFieldCurrent.toJSONString()) + "]"; ';
                $sOptions .= $sCallBack . '; getField("' . $rowIdField . '[' . $this->name . '").value = obj.id;';

                $sOwnerId = (isset($owner->owner->id)) ? $owner->owner->id : $owner->id;
                $sOptions .= 'var indexField =  "' . $rowIdField . '[' . $this->name . '";';
                $sOptions .= 'indexField = indexField.match(/\[[0-9]+\]/g); ';
                $sOptions .= 'indexFieldVal = indexField[0].replace(/\[|\]/g,""); ';
                $sOptions .= 'var gridField = gridGetAllFieldAndValue("' . $ownerName . '][" + indexFieldVal + "][' . $this->name . '", 0); '; //Not get current field
                $sOptions .= 'var response = ajax_function("../gulliver/defaultAjaxDynaform", "reloadField", "form=' . $sOwnerId . '&fields=" + sFieldCurrent + "&grid=' . $ownerName . '" + ((gridField != "")? "&gridField=" + encodeURIComponent("{" + gridField + "}") : "") + "&row=" + indexFieldVal, "POST"); ';
                $sOptions .= '';
                $sOptions .= 'if (response.substr(0,1) === \'[\') { ';
                $sOptions .= '  var newcont; ';
                $sOptions .= '  eval(\'newcont=\' + response + \';\'); ';
                $sOptions .= '';
                $sOptions .= '  for(var i = 0; i<newcont.length; i++) { ';
                $sOptions .= '    var depField = "' . $rowIdField . '[" + newcont[i].name; ';
                $sOptions .= '    getField(depField).value = newcont[i].value; ';
                $sOptions .= '
                                  switch (newcont[i].content.type) {
                                      case "dropdown":
                                          dropDownSetOption({element: getField(depField), name: depField}, newcont[i].content);
                                          break;
                                      case "text":
                                          getField(depField).value = "";

                                          if (newcont[i].content.options) {
                                              if (newcont[i].content.options[0]) {
                                                  getField(depField).value = newcont[i].content.options[0].value;
                                              }
                                          }
                                          break;
                                  }
                ';
                $sOptions .= '  } ';
                $sOptions .= '} else { ';
                $sOptions .= '  alert(\'Invalid response: \' + response); ';
                $sOptions .= '} ';
                $sOptions .= '} ';
                $sOptions .= 'return false; ';
                $sOptions .= '}';

                $str .= '<script type="text/javascript">';
                $str .= 'var as_json = new bsn.AutoSuggest(\'form' . $rowId . '[' . $this->name . '_label]\', {' . $sOptions . $storeEntryData . '}, "' . $this->searchType . '"); ';
                $str .= '</script>';

                return $str;
            }
        } else {
            $str = $this->htmlentities($formVariableValue, ENT_COMPAT, 'utf-8');
            $str .= '<input type="hidden" id="form' . $rowId . '[' . $this->name . '_label]" name="form' . $rowId . '[' . $this->name . '_label]" value="' . $this->htmlentities($formVariableValue, ENT_COMPAT, 'utf-8') . '" ';
            $str .= $this->NSDependentFields(true) . ' ';
            $str .= $this->NSRequiredValue() . ' ';
            $str .= $this->NSGridLabel() . ' ';
            $str .= '/>';
            $str .= '<input type="hidden" id="form' . $rowId . '[' . $this->name . ']" name="form' . $rowId . '[' . $this->name . ']" value="' . $this->htmlentities($formVariableKeyValue, ENT_COMPAT, 'utf-8') . '" ';
            $str .= $this->NSGridType() . ' ';
            $str .= '/>';

            return $str;
        }
    }

    /**
     * Function renderGrid
     *
     * @access public
     * @param string values
     * @param string owner
     * @return string
     */
    public function renderGrid($values = array(), $owner = null, $paramDummy3 = null, $paramDummy4 = null)
    {
        $aResult = [];
        $r = 1;

        foreach ($values as $v) {
            $aResult[] = $this->renderFieldGrid($v, $owner, '[' . $owner->name . '][' . $r . ']', $owner->name, $r);
            $r++;
        }
        return $aResult;
    }

    /**
     * render in a table
     *
     * @param <any> $values
     * @param <String> $owner
     * @return <String> $result
     */
    public function renderTable($values = "", $owner = null, $paramDummy3 = null)
    {
        $result = $this->htmlentities($values, ENT_COMPAT, 'utf-8');
        return $result;
    }
}

/**
 * prepare the field for printing
 *
 * @package gulliver.system
 */
class XmlFormFieldPrint extends XmlFormFieldSimpleText //by neyek
{
    //Instead of public --> link
    public $link = '';
    public $value = '';
    public $target = '';
    public $colClassName = 'RowLink';

    //properties
    public $width;
    public $height;
    public $top;
    public $left;
    public $resizable;

    /**
     * Function render
     *
     * @param string value
     * @return string
     */
    //750, 450, 10, 32, 1
    public function render($value = null, $owner = null)
    {
        $onclick = G::replaceDataField($this->onclick, $owner->values);
        $link = G::replaceDataField($this->link, $owner->values);
        $target = G::replaceDataField($this->target, $owner->values);
        $value = G::replaceDataField($this->value, $owner->values);
        $label = G::replaceDataField($this->label, $owner->values);

        $html = '<a href="javascript:;" onclick="dynaFormPrint(\'' . $owner->parentFormId . '\', \'' . $this->htmlentities($link, ENT_QUOTES, 'utf-8') . '\', ' . $this->width . ', ' . $this->height . ', ' . $this->left . ', ' . $this->top . ', ' . $this->resizable . '); return false;">
                  <image title="' . $this->htmlentities($label, ENT_QUOTES, 'utf-8') . '" src="/images/printer.png" width="15" height="15" border="0"/>
                  </a>';

        return $html;
    }
}

/*DEPRECATED*/

/**
 * caption field for dynaforms
 *
 * @package gulliver.system
 */
class XmlFormFieldCaption extends XmlFormField
{
    public $defaultValue = '';
    public $required = false;
    public $dependentFields = '';
    public $readonly = false;
    public $option = [];
    public $sqlConnection = 0;
    public $sql = '';
    public $sqlOption = [];
    public $saveLabel = 0;
    //public $hint;


    /**
     *
     * @param $value
     * @param $owner
     * @return true
     */
    public function validateValue($value)
    {
        return true;
    }

    /**
     * Function render
     *
     * @access public
     * @param string value
     * @return string modified
     */
    public function render($value = null, $owner = null, $rowId = '', $onlyValue = false, $row = -1, $therow = -1)
    {
        if (($this->pmconnection != '') && ($this->pmfield != '') && $value == null) {
            $value = $this->getPMTableValue($owner);
        }
        if ($therow == -1) {
            //print_r($this->executeSQL ( $owner, $row ));print"<hr>";
            $this->executeSQL($owner, $row);
        } else {
            if ($row == $therow) {
                $this->executeSQL($owner, $row);
            }
        }
        $html = '';

        if (!$onlyValue) {
            foreach ($this->option as $optionName => $option) {
                if ($optionName == $value) {
                    $value = $option;
                }
            }
            foreach ($this->sqlOption as $optionName => $option) {
                if ($optionName == $value) {
                    $value = $option;
                }
            }
        } else {
            foreach ($this->option as $optionName => $option) {
                if ($optionName == $value) {
                    $$value = $option;
                }
            }
            foreach ($this->sqlOption as $optionName => $option) {
                if ($optionName == $value) {
                    $value = $option;
                }
            }
        }
        $pID = "form[$this->name]";
        $htm = $this->htmlentities($value, ENT_COMPAT, 'utf-8');
        $htm .= '<input type="hidden" id="' . $pID . '" name="' . $pID . '" value="' . $value . '">';
        return $htm;
    }
}

/**
 * Class XmlFormFieldPassword
 *
 * @package gulliver.system
 * @access public
 */
class XmlFormFieldPassword extends XmlFormField
{
    public $size = 15;
    public $maxLength = 15;
    public $required = false;
    public $readOnly = false;
    public $autocomplete = "on";

    /**
     * Function render
     *
     * @access public
     * @param string value
     * @return string
     */
    public function render($value = null, $paramDummy2 = null)
    {
        if ($this->autocomplete === '1') {
            $this->autocomplete = "on";
        } else {
            if ($this->autocomplete === '0') {
                $this->autocomplete = "off";
            }
        }

        if ($this->mode === 'edit') {
            if ($this->readOnly) {
                return '<input class="module_app_input___gray" id="form[' . $this->name . ']" name="form[' . $this->name . ']" type ="password" autocomplete="' . $this->autocomplete . '" size="' . $this->size . '" maxlength="' . $this->maxLength . '" value=\'' . $this->htmlentities($value, ENT_COMPAT, 'utf-8') . '\' ' . $this->NSFieldType() . ' readOnly="readOnly"/>';
            } else {
                $html = '<input class="module_app_input___gray" id="form[' . $this->name . ']" name="form[' . $this->name . ']" type ="password" autocomplete="' . $this->autocomplete . '" size="' . $this->size . '" maxlength="' . $this->maxLength . '" value=\'' . $this->htmlentities($value, ENT_COMPAT, 'utf-8') . '\' ' . $this->NSFieldType() . '/>';
                $html .= $this->renderHint();
                return $html;
            }
        } elseif ($this->mode === 'view') {
            $html = '<input class="module_app_input___gray" id="form[' . $this->name . ']" name="form[' . $this->name . ']" type ="hidden" autocomplete="' . $this->autocomplete . '" size="' . $this->size . '" maxlength="' . $this->maxLength . '" value=\'' . $this->htmlentities($value, ENT_COMPAT, 'utf-8') . '\' ' . $this->NSFieldType() . ' readOnly="readOnly"/>';
            $html .= $this->htmlentities(str_repeat('*', 10), ENT_COMPAT, 'utf-8');
            return $html;
        } else {
            return $this->htmlentities(str_repeat('*', 10), ENT_COMPAT, 'utf-8');
        }
    }
}

/**
 * Class XmlFormFieldTextarea
 *
 * @package gulliver.system
 * @access public
 */
class XmlFormFieldTextarea extends XmlFormField
{
    public $rows = 12;
    public $cols = 40;
    public $required = false;
    public $readOnly = false;
    public $resizable = false;
    public $wrap = 'OFF';
    public $className;
    public $renderMode = '';

    /**
     * Function render
     *
     * @access public
     * @param string value
     * @return string
     */
    public function render($value = null, $owner = null)
    {
        if (($this->pmconnection != '') && ($this->pmfield != '') && $value == null) {
            $value = $this->getPMTableValue($owner);
        } else {
            $this->executeSQL($owner);
            if (isset($this->sqlOption)) {
                $firstElement = key($this->sqlOption);
            }
            if (isset($firstElement)) {
                $value = $firstElement;
            }
        }

        $className = isset($this->className) ? $this->className : 'module_app_input___gray';

        if ($this->renderMode == '') {
            $this->renderMode = $this->mode;
        }
        $resizable = ($this->resizable == 1 || $this->resizable == '1') ? 'resize:both;' : 'resize:none;';
        $html = '';
        $scrollStyle = $this->style . "overflow:scroll;overflow-y:scroll;overflow-x:hidden;overflow:-moz-scrollbars-vertical;" . $resizable;
        if ($this->renderMode == 'edit') {
            //EDIT MODE
            $readOnlyText = ($this->readOnly == 1 || $this->readOnly == '1') ? 'readOnly="readOnly"' : '';
            $html .= '<textarea ' . $readOnlyText . ' ';
            $html .= 'id="form[' . $this->name . ']" ';
            $html .= 'name="form[' . $this->name . ']" ';
            $html .= 'wrap="soft" cols="' . $this->cols . '" rows="' . $this->rows . '" ';
            $html .= 'style="' . $scrollStyle . '" wrap="' . $this->htmlentities($this->wrap, ENT_QUOTES, 'UTF-8') . '" ';
            $html .= $this->NSDefaultValue() . ' ';
            $html .= $this->NSRequiredValue() . ' ';
            $html .= $this->NSFieldType() . ' ';
            $html .= 'class="' . $className . '" >';
            $html .= $this->htmlentities($value, ENT_COMPAT, 'utf-8');
            $html .= '</textarea>';
        } else {
            //VIEW MODE
            $html .= '<textarea readOnly ';
            $html .= 'id="form[' . $this->name . ']" ';
            $html .= 'name="form[' . $this->name . ']" ';
            $html .= 'wrap="soft" cols="' . $this->cols . '" rows="' . $this->rows . '" ';
            $html .= $this->NSFieldType() . ' style="border:0px;backgroud-color:inherit;' . $scrollStyle . '" wrap="' . $this->htmlentities($this->wrap, ENT_QUOTES, 'UTF-8') . '" ';
            $html .= 'class="FormTextArea" >';
            $html .= $this->htmlentities($value, ENT_COMPAT, 'utf-8');
            $html .= '</textarea>';
        }

        $html .= $this->renderHint();
        return $html;
    }

    /**
     * Function renderGrid
     *
     * @access public
     * @param string value
     * @param string owner
     * @return string
     */
    public function renderGrid($values = array(), $owner = null, $paramDummy3 = null, $paramDummy4 = null)
    {
        $this->gridFieldType = 'textarea';

        if ($owner->mode != 'view') {
            $this->renderMode = $this->modeForGrid;
        }

        $result = [];
        $arrayOptions = [];

        $r = 1;

        foreach ($values as $v) {
            $this->executeSQL($owner, $r);

            if (isset($this->sqlOption)) {
                $firstElement = key($this->sqlOption);
            }

            if (isset($firstElement)) {
                $v = $firstElement;
            }

            $arrayOptions[$r] = $v;
            $resizable = ($this->resizable == 1 || $this->resizable == '1') ? 'resize:both;' : 'resize:none;';
            $scrollStyle = $this->style . "overflow:scroll;overflow-y:scroll;overflow-x:hidden;overflow:-moz-scrollbars-vertical;" . $resizable;
            $html = '';
            if ($this->renderMode == 'edit') {
                //EDIT MODE
                $readOnlyText = ($this->readOnly == 1 || $this->readOnly == '1') ? 'readOnly="readOnly"' : '';
                $html .= '<textarea ' . $readOnlyText . ' class="module_app_input___gray" ';
                $html .= 'id="form[' . $owner->name . '][' . $r . '][' . $this->name . ']" ';
                $html .= 'name="form[' . $owner->name . '][' . $r . '][' . $this->name . ']" ';
                $html .= 'wrap="soft" cols="' . $this->cols . '" rows="' . $this->rows . '" ';
                $html .= 'style="' . $scrollStyle . '" ';
                $html .= $this->NSDefaultValue() . ' ';
                $html .= $this->NSRequiredValue() . ' ';
                $html .= $this->NSGridType() . ' ';
                $html .= $this->NSGridLabel() . ' ';
                $html .= '>';
                $html .= $this->htmlentities($v, ENT_COMPAT, 'utf-8');
                $html .= '</textarea>';
            } else {
                //VIEW MODE
                $html .= '<textarea readOnly ';
                $html .= 'id="form[' . $owner->name . '][' . $r . '][' . $this->name . ']" ';
                $html .= $this->NSGridType() . ' ';
                $html .= 'name="form[' . $owner->name . '][' . $r . '][' . $this->name . ']" ';
                $html .= 'wrap="soft" cols="' . $this->cols . '" rows="' . $this->rows . '" ';
                $html .= 'style="' . $scrollStyle . '" wrap="' . $this->htmlentities($this->wrap, ENT_QUOTES, 'UTF-8') . '" ';
                $html .= 'class="FormTextArea" >';
                $html .= $this->htmlentities($v, ENT_COMPAT, 'utf-8');
                $html .= '</textarea>';
            }
            $result[] = $html;
            $r++;
        }

        $this->options = $arrayOptions;
        return $result;
    }
}

/**
 * Class XmlFormFieldCurrency
 *
 * @package gulliver.system
 * @access public
 */
class XmlFormFieldCurrency extends XmlFormFieldSimpleText
{
    public $group = 0;
    public $size = 15;
    public $required = false;
    public $linkField = '';
    public $readOnly = false;
    public $maxLength = 15;

    public $mask = '_###,###,###,###;###,###,###,###.## $';
    public $currency = '$';
    //Atributes only for grids
    public $formula = '';
    public $function = '';
    public $gridFieldType = 'currency';
    public $comma_separator = '.';
    public $sqlOption = [];

    /**
     * render the field in a dynaform
     *
     * @param <String> $value
     * @param <String> $owner
     * @return <String>
     */
    public function render($value = null, $owner = null)
    {
        if (($this->pmconnection != '') && ($this->pmfield != '') && $value == null) {
            $value = $this->getPMTableValue($owner);
        } else {
            $this->executeSQL($owner);
            if (isset($this->sqlOption)) {
                $firstElement = key($this->sqlOption);
            }
            if (isset($firstElement)) {
                $value = $firstElement;
            }
        }

        if ($this->renderMode == '') {
            $this->renderMode = $this->mode;
        }
        $onkeypress = G::replaceDataField($this->onkeypress, $owner->values);

        $html = '';
        $currency = preg_replace('/([_;#,.])/', '', $this->mask);
        if (!$value) {
            $value = $currency;
        }

        if ($this->renderMode == 'edit') {
            //EDIT MODE
            $readOnlyText = ($this->readOnly == 1 || $this->readOnly == '1') ? 'readOnly="readOnly"' : '';
            $html .= '<input ' . $readOnlyText . ' class="module_app_input___gray" ';
            $html .= 'id="form[' . $this->name . ']" ';
            $html .= 'name="form[' . $this->name . ']" ';
            $html .= 'type="text" size="' . $this->size . '" maxlength="' . $this->maxLength . '" ';
            $html .= 'value="' . $this->htmlentities($value, ENT_QUOTES, 'utf-8') . '" ';
            $html .= 'style="' . $this->htmlentities($this->style, ENT_COMPAT, 'utf-8') . '" ';
            $html .= 'onkeypress="' . $this->htmlentities($onkeypress, ENT_COMPAT, 'utf-8') . '" ';
            $html .= $this->NSDefaultValue() . ' ';
            $html .= $this->NSRequiredValue() . ' ';
            $html .= $this->NSFieldType() . ' ';
            $html .= 'pm:decimal_separator="' . $this->comma_separator . '" ';
            $html .= '/>';
        } else {
            //VIEW MODE
            $html .= $this->htmlentities($value, ENT_COMPAT, 'utf-8');
            $html .= '<input ';
            $html .= 'id="form[' . $this->name . ']" ';
            $html .= 'name="form[' . $this->name . ']" ';
            $html .= $this->NSFieldType() . ' ';
            $html .= 'type="hidden" value="' . $this->htmlentities($value, ENT_COMPAT, 'utf-8') . '" />';
        }
        if (($this->readOnly == 1) && ($this->renderMode == 'edit')) {
            $html = str_replace("class=\"module_app_input___gray\"", "class=\"module_app_input___gray_readOnly\"", $html);
        }
        $html .= $this->renderHint();

        return $html;
    }

    /**
     * Function renderGrid
     *
     * @author alvaro campos sanchez <alvaro@colosa.com>
     * @access public
     * @param string values
     * @param string owner
     * @return string
     */
    public function renderGrid($values = array(), $owner = null, $paramDummy3 = null, $paramDummy4 = null)
    {
        $result = [];
        $r = 1;
        if ($owner->mode != 'view') {
            $this->renderMode = $this->modeForGrid;
        }

        foreach ($values as $v) {
            $this->executeSQL($owner, $r);
            $firstElement = key($this->sqlOption);
            if (isset($firstElement)) {
                $v = $firstElement;
            }

            $html = '';
            $currency = preg_replace('/([_;#,.])/', '', $this->mask);
            if (!$v) {
                $v = $currency;
            }
            if ($this->renderMode === 'edit') {
                //EDIT MODE
                $readOnlyText = ($this->readOnly == 1 || $this->readOnly == '1') ? 'readOnly="readOnly"' : '';
                $html .= '<input ' . $readOnlyText . ' class="module_app_input___gray" ';
                $html .= 'id="form[' . $owner->name . '][' . $r . '][' . $this->name . ']" ';
                $html .= 'name="form[' . $owner->name . '][' . $r . '][' . $this->name . ']" ';
                $html .= 'type="text" size="' . $this->size . '" maxlength="' . $this->maxLength . '" ';
                $html .= 'value="' . $this->htmlentities($v, ENT_QUOTES, 'utf-8') . '" ';
                $html .= 'style="' . $this->htmlentities($this->style, ENT_COMPAT, 'utf-8') . '" ';
                $html .= $this->NSDefaultValue() . ' ';
                $html .= $this->NSRequiredValue() . ' ';
                $html .= $this->NSGridType() . ' ';
                $html .= $this->NSGridLabel() . ' ';
                $html .= '/>';
            } else {
                //VIEW MODE
                $html .= $this->htmlentities($v, ENT_QUOTES, 'utf-8');
                $html .= '<input ';
                $html .= 'id="form[' . $owner->name . '][' . $r . '][' . $this->name . ']" ';
                $html .= 'name="form[' . $owner->name . '][' . $r . '][' . $this->name . ']" ';
                $html .= $this->NSGridType() . ' ';
                $html .= 'type="hidden" value="' . $this->htmlentities($v, ENT_QUOTES, 'utf-8') . '" />';
            }
            $result[] = $html;
            $r++;
        }
        return $result;
    }
}

/*DEPRECATED*/

/**
 *
 * @package gulliver.system
 */
class XmlFormFieldCaptionCurrency extends XmlFormField
{

    /**
     * Function render
     *
     * @access public
     * @param string value
     * @return string
     */
    public function render($value = null, $paramDummy2 = null)
    {
        return '$ ' . $this->htmlentities($value, ENT_COMPAT, 'utf-8');
    }
}

/**
 * Class XmlFormFieldPercentage
 *
 * @package gulliver.system
 * @access public
 */
class XmlFormFieldPercentage extends XmlFormFieldSimpleText
{
    public $size = 15;
    public $required = false;
    public $linkField = '';
    public $readOnly = false;
    public $maxLength = 15;
    public $mask = '###.## %';
    //Atributes only for grids
    public $formula = '';
    public $function = '';
    public $gridFieldType = 'percentage';
    public $comma_separator = '.';
    public $sqlOption = [];

    public function render($value = null, $owner = null)
    {
        if (($this->pmconnection != '') && ($this->pmfield != '') && $value == null) {
            $value = $this->getPMTableValue($owner);
        } else {
            $this->executeSQL($owner);
            if (isset($this->sqlOption)) {
                $firstElement = key($this->sqlOption);
            }
            if (isset($firstElement)) {
                $value = $firstElement;
            }
        }

        if ($this->renderMode == '') {
            $this->renderMode = $this->mode;
        }
        $onkeypress = G::replaceDataField($this->onkeypress, $owner->values);

        $html = '';

        if ($this->renderMode == 'edit') {
            //EDIT MODE
            $readOnlyText = ($this->readOnly == 1 || $this->readOnly == '1') ? 'readOnly="readOnly"' : '';
            $html .= '<input ' . $readOnlyText . ' class="module_app_input___gray" ';
            $html .= 'id="form[' . $this->name . ']" ';
            $html .= 'name="form[' . $this->name . ']" ';
            $html .= 'type="text" size="' . $this->size . '" maxlength="' . $this->maxLength . '" ';
            $html .= 'value="' . $this->htmlentities($value, ENT_QUOTES, 'utf-8') . '" ';
            $html .= 'style="' . $this->htmlentities($this->style, ENT_COMPAT, 'utf-8') . '" ';
            $html .= 'onkeypress="' . $this->htmlentities($onkeypress, ENT_COMPAT, 'utf-8') . '" ';
            $html .= $this->NSDefaultValue() . ' ';
            $html .= $this->NSRequiredValue() . ' ';
            $html .= $this->NSFieldType() . ' ';
            $html .= 'pm:decimal_separator="' . $this->comma_separator . '" ';
            $html .= '/>';
        } else {
            //VIEW MODE
            $html .= $this->htmlentities($value, ENT_COMPAT, 'utf-8');
            $html .= '<input ';
            $html .= 'id="form[' . $this->name . ']" ';
            $html .= 'name="form[' . $this->name . ']" ';
            $html .= $this->NSFieldType() . ' ';
            $html .= 'type="hidden" value="' . $this->htmlentities($value, ENT_COMPAT, 'utf-8') . '" />';
        }

        if (($this->readOnly == 1) && ($this->renderMode == 'edit')) {
            $html = str_replace("class=\"module_app_input___gray\"", "class=\"module_app_input___gray_readOnly\"", $html);
        }
        $html .= $this->renderHint();
        return $html;
    }

    public function renderGrid($values = array(), $owner = null, $paramDummy3 = null, $paramDummy4 = null)
    {
        $result = [];
        $r = 1;
        if ($owner->mode != 'view') {
            $this->renderMode = $this->modeForGrid;
        }

        foreach ($values as $v) {
            $this->executeSQL($owner, $r);
            $firstElement = key($this->sqlOption);
            if (isset($firstElement)) {
                $v = $firstElement;
            }

            $html = '';
            $percentage = preg_replace('/([_;#,.])/', '', $this->mask);
            if (!$v) {
                $v = $percentage;
            }
            if ($this->renderMode === 'edit') {
                //EDIT MODE
                $readOnlyText = ($this->readOnly == 1 || $this->readOnly == '1') ? 'readOnly="readOnly"' : '';
                $html .= '<input ' . $readOnlyText . ' class="module_app_input___gray" ';
                $html .= 'id="form[' . $owner->name . '][' . $r . '][' . $this->name . ']" ';
                $html .= 'name="form[' . $owner->name . '][' . $r . '][' . $this->name . ']" ';
                $html .= 'type="text" size="' . $this->size . '" maxlength="' . $this->maxLength . '" ';
                $html .= 'value="' . $this->htmlentities($v, ENT_QUOTES, 'utf-8') . '" ';
                $html .= 'style="' . $this->htmlentities($this->style, ENT_COMPAT, 'utf-8') . '" ';
                $html .= $this->NSDefaultValue() . ' ';
                $html .= $this->NSRequiredValue() . ' ';
                $html .= $this->NSGridType() . ' ';
                $html .= $this->NSGridLabel() . ' ';
                $html .= '/>';
            } else {
                //VIEW MODE
                $html .= $this->htmlentities($v, ENT_QUOTES, 'utf-8');
                $html .= '<input ';
                $html .= 'id="form[' . $owner->name . '][' . $r . '][' . $this->name . ']" ';
                $html .= 'name="form[' . $owner->name . '][' . $r . '][' . $this->name . ']" ';
                $html .= $this->NSGridType() . ' ';
                $html .= 'type="hidden" value="' . $this->htmlentities($v, ENT_QUOTES, 'utf-8') . '" />';
            }
            $result[] = $html;
            $r++;
        }
        return $result;
    }
}

/*DEPRECATED*/

/**
 *
 * @package gulliver.system
 */
class XmlFormFieldCaptionPercentage extends XmlFormField
{
    public function render($value = null, $paramDummy2 = null)
    {
        return $this->htmlentities($value, ENT_COMPAT, 'utf-8');
    }
}

/**
 * Class XmlFormFieldDate
 *
 * @package gulliver.system
 * @access public
 */
class XmlFormFieldDate2 extends XmlFormFieldSimpleText
{
    //Instead of size --> startDate
    public $startDate = '';
    //Instead of maxLength --> endDate
    public $endDate = '';
    //for dinamically dates,   beforeDate << currentDate << afterDate
    // beforeDate='1y' means one year before,  beforeDate='3m' means 3 months before
    // afterDate='5y' means five year after,  afterDate='15d' means 15 days after
    // startDate and endDate have priority over beforeDate and AfterDate.
    public $afterDate = '';
    public $beforeDate = '';
    public $defaultValue = null;
    public $format = 'Y-m-d';
    public $required = false;
    public $readOnly = false;
    public $mask = 'yyyy-mm-dd';
    public $dependentFields = '';

    /**
     * Verify the date format
     *
     * @param $date
     * @return Boolean true/false
     */
    public function verifyDateFormat($date)
    {
        $aux = explode('-', $date);
        if (count($aux) != 3) {
            return false;
        }
        if (!(is_numeric($aux[0]) && is_numeric($aux[1]) && is_numeric($aux[2]))) {
            return false;
        }
        if ($aux[0] < 1900 || $aux[0] > 2100) {
            return false;
        }
        return true;
    }

    /**
     * checks if a date has he correct format
     *
     * @param $date
     * @return <Boolean>
     */
    public function isvalidBeforeFormat($date)
    {
        $part1 = substr($date, 0, strlen($date) - 1);
        $part2 = substr($date, strlen($date) - 1);
        if ($part2 != 'd' && $part2 != 'm' && $part2 != 'y') {
            return false;
        }
        if (!is_numeric($part1)) {
            return false;
        }
        return true;
    }

    /**
     * Calculate the date before the format
     *
     * @param <type> $date
     * @param <type> $sign
     * @return <date> $res date based on the data insert
     */
    public function calculateBeforeFormat($date, $sign)
    {
        $part1 = $sign * substr($date, 0, strlen($date) - 1);
        $part2 = substr($date, strlen($date) - 1);
        switch ($part2) {
            case 'd':
                $res = date('Y-m-d', mktime(0, 0, 0, date('m'), date('d') + $part1, date('Y')));
                break;
            case 'm':
                $res = date('Y-m-d', mktime(0, 0, 0, date('m') + $part1, date('d'), date('Y')));
                break;
            case 'y':
                $res = date('Y-m-d', mktime(0, 0, 0, date('m'), date('d'), date('Y') + $part1));
                break;

        }
        return $res;
    }

    /**
     * render the field in a dynaform
     *
     * @param $value
     * @param $owner
     * @return <String>
     */
    public function render($value = null, $owner = null)
    {
        $value = G::replaceDataField($value, $owner->values);
        $startDate = G::replaceDataField($this->startDate, $owner->values);
        $endDate = G::replaceDataField($this->endDate, $owner->values);
        $beforeDate = G::replaceDataField($this->beforeDate, $owner->values);
        $afterDate = G::replaceDataField($this->afterDate, $owner->values);
        //for backward compatibility size and maxlength
        if ($startDate != '') {
            if (!$this->verifyDateFormat($startDate)) {
                $startDate = '';
            }
        }
        if (isset($beforeDate) && $beforeDate != '') {
            if ($this->isvalidBeforeFormat($beforeDate)) {
                $startDate = $this->calculateBeforeFormat($beforeDate, -1);
            }
        }

        if ($startDate == '' && isset($this->size) && is_numeric($this->size) && $this->size >= 1900 && $this->size <= 2100) {
            $startDate = $this->size . '-01-01';
        }

        if ($startDate == '') {
            $startDate = date('Y-m-d'); // the default is the current date
        }

        //for backward compatibility maxlength
        //if ( $this->endDate == '')   $this->finalYear = date('Y') + 8;
        //for backward compatibility size and maxlength
        if ($endDate != '') {
            if (!$this->verifyDateFormat($endDate)) {
                $endDate = '';
            }
        }

        if (isset($afterDate) && $afterDate != '') {
            if ($this->isvalidBeforeFormat($afterDate)) {
                $endDate = $this->calculateBeforeFormat($afterDate, +1);
            }
            if ($endDate) {
                $sign = '1';
                $date = $afterDate;
                $part1 = $sign * substr($date, 0, strlen($date) - 1);
                $part2 = substr($date, strlen($date) - 1);
                switch ($part2) {
                    case 'd':
                        $res = date('Y-m-d', mktime(0, 0, 0, date('m'), date('d') + $part1, date('Y')));
                        break;
                    case 'm':
                        $res = date('Y-m-d', mktime(0, 0, 0, date('m') + $part1, date('d') - 1, date('Y')));
                        break;
                    case 'y':
                        $res = (intVal(date('Y')) + $part1) . '-' . date('m') . '-' . date('d');
                        break;
                }

                $endDate = $res;
            }
        }

        if (isset($this->maxlength) && is_numeric($this->maxlength) && $this->maxlength >= 1900 && $this->maxlength <= 2100) {
            $endDate = $this->maxlength . '-01-01';
        }
        if ($endDate == '') {
            //$this->endDate = mktime ( 0,0,0,date('m'),date('d'),date('y') );  // the default is the current date + 2 years
            $endDate = date('Y-m-d', mktime(0, 0, 0, date('m'), date('d'), date('Y') + 2)); // the default is the current date + 2 years
        }
        if ($value == '') {
            $value = date('Y-m-d');
        }
        $html = "<input type='hidden' id='form[" . $this->name . "]' name='form[" . $this->name . "]' value='" . $value . "'>";
        $html .= "<span id='span[" . $owner->id . "][" . $this->name . "]' name='span[" . $owner->id . "][" . $this->name . "]' style='border:1;border-color:#000;width:100px;'>" . $value . " </span> ";
        if ($this->mode == 'edit') {
            $html .= "<a href='#' onclick=\"showDatePicker(event,'" . $owner->id . "', '" . $this->name . "', '" . $value . "', '" . $startDate . "', '" . $endDate . "'); return false;\" ><img src='/controls/cal.gif' border='0'></a>";
        }
        return $html;
    }

    /**
     * render the field in a grid
     *
     * @param $values
     * @param $owner
     * @param $onlyValue
     * @return <String>
     */
    public function renderGrid($values = null, $owner = null, $onlyValue = false, $paramDummy4 = null)
    {
        $result = [];
        $r = 1;
        foreach ($values as $v) {
            $v = G::replaceDataField($v, $owner->values);
            $startDate = G::replaceDataField($this->startDate, $owner->values);
            $endDate = G::replaceDataField($this->endDate, $owner->values);
            $beforeDate = G::replaceDataField($this->beforeDate, $owner->values);
            $afterDate = G::replaceDataField($this->afterDate, $owner->values);
            //for backward compatibility size and maxlength
            if ($startDate != '') {
                if (!$this->verifyDateFormat($startDate)) {
                    $startDate = '';
                }
            }
            if ($startDate == '' && isset($beforeDate) && $beforeDate != '') {
                if ($this->isvalidBeforeFormat($beforeDate)) {
                    $startDate = $this->calculateBeforeFormat($beforeDate, -1);
                }
            }

            if ($startDate == '' && isset($this->size) && is_numeric($this->size) && $this->size >= 1900 && $this->size <= 2100) {
                $startDate = $this->size . '-01-01';
            }

            if ($startDate == '') {
                $startDate = date('Y-m-d'); // the default is the current date
            }

            //for backward compatibility maxlength
            //if ( $this->endDate == '')   $this->finalYear = date('Y') + 8;
            //for backward compatibility size and maxlength
            if ($endDate != '') {
                if (!$this->verifyDateFormat($endDate)) {
                    $endDate = '';
                }
            }

            if ($endDate == '' && isset($afterDate) && $afterDate != '') {
                if ($this->isvalidBeforeFormat($afterDate)) {
                    $endDate = $this->calculateBeforeFormat($afterDate, +1);
                }
            }

            if ($endDate == '' && isset($this->maxlength) && is_numeric($this->maxlength) && $this->maxlength >= 1900 && $this->maxlength <= 2100) {
                $endDate = $this->maxlength . '-01-01';
            }
            if ($endDate == '') {
                //$this->endDate = mktime ( 0,0,0,date('m'),date('d'),date('y') );  // the default is the current date + 2 years
                $endDate = date('Y-m-d', mktime(0, 0, 0, date('m'), date('d'), date('Y') + 2)); // the default is the current date + 2 years
            }
            if ($v == '') {
                $v = date('Y-m-d');
            }
            if (!$onlyValue) {
                $html = "<input type='hidden' id='form[" . $owner->name . '][' . $r . '][' . $this->name . "]' name='form[" . $owner->name . '][' . $r . '][' . $this->name . "]' value='" . $v . "'>";
                if (isset($owner->owner->id)) {
                    $html .= "<span id='span[" . $owner->owner->id . "][" . $owner->name . '][' . $r . '][' . $this->name . "]' name='span[" . $owner->owner->id . "][" . $owner->name . '][' . $r . '][' . $this->name . "]' style='border:1;border-color:#000;width:100px;'>" . $v . " </span> ";
                } else {
                    $html .= "<span id='span[" . $owner->id . "][" . $owner->name . '][' . $r . '][' . $this->name . "]' name='span[" . $owner->id . "][" . $owner->name . '][' . $r . '][' . $this->name . "]' style='border:1;border-color:#000;width:100px;'>" . $v . " </span> ";
                }
                if ($this->mode == 'edit') {
                    $html .= "<a href='#' onclick=\"showDatePicker(event,'" . (isset($owner->owner) ? $owner->owner->id : $owner->id) . "', '" . $owner->name . '][' . $r . '][' . $this->name . "', '" . $v . "', '" . $startDate . "', '" . $endDate . "'); return false;\" ><img src='/controls/cal.gif' border='0'></a>";
                }
            } else {
                $html = $v;
            }
            $result[] = $html;
            $r++;
        }
        return $result;
    }
}

/*DEPRECATED*/

/**
 *
 * @package gulliver.system
 */
class XmlFormFieldDateView extends XmlFormField
{
    public function render($value = null, $paramDummy2 = null)
    {
        return $this->htmlentities($value, ENT_COMPAT, 'utf-8');
    }
}

/**
 * Class XmlFormFieldYesNo
 *
 * @package gulliver.system
 * @access public
 */
class XmlFormFieldYesNo extends XmlFormField
{
    public $required = false;
    public $readonly = false;
    public $renderMode = '';

    /**
     * Function render
     *
     * @access public
     * @param string value
     * @return string
     */
    public function render($value = null, $owner = null)
    {
        if (($this->pmconnection != '') && ($this->pmfield != '') && $value == null) {
            $value = $this->getPMTableValue($owner);
        }
        if ($value == '') {
            $value = '0';
        }
        if ($this->renderMode == '') {
            $this->renderMode = $this->mode;
        }
        $html = '';
        if ($this->renderMode == 'edit') {
            //EDIT MODE
            $readOnlyText = ($this->readonly == 1 || $this->readonly == '1') ? 'disabled' : '';
            $html .= '<select ' . $readOnlyText . ' class="module_app_input___gray" ';
            if ($readOnlyText == '') {
                $html .= 'id="form[' . $this->name . ']" ';
                $html .= 'name="form[' . $this->name . ']" ';
                $html .= $this->NSFieldType() . ' ';
            }
            $html .= $this->NSDefaultValue() . ' ';
            $html .= $this->NSRequiredValue() . ' ';
            $html .= '>';
            $html .= '<option value="0"' . (($value === '0') ? ' selected' : '') . '>' . G::LoadTranslation('ID_NO_VALUE') . '</option>';
            $html .= '<option value="1"' . (($value === '1') ? ' selected' : '') . '>' . G::LoadTranslation('ID_YES_VALUE') . '</option>';
            $html .= '</select>';
            if ($readOnlyText != '') {
                $html .= '<input ';
                $html .= 'id="form[' . $this->name . ']" ';
                $html .= 'name="form[' . $this->name . ']" ';
                $html .= $this->NSFieldType() . ' ';
                $html .= 'type="hidden" value="' . (($value === '0') ? '0' : '1') . '" />';
            }
        } else {
            //VIEW MODE
            $html .= '<span id="' . $this->name . '">';
            $html .= ($value === '0') ? G::LoadTranslation('ID_NO_VALUE') : G::LoadTranslation('ID_YES_VALUE');
            $html .= '<input ';
            $html .= 'id="form[' . $this->name . ']" ';
            $html .= 'name="form[' . $this->name . ']" ';
            $html .= $this->NSFieldType() . ' ';
            $html .= 'type="hidden" value="' . (($value === '0') ? '0' : '1') . '" />';
        }

        $html .= $this->renderHint();
        return $html;
    }

    /**
     * render the field in a grid
     *
     * @param $values
     * @param $owner
     * @return <array>
     */
    public function renderGrid($values = array(), $owner = null, $paramDummy3 = null, $paramDummy4 = null)
    {
        $this->gridFieldType = 'yesno';
        $result = [];
        $r = 1;
        if ($owner->mode != 'view') {
            $this->renderMode = $this->modeForGrid;
        }
        foreach ($values as $v) {
            $html = '';
            if ($v == '') {
                $v = '0';
            }
            if ($this->renderMode == 'edit') {
                //EDIT MODE
                $readOnlyText = ($this->readonly == 1 || $this->readonly == '1') ? 'disabled' : '';
                $html .= '<select ' . $readOnlyText . ' class="module_app_input___gray" ';
                if ($readOnlyText == '') {
                    $html .= 'id="form[' . $owner->name . '][' . $r . '][' . $this->name . ']" ';
                    $html .= 'name="form[' . $owner->name . '][' . $r . '][' . $this->name . ']" ';
                    $html .= $this->NSGridType() . ' ';
                }
                $html .= $this->NSDefaultValue() . ' ';
                $html .= $this->NSRequiredValue() . ' ';
                $html .= $this->NSGridLabel() . ' ';
                $html .= '>';
                $html .= '<option value="0"' . (($v === '0') ? ' selected="selected"' : '') . '>' . G::LoadTranslation('ID_NO_VALUE') . '</option>';
                $html .= '<option value="1"' . (($v === '1') ? ' selected="selected"' : '') . '>' . G::LoadTranslation('ID_YES_VALUE') . '</option>';
                $html .= '</select>';
                if ($readOnlyText != '') {
                    $html .= '<input ';
                    $html .= 'id="form[' . $owner->name . '][' . $r . '][' . $this->name . ']" ';
                    $html .= 'name="form[' . $owner->name . '][' . $r . '][' . $this->name . ']" ';
                    $html .= $this->NSGridType() . ' ';
                    $html .= 'type="hidden" value="' . (($v === '0') ? '0' : '1') . '" />';
                }
            } else {
                //VIEW MODE
                $html .= ($v === '0') ? G::LoadTranslation('ID_NO_VALUE') : G::LoadTranslation('ID_YES_VALUE');
                $html .= '<input ';
                $html .= 'id="form[' . $owner->name . '][' . $r . '][' . $this->name . ']" ';
                $html .= 'name="form[' . $owner->name . '][' . $r . '][' . $this->name . ']" ';
                $html .= $this->NSGridType() . ' ';
                $html .= 'type="hidden" value="' . (($v === '0') ? '0' : '1') . '" />';
            }
            $result[] = $html;
            $r++;
        }
        return $result;
    }
}

/**
 * Class XmlFormFieldLink
 *
 * @package gulliver.system
 * @access public
 */
class XmlFormFieldLink extends XmlFormField
{
    //Instead of var --> link
    public $link = '';
    public $value = '';
    public $target = '';
    public $style = '';
    public $colClassName = 'RowLink';
    public $gridFieldType = 'link';

    /**
     * Function render
     *
     * @access public
     * @param string value
     * @return string
     */
    public function render($value = null, $label = null, $owner = null, $row = -1)
    {
        $id = null;
        $v = null;

        switch ($owner->type) {
            case "grid":
                $id = $owner->name . "][" . $row . "][" . $this->name;
                $v = (isset($owner->values[$owner->name][$row])) ? $owner->values[$owner->name][$row] : [];
                //g::pr($this->NSGridType().'gyygygy');die;
                $pmtype = $this->NSGridType();
                break;
            default:
                $id = $this->name;
                $v = $owner->values;
                $pmtype = $this->NSFieldType();
                break;
        }

        $link = "";
        if ($this->link != "") {
            $link = G::replaceDataField($this->link, $v);
        } else {
            $link = !empty($value) ? $value : "";
        }
        $labelAux1 = (!empty($label)) ? $label : G::replaceDataField($this->label, $v);
        $labelAux2 = (!empty($label)) ? $label : G::replaceDataField($this->value, $v);
        $onclick = G::replaceDataField($this->onclick, $v);
        $target = G::replaceDataField($this->target, $v);

        $html = "<a " . $pmtype . " class=\"tableOption\" href=\"" . $this->htmlentities($link, ENT_QUOTES, "utf-8") . "\"";
        $html = $html . " id=\"form[$id]\" name=\"form[$id]\" pm:field=\"pm:field\" ";
        if ((strrpos($_SERVER['HTTP_USER_AGENT'], "Chrome") === false ? false : true) && trim($this->htmlentities($link, ENT_QUOTES, "utf-8")) === "#") {
            $html = $html . (($this->onclick) ? " onclick=\"" . htmlentities($onclick, ENT_QUOTES, "utf-8") . " return false;\"" : " onclick=\" return false;\"");
        } else {
            $html = $html . (($this->onclick) ? " onclick=\"" . htmlentities($onclick, ENT_QUOTES, "utf-8") . "\"" : null);
        }
        $html = $html . (($this->target) ? " target=\"" . htmlentities($target, ENT_QUOTES, "utf-8") . "\"" : null);

        switch ($owner->type) {
            case "grid":
                if ($this->mode == "view") {
                    $html = $html . " style=\"color: #006699; text-decoration: none; font-weight: normal;\"";
                }
                break;
            default:
                $html = $html . " style=\"" . htmlentities($this->style, ENT_QUOTES, "utf-8") . "\"";
                break;
        }

        $html = $html . ">" . $this->htmlentities(($this->value == "") ? $labelAux1 : $labelAux2, ENT_QUOTES, "utf-8") . "</a>";

        switch ($owner->type) {
            case "grid":
                break;
            default:
                $html = $html . $this->renderHint();
                break;
        }

        return $html;
    }

    /**
     * render the field in a grid
     *
     * @param $values
     * @param $owner
     * @return <array>
     */
    public function renderGrid($value = array(), $label = array(), $owner = null, $paramDummy4 = null)
    {
        $arrayResult = [];
        $row = 1;

        foreach ($value as $index => $v) {
            $arrayResult[] = $this->render(
                (isset($value[$index])) ? $value[$index] : null,
                (isset($label[$index])) ? $label[$index] : null,
                $owner,
                $row
            );

            $row = $row + 1;
        }

        return $arrayResult;
    }

    /**
     * render the field in a table
     *
     * @param $values
     * @param $owner
     * @return <String>
     */
    public function renderTable($value = null, $owner = null, $paramDummy3 = null)
    {
        $onclick = $this->htmlentities(G::replaceDataField($this->onclick, $owner->values), ENT_QUOTES, 'utf-8');
        $link = $this->htmlentities(G::replaceDataField($this->link, $owner->values), ENT_QUOTES, 'utf-8');
        $target = G::replaceDataField($this->target, $owner->values);
        $value = G::replaceDataField($this->value, $owner->values);
        $label = G::replaceDataField($this->label, $owner->values);
        $aLabel = $this->htmlentities($this->value === '' ? $label : $value, ENT_QUOTES, 'utf-8');
        if (isset($aLabel) && strlen($aLabel) > 0) {
            return '<a class="tableOption" href=\'' . $link . '\'' . (($this->onclick) ? ' onclick="' . $onclick . '"' : '') . (($this->target) ? ' target="' . htmlentities($target, ENT_QUOTES, 'utf-8') . '"' : '') . '>' . $aLabel . '</a>';
        } else {
            return '';
        }
    }
}

/**
 * Class XmlFormFieldFile
 *
 * @package gulliver.system
 * @access public
 */
class XmlFormFieldFile extends XmlFormField
{
    public $required = false;
    public $input = null;
    public $gridFieldType = 'file';

    /**
     * Function render
     *
     * @access public
     * @param string value
     * @return string
     */
    public function render($value = null, $owner = null, $rowId = null, $row = -1, $therow = -1)
    {
        $permission = false;
        $url = null;

        switch ($owner->type) {
            case "xmlform":
                $pmtype = $this->NSFieldType();
                break;
            case "grid":
                $pmtype = $this->NSGridType();
                break;
        }

        if (isset($_SESSION["APPLICATION"]) && isset($_SESSION["USER_LOGGED"]) && isset($_SESSION["TASK"]) && isset($this->input) && $this->input != null && $this->mode == "view") {
            require_once("classes/model/AppDocument.php");


            $case = new Cases();
            $arrayField = $case->loadCase($_SESSION["APPLICATION"]);
            $arrayPermission = $case->getAllObjects($arrayField["PRO_UID"], $_SESSION["APPLICATION"], $_SESSION["TASK"], $_SESSION["USER_LOGGED"]);

            $criteria = new Criteria();
            $criteria->add(AppDocumentPeer::APP_DOC_UID, $arrayPermission["INPUT_DOCUMENTS"], Criteria::IN);

            switch ($owner->type) {
                case "xmlform":
                    break;
                case "grid":
                    $criteria->add(AppDocumentPeer::APP_DOC_FIELDNAME, $owner->name . "_" . $row . "_" . $this->name);
                    break;
            }

            $criteria->addDescendingOrderByColumn(AppDocumentPeer::APP_DOC_CREATE_DATE);
            $rsCriteria = AppDocumentPeer::doSelectRS($criteria);
            $rsCriteria->setFetchmode(ResultSet::FETCHMODE_ASSOC);
            $sw = 0;

            while (($rsCriteria->next()) && $sw == 0) {
                $row = $rsCriteria->getRow();

                if ($row["DOC_UID"] == $this->input) {
                    $permission = true;
                    $url = System::getServerProtocolHost() . dirname($_SERVER["REQUEST_URI"]) . "/cases_ShowDocument?a=" . $row["APP_DOC_UID"] . "&v=" . $row["DOC_VERSION"];
                    $sw = 1;
                }
            }
        }

        $html1 = null;
        $html2 = null;
        $mode = ($this->mode == "view") ? " disabled=\"disabled\"" : null;
        $styleDisplay = null;

        if ($this->mode == "view") {
            if ($permission) {
                $html1 = "<a href=\"" . $url . "\"" . (($owner->type == "grid") ? " class=\"tableOption\" style=\"color: #006699; text-decoration: none; font-weight: normal;\"" : null) . ">";
                $html2 = "</a>";
            }

            $html1 = $html1 . $value;
            $styleDisplay = "display: none;";
        }

        $arrayInputDocumentData = [];
        $inpDocMaxFilesize = "";

        if (isset($this->input) && $this->input != null) {
            try {
                $inputDocument = new InputDocument();
                $arrayInputDocumentData = $inputDocument->load($this->input);
            } catch (Exception $e) {
                //Then the input document doesn"t exits, id referencial broken
            }
        }

        if (count($arrayInputDocumentData) > 0) {
            $inpDocMaxFilesize = $arrayInputDocumentData["INP_DOC_MAX_FILESIZE"] * (($arrayInputDocumentData["INP_DOC_MAX_FILESIZE_UNIT"] == "MB") ? 1024 * 1024 : 1024); //Bytes
        }

        $pmInputDocument = "pmindocmaxfilesize=\"" . $inpDocMaxFilesize . "\""; //Bytes

        $html = $html1 . "<input type=\"file\" " . $pmtype . " " . $pmInputDocument . " id=\"form" . $rowId . "[" . $this->name . "]\" name=\"form" . $rowId . "[" . $this->name . "]\" value=\"" . $value . "\" class=\"module_app_input___gray_file\" style=\"" . $styleDisplay . "\"" . $mode . " " . $this->NSRequiredValue() . " />" . $html2;

        if (isset($this->input) && $this->input != null) {
            if (count($arrayInputDocumentData) > 0) {
                $maxUploadFilesizeLabel = ($arrayInputDocumentData["INP_DOC_MAX_FILESIZE"] . "" != "0" && $arrayInputDocumentData["INP_DOC_MAX_FILESIZE"] != "") ? G::LoadTranslation("ID_MAX_FILE_SIZE") . " [" . $arrayInputDocumentData["INP_DOC_MAX_FILESIZE"] . " " . $arrayInputDocumentData["INP_DOC_MAX_FILESIZE_UNIT"] . "]" : "";

                $arrayInputDocumentData["INP_DOC_TITLE"] = (isset($arrayInputDocumentData["INP_DOC_TITLE"])) ? $arrayInputDocumentData["INP_DOC_TITLE"] : null;
                $html = $html . "<br /><label><img src=\"/images/inputdocument.gif\" width=\"22px\" width=\"22px\" alt=\"\" /><font size=\"1\">(" . trim($arrayInputDocumentData["INP_DOC_TITLE"]) . ") " . $maxUploadFilesizeLabel . "</font></label>";
            } else {
                $html = $html . "&nbsp;<font color=\"red\"><img src=\"/images/alert_icon.gif\" width=\"16px\" width=\"16px\" alt=\"\" /><font size=\"1\">(" . G::loadTranslation("ID_INPUT_DOC_DOESNT_EXIST") . ")</font></font>";
            }
        }

        $html = $html . $this->renderHint();

        return $html;
    }

    public function renderGrid($value = array(), $owner = null, $therow = -1, $paramDummy4 = null)
    {
        $arrayResult = [];
        $r = 1;

        foreach ($value as $v) {
            $arrayResult[] = $this->render($v, $owner, "[" . $owner->name . "][" . $r . "]", $r, $therow);
            $r = $r + 1;
        }

        return $arrayResult;
    }
}

/**
 * Class XmlFormFieldDropdownpt
 * hook, dropdown field for Propel table
 *
 * @package gulliver.system
 * @access public
 */
class XmlFormFieldDropdownpt extends XmlFormField
{
    public $value;

    public function render($value = null, $owner = null)
    {
        $this->value = $value;

        $id = $this->value->id;
        $value = isset($this->value->value) ? $this->value->value : '';
        $items = $this->value->items;

        $res = '<select id="form[' . $id . ']" name="form[' . $this->name . ']" class="module_app_input___gray"><option value="0"></option>';
        foreach ($items as $k => $v) {
            $res .= '<option value="' . $k . '">' . $v . '</option>';
        }
        $res .= "</select>";
        return $res;
    }

    /* Used in Form::validatePost
    */
    public function maskValue($value, &$owner)
    {
        return ($value === $this->value) ? $value : $this->falseValue;
    }
}

/**
 * Class XmlFormFieldCheckboxpt
 * checkbox field for Propel table
 *
 * @package gulliver.system
 * @access public
 */
class XmlFormFieldCheckboxpt extends XmlFormField
{
    public $required = false;
    public $value = 'on';
    public $falseValue = 'off';
    public $labelOnRight = true;

    /**
     * Render the field in a dynaform
     *
     * @param $value
     * @param $owner
     * @return <>
     */
    public function render($value = null, $owner = null)
    {
        if (($this->pmconnection != '') && ($this->pmfield != '') && $value == null) {
            $value = $this->getPMTableValue($owner);
        }
        $checked = (isset($value) && ($value == $this->value)) ? 'checked' : '';
        $res = "<input id='form[" . $this->name . "][{$this->value}]' value='{$this->value}' name='form[" . $this->name . "][{$this->value}]' type='checkbox' />";
        return $res;
    }

    /**
     * Render the field in a grid
     *
     * @param $value
     * @param $owner
     * @return <Array> result
     */
    public function renderGrid($values = array(), $owner = null, $paramDummy3 = null, $paramDummy4 = null)
    {
        $result = [];
        $r = 1;
        foreach ($values as $v) {
            $checked = (($v == $this->value) ? 'checked="checked"' : '');
            $disabled = (($this->value == 'view') ? 'disabled="disabled"' : '');
            $html = $res = "<input id='form[" . $owner->name . "][" . $r . "][" . $this->name . "]' value='{$this->value}' name='form[" . $owner->name . "][" . $r . "][" . $this->name . "]' type='checkbox' $checked $disabled />";
            $result[] = $html;
            $r++;
        }
        return $result;
    }

    /**
     * Used in Form::validatePost
     *
     * @param $value
     * @param &$owner
     * @return either the value or falseValue attributes
     */
    public function maskValue($value, &$owner)
    {
        return ($value === $this->value) ? $value : $this->falseValue;
    }
}

/**
 * Class XmlFormFieldCheckbox
 *
 * @package gulliver.system
 * @access public
 */
class XmlFormFieldCheckbox extends XmlFormField
{
    public $required = false;
    public $value = 'on';
    public $falseValue = 'off';
    public $labelOnRight = false;
    public $readOnly = false;

    /**
     * Function render
     *
     * @access public
     * @param string value
     * @return string
     */
    public function render($value = null, $owner = null)
    {
        if (($this->pmconnection != '') && ($this->pmfield != '') && $value == null) {
            $value = $this->getPMTableValue($owner);
        }

        $disabled = '';
        if ($this->readOnly === 'readonly' or $this->readOnly === '1') {
            $readOnly = 'readonly="readonly" onclick="javascript: return false;"'; //$disabled = "disabled";
        } else {
            $readOnly = '';
        }

        $checked = (isset($value) && ($value == $this->value)) ? 'checked' : '';

        if ($this->mode === 'edit') {
            //$readOnly = isset ( $this->readOnly ) && $this->readOnly ? 'disabled' : '';
            if ($this->labelOnRight) {
                $res = "<input id='form[" . $this->name . "]' value='{$this->value}' " . $this->NSFieldType() . " name='form[" . $this->name . "]' type='checkbox' $checked $readOnly $disabled><span class='FormCheck'>" . $this->label . '</span></input>';
            } else {
                $res = "<input id='form[" . $this->name . "]' value='{$this->value}' " . $this->NSFieldType() . " name='form[" . $this->name . "]' type='checkbox' $checked $readOnly $disabled/>";
            }
            $res .= $this->renderHint();

            //      $res = "<input id='form[" . $this->name . "]' value='" . $this->name . "' name='form[" .$this->name . "]' type='checkbox' $checked $readOnly >" . $this->label ;
            return $res;
        } elseif ($this->mode === 'view') {
            $checked = (isset($value) && ($value == $this->value)) ? 'checked' : '';
            if ($this->labelOnRight) {
                $html = "<input id='form[" . $this->name . "]' value='{$this->value}' type='checkbox' $checked $readOnly disabled />
                 <span class='FormCheck'>" . $this->label . '</span></input>';
            } else {
                $html = "<input id='form[" . $this->name . "]' value='{$this->value}' type='checkbox' $checked $readOnly disabled />";
            }
            $html .= "<input name='form[" . $this->name . "]' type='hidden' " . $this->NSFieldType() . " value='{$value}' />";
            return $html;
        }
    }

    /**
     * Render the field in a grid
     *
     * @param $value
     * @param $owner
     * @return <Array> result
     */
    public function renderGrid($values = array(), $owner = null, $paramDummy3 = null, $paramDummy4 = null)
    {
        $this->gridFieldType = 'checkbox';
        $result = [];
        $r = 1;
        foreach ($values as $v) {
            $checked = (($v == $this->value) ? 'checked="checked"' : '');
            if ($this->readOnly === 'readonly' or $this->readOnly === '1') {
                $disabled = "disabled";
            } else {
                $disabled = '';
            }
            if ($this->mode === 'edit') {
                $html = $res = "<input id='form[" . $owner->name . "][" . $r . "][" . $this->name . "]' value='{$this->value}' falseValue= " . $this->falseValue . "  name='form[" . $owner->name . "][" . $r . "][" . $this->name . "]' type='checkbox' $checked $disabled readonly = '{$this->readOnly}' " . $this->NSDefaultValue() . " " . $this->NSGridType() . "/>";
                $result[] = $html;
                $r++;
            } else {
                //$disabled = (($this->value == 'view') ? 'disabled="disabled"' : '');
                $html = $res = "<input id='form[" . $owner->name . "][" . $r . "][" . $this->name . "]' value='{$this->value}' falseValue= " . $this->falseValue . " name='form[" . $owner->name . "][" . $r . "][" . $this->name . "]' type='checkbox' $checked disabled readonly = '{$this->readOnly}' " . $this->NSDefaultValue() . " " . $this->NSGridType() . "/>";
                $result[] = $html;
                $r++;
            }
        }
        return $result;
    }

    /**
     * Used in Form::validatePost
     *
     * @param $value
     * @param $owner
     * @return either the value or falseValue
     */
    public function maskValue($value, &$owner)
    {
        return ($value === $this->value) ? $value : $this->falseValue;
    }
}

/*DEPRECATED*/

/**
 *
 * @package gulliver.system
 */
class XmlFormFieldCheckbox2 extends XmlFormField
{
    public $required = false;

    public function render($value = null, $paramDummy2 = null)
    {
        return '<input class="FormCheck" name="' . $this->name . '" type ="checkbox" disabled>' . $this->label . '</input>';
    }
}

/**
 * Class XmlFormFieldButton
 *
 * @package gulliver.system
 * @access public
 */
class XmlFormFieldButton extends XmlFormField
{
    public $onclick = '';
    public $align = 'center';
    public $style;

    /**
     * Function render
     *
     * @access public
     * @param string value
     * @return string
     */
    public function render($value = null, $owner = null)
    {
        $onclick = G::replaceDataField($this->onclick, $owner->values);
        $label = G::replaceDataField($this->label, $owner->values);
        if ($this->mode === 'edit') {
            $re = "<input style=\"{$this->style}\" class='module_app_button___gray {$this->className}' id=\"form[{$this->name}]\" " . $this->NSFieldType() . " name=\"form[{$this->name}]\" type='button' value=\"{$label}\" " . (($this->onclick) ? 'onclick="' . htmlentities($onclick, ENT_COMPAT, 'utf-8') . '"' : '') . " />";
            return $re;
        } elseif ($this->mode === 'view') {
            return "<input style=\"{$this->style};display:none\" disabled='disabled' class='module_app_button___gray module_app_buttonDisabled___gray {$this->className}' id=\"form[{$this->name}]\" " . $this->NSFieldType() . " name=\"form[{$this->name}]\" type='button' value=\"{$label}\" " . (($this->onclick) ? 'onclick="' . htmlentities($onclick, ENT_COMPAT, 'utf-8') . '"' : '') . " />";
        } else {
            return $this->htmlentities($value, ENT_COMPAT, 'utf-8');
        }
    }
}

/**
 * Class XmlFormFieldReset
 *
 * @package gulliver.system
 * @access public
 */
class XmlFormFieldReset extends XmlFormField
{

    /**
     * Function render
     *
     * @access public
     * @param string value
     * @return string
     */
    public function render($value = null, $owner = null)
    {
        $onclick = G::replaceDataField($this->onclick, $owner->values);
        $mode = ($this->mode == 'view') ? ' disabled="disabled"' : '';
        //return '<input name="'.$this->name.'" type ="reset" value="'.$this->label.'"/>';
        //    return "<input style=\"{$this->style}\" $mode class='module_app_button___gray {$this->className}' id=\"form[{$this->name}]\" name=\"form[{$this->name}]\" type='reset' value=\"{$this->label}\" " . (($this->onclick) ? 'onclick="' . htmlentities ( $onclick, ENT_COMPAT, 'utf-8' ) . '"' : '') . " />";
        if ($this->mode === 'edit') {
            return "<input style=\"{$this->style}\" $mode class='module_app_button___gray {$this->className}' id=\"form[{$this->name}]\" " . $this->NSFieldType() . " name=\"form[{$this->name}]\" type='reset' value=\"{$this->label}\" " . (($this->onclick) ? 'onclick="' . htmlentities($onclick, ENT_COMPAT, 'utf-8') . '"' : '') . " />";
        } elseif ($this->mode === 'view') {
            return "<input style=\"{$this->style};display:none\" $mode class='module_app_button___gray {$this->className}' id=\"form[{$this->name}]\" " . $this->NSFieldType() . " name=\"form[{$this->name}]\" type='reset' value=\"{$this->label}\" " . (($this->onclick) ? 'onclick="' . htmlentities($onclick, ENT_COMPAT, 'utf-8') . '"' : '') . " />";
        } else {
            return $this->htmlentities($value, ENT_COMPAT, 'utf-8');
        }
    }
}

/**
 * Class XmlFormFieldSubmit
 *
 * @package gulliver.system
 * @access public
 */
class XmlFormFieldSubmit extends XmlFormField
{
    public $onclick = '';

    /**
     * Function render
     *
     * @access public
     * @param string value
     * @return string
     */
    public function render($value = null, $owner = null)
    {
        $onclick = G::replaceDataField($this->onclick, $owner->values);

        if ($this->mode === 'edit') {
            //      if ($this->readOnly)
            //        return '<input id="form['.$this->name.']" name="form['.$this->name.']" type=\'submit\' value=\''. $this->label .'\' disabled/>';
            return "<input style=\"{$this->style}\" class='module_app_button___gray {$this->className}' id=\"form[{$this->name}]\" " . $this->NSFieldType() . " name=\"form[{$this->name}]\" type='submit' value=\"{$this->label}\" " . (($this->onclick) ? 'onclick="' . htmlentities($onclick, ENT_COMPAT, 'utf-8') . '"' : '') . " />";
        } elseif ($this->mode === 'view') {
            //return "<input style=\"{$this->style};display:none\" disabled='disabled' class='module_app_button___gray module_app_buttonDisabled___gray {$this->className}' id=\"form[{$this->name}]\" name=\"form[{$this->name}]\" type='submit' value=\"{$this->label}\" " . (($this->onclick) ? 'onclick="' . htmlentities ( $onclick, ENT_COMPAT, 'utf-8' ) . '"' : '') . " />";
            //$sLinkNextStep = 'window.open("' . $owner->fields['__DYNAFORM_OPTIONS']->xmlMenu->values['NEXT_STEP'] . '", "_self");';
            $html = '';
            if (isset($_SESSION['CURRENT_DYN_UID'])) {
                $sLinkNextStep = 'window.location=("casesSaveDataView?UID=' . $_SESSION['CURRENT_DYN_UID'] . '");';
                $html = '<input style="' . $this->style . '" class="module_app_button___gray ' . $this->className . '" id="form[' . $this->name . ']" ' . $this->NSFieldType() . ' name="form[' . $this->name . ']" type="button" value="' . G::LoadTranslation('ID_CONTINUE') . '"  onclick="' . htmlentities($sLinkNextStep, ENT_COMPAT, 'utf-8') . '" />';
            }
            return $html;
        } else {
            return $this->htmlentities($value, ENT_COMPAT, 'utf-8');
        }
    }
}

/**
 * Class XmlFormFieldHidden
 *
 * @package gulliver.system
 * @access public
 */
class XmlFormFieldHidden extends XmlFormField
{
    public $sqlConnection = 0;
    public $sql = '';
    public $sqlOption = [];
    public $dependentFields = '';
    public $gridFieldType = 'hidden';

    /**
     * Function render
     *
     * @access public
     * @param string value
     * @param string owner
     * @return string
     */
    public function render($value = null, $owner = null)
    {
        if (($this->pmconnection != '') && ($this->pmfield != '') && $value == null) {
            $value = $this->getPMTableValue($owner);
        } else {
            $this->executeSQL($owner);

            if (isset($this->sqlOption)) {
                reset($this->sqlOption);
                $firstElement = key($this->sqlOption);
                if (isset($firstElement)) {
                    $value = $firstElement;
                }
            }
        }
        //$html .= 'value="' . $this->htmlentities( $value, ENT_QUOTES, 'utf-8' ) . '" ';
        if ($this->mode === 'edit') {
            return '<input id="form[' . $this->name . ']" ' . $this->NSFieldType() . ' name="form[' . $this->name . ']" type=\'hidden\' value=\'' . $this->htmlentities($value, ENT_QUOTES, 'utf-8') . '\'/>';
        } elseif ($this->mode === 'view') {
            //a button? who wants a hidden field be showed like a button?? very strange.
            return '<input id="form[' . $this->name . ']" ' . $this->NSFieldType() . ' name="form[' . $this->name . ']" type=\'text\' value=\'' . $this->htmlentities($value, ENT_QUOTES, 'utf-8') . '\' style="display:none"/>';
        } else {
            return $this->htmlentities($value, ENT_COMPAT, 'utf-8');
        }
    }

    /**
     * Render the field in a grid
     *
     * @param $value
     * @param $owner
     * @return <Array> result
     */
    public function renderGrid($values = null, $owner = null, $paramDummy3 = null, $paramDummy4 = null)
    {
        $result = [];
        $r = 1;
        foreach ($values as $v) {
            $result[] = '<input type="hidden" ' . $this->NSGridType() . ' value="' . $this->htmlentities($v, ENT_COMPAT, 'utf-8') . '" id="form[' . $owner->name . '][' . $r . '][' . $this->name . ']" name="form[' . $owner->name . '][' . $r . '][' . $this->name . ']" />';
            $r++;
        }

        return $result;
    }

    /**
     * Render the field in a table
     *
     * @param $value
     * @param $owner
     * @return <Array> result
     */
    public function renderTable($value = "", $owner = null, $paramDummy3 = null)
    {
        return '<input id="form[' . $this->name . ']"  name="form[' . $this->name . ']" type=\'hidden\' value=\'' . $value . '\'/>';
    }
}

/**
 * Class XmlFormFieldDropdown
 *
 * @package gulliver.system
 * @access public
 */
class XmlFormFieldDropdown extends XmlFormField
{
    public $defaultValue = '';
    public $required = false;
    public $dependentFields = '';
    public $readonly = false;
    public $optgroup = 0;
    public $option = [];
    public $sqlConnection = 0;
    public $sql = '';
    public $sqlOption = [];
    public $saveLabel = 0;
    public $modeGridDrop = '';
    public $renderMode = '';
    public $selectedValue = '';

    public function validateValue($value)
    {
        return true;
    }

    /**
     * Function render
     *
     * @access public
     * @param string value
     * @param string owner
     * @return string
     */
    public function render($value = null, $owner = null, $rowId = '', $onlyValue = false, $row = -1, $therow = -1)
    {
        $displayStyle = '';

        //Returns value from a PMTable when it is exists.
        if (($this->pmconnection != '') && ($this->pmfield != '') && $value == null) {
            $value = $this->getPMTableValue($owner);
        }
        //Recalculate SQL options if $therow is not defined or the row id equal
        if ($therow == -1) {
            //echo 'Entro:'.$this->dependentFields;
            $this->executeSQL($owner, $row);
        } else {
            if ($row == $therow) {
                $this->executeSQL($owner, $row);
            }
        }

        $html = '';
        $displayLabel = '';

        if ($this->renderMode == '') {
            $this->renderMode = $this->mode;
        }

        if (!$onlyValue) {
            //Render Field if not defined onlyValue
            if ($this->renderMode != 'edit') {
                //EDIT MODE
                $displayStyle = 'display:none;';
            }
            $readOnlyField = ($this->readonly == 1 || $this->readonly == '1') ? 'disabled' : '';
            $html = '<select ' . $readOnlyField . ' class="module_app_input___gray" ';
            $html .= 'id="form' . $rowId . '[' . $this->name . ']" ';
            $html .= 'name="form' . $rowId . '[' . $this->name . ']" ';
            if ($this->style) {
                $html .= 'style="' . $displayStyle . $this->style . '" ';
            }
            if ($displayStyle != '') {
                $html .= 'style="' . $displayStyle . '" ';
            }
            $html .= $this->NSRequiredValue() . ' ';
            $html .= $this->NSDefaultValue() . ' ';
            $html .= $this->NSGridLabel() . ' ';
            $html .= $rowId == '' ? $this->NSFieldType() : $this->NSGridType() . ' ';
            $html .= $this->NSDependentFields(true) . ' ';
            $html = $html . (($this->optgroup == 1) ? "pm:optgroup=\"1\" " : null);
            $html = $html . ">";

            $findValue = '';
            $firstValue = '';
            $count = 0;
            $swOption = 0;

            $htmlOptGroup = null;
            $swOptGroupPrev = 0;
            $swAppend = 0;

            foreach ($this->option as $optValue => $optName) {
                settype($optValue, "string");

                if ($this->optgroup == 1 && preg_match("/^optgroup\d+$/", $optValue)) {
                    if ($swOptGroupPrev == 1 && $swAppend == 1) {
                        $html = $html . "</optgroup>";
                    }

                    $htmlOptGroup = "<optgroup label=\"$optName\">";
                    $swOptGroupPrev = 1;
                    $swAppend = 0;
                } else {
                    $html = $html . $htmlOptGroup . "<option value=\"$optValue\"" . (($optValue == $value) ? " selected=\"selected\"" : null) . ">$optName</option>";
                    $htmlOptGroup = null;
                    $swAppend = 1;

                    if ($optValue === $value) {
                        $findValue = $optValue;
                        $displayLabel = $optName;
                    }

                    if ($firstValue == "") {
                        $firstValue = $optValue;
                    }

                    $count = $count + 1;
                    $swOption = 1;
                }
            }

            foreach ($this->sqlOption as $optValue => $optName) {
                settype($optValue, "string");

                if ($this->optgroup == 1 && preg_match("/^optgroup\d+$/", $optValue)) {
                    if ($swOptGroupPrev == 1 && $swAppend == 1) {
                        $html = $html . "</optgroup>";
                    }

                    $htmlOptGroup = "<optgroup label=\"$optName\">";
                    $swOptGroupPrev = 1;
                    $swAppend = 0;
                } else {
                    $html = $html . $htmlOptGroup . "<option value=\"$optValue\"" . (($optValue == $value) ? " selected=\"selected\"" : null) . ">$optName</option>";
                    $htmlOptGroup = null;
                    $swAppend = 1;

                    if ($optValue === $value) {
                        $findValue = $optValue;
                        $displayLabel = $optName;
                    }

                    if ($firstValue == "") {
                        $firstValue = $optValue;
                    }

                    $swOption = 1;
                }
            }

            if ($swOption == 1) {
                if ($swOptGroupPrev == 1 && $swAppend == 1) {
                    $html = $html . "</optgroup>";
                }
            } else {
                $html = $html . "<option value=\"\"></option>";
            }

            if ($value !== $findValue && $this->renderMode == 'view') {
                $html .= "<option value=\"$value\" selected=\"selected\">$value</option>";
            }

            $html .= '</select>';
            if ($readOnlyField != '') {
                $html .= '<input type="hidden" ';
                $html .= 'id="form' . $rowId . '[' . $this->name . ']" ';
                $html .= 'name="form' . $rowId . '[' . $this->name . ']" ';
                $html .= 'value="' . (($findValue != '') ? $findValue : $firstValue) . '" />';
            }

            $this->selectedValue = (!empty($findValue) ? $findValue : ($count == 0)) ? $firstValue : "";
        } else {
            //Render Field showing only value;
            foreach ($this->option as $optValue => $optName) {
                if ($optValue == $value) {
                    $html = $optName;
                }
            }
            foreach ($this->sqlOption as $optValue => $optName) {
                if ($optValue == $value) {
                    $html = $optName;
                }
            }
        }

        if ($this->gridFieldType == '') {
            $html .= $this->renderHint();
        }
        if ($displayStyle != '') {
            if ($value === $findValue) {
                $html = $displayLabel . $html;
            } else {
                $html = $value . $html;
            }
        }
        return $html;
    }

    /**
     * Function renderGrid
     *
     * @access public
     * @param string values
     * @return string
     */
    public function renderGrid($values = array(), $owner = null, $onlyValue = false, $therow = -1)
    {
        $this->gridFieldType = 'dropdown';
        $result = [];
        $r = 1;
        if ($owner->mode != 'view') {
            $this->renderMode = $this->modeForGrid;
        }

        foreach ($values as $v) {
            $result[] = $this->render($v, $owner, '[' . $owner->name . '][' . $r . ']', $onlyValue, $r, $therow);
            $r++;
        }
        return $result;
    }
}

/**
 * Class XmlFormFieldListbox
 *
 * @package gulliver.system
 * @access public
 */
class XmlFormFieldListbox extends XmlFormField
{
    public $defaultValue = '';
    public $required = false;
    public $option = [];
    public $sqlConnection = 0;
    public $size = 4;
    public $width = '';
    public $sql = '';
    public $sqlOption = [];

    /**
     * Function render
     *
     * @access public
     * @param string value
     * @param string owner
     * @return string
     */
    public function render($value = null, $owner = null)
    {
        if (($this->pmconnection != '') && ($this->pmfield != '') && $value == null) {
            $value = $this->getPMTableValue($owner);
        }
        $this->executeSQL($owner);
        if (!is_array($value)) {
            $value = explode('|', $value);
        }

        $arrayAux = [];

        foreach ($value as $index2 => $value2) {
            if (!is_array($value2)) {
                $arrayAux[] = $value2 . "";
            } else {
                $arrayAux[] = "";
            }
        }

        $value = $arrayAux;

        if ($this->mode === 'edit') {
            $itemWidth = '';
            if ($this->width != '') {
                $itemWidth = 'style="width:' . $this->width . '"';
            }
            $html = '<select multiple="multiple" id="form[' . $this->name . ']" ' . $this->NSFieldType() . ' name="form[' . $this->name . '][]" size="' . $this->size . '" ' . $itemWidth . '  ' . $this->NSFieldType() . '>';
            foreach ($this->option as $optionName => $option) {
                $html .= "<option value=\"" . $optionName . "\" " . ((in_array($optionName . "", $value)) ? "selected=\"selected\"" : "") . ">" . $option . "</option>";
            }
            foreach ($this->sqlOption as $optionName => $option) {
                $html .= "<option value=\"" . $optionName . "\" " . ((in_array($optionName . "", $value)) ? "selected=\"selected\"" : "") . ">" . $option . "</option>";
            }
            $html .= '</select>';

            $html .= $this->renderHint();
            return $html;
        } elseif ($this->mode === 'view') {
            $valuesFound = array('__NULL__');
            $html = '<select id="form[' . $this->name . ']" ' . $this->NSFieldType() . ' multiple="multiple" size="' . $this->size . '" style="background: none;" disabled="disabled">';
            foreach ($this->option as $optionName => $option) {
                if (in_array($optionName . "", $value)) {
                    $valuesFound[] = $optionName . "";
                }
                $html .= "<option value=\"" . $optionName . "\" " . ((in_array($optionName . "", $value)) ? "class=\"module_ListBoxView\" selected=\"selected\"" : "") . ">" . $option . "</option>";
            }
            foreach ($this->sqlOption as $optionName => $option) {
                if (in_array($optionName . "", $value)) {
                    $valuesFound[] = $optionName . "";
                }
                $html .= "<option value=\"" . $optionName . "\" " . ((in_array($optionName . "", $value)) ? "class=\"module_ListBoxView\" selected=\"selected\"" : "") . ">" . $option . "</option>";
            }
            if (count($valuesFound) - 1 < count($value)) {
                $valuesNotFound = array_diff($value, $valuesFound);
                foreach ($valuesNotFound as $option) {
                    $html .= "<option value=\"" . $option . "\" class=\"module_ListBoxView\" selected=\"selected\">" . $option . "</option>";
                }
            }
            $html .= '</select>';
            foreach ($this->option as $optionName => $option) {
                $html .= "<input type=\"hidden\" id=\"form[" . $this->name . "][" . $optionName . "]\" name=\"form[" . $this->name . "][]\" " . $this->NSFieldType() . " value=\"" . ((in_array($optionName . "", $value)) ? $optionName : "__NULL__") . "\">";
            }
            foreach ($this->sqlOption as $optionName => $option) {
                $html .= "<input type=\"hidden\" id=\"form[" . $this->name . "][" . $optionName . "]\" name=\"form[" . $this->name . "][]\" " . $this->NSFieldType() . " value=\"" . ((in_array($optionName . "", $value)) ? $optionName : "__NULL__") . "\">";
            }
            if (count($valuesFound) - 1 < count($value)) {
                $valuesNotFound = array_diff($value, $valuesFound);
                foreach ($valuesNotFound as $option) {
                    $html .= "<input type=\"hidden\" id=\"form[" . $this->name . "][" . $option . "]\" name=\"form[" . $this->name . "][]\" " . $this->NSFieldType() . " value=\"" . $option . "\">";
                }
            }
            return $html;
        } else {
            return $this->htmlentities($value, ENT_COMPAT, 'utf-8');
        }
    }

    /**
     * Render the field in a grid
     *
     * @param $value
     * @param $owner
     * @return <Array> result
     */
    public function renderGrid($value = null, $owner = null, $paramDummy3 = null, $paramDummy4 = null)
    {
        return $this->render($value, $owner);
    }
}

/**
 * Class XmlFormFieldRadioGroup
 *
 * @package gulliver.system
 * @access public
 */
class XmlFormFieldRadioGroup extends XmlFormField
{
    public $defaultValue = '';
    public $required = false;
    public $option = [];
    public $sqlConnection = 0;
    public $sql = '';
    public $sqlOption = [];
    public $viewAlign = 'vertical';
    public $linkType;

    /**
     * Function render
     *
     * @access public
     * @param string value
     * @param string owner
     * @return string
     */
    public function render($value = null, $owner = null)
    {
        if (($this->pmconnection != '') && ($this->pmfield != '') && $value == null) {
            $value = $this->getPMTableValue($owner);
        }
        $this->executeSQL($owner);
        if ($this->mode === 'edit') {
            $html = '';
            $i = 0;
            foreach ($this->options as $optionName => $option) {
                if (isset($this->linkType) && ($this->linkType == 1 || $this->linkType == "1")) {
                    $html .= '<input id="form[' . $this->name . '][' . $optionName . ']" ' . $this->NSFieldType() . ' name="form[' . $this->name . ']" type="radio" value="' . $optionName . '" ' . (($optionName == $value) ? ' checked' : '') . '><a href="#" onclick="executeEvent(\'form[' . $this->name . '][' . $optionName . ']\', \'click\'); return false;">' . $option . '</a></input>';
                } else {
                    $html .= '<input id="form[' . $this->name . '][' . $optionName . ']" ' . $this->NSFieldType() . ' name="form[' . $this->name . ']" type="radio" value="' . $optionName . '" ' . (($optionName == $value) ? ' checked' : '') . '><label for="form[' . $this->name . '][' . $optionName . ']">' . $option . '</label></input>';
                }
                if (++$i == count($this->options)) {
                    $html .= '&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;' . $this->renderHint();
                }

                if ($this->viewAlign == 'horizontal') {
                    $html .= '&nbsp;';
                } else {
                    $html .= '<br>';
                }
            }
            return $html;
        } elseif ($this->mode === 'view') {
            $html = '';
            $existsValue = false;
            foreach ($this->options as $optionName => $option) {
                $html .= '<input class="module_app_input___gray" id="form[' . $this->name . '][' . $optionName . ']" ' . $this->NSFieldType() . ' name="form[' . $this->name . ']" type=\'radio\' value="' . $optionName . '" ' . (($optionName == $value) ? 'checked' : '') . ' disabled><span class="FormCheck"><label for="form[' . $this->name . '][' . $optionName . ']">' . $option . '</label></span></input><br>';
                if ($optionName == $value) {
                    $existsValue = true;
                    $html .= '<input type="hidden"  id="form[' . $this->name . '][' . $optionName . ']" name="form[' . $this->name . ']" value="' . (($optionName == $value) ? $optionName : '') . '">';
                }
            }
            if (!$existsValue && $value !== '') {
                $html .= '<input class="module_app_input___gray" id="form[' . $this->name . '][' . $value . ']" ' . $this->NSFieldType() . ' name="form[' . $this->name . ']" type=\'radio\' value="' . $value . '" checked disabled><span class="FormCheck"><label for="form[' . $this->name . '][' . $value . ']">' . $value . '</label></span></input><br>';
                $html .= '<input type="hidden"  id="form[' . $this->name . '][' . $value . ']" name="form[' . $this->name . ']" value="' . $value . '">';
            }
            return $html;
        } else {
            return $this->htmlentities($value, ENT_COMPAT, 'utf-8');
        }
    }
}

/*DEPRECATED*/

/**
 *
 * @package gulliver.system
 *
 */
class XmlFormFieldRadioGroupView extends XmlFormField
{
    public $defaultValue = '';
    public $required = false;
    public $option = [];
    public $sqlConnection = 0;
    public $sql = '';
    public $sqlOption = [];

    /**
     * Function render
     *
     * @access public
     * @param string value
     * @param string owner
     * @return string
     */
    public function render($value = null, $owner = null)
    {
        $this->executeSQL($owner);
        $html = '';
        foreach ($this->option as $optionName => $option) {
            $html .= '<input type=\'radio\'`disabled/><span class="FormCheck">' . $option . '</span><br>';
        }
        return $html;
    }
}

/**
 * Class XmlFormFieldCheckGroup
 *
 * @package gulliver.system
 * @access public
 */
class XmlFormFieldCheckGroup extends XmlFormField
{
    public $required = false;
    public $option = [];
    public $sqlConnection = 0;
    public $sql = '';
    public $sqlOption = [];
    /*function validateValue( $value , $owner )
    {
    	$this->executeSQL( $owner );
    	return isset($value) && ( array_key_exists( $value , $this->options ) );
    }*/
    /**
     * Function render
     *
     * @access public
     * @param string value
     * @param string owner
     * @return string
     */
    public function render($value = null, $owner = null)
    {
        if (($this->pmconnection != '') && ($this->pmfield != '') && $value == null) {
            $value = $this->getPMTableValue($owner);
        }
        $this->executeSQL($owner);
        if (!is_array($value)) {
            $value = explode('|', $value);
        }

        $arrayAux = [];

        foreach ($value as $index2 => $value2) {
            $arrayAux[] = $value2 . "";
        }

        $value = $arrayAux;

        if ($this->mode === 'edit') {
            $i = 0;
            $html = '';
            foreach ($this->options as $optionName => $option) {
                $html .= "<input type=\"checkbox\" id=\"form[" . $this->name . "][" . $optionName . "]\" " . $this->NSFieldType() . " name=\"form[" . $this->name . "][]\"  value=\"" . $optionName . "\"" . (in_array($optionName . "", $value) ? "checked = \"checked\" " : "") . "><span class=\"FormCheck\"><label for=\"form[" . $this->name . "][" . $optionName . "]\">" . $option . "</label></span></input>";

                if (++$i == count($this->options)) {
                    $html .= '&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;' . $this->renderHint();
                }
                $html .= '<br>';
            } //fin for
            return $html;
        } elseif ($this->mode === 'view') {
            $valuesFound = array('__NULL__');
            $html = '';
            foreach ($this->options as $optionName => $option) {
                if (in_array($optionName . "", $value)) {
                    $valuesFound[] = $optionName . "";
                }
                $html .= "<input " . $this->NSFieldType() . "class=\"FormCheck\" type=\"checkbox\" id=\"form[" . $this->name . "][" . $optionName . "]\" value=\"" . $optionName . "\"" . (in_array($optionName . "", $value) ? " checked=\"checked\" " : "") . " disabled=\"disabled\"><span class=\"FormCheck\"><label for=\"form[" . $this->name . "][" . $optionName . "]\">" . $option . "</label></span></input><br />";
                $html .= "<input type=\"hidden\" name=\"form[" . $this->name . "][]\"  value=\"" . ((in_array($optionName . "", $value)) ? $optionName : "__NULL__") . "\">";
            }
            if (count($valuesFound) - 1 < count($value)) {
                $valuesNotFound = array_diff($value, $valuesFound);
                foreach ($valuesNotFound as $option) {
                    $html .= "<input " . $this->NSFieldType() . "class=\"FormCheck\" type=\"checkbox\" id=\"form[" . $this->name . "][" . $option . "]\" value=\"" . $option . "\" checked=\"checked\" disabled=\"disabled\"><span class=\"FormCheck\"><label for=\"form[" . $this->name . "][" . $option . "]\">" . $option . "</label></span></input><br />";
                    $html .= "<input type=\"hidden\" name=\"form[" . $this->name . "][]\"  value=\"" . $option . "\">";
                }
            }
            return $html;
        } else {
            return $this->htmlentities($value, ENT_COMPAT, 'utf-8');
        }
    }

    /**
     * Renderring the checkgroup inner grid for Staff Eval Plugin
     * @see class.form.php#validate[];
     * @author Edauto
     * @since  2012-07-20
     */
    public function renderGrid($values = null, $owner = null, $onlyValue = false, $therow = -1)
    {
        $this->executeSQL($owner);
        $disable = ($owner->mode === 'view') ? 'disabled="disabled" ' : ' ';
        $r = 1;
        $result = [];
        foreach ($values as $v) { // foreach the grid row with selection
            $i = 1;
            $html = '';
            if (!is_array($v)) {
                $aV = explode('|', str_replace(" ", "", $v));
            } else {
                $aV = $v;
            }
            foreach ($this->options as $optionName => $option) { // foreach the options of checkbox group
                $bChecked = in_array($i, $aV, true) || in_array($optionName, $aV, true);
                $html .= '<input id="form[' . $owner->name . '][' . $r . '][' . $this->name . '][' . $optionName . ']" ';
                $html .= 'name="form[' . $owner->name . '][' . $r . '][' . $this->name . '][]" ';
                $html .= 'type="checkbox" value="' . $optionName . '" ' . ($bChecked ? 'checked ' : ' ');
                $html .= $disable . '><span class="FormCheck">' . $option . '</span></input>';
                if (++$i == count($this->options)) {
                    $html .= ' ' . $this->renderHint();
                }
                $html .= '<br />';
            }
            $result[] = $html;
            $r++;
        }
        return $result;
    }
}

/* TODO: DEPRECATED */

/**
 *
 * @package gulliver.system
 *
 */
class XmlFormFieldCheckGroupView extends XmlFormField
{
    public $option = [];
    public $sqlConnection = 0;
    public $sql = '';
    public $sqlOption = [];

    /**
     * Function render
     *
     * @access public
     * @param string value
     * @return string
     */
    public function render($value = null, $paramDummy2 = null)
    {
        $html = '';
        foreach ($this->option as $optionName => $option) {
            $html .= '<input type=\'checkbox\' disabled/><span class="FormCheck">' . $option . '</span><br>';
        }
        return $html;
    }
}

/**
 * Class XmlFormFieldGrid
 *
 * @package gulliver.system
 * @access public
 */
class XmlFormFieldGrid extends XmlFormField
{
    public $xmlGrid = '';
    public $initRows = 1;
    public $group = 0;
    public $addRow = "1";
    public $deleteRow = "1";
    public $editRow = "0";
    public $sql = '';
    //TODO: 0=doesn't excecute the query, 1=Only the first time, 2=Allways
    public $fillType = 0;
    public $fields = [];
    public $scriptURL;
    public $id = '';

    /**
     * Function XmlFormFieldGrid
     *
     * @access public
     * @param string xmlnode
     * @param string language
     * @param string home
     * @return string
     */
    public function __construct($xmlnode, $language, $home)
    {
        parent::__construct($xmlnode, $language);
        $this->parseFile($home, $language);
    }

    /**
     * Function parseFile
     *
     * @access public
     * @param string home
     * @param string language
     * @return string
     */
    public function parseFile($home, $language)
    {
        if (file_exists($home . $this->xmlGrid . '.xml')) {
            $this->xmlform = new XmlForm();
            $this->xmlform->home = $home;
            $this->xmlform->parseFile($this->xmlGrid . '.xml', $language, false);
            $this->fields = $this->xmlform->fields;
            $this->scriptURL = $this->xmlform->scriptURL;
            $this->id = $this->xmlform->id;
            $this->modeGrid = $this->xmlform->mode;
            unset($this->xmlform);
        }
    }

    /**
     * Render the field in a dynaform
     *
     * @param $value
     * @param $owner
     * @return <Template Object>
     */

    public function render($values = null, $owner = null)
    {
        $emptyRow = $this->setScrollStyle($owner);
        return $this->renderGrid($emptyRow, $owner);
    }

    /**
     * Function renderGrid
     *
     * @access public
     * @param string values
     * @return string
     */
    public function renderGrid($values = array(), $owner = null, $therow = -1, $paramDummy4 = null)
    {
        $this->id = $this->owner->id . $this->name;
        $using_template = 'grid';

        if (isset($this->mode)) {
            $ownerMode = $this->mode;
        } else {
            $ownerMode = '';
        }

        if ($ownerMode != '') {
            $this->mode = $ownerMode;
        }

        if ($this->mode == '') {
            $this->mode = 'edit';
        }

        $this->modeForGrid = $this->mode;

        if ($this->mode == 'view') {
            $using_template = 'grid_view';
        }

        $tpl = new xmlformTemplate($this, PATH_CORE . "templates" . PATH_SEP . "$using_template.html");

        if (!isset($values) || !is_array($values) || sizeof($values) == 0) {
            $values = array_keys($this->fields);
        }

        if ($therow != -1) {
            //Check if values arrary is complete to can flip.
            $xValues = [];
            if (isset($values[$therow])) {
                $aRow = $values[$therow];
            } else {
                $aRow = [];
            }
            for ($c = 1; $c <= $therow; $c++) {
                if ($c == $therow) {
                    $xValues[$therow] = $aRow;
                } else {
                    if (is_array($aRow)) {
                        foreach ($aRow as $key => $value) {
                            $xValues[$c][$key] = "";
                        }
                    } else {
                        //
                    }
                }
            }
            $values = $xValues;
        }

        $aValuekeys = array_keys($values);

        if (count($aValuekeys) > 0 && (int)$aValuekeys[0] == 1) {
            $values = $this->flipValues($values);
        }

        //if ($therow == 1)g::pr($values);
        $this->rows = count(reset($values));

        //Fields required in grid (view in sql attribute)
        $arrayField = [];
        $arrayFieldRequired = [];

        foreach ($this->fields as $index1 => $value1) {
            $field = $value1;

            $arrayField[] = $field->name;
            $arrayFieldRequired[] = "SYS_GRID_AGGREGATE_" . $this->name . "_" . $field->name;

            preg_match_all("/@[@%#\?\$\=]([A-Za-z_]\w*)/", $field->sql, $arrayMatch, PREG_SET_ORDER);

            foreach ($arrayMatch as $value2) {
                $arrayFieldRequired[] = $value2[1];
            }
        }

        $arrayFieldRequired = array_unique($arrayFieldRequired);
        $arrayFieldRequired = array_diff($arrayFieldRequired, $arrayField);

        //Fields Grid only required fields of the grid, no all fields of dynaform main
        if (isset($owner->values) && count($arrayFieldRequired) > 0) {
            foreach ($owner->values as $key => $value) {
                if (in_array($key, $arrayFieldRequired) && !isset($values[$key])) {
                    $values[$key] = [];
                    //for($r=0; $r < $this->rows ; $r++ ) {
                    $values[$key] = $value;
                    //}
                }
            }
        }

        foreach ($this->fields as $k => $v) {
            if (isset($values['SYS_GRID_AGGREGATE_' . $this->name . '_' . $k])) {
                $this->fields[$k]->aggregate = $values['SYS_GRID_AGGREGATE_' . $this->name . '_' . $k];
            } else {
                $this->fields[$k]->aggregate = '0';
            }
        }

        $this->values = $values;

        $this->NewLabel = G::LoadTranslation('ID_NEW');
        $this->DeleteLabel = G::LoadTranslation('ID_DELETE');

        $tpl->template = $tpl->printTemplate($this);
        //In the header
        $oHeadPublisher = headPublisher::getSingleton();
        $oHeadPublisher->addScriptFile($this->scriptURL);
        $oHeadPublisher->addScriptCode($tpl->printJavaScript($this));
        return $tpl->printObject($this, $therow);
    }

    /**
     * Change the columns for rows and rows to columns
     *
     * @param <array> $arrayData
     * @return <array>
     */
    public function flipValues($arrayData)
    {
        $flipped = [];

        foreach ($arrayData as $rowIndex => $rowValue) {
            if (is_array($rowValue)) {
                foreach ($rowValue as $colIndex => $colValue) {
                    if (!isset($flipped[$colIndex]) || !is_array($flipped[$colIndex])) {
                        $flipped[$colIndex] = [];
                    }

                    $flipped[$colIndex][$rowIndex] = $colValue;
                }
            }
        }

        return $flipped;
    }

    public function setScrollStyle($owner)
    {
        $arrayKeys = array_keys($this->fields);
        $emptyRow = [];
        $fieldsSize = 0;
        foreach ($arrayKeys as $key) {
            if (isset($this->fields[$key]->defaultValue)) {
                $emptyValue = $this->fields[$key]->defaultValue;
            } else {
                $emptyValue = '';
            }
            if (isset($this->fields[$key]->size)) {
                $size = $this->fields[$key]->size;
            }
            if (!isset($size)) {
                $size = 15;
            }
            $fieldsSize += $size;
            $emptyRow[$key] = array($emptyValue);
        }

        if (isset($owner->adjustgridswidth) && $owner->adjustgridswidth == '1') {
            // 400w -> 34s to Firefox
            // 400w -> 43s to Chrome
            $baseWidth = 400;
            $minusWidth = 30;
            if (preg_match('/chrome/i', $_SERVER['HTTP_USER_AGENT'])) {
                $baseSize = 43;
            } else {
                if (strpos($_SERVER['HTTP_USER_AGENT'], 'MSIE') !== false) {
                    $minusWidth = 20;
                }
                $baseSize = 34;
            }

            $baseWidth = 400;
            $formWidth = (int)$owner->width;
            $maxSize = (($formWidth * $baseSize) / $baseWidth);

            if ($fieldsSize > $maxSize) {
                $this->scrollStyle = 'height:100%; overflow-x: scroll; width:';
                $this->scrollStyle .= $formWidth - $minusWidth . ';';
            }
        }

        return $emptyRow;
    }
}

/**
 * Class XmlFormFieldJavaScript
 *
 * @package gulliver.system
 * @access public
 */
class XmlFormFieldJavaScript extends XmlFormField
{
    public $code = '';
    public $replaceTags = true;

    /**
     * Function XmlFormFieldJavaScript
     *
     * @access public
     * @param string xmlNode
     * @param string lang
     * @param string home
     * @return string
     */
    public function __construct($xmlNode, $lang = 'en', $home = '')
    {
        //Loads any attribute that were defined in the xmlNode
        //except name and label.
        $myAttributes = get_class_vars(get_class($this));
        foreach ($myAttributes as $k => $v) {
            $myAttributes[$k] = strtoupper($k);
        }
        foreach ($xmlNode->attributes as $k => $v) {
            $key = array_search(strtoupper($k), $myAttributes);
            if ($key) {
                eval('$this->' . $key . '=$v;');
            }
        }
        //Loads the main attributes
        $this->name = $xmlNode->name;
        $this->type = strtolower($xmlNode->attributes['type']);
        //$data: Includes labels and options.
        $this->code = $xmlNode->value;
    }

    /**
     * Function render
     *
     * @access public
     * @param string value
     * @return string
     */
    public function render($value = null, $owner = null)
    {
        $code = ($this->replaceTags) ? G::replaceDataField($this->code, $owner->values) : $this->code;
        return $code;
    }

    /**
     * Function renderGrid
     *
     * @access public
     * @param string value
     * @param string owner
     * @return string
     */
    public function renderGrid($values = null, $owner = null, $paramDummy3 = null, $paramDummy4 = null)
    {
        return array('');
    }

    /**
     * A javascript node has no value
     *
     * @param $value
     * @return false
     */
    public function validateValue($value)
    {
        return false;
    }
}

/**
 * Comment Working for after and before date attributes
 *
 * @package gulliver.system
 */
class XmlFormFieldDate extends XmlFormFieldSimpleText
{
    public $required = false;
    public $readOnly = false;

    public $startDate = '';
    public $endDate = '';
    /**
     * for dinamically dates,   beforeDate << currentDate << afterDate
     * beforeDate='1y' means one year before,  beforeDate='3m' means 3 months before
     * afterDate='5y' means five year after,  afterDate='15d' means 15 days after
     * startDate and endDate have priority over beforeDate and AfterDate
     **/
    public $afterDate = '';
    public $beforeDate = '';
    public $defaultValue = null;
    public $format = '%Y-%m-%d';

    public $mask = '%Y-%m-%d';
    public $dependentFields = '';
    public $editable;
    public $onchange;
    public $renderMode = '';
    public $gridFieldType = '';

    /*
    * Verify the format of a date
    * @param <Date> $date
    * @return <Boolean> true/false
    */
    public function verifyDateFormat($date)
    {
        $dateTime = explode(" ", $date); //To accept the Hour part
        $aux = explode('-', $dateTime[0]);
        if (count($aux) != 3) {
            return false;
        }
        if (!(is_numeric($aux[0]) && is_numeric($aux[1]) && is_numeric($aux[2]))) {
            return false;
        }
        if ($aux[0] < 1900 || $aux[0] > 2100) {
            return false;
        }
        return true;
    }

    /**
     * Check if a date had a valid format before
     *
     * @param <Date> $date
     * @return <Boolean> true/false
     */
    public function isvalidBeforeFormat($date)
    {
        $part1 = substr($date, 0, strlen($date) - 1);
        $part2 = substr($date, strlen($date) - 1);
        if ($part2 != 'd' && $part2 != 'm' && $part2 != 'y') {
            return false;
        }
        if (!is_numeric($part1)) {
            return false;
        }
        return true;
    }

    /**
     * Calculations in Date
     *
     * @param <Date> $date
     * @param $sign
     * @return <Date>
     */
    public function calculateBeforeFormat($date, $sign)
    {
        $part1 = $sign * substr($date, 0, strlen($date) - 1);
        $part2 = substr($date, strlen($date) - 1);

        $year = (int)(date("Y"));
        $month = (int)(date("m"));
        $day = (int)(date("d"));

        $osIsLinux = strtoupper(substr(PHP_OS, 0, 3)) != "WIN";
        $checkYear = false;

        switch ($part2) {
            case "y":
                $year = $year + $part1;

                $res = date("Y-m-d", mktime(0, 0, 0, $month, $day, $year));

                $checkYear = true;
                break;
            case "m":
                $month = $month + $part1;

                $res = date("Y-m-d", mktime(0, 0, 0, $month, $day, $year));

                if ($month > 12) {
                    $year = $year + (int)($month / 12);

                    $checkYear = true;
                }
                break;
            case "d":
                $res = date("Y-m-d", mktime(0, 0, 0, $month, $day + $part1, $year));

                $dayAux = ($month * 31) - (31 - $day) + $part1;

                if ($dayAux > 365) {
                    $year = $year + (int)($dayAux / 365);

                    $checkYear = true;
                }
                break;
        }

        if (!$osIsLinux && $checkYear && !preg_match("/^$year\-\d{2}\-\d{2}$/", $res)) {
            $res = preg_replace("/^\d{4}(\-\d{2}\-\d{2})$/", "$year$1", $res);
        }

        return $res;
    }

    /**
     * render the field in a dynaform
     *
     * @param $value
     * @param $owner
     * @return renderized widget
     */
    public function render($value = null, $owner = null)
    {
        $this->renderMode = $this->mode;
        if (($this->pmconnection != '') && ($this->pmfield != '') && $value == null) {
            $value = $this->getPMTableValue($owner);
        } else {
            $value = G::replaceDataField($value, $owner->values);
        }
        //$this->defaultValue = G::replaceDataField( $this->defaultValue, $owner->values);
        $id = "form[$this->name]";

        return $this->draw_widget($id, $value, $owner);
    }

    /**
     * render the field in a grid
     *
     * @param $values
     * @param $owner
     * @param $onlyValue
     * @return Array $result
     */
    public function renderGrid($values = null, $owner = null, $onlyValue = false, $paramDummy4 = null)
    {
        $this->gridFieldType = 'date';
        $result = [];
        $r = 1;
        /*    if( ! isset($owner->modeGrid)) $owner->modeGrid = '';
        $this->mode = $this->modeForGrid;*/
        if ($owner->mode != 'view') {
            $this->renderMode = $this->modeForGrid;
        }
        foreach ($values as $v) {
            $v = G::replaceDataField($v, $owner->values);
            if (!$onlyValue) {
                if ($this->mode === 'view' || (isset($owner->modeGrid) && $owner->modeGrid === 'view')) {
                    if ($this->required) {
                        $isRequired = '1';
                    } else {
                        $isRequired = '0';
                    }
                    $mask = str_replace("%", "", $this->mask);
                    if (trim($v) !== "") {
                        $v = date(masktophp($mask, $v));
                    }
                    $html = '<input ' . $this->NSRequiredValue() . ' class="module_app_input___gray" ' . $this->NSGridType() . ' id="form[' . $owner->name . '][' . $r . '][' . $this->name . ']" name="form[' . $owner->name . '][' . $r . '][' . $this->name . ']" type ="text" size="' . $this->size . '" maxlength="' . $this->maxLength . '" value="' . $this->htmlentities($v, ENT_COMPAT, 'utf-8') . '" pm:required="' . $isRequired . '" style="display:none;' . htmlentities($this->style, ENT_COMPAT, 'utf-8') . '" />' . htmlentities($v, ENT_COMPAT, 'utf-8');
                } else {
                    $id = 'form[' . $owner->name . '][' . $r . '][' . $this->name . ']';
                    $html = $this->draw_widget($id, $v, $owner, true);
                }
            } else {
                $html = $v;
            }
            $result[] = $html;
            $r++;
        }
        return $result;
    }

    /**
     * Returns the html code to draw the widget
     *
     * @param $pID
     * @param $value
     * @param $owner
     * @return <String>
     */
    public function draw_widget($pID, $value, $owner = '', $inGrid = false)
    {
        $startDate = G::replaceDataField($this->startDate, $owner->values);
        $endDate = G::replaceDataField($this->endDate, $owner->values);
        $beforeDate = G::replaceDataField($this->beforeDate, $owner->values);
        $afterDate = G::replaceDataField($this->afterDate, $owner->values);
        $defaultValue = $this->defaultValue;
        if ($startDate != '') {
            if (!$this->verifyDateFormat($startDate)) {
                $startDate = '';
            }
        }

        if (isset($beforeDate) && $beforeDate != '') {
            if ($this->isvalidBeforeFormat($beforeDate)) {
                $startDate = $this->calculateBeforeFormat($beforeDate, 1);
            }
        }

        if ($startDate == '' && isset($this->size) && is_numeric($this->size) && $this->size >= 1900 && $this->size <= 2100) {
            $startDate = $this->size . '-01-01';
        }

        if ($endDate != '') {
            if (!$this->verifyDateFormat($endDate)) {
                $endDate = '';
            }
        }

        if (isset($afterDate) && $afterDate != '') {
            if ($this->isvalidBeforeFormat($afterDate)) {
                $endDate = $this->calculateBeforeFormat($afterDate, +1);
            }
        }

        if (isset($this->maxlength) && is_numeric($this->maxlength) && $this->maxlength >= 1900 && $this->maxlength <= 2100) {
            $endDate = $this->maxlength . '-01-01';
        }

        if ($endDate == '') {
            // the default is the current date + 2 years
            $endDate = date('Y-m-d', mktime(0, 0, 0, date('m'), date('d'), date('Y') + 2));
        }

        //validating the mask, if it is not set,
        if (isset($this->mask) && $this->mask != '') {
            $mask = $this->mask;
        } else {
            $mask = '%Y-%m-%d'; //set default
        }

        $valueDemo = masktophp($mask, "today");

        if ($this->defaultValue != "") {
            $defaultValue = masktophp($mask, $defaultValue);
        }

        if (strpos($mask, '%') === false) {
            if (strpos($mask, '-') !== false) {
                $separator = '-';
            }
            if (strpos($mask, '/') !== false) {
                $separator = '/';
            }
            if (strpos($mask, '.') !== false) {
                $separator = '.';
            }

            $maskparts = explode($separator, $mask);
            $mask = '';
            foreach ($maskparts as $part) {
                if ($mask != '') {
                    $mask .= $separator;
                }
                if ($part == 'yyyy') {
                    $part = 'Y';
                }
                if ($part == 'dd') {
                    $part = 'd';
                }
                if ($part == 'mm') {
                    $part = 'm';
                }
                if ($part == 'yy') {
                    $part = 'y';
                }
                $mask .= '%' . $part;
            }
        }

        $tmp = str_replace("%", "", $mask);
        if (trim($value) == '' or $value == null) {
            $value = ''; //date ($tmp);
        } else {
            if ($value != "") {
                $value = masktophp($mask, $value);
            }
        }

        //onchange
        if (isset($this->onchange) && $this->onchange != '') {
            $onchange = 'onchange="' . $this->onchange . '"';
        } else {
            $onchange = '';
        }

        if ($inGrid) {
            $pmtype = $this->NSGridType();
        } else {
            $pmtype = $this->NSFieldType();
        }

        if ($this->renderMode == 'edit') {
            $maskleng = strlen($mask);
            $hour = '%H';
            $min = '%M';
            $sec = '%S';
            $sizehour = strpos($mask, $hour);
            $sizemin = strpos($mask, $min);
            $sizesec = strpos($mask, $sec);
            $Time = 'false';

            if (($sizehour !== false) && ($sizemin !== false) && ($sizesec !== false)) {
                $Time = "true";
            }

            $sizeend = $this->size;

            if ($this->required) {
                $isRequired = '1';
            } else {
                $isRequired = '0';
            }

            if ($this->editable != "0") {
                $html = '<input ' . $pmtype . ' pm:required="' . $isRequired . '" id="' . $pID . '" name="' . $pID . '" pm:mask="' . $mask . '" pm:start="' . $startDate . '" pm:end="' . $endDate . '" pm:time="' . $Time . '" class="module_app_input___gray" size="' . $sizeend . '" value="' . $value . '" pm:defaultvalue="' . $defaultValue . '" />';
                $html .= '<a onclick="removeValue(\'' . $pID . '\'); return false;" style="position:relative;left:-17px;top:2px;" ><img src="/images/icons_silk/calendar_x_button.png" /></a>';
                $html .= '<a id="' . $pID . '[btn]" style="position: relative; top: 2px; left: -16px;" ><img src="/images/pmdateicon.png" border="0" width="12" height="14" /></a>';
                $html .= '<script>datePicker4("", \'' . $pID . '\', \'' . $mask . '\', \'' . $startDate . '\', \'' . $endDate . '\',' . $Time . ')</script>';
            } else {
                $html = '<input ' . $pmtype . ' pm:required="' . $isRequired . '" id="' . $pID . '" name="' . $pID . '" pm:mask="' . $mask . '" pm:start="' . $startDate . '" pm:end="' . $endDate . '" pm:time="' . $Time . '" ' . $onchange . ' class="module_app_input___gray" size="' . $sizeend . '" value="' . $value . '" pm:defaultvalue="' . $defaultValue . '" readonly="readonly"  />' . '<a onclick="removeValue(\'' . $pID . '\'); return false;" style="position:relative;left:-17px;top:2px;" >' . '  <img src="/images/icons_silk/calendar_x_button.png" />' . '</a>' . '<a id="' . $pID . '[btn]" style="position: relative; top: 2px; left: -16px;" >' . '  <img src="/images/pmdateicon.png" border="0" width="12" height="14" />' . '</a>' . '<script>datePicker4("", \'' . $pID . '\', \'' . $mask . '\', \'' . $startDate . '\', \'' . $endDate . '\',' . $Time . ')</script>';
            }
        } else {
            $html = "<span style='border:1;border-color:#000;width:100px;'>$value</span>" . '<input type="hidden" id="' . $pID . '" name="' . $pID . '" ' . $pmtype . ' pm:mask="' . $mask . '" pm:start="' . $startDate . '"' . 'pm:end="' . $endDate . '"  ' . $onchange . ' class="module_app_input___gray" value="' . $value . '"/>';
        }
        /**
         * * Commented because seems is not working well *
         * $idIsoDate = substr($pID,0,strlen($pID)-1).'_isodate]';
         * $amask = explode('-',str_replace('%','',$mask));
         * $axDate = explode('-',$value);
         * $valisoDate = '';
         *
         * if ( sizeof($amask) == sizeof($axDate) ) {
         * $aisoDate = array_combine($amask, $axDate);
         * if ( isset($aisoDate['Y']) && isset($aisoDate['m']) && isset($aisoDate['d']) )
         * $valisoDate = $aisoDate['Y'].'-'.$aisoDate['m'].'-'.$aisoDate['d'];
         * }
         *
         * $html .= '<input type="hidden" id="'.$idIsoDate.'" name="'.$idIsoDate.'" value="'.$valisoDate.'"/>';
         * *
         */
        if ($this->gridFieldType == '') {
            $html .= $this->renderHint();
        }
        return $html;
    }

    public function maskDateValue($value, $field)
    {
        $value = trim($value);
        $mask = $field->mask;
        if ($value == '' || $mask == '') {
            return $value;
        }
        if (strpos($mask, '%') === false) {
            if (strpos($mask, '-') !== false) {
                $separator = '-';
            }
            if (strpos($mask, '/') !== false) {
                $separator = '/';
            }
            if (strpos($mask, '.') !== false) {
                $separator = '.';
            }

            $maskparts = explode($separator, $mask);
            $mask = '';
            foreach ($maskparts as $part) {
                if ($mask != '') {
                    $mask .= $separator;
                }
                if ($part == 'yyyy') {
                    $part = 'Y';
                }
                if ($part == 'dd') {
                    $part = 'd';
                }
                if ($part == 'mm') {
                    $part = 'm';
                }
                if ($part == 'yy') {
                    $part = 'y';
                }
                $mask .= '%' . $part;
            }
        }

        $withHours = (strpos($mask, '%H') !== false || strpos($mask, '%I') !== false || strpos($mask, '%k') !== false || strpos($mask, '%l') !== false || strpos($mask, '%M') !== false || strpos($mask, '%S') !== false);

        $tmp = str_replace("%", "", $mask);
        return $this->date_create_from_format($tmp, $value, $withHours);
    }

    /*
      //Year
      %Y year with the century
      %y year without the century (range 00 to 99)
      //Month
      %m month, range 01 to 12
      %B full month name
      %b abbreviated month name
      //Day
      %d the day of the month (range 01 to 31)
      %e the day of the month (range 1 to 31)
      //Hour
      %H hour, range 00 to 23 (24h format)
      %I hour, range 01 to 12 (12h format)
      %k hour, range 0 to 23 (24h format)
      %l hour, range 1 to 12 (12h format)
      //Min
      %M minute, range 00 to 59
      //Sec
      %S seconds, range 00 to 59
    */
    public function date_create_from_format($dformat, $dvalue, $withHours = false)
    {
        $schedule = $dvalue;
        $schedule_format = str_replace(array('Y', 'y', 'm', 'B', 'b', 'd', 'e', 'H', 'I', 'k', 'l', 'M', 'S'), array('%Y', '%y', '%m', '%B', '%b', '%d', '%e', '%H', '%I', '%k', '%l', '%M', '%S'), $dformat);
        $ugly = strptime($schedule, $schedule_format);
        $ymd = sprintf(
            '%04d-%02d-%02d %02d:%02d:%02d',
            $ugly['tm_year'] + 1900,
            $ugly['tm_mon'] + 1,
            $ugly['tm_mday'],
            $ugly['tm_hour'],
            $ugly['tm_min'],
            $ugly['tm_sec']
        );
        try {
            $new_schedule = new DateTime($ymd);
        } catch (Exception $error) {
            $new_schedule = new DateTime();
        }
        return $new_schedule->format('Y-m-d' . ($withHours ? ' H:i:s' : ''));
    }
}

/**
 * Calendar Widget with Javascript Routines
 *
 * @package gulliver.system
 */
class XmlFormFieldDate5 extends XmlFormFieldSimpleText
{
    public $required = false;
    public $readOnly = false;

    public $startDate = '';
    public $endDate = '';
    /*
    * for dinamically dates,   beforeDate << currentDate << afterDate
    * beforeDate='1y' means one year before,  beforeDate='3m' means 3 months before
    * afterDate='5y' means five year after,  afterDate='15d' means 15 days after
    * startDate and endDate have priority over beforeDate and AfterDate
    */
    public $afterDate = '';
    public $beforeDate = '';
    public $defaultValue = null;
    public $format = 'Y-m-d';

    public $mask = 'Y-m-d';
    public $dependentFields = '';

    public $showtime;
    public $onchange;
    public $editable;
    public $relativeDates;

    //var $hint;


    /**
     * Verify the format of a date
     *
     * @param <Date> $date
     * @return <Boolean> true/false
     */
    public function verifyDateFormat($date, $mask = '')
    {
        $dateTime = explode(" ", $date); //To accept the Hour part
        $aDate = explode('-', str_replace("/", "-", $dateTime[0]));
        $bResult = true;

        foreach ($aDate as $sDate) {
            if (!is_numeric($sDate)) {
                $bResult = false;
                break;
            }
        }

        if ($mask != '') {
            $aDate = $this->getSplitDate($dateTime[0], $mask);
            $aDate[0] = ($aDate[0] == '') ? date('Y') : $aDate[0];
            $aDate[1] = ($aDate[1] == '') ? date('m') : $aDate[1];
            $aDate[2] = ($aDate[2] == '') ? date('d') : $aDate[2];

            return true;
            if (checkdate($aDate[1], $aDate[2], $aDate[0])) {
            } else {
                return false;
            }
        }
        return true;
    }

    /**
     * Check if a date had a valid format before
     *
     * @param <Date> $date
     * @return <Boolean> true/false
     */
    public function isvalidBeforeFormat($date)
    {
        $part1 = substr($date, 0, strlen($date) - 1);
        $part2 = substr($date, strlen($date) - 1);
        if ($part2 != 'd' && $part2 != 'm' && $part2 != 'y') {
            return false;
        }
        if (!is_numeric($part1)) {
            return false;
        }
        return true;
    }

    public function calculateBeforeFormat($date, $sign)
    {
        $part1 = $sign * substr($date, 0, strlen($date) - 1);
        $part2 = substr($date, strlen($date) - 1);

        #TODO
        # neyek
        /*
        * Because mktime has the restriccion for:
        * The number of the year, may be a two or four digit value, with values between 0-69 mapping to 2000-2069 and 70-100 to 1970-2000.
        * On systems where time_t is a 32bit signed integer, as most common today, the valid range for year  is somewhere
        * between 1901 and 2038. However, before PHP 5.1.0 this range was limited from 1970 to 2038 on some systems (e.g. Windows).
        */
        # improving required

        switch ($part2) {
            case 'd':
                $res = date('Y-m-d', mktime(0, 0, 0, date('m'), date('d') + $part1, date('Y')));
                break;
            case 'm':
                $res = date('Y-m-d', mktime(0, 0, 0, date('m') + $part1, date('d') - 1, date('Y')));
                break;
            case 'y':
                //$res = date ( 'Y-m-d', mktime ( 0, 0, 0, date ( 'm' ), date ( 'd' ), date ( 'Y' ) + $part1) );
                //hook
                $res = (intVal(date('Y')) + $part1) . '-' . date('m') . '-' . date('d');
                break;
        }

        return $res;
    }

    /**
     * render the field in a dynaform
     *
     * @param $value
     * @param $owner
     * @return renderized widget
     */
    public function render($value = null, $owner = null)
    {
        if (($this->pmconnection != '') && ($this->pmfield != '') && $value == null) {
            $value = $this->getPMTableValue($owner);
        } else {
            $value = G::replaceDataField($value, $owner->values);
        }
        //$this->defaultValue = G::replaceDataField( $this->defaultValue, $owner->values);
        $id = "form[$this->name]";
        return $this->draw_widget($id, $value, $owner);
    }

    /**
     * render the field in a grid
     *
     * @param $values
     * @param $owner
     * @param $onlyValue
     * @return Array $result
     */
    public function renderGrid($values = null, $owner = null, $onlyValue = false, $paramDummy4 = null)
    {
        $result = [];
        $r = 1;
        foreach ($values as $v) {
            $v = ($v != '') ? G::replaceDataField($v, $owner->values) : $this->defaultValue;
            if (!$onlyValue) {
                $id = 'form[' . $owner->name . '][' . $r . '][' . $this->name . ']';
                $html = $this->draw_widget($id, $v, $owner);
            } else {
                $html = $v;
            }
            $result[] = $html;
            $r++;
        }
        return $result;
    }

    /**
     * Returns the html code to draw the widget
     *
     * @param $pID
     * @param $value
     * @param $owner
     * @return <String>
     */
    public function draw_widget($pID, $value, $owner = '')
    {

        /*for deprecated mask definitions...*/

        #first deprecated simple (yyyy-mm-dd) and personalizes combinations
        $this->mask = str_replace('yyyy', 'Y', $this->mask);
        $this->mask = str_replace('yy', 'y', $this->mask);
        $this->mask = str_replace('mm', 'm', $this->mask);
        $this->mask = str_replace('dd', 'd', $this->mask);

        #second deprecated (%Y-%m-%d) and other combinations
        $this->mask = str_replace('%', '', $this->mask);

        if (isset($this->mask) && $this->mask != '') {
            $mask = $this->mask;
        } else {
            #Default mask
            $mask = 'Y-m-d';
        }

        // Note added by Gustavo Cruz
        // set the variable isRequired if the needs to be validated
        //
        if ($this->required) {
            $isRequired = '1';
        } else {
            $isRequired = '0';
        }

        $startDate = G::replaceDataField($this->startDate, $owner->values);
        $endDate = G::replaceDataField($this->endDate, $owner->values);

        $beforeDate = G::replaceDataField($this->beforeDate, $owner->values);
        $afterDate = G::replaceDataField($this->afterDate, $owner->values);

        if ($startDate != '') {
            if (!$this->verifyDateFormat($startDate)) {
                $startDate = '';
            }
        }
        if (isset($beforeDate) && $beforeDate != '') {
            if ($this->isvalidBeforeFormat($beforeDate)) {
                $startDate = $this->calculateBeforeFormat($beforeDate, 1);
            }
        }

        if ($startDate == '' && isset($this->size) && is_numeric($this->size) && $this->size >= 1900 && $this->size <= 2100) {
            $startDate = $this->size . '-01-01';
        }

        if ($startDate == '') {
            //$startDate = date ( 'Y-m-d' ); // the default is the current date
        }

        if ($endDate != '') {
            if (!$this->verifyDateFormat($endDate)) {
                $endDate = '';
            }
        }

        if (isset($afterDate) && $afterDate != '') {
            if ($this->isvalidBeforeFormat($afterDate)) {
                $endDate = $this->calculateBeforeFormat($afterDate, +1);
            }
        }

        if (isset($this->maxlength) && is_numeric($this->maxlength) && $this->maxlength >= 1900 && $this->maxlength <= 2100) {
            $endDate = $this->maxlength . '-01-01';
        }
        if ($endDate == '') {
            //$this->endDate = mktime ( 0,0,0,date('m'),date('d'),date('y') );  // the default is the current date + 2 years
            $endDate = date('Y-m-d', mktime(0, 0, 0, date('m'), date('d'), date('Y') + 2)); // the default is the current date + 2 years
        }

        $tmp = str_replace("%", "", $mask);
        if (trim($value) == '' or $value == null) {
            $value = ''; //date ($tmp);
        } else {
            switch (strtolower($value)) {
                case 'today':
                    $value = date($tmp);
                    break;
                default:
                    if (!$this->verifyDateFormat($value, $mask)) {
                        $value = '';
                    }
                    break;
            }
        }

        if ($value == '') {
            $valueDate = array(date('Y'), date('m'), date('d')
            );
        } else {
            $valueDate = $this->getSplitDate($value, $mask);
        }

        $startDate = $this->getSplitDate($startDate, 'Y-m-d');
        //adatation for new js calendar widget
        $startDate[2] = $startDate[2] - 1;

        $endDate = $this->getSplitDate($endDate, 'Y-m-d');
        //adatation for new js calendar widget
        $endDate[2] = $endDate[2] + 1;

        $extra = (defined('SYS_LANG_DIRECTION') && SYS_LANG_DIRECTION == 'R') ? 'direction:rtl; float:right' : 'direction:ltr';

        if (isset($this->showtime) && $this->showtime) {
            $mask .= ' h:i';
            $img = (defined('SYS_LANG_DIRECTION') && SYS_LANG_DIRECTION == 'R') ? 'pmdatetimeiw.png' : 'pmdatetime.png';
            $style = 'background-image:url(/images/' . $img . ');float:left; width:131px; height:22px;padding:2px 1px 1px 3px;cursor:pointer;color:#000; ' . $extra . ';';
            $showTime = 'true';
        } else {
            $img = (defined('SYS_LANG_DIRECTION') && SYS_LANG_DIRECTION == 'R') ? 'pmdateiw.png' : 'pmdate.png';
            $style = 'background-image:url(/images/' . $img . ');float:left; width:100px; height:22px;padding:2px 1px 1px 3px;cursor:pointer;color:#000; direction:' . $extra . ';';
            $showTime = 'false';
        }

        if ($this->editable == "1") {
            $style = '';
        }

        // Note added by Gustavo Cruz
        // also the fields rendered in a grid needs now have an attribute required set to 0 or 1
        // that it means not required or required respectively.
        if ($this->mode == 'edit' && $this->readOnly != "1") {
            if ($this->editable != "1") {
                $html = '<input type="text" required="' . $isRequired . '" style="display:none" id="' . $pID . '" name="' . $pID . '" value="' . $value . '" onchange="' . $this->onchange . '"/>';
                $html .= '<div id="' . $pID . '[div]" name="' . $pID . '[div]" onclick="var oc=new NeyekCalendar(\'' . $pID . '\');
            oc.picker(
              {\'year\':\'' . $valueDate[0] . '\',\'month\':\'' . $valueDate[1] . '\',\'day\':\'' . $valueDate[2] . '\'},
            \'' . $mask . '\',
            \'' . SYS_LANG . '\',
            {\'year\':\'' . $startDate[0] . '\',\'month\':\'' . $startDate[1] . '\',\'day\':\'' . $startDate[2] . '\'},
            {\'year\':\'' . $endDate[0] . '\',\'month\':\'' . $endDate[1] . '\',\'day\':\'' . $endDate[2] . '\'},
            ' . $showTime . ',
            event
          ); return false;" style="' . $style . '">&nbsp;' . $value . '</div>';
            } else {
                $html = '<input id="' . $pID . '" name="' . $pID . '" style="' . $style . '" value="' . $value . '" size="14" class="module_app_input___gray" onchange="' . $this->onchange . '">&nbsp;';
                $html .= '<a href="#" onclick="var oc=new NeyekCalendar(\'' . $pID . '\', 1);
            oc.picker(
              {\'year\':\'' . $valueDate[0] . '\',\'month\':\'' . $valueDate[1] . '\',\'day\':\'' . $valueDate[2] . '\'},
            \'' . $mask . '\',
            \'' . SYS_LANG . '\',
            {\'year\':\'' . $startDate[0] . '\',\'month\':\'' . $startDate[1] . '\',\'day\':\'' . $startDate[2] . '\'},
            {\'year\':\'' . $endDate[0] . '\',\'month\':\'' . $endDate[1] . '\',\'day\':\'' . $endDate[2] . '\'},
            ' . $showTime . ',
            event
          ); return false;"><img src="/images/pmdateicon.png" width="16px" height="18px" border="0"></a>';
            }
        } else {
            $html = '<input type="hidden" id="' . $pID . '" name="' . $pID . '" value="' . $value . '" onchange="' . $this->onchange . '"/>';
            $html .= "<span style='border:1;border-color:#000;width:100px;' name='" . $pID . "'>$value</span>";
        }
        //    if($this->hint){
        //           $html .= '<a href="#" onmouseout="hideTooltip()" onmouseover="showTooltip(event, \''.$this->hint.'\');return false;">
        //                  <image src="/images/help4.gif" width="15" height="15" border="0"/>
        //                </a>';
        //    }
        //print '<input type="text" id="'.$pID.'" name="'.$pID.'" value="'.$value.'" onchange="'.$this->onchange.'"/>';
        $html .= $this->renderHint();
        return $html;
    }

    /**
     * modify the date format
     *
     * @param <Date> $date
     * @param $mask
     * @return <type>
     */
    public function getSplitDate($date, $mask)
    {
        $sw1 = false;
        for ($i = 0; $i < 3; $i++) {
            $item = substr($mask, $i * 2, 1);
            switch ($item) {
                case 'Y':
                    switch ($i) {
                        case 0:
                            $d1 = substr($date, 0, 4);
                            break;
                        case 1:
                            $d1 = substr($date, 3, 4);
                            break;
                        case 2:
                            $d1 = substr($date, 6, 4);
                            break;
                    }
                    $sw1 = true;
                    break;
                case 'y':
                    switch ($i) {
                        case 0:
                            $d1 = substr($date, 0, 2);
                            break;
                        case 1:
                            $d1 = substr($date, 3, 2);
                            break;
                        case 2:
                            $d1 = substr($date, 6, 2);
                            break;
                    }
                    break;
                case 'm':
                    switch ($i) {
                        case 0:
                            $d2 = substr($date, 0, 2);
                            break;
                        case 1:
                            $d2 = ($sw1) ? substr($date, 5, 2) : substr($date, 3, 2);
                            break;
                        case 2:
                            $d2 = ($sw1) ? substr($date, 8, 2) : substr($date, 5, 2);
                            break;
                    }
                    break;
                case 'd':
                    switch ($i) {
                        case 0:
                            $d3 = substr($date, 0, 2);
                            break;
                        case 1:
                            $d3 = ($sw1) ? substr($date, 5, 2) : substr($date, 3, 2);
                            break;
                        case 2:
                            $d3 = ($sw1) ? substr($date, 8, 2) : substr($date, 5, 2);
                            break;
                    }
                    break;
            }
        }
        return array(isset($d1) ? $d1 : '', isset($d2) ? $d2 : '', isset($d3) ? $d3 : ''
        );
    }
}

/**
 *
 * @package gulliver.system
 */
class XmlFormFieldXmlform extends XmlFormField
{
    public $xmlfile = '';
    public $initRows = 1;
    public $group = 0;
    public $addRow = true;
    public $deleteRow = false;
    public $editRow = false;
    public $sql = '';
    //TODO: 0=doesn't excecute the query, 1=Only the first time, 2=Allways
    public $fillType = 0;
    public $fields = [];
    public $scriptURL;
    public $id = '';

    /**
     * Function XmlFormFieldXmlform
     *
     * @access public
     * @param string xmlnode
     * @param string language
     * @param string home
     * @return string
     */
    public function __construct($xmlnode, $language, $home)
    {
        parent::__construct($xmlnode, $language);
        $this->parseFile($home, $language);
    }

    /**
     * Function parseFile
     *
     * @access public
     * @param string home
     * @param string language
     * @return string
     */
    public function parseFile($home, $language)
    {
        $this->xmlform = new XmlForm();
        $this->xmlform->home = $home;
        $this->xmlform->parseFile($this->xmlfile . '.xml', $language, false);
        $this->fields = $this->xmlform->fields;
        $this->scriptURL = $this->xmlform->scriptURL;
        $this->id = $this->xmlform->id;
        unset($this->xmlform);
    }

    /**
     * Function render
     *
     * @access public
     * @param string values
     * @return string
     */
    public function render($values = null, $paramDummy2 = null)
    {
        $html = '';
        foreach ($this->fields as $f => $v) {
            $html .= $v->render('');
        }
        $this->id = $this->owner->id . $this->name;
        $tpl = new xmlformTemplate($this, PATH_CORE . 'templates/xmlform.html');
        $this->values = $values;
        //$this->rows=count(reset($values));
        $tpl->template = $tpl->printTemplate($this);
        //In the header
        $oHeadPublisher = headPublisher::getSingleton();
        $oHeadPublisher->addScriptFile($this->scriptURL);
        $oHeadPublisher->addScriptCode($tpl->printJavaScript($this));
        return $tpl->printObject($this);
    }
}

/**
 * Class XmlForm
 * Main Class
 *
 * @package gulliver.system
 * @access public
 */
class XmlForm
{
    public $tree;
    public $id = '';
    public $name = '';
    public $language;
    /* @attribute string version 0.xxx = Previous to pre-open source
     */
    public $version = '0.3';
    public $fields = [];
    public $title = '';
    public $home = '';
    public $parsedFile = '';
    public $type = 'xmlform';
    public $fileName = '';
    public $scriptFile = '';
    public $scriptURL = '';
    /* Special propose attributes*/
    public $sql;
    public $sqlConnection;
    /*Attributes for the xmlform template*/
    public $width = 600;
    public $height = "100%";
    public $border = 1;
    public $mode = '';
    // public $labelWidth = 140;
    // public $labelWidth        = 180;
    public $labelWidth = "40%";
    public $onsubmit = '';
    public $requiredFields = [];
    public $fieldContentWidth = 450;

    /**
     * List of xmlform controls and its classes.
     *
     * @var string[]
     */
    private static $controls = [
        'button' => XmlFormFieldButton::class,
        'caption' => XmlFormFieldCaption::class,
        'captioncurrency' => XmlFormFieldCaptionCurrency::class,
        'captionpercentage' => XmlFormFieldCaptionPercentage::class,
        'cellmark' => XmlFormFieldCellMark::class,
        'checkbox2' => XmlFormFieldCheckbox2::class,
        'checkbox' => XmlFormFieldCheckbox::class,
        'checkboxpt' => XmlFormFieldCheckboxpt::class,
        'checkboxtable' => XmlFormFieldCheckBoxTable::class,
        'checkgroup' => XmlFormFieldCheckGroup::class,
        'checkgroupview' => XmlFormFieldCheckGroupView::class,
        'currency' => XmlFormFieldCurrency::class,
        'date2' => XmlFormFieldDate2::class,
        'date5' => XmlFormFieldDate5::class,
        'date' => XmlFormFieldDate::class,
        'dateview' => XmlFormFieldDateView::class,
        'dropdown' => XmlFormFieldDropdown::class,
        'dropdownpt' => XmlFormFieldDropdownpt::class,
        'dveditor' => XmlFormFieldDVEditor::class,
        'fastsearch' => XmlFormFieldFastSearch::class,
        'file' => XmlFormFieldFile::class,
        'grid' => XmlFormFieldGrid::class,
        'hidden' => XmlFormFieldHidden::class,
        'hours' => XmlFormFieldHours::class,
        'html' => XmlFormFieldHTML::class,
        'image' => XmlFormFieldImage::class,
        'javascript' => XmlFormFieldJavaScript::class,
        'label' => XmlFormFieldLabel::class,
        'link' => XmlFormFieldLink::class,
        'listbox' => XmlFormFieldListbox::class,
        'password' => XmlFormFieldPassword::class,
        'percentage' => XmlFormFieldPercentage::class,
        'popupoption' => XmlFormFieldPopupOption::class,
        'print' => XmlFormFieldPrint::class,
        'radiogroup' => XmlFormFieldRadioGroup::class,
        'radiogroupview' => XmlFormFieldRadioGroupView::class,
        'reset' => XmlFormFieldReset::class,
        'simpletext' => XmlFormFieldSimpleText::class,
        'submit' => XmlFormFieldSubmit::class,
        'subtitle' => XmlFormFieldSubtitle::class,
        'suggest' => XmlFormFieldSuggest::class,
        'text' => XmlFormFieldText::class,
        'textarea' => XmlFormFieldTextarea::class,
        'textareapm' => XmlFormFieldTextareaPm::class,
        'textpm' => XmlFormFieldTextPm::class,
        'title' => XmlFormFieldTitle::class,
        'toolbar' => XmlFormFieldToolBar::class,
        'toolbutton' => XmlFormFieldToolButton::class,
        'wysiwyg_editor' => XmlFormFieldWYSIWYGEditor::class,
        'xmlform' => XmlFormFieldXmlform::class,
        'xmlmenu' => XmlFormFieldXmlMenu::class,
        'yesno' => XmlFormFieldYesNo::class,
    ];

    /**
     * Get xmlform control class by type.
     *
     * @param string $type
     * @return string
     */
    private function getClassByControlType($type)
    {
        $key = strtolower($type);
        if (isset(self::$controls[$key])) {
            return self::$controls[$key];
        } elseif (class_exists('XmlForm_Field_' . $type)) {
            return 'XmlForm_Field_' . $type;
        } elseif (class_exists('XmlForm_Field_' . $key)) {
            return 'XmlForm_Field_' . $key;
        } else {
            return XmlFormField::class;
        }
    }

    /**
     * Function xmlformTemplate
     *
     * @access public
     * @param string form
     * @param string templateFile
     * @return string
     */
    public function parseFile($filename, $language, $forceParse)
    {
        $this->language = $language;
        $filenameInitial = $filename;
        $filename = $this->home . $filename;

        //if the xmlform file doesn't exists, then try with the plugins folders
        if (!is_file($filename)) {
            $aux = explode(PATH_SEP, $filenameInitial);
            //check if G_PLUGIN_CLASS is defined, because publisher can be called without an environment
            if (count($aux) > 2) {
                //Subfolders
                $filename = array_pop($aux);
                $aux0 = implode(PATH_SEP, $aux);
                $aux = [];
                $aux[0] = $aux0;
                $aux[1] = $filename;
            }
            if (count($aux) == 2 && defined('G_PLUGIN_CLASS')) {
                $oPluginRegistry = PluginRegistry::loadSingleton();
                if ($response = $oPluginRegistry->isRegisteredFolder($aux[0])) {
                    if ($response !== true) {
                        $sPath = PATH_PLUGINS . $response . PATH_SEP;
                    } else {
                        $sPath = PATH_PLUGINS;
                    }
                    $filename = $sPath . $aux[0] . PATH_SEP . $aux[1];
                }
            }
        }

        $this->fileName = $filename;
        $parsedFile = dirname($filename) . PATH_SEP . basename($filename, 'xml') . $language;

        $parsedFilePath = defined('PATH_C') ? (!empty(config("system.workspace")) ? PATH_C . 'ws' . PATH_SEP . config("system.workspace") . PATH_SEP : PATH_C) : PATH_DATA;
        $parsedFilePath .= 'xmlform/' . substr($parsedFile, strlen($this->home));

        // Improvement for the js cache - Start
        $realPath = substr(realpath($this->fileName), strlen(realpath($this->home)), -4);
        if (substr($realPath, 0, 1) != PATH_SEP) {
            $realPath = PATH_SEP . $realPath;
        }
        $filesToDelete = substr((defined('PATH_C') ? PATH_C : PATH_DATA) . 'xmlform/', 0, -1) . $realPath . '.*.js';
        $auxPath = explode(PATH_SEP, $realPath);
        $auxPath[count($auxPath) - 1] = $auxPath[count($auxPath) - 1] . '.' . G::encryptOld(filemtime($this->fileName));
        $realPath = implode(PATH_SEP, $auxPath);
        // Improvement for the js cache - End
        $this->parsedFile = $parsedFilePath;
        $this->scriptURL = '/jsform' . $realPath . '.js';
        $this->scriptFile = substr((defined('PATH_C') ? PATH_C : PATH_DATA) . 'xmlform/', 0, -1) . substr($this->scriptURL, 7);
        $this->id = G::createUID('', substr($this->fileName, strlen($this->home)));
        $this->scriptURL = str_replace('\\', '/', $this->scriptURL);

        $newVersion = false;
        if ($forceParse || ((!file_exists($this->parsedFile)) || (filemtime($filename) > filemtime($this->parsedFile)) || (filemtime(__FILE__) > filemtime($this->parsedFile))) || (!file_exists($this->scriptFile)) || (filemtime($filename) > filemtime($this->scriptFile))) {
            if (glob($filesToDelete)) {
                foreach (glob($filesToDelete) as $fileToDelete) {
                    @unlink($fileToDelete);
                }
            }
            $this->tree = new Xml_Document();
            $this->tree->parseXmlFile($filename);
            //$this->tree->unsetParent();
            if (!is_object($this->tree->children[0])) {
                throw new Exception('Failure loading root node.');
            }
            $this->tree = $this->tree->children[0]->toTree();
            //ERROR CODE [1] : Failed to read the xml document
            if (!isset($this->tree)) {
                return 1;
            }
            $xmlNode = &$this->tree->children;

            //Set the form's attributes
            $myAttributes = get_class_vars(get_class($this));
            foreach ($myAttributes as $k => $v) {
                $myAttributes[$k] = strtolower($k);
            }
            foreach ($this->tree->attributes as $k => $v) {
                $key = array_search(strtolower($k), $myAttributes);
                if (($key !== false) && (strtolower($k) !== 'fields') && (strtolower($k) !== 'values')) {
                    $this->{$key} = $v;
                }
            }
            //Reeplace non valid characters in xmlform name with "_"
            $this->name = preg_replace('/\W/', '_', $this->name);
            //Create fields


            foreach ($xmlNode as $k => $v) {
                if (($xmlNode[$k]->type !== 'cdata') && isset($xmlNode[$k]->attributes['type'])) {
                    $class = $this->getClassByControlType($xmlNode[$k]->attributes['type']);
                    $field = new $class($xmlNode[$k], $language, $this->home, $this);
                    $field->language = $this->language;
                    $this->fields[$field->name] = $field;
                }

                if (isset($xmlNode[$k]->attributes['required']) || isset($xmlNode[$k]->attributes['validate'])) {
                    // the fields or xml nodes with a required attribute are put in an array that is passed to the view file
                    $isEditMode = isset($xmlNode[$k]->attributes['mode']) && $xmlNode[$k]->attributes['mode'] == 'view' ? false : true;

                    if ($isEditMode && $this->mode != 'view') {
                        $validateValue = "";
                        if (isset($xmlNode[$k]->attributes['validate'])) {
                            $validateValue = $xmlNode[$k]->attributes['validate'];
                        }
                        $requiredValue = "0";
                        if (isset($xmlNode[$k]->attributes['required'])) {
                            $requiredValue = $xmlNode[$k]->attributes['required'] == 1 ? '1' : '0';
                        }

                        $this->requiredFields[] = array('name' => $field->name, 'type' => $xmlNode[$k]->attributes['type'], 'label' => addslashes(trim($field->label)), 'validate' => $validateValue, 'required' => $requiredValue
                        );
                    }
                }
            }

            //$oJSON = new Services_JSON();
            $jsonRequired = G::json_encode($this->requiredFields);
            $this->objectRequiredFields = str_replace('"', "%27", str_replace("'", "%39", $jsonRequired));

            //Load the default values
            //$this->setDefaultValues();
            //Save the cache file
            if (!is_dir(dirname($this->parsedFile))) {
                G::mk_dir(dirname($this->parsedFile));
            }
            $f = fopen($this->parsedFile, 'w+');
            //ERROR CODE [2] : Failed to open cache file
            if ($f === false) {
                return 2;
            }
            fwrite($f, "<?php\n");
            /*  fwrite ($f, '$this = unserialize( \'' .
                  addcslashes( serialize ( $this ), '\\\'' ) . '\' );' . "\n" );*/
            foreach ($this as $key => $value) {
                //cho $key .'<br/>';
                switch ($key) {
                    case 'home':
                    case 'fileName':
                    case 'parsedFile':
                    case 'scriptFile':
                    case 'scriptURL':
                        break;
                    default:
                        switch (true) {
                            case is_string($this->{$key}):
                                fwrite($f, '$this->' . $key . '=\'' . addcslashes($this->{$key}, '\\\'') . '\'' . ";\n");
                                break;
                            case is_bool($this->{$key}):
                                fwrite($f, '$this->' . $key . '=' . (($this->{$key}) ? 'true;' : 'false') . ";\n");
                                break;
                            case is_null($this->{$key}):
                                fwrite($f, '$this->' . $key . '=null' . ";\n");
                                break;
                            case is_float($this->{$key}):
                            case is_int($this->{$key}):
                                fwrite($f, '$this->' . $key . '=' . $this->{$key} . ";\n");
                                break;
                            default:
                                fwrite($f, '$this->' . $key . ' = unserialize( \'' . addcslashes(serialize($this->{$key}), '\\\'') . '\' );' . "\n");
                        }
                }
            }
            fwrite($f, "?>");
            fclose($f);
            $newVersion = true;
        } //if $forceParse
        //Loads the parsedFile.
        require($this->parsedFile);
        $this->fileName = $filename;
        $this->parsedFile = $parsedFile;

        //RECREATE LA JS file
        //Note: Template defined with publisher doesn't affect the .js file
        //created at this point.
        if ($newVersion) {
            $template = PATH_CORE . 'templates/' . $this->type . '.html';
            //If the type is not the correct template name, use xmlform.html
            //if (!file_exists($template)) $template = PATH_CORE . 'templates/xmlform.html';
            if (($template !== '') && (file_exists($template))) {
                if (!is_dir(dirname($this->scriptFile))) {
                    G::mk_dir(dirname($this->scriptFile));
                }
                $f = fopen($this->scriptFile, 'w');
                $o = new xmlformTemplate($this, $template);
                $scriptContent = $o->printJSFile($this);
                unset($o);
                fwrite($f, $scriptContent);
                fclose($f);
            }
        }
        return 0;
    }

    /**
     * Generic function to set values for the current object.
     *
     * @param $newValues
     * @return void
     */
    public function setValues($newValues = array())
    {
        foreach ($this->fields as $k => $v) {
            if (array_key_exists($k, $newValues)) {
                $this->values[$k] = $newValues[$k];
            }
        }
        foreach ($this->fields as $k => $v) {
            if (is_object($this->fields[$k]) && get_class($this->fields[$k]) != '__PHP_Incomplete_Class') {
                $this->fields[$k]->owner = &$this;
            }
        }
    }

    /**
     * Generic function to print the current object.
     *
     * @param $template
     * @param &$scriptContent
     * @return string
     */
    public function render($template, &$scriptContent)
    {
        $o = new xmlformTemplate($this, $template);
        if (is_array(reset($this->values))) {
            $this->rows = count(reset($this->values));
        }
        $o->template = $o->printTemplate($this);
        $scriptContent = $o->printJavaScript($this);
        return $o->printObject($this);
    }

    /**
     * Clone the current object
     *
     * @return Object
     */
    public function cloneObject()
    {
        return unserialize(serialize($this));
    }
}

/**
 * @package gulliver.system
 */
class XmlFormFieldImage extends XmlFormField
{
    public $file = '';
    public $home = 'public_html';
    public $withoutLabel = false;

    /**
     * Function render
     * @access public
     * @param string values
     * @return string
     */
    public function render($value = null, $owner = null)
    {
        $url = G::replaceDataField($this->file, $owner->values);
        if ($this->home === "methods") {
            $url = G::encryptlink(SYS_URI . $url);
        }
        if ($this->home === "public_html") {
            $url = '/' . $url;
        }
        return '<img src="' . htmlentities($url, ENT_QUOTES, 'utf-8') . '" ' .
            (($this->style) ? 'style="' . $this->style . '"' : '')
            . ' alt ="' . htmlentities($value, ENT_QUOTES, 'utf-8') . '"/>';
    }
}

//mask function to php
function masktophp($mask, $value)
{
    $tmp = str_replace("%", "", $mask);
    if (preg_match('/M/', $tmp)) {
        $tmp = str_replace("M", "i", $tmp);
    }
    if (preg_match('/b/', $tmp)) {
        $tmp = str_replace("b", "M", $tmp);
    }
    if (preg_match('/B/', $tmp)) {
        $tmp = str_replace("B", "F", $tmp);
    }
    if (preg_match('/S/', $tmp)) {
        $tmp = str_replace("S", "s", $tmp);
    }
    if (preg_match('/o/', $tmp)) {
        $tmp = str_replace("o", "n", $tmp);
    }
    if (preg_match('/a/', $tmp)) {
        $tmp = str_replace("a", "D", $tmp);
    }
    if (preg_match('/l/', $tmp)) {
        $tmp = str_replace("l", "g", $tmp);
    }
    if (preg_match('/A/', $tmp)) {
        $tmp = str_replace("A", "l", $tmp);
    }
    if (preg_match('/I/', $tmp)) {
        $tmp = str_replace("I", "h", $tmp);
    }
    if (preg_match('/j/', $tmp)) {
        $tmp = str_replace("j", "z", $tmp);
    }
    if (preg_match('/k/', $tmp)) {
        $tmp = str_replace("k", "G", $tmp);
    }
    if (preg_match('/e/', $tmp)) {
        $tmp = str_replace("e", "j", $tmp);
    }
    if (preg_match('/u/', $tmp)) {
        $tmp = str_replace("u", "N", $tmp);
    }
    if (preg_match('/p/', $tmp)) {
        $tmp = str_replace("p", "A", $tmp);
    }
    if (preg_match('/P/', $tmp)) {
        $tmp = str_replace("P", "a", $tmp);
    }

    if ($value == 'today') {
        $value = date($tmp);
    } else {
        $value = date($tmp, strtotime($value));
    }
    return $value;
}

if (!function_exists('strptime')) {
    function strptime($date, $format)
    {
        $masks = array(
            '%d' => '(?P<d>[0-9]{2})',
            '%m' => '(?P<m>[0-9]{2})',
            '%Y' => '(?P<Y>[0-9]{4})',
            '%H' => '(?P<H>[0-9]{2})',
            '%M' => '(?P<M>[0-9]{2})',
            '%S' => '(?P<S>[0-9]{2})',
            // usw..
        );

        $rexep = "#" . strtr(preg_quote($format), $masks) . "#";
        if (!preg_match($rexep, $date, $out)) {
            return false;
        }

        if (!isset($out['S'])) {
            $out['S'] = 0;
        } else {
            $out['S'] = (int)$out['S'];
        }

        if (!isset($out['M'])) {
            $out['M'] = 0;
        } else {
            $out['M'] = (int)$out['M'];
        }

        if (!isset($out['H'])) {
            $out['H'] = 0;
        } else {
            $out['H'] = (int)$out['H'];
        }

        if (!isset($out['d'])) {
            $out['d'] = 0;
        } else {
            $out['d'] = (int)$out['d'];
        }

        if (!isset($out['m'])) {
            $out['m'] = 0;
        } else {
            $out['m'] = (int)$out['m'];
        }

        if (!isset($out['Y'])) {
            $out['Y'] = 0;
        } else {
            $out['Y'] = (int)$out['Y'];
        }

        $ret = array(
            "tm_sec" => $out['S'],
            "tm_min" => $out['M'],
            "tm_hour" => $out['H'],
            "tm_mday" => $out['d'],
            "tm_mon" => $out['m'] ? $out['m'] - 1 : 0,
            "tm_year" => $out['Y'] > 1900 ? $out['Y'] - 1900 : 0,
        );
        return $ret;
    }
}
