Skip to content
Snippets Groups Projects
Select Git revision
  • fcdae77b6b085d614fa4a42b0cb2fa0d47f0e0e9
  • master default protected
  • Legacy_Php7
3 results

formgen.class.php

Blame
  • formgen.class.php 16.72 KiB
    <?php
    
    /* ######################################################################
    
      IML DEPLOYMENT
    
      class formgen - (copied and improved from simap prototype project)
      It generates Form elements. This class does what I need it is not
      feature complete.
    
      ---------------------------------------------------------------------
      Axel <axel.hahn@iml.unibe.ch>
      2013-11-08        Axel
      2024-08-23  v1.1  Axel  php8 only; added variable types; short array syntax
      2024-11-29  v1.2  Axel  add feature array for customized code
      ###################################################################### */
    
    class formgen
    {
    
        var $aForm = [];
        var $sRequired = ' <span title="Eingabe ist erforderlich"><span style="color:#c00;">*</span></span>';
    
        var array $aFeatures = [
            'bootstrap-select' => true,
        ];
    
        /**
         * Constructor
         * @param array $aNewFormData
         */
        public function __construct($aNewFormData = [])
        {
            if (is_array($aNewFormData) && count($aNewFormData)) {
                $this->setFormarray($aNewFormData);
            }
        }
    
        /**
         * Set a new array for a new form
         * @param array $aNewFormData
         * @return boolean
         */
        public function setFormarray($aNewFormData = [])
        {
            if (!is_array($aNewFormData) || !count($aNewFormData)) {
                return false;
            }
            $this->aForm = $aNewFormData;
            return true;
        }
    
        /**
         * Get html code for a completely rendered form
         * @param  string $sFormId
         * @return string html output
         */
        public function renderHtml(string $sFormId): string
        {
            $sReturn = false;
            if (!isset($this->aForm[$sFormId])) {
                throw new Exception("ERROR: " . __CLASS__ . ":" . __FUNCTION__ . " - form id " . $sFormId . " does not exist.");
            }
            // FORM tag
            $sReturn .= '<form ';
            if (isset($this->aForm[$sFormId]["meta"])) {
                foreach (["method", "action", "target", "accept-charset", "class", "id", "name"] as $sAttr) {
                    if (isset($this->aForm[$sFormId]["meta"][$sAttr])) {
                        $sReturn .= $sAttr . '="' . $this->aForm[$sFormId]["meta"][$sAttr] . '" ';
                    }
                }
            }
            $sReturn .= '>';
    
            // ... and all its elements
            foreach ($this->aForm[$sFormId]["form"] as $elementKey => $elementData) {
                $sReturn .= $this->renderHtmlElement($elementKey, $elementData);
            }
            $sReturn .= '</form>';
    
            return $sReturn;
        }
    
        /**
         * Add html attributes if they exist
         * @param array $aAttributes  list of attributes to search for
         * @param array $elementData  array of form element
         * @return string
         */
        private function _addHtmlAtrributes(array $aAttributes, array $elementData): string
        {
            $sReturn = false;
            foreach ($aAttributes as $sAtrr) {
                if (isset($elementData[$sAtrr]) && $elementData[$sAtrr]) {
                    $sReturn .= ($sReturn ? ' ' : '')
                        . $sAtrr . '="' . $elementData[$sAtrr] . '"'
                    ;
                }
            }
            return $sReturn;
        }
    
        /**
         * Add a label next to a form element
         * @param string $sLabel  Labeltext to show
         * @param string $sFor    for attribute to ad (points to the id of the form element)
         * @param string $sClass  css class
         * @return string
         */
        private function _addLabel(string $sLabel, string $sFor, string $sClass = ''): string
        {
            return "<label for=\"$sFor\""
                . ($sClass ? " class=\"$sClass\"" : '')
                . ">$sLabel</label>"
                . "\n"
                ;
        }
    
        /**
         * Ensure that all required keys are set
         * @param  array  $aArray         given array
         * @param  array  $aRequiredKeys  set of required keys
         * @param  string $sLabel         form label - will be shown in error message
         * @throws \Exception
         * @return bool
         */
        private function _checkReqiredKeys(array $aArray, array $aRequiredKeys, string $sLabel = ''): bool
        {
            $bReturn = true;
            foreach ($aRequiredKeys as $sKey) {
                if (!isset($aArray[$sKey])) {
                    throw new Exception("ERROR: $sLabel<br>Missing key \"$sKey\" in the array of a form element:<pre>" . print_r($aArray, true) . "</pre>");
                }
            }
            return $bReturn;
        }
    
        /**
         * Render a single form element
         * @param string $sId          id of a form element
         * @param array  $elementData  array of form element
         * @return string html output
         */
        public function renderHtmlElement(string $sId, array $elementData): string
        {
            $sReturn = false;
            $sDefaultAttributes = ""
                . "class,"
    
                // events ... see https://developer.mozilla.org/en-US/docs/Web/API/Element
                . "onauxclick,onclick,ondblclick,oncontextmenu,onfocusin,onfocusout,"
                . "onkeydown,onkeypress,onkeyup,"
                . "onmousedown,onmouseenter,onmouseleave,onmousemove,onmouseout,onmouseover,onmouseup,"
                //
                . "title"
            ;
    
            if (!isset($elementData["type"])) {
                print_r($elementData);
                throw new Exception("ERROR: " . __CLASS__ . ":" . __FUNCTION__ . " - key &quot;type&quot; does not exist.");
            }
    
            $sFormElement = false;
            $sLabelText = '';
            $sLabelElement = false;
    
            $sHtmlDefault = '';
            $sHtmlTable = '';
    
            if (isset($elementData["label"])) {
                $sLabelText = $elementData["label"];
                $sLabelText .= (isset($elementData["required"]) && $elementData["required"]) ? $this->sRequired : '';
            }
    
            switch ($elementData["type"]) {
                case "button":
                    $this->_checkReqiredKeys($elementData, ["value"]);
                    $elementData["class"] = $elementData["class"] ? $elementData["class"] : "btn btn-default";
                    $sFormElement .= '    <button id="' . $sId . '" ';
                    $sFormElement .= $this->_addHtmlAtrributes(explode(",", "$sDefaultAttributes,checked,name"), $elementData);
                    $sFormElement .= '>' . $elementData["value"] . '</button>';
                    $sFormElement .= "\n";
    
                    $sHtmlDefault = $sFormElement;
                    break;
    
                case "checkbox":
                    $this->_checkReqiredKeys($elementData, ["name"]);
                    foreach ($elementData["options"] as $idOption => $aOptionData) {
                        $sFormElement .= "\n" . '<div class="checkbox">';
                        $s = preg_replace('/\W/iu', '', $sId . $idOption);
                        $sOptionId = preg_replace('/[äöüß]/i', '', $s);
                        $sFormElement .= '    <input type="checkbox" id="' . $sOptionId . '" value="' . (isset($aOptionData["value"]) ? $aOptionData["value"] : $idOption) . '" ';
                        $sFormElement .= $this->_addHtmlAtrributes(explode(",", "$sDefaultAttributes,checked"), $aOptionData);
                        $sFormElement .= ' name="' . $elementData["name"] . '[]"';
                        $sFormElement .= '/><label for="' . $sOptionId . '">' . $aOptionData["label"] . '</label></div>';
                    }
                    $sFormElement .= "\n";
                    // $sLabelElement.='<span class="help-block">' . $sLabelText . '</span>';
                    $sLabelElement .= '<div class="col-sm-2">' . $sLabelText . '</div>';
                    $sLabelElement .= "\n";
    
                    // $sHtmlDefault = $sLabelElement . $sFormElement;
                    $sHtmlDefault = $sLabelElement . '<div class="col-sm-10">' . "\n" . $sFormElement . '</div>' . "\n";
                    $sHtmlTable = '<td>' . $sLabelText . '</td><td>' . $sFormElement . '</td>';
                    break;
    
                case "hidden":
                    $this->_checkReqiredKeys($elementData, ["value"]);
                    $sFormElement .= '    <input type="hidden" id="' . $sId . '" ';
                    $sFormElement .= $this->_addHtmlAtrributes(explode(",", "name,value"), $elementData);
                    $sFormElement .= " />";
                    $sFormElement .= "\n";
    
                    $sHtmlDefault = $sFormElement . "\n";
                    break;
    
                case "markup":
                    if (isset($elementData["value"]))
                        $sHtmlDefault = $elementData["value"] . "\n";
                    break;
    
                case "radio":
                    $this->_checkReqiredKeys($elementData, ["name"]);
                    foreach ($elementData["options"] as $idOption => $aOptionData) {
                        $sFormElement .= "\n" . '<div class="radio">';
                        $s = preg_replace('/\W/iu', '', $sId . $idOption);
                        $sOptionId = preg_replace('/[äöüß]/i', '', $s);
                        $sFormElement .= '    <input type="radio" id="' . $sOptionId . '" value="' . (isset($aOptionData["value"]) ? $aOptionData["value"] : $idOption) . '" ';
                        $sFormElement .= $this->_addHtmlAtrributes(explode(",", "$sDefaultAttributes,checked,disabled"), $aOptionData);
                        $sFormElement .= " " . $this->_addHtmlAtrributes(explode(",", "name"), $elementData);
                        $sFormElement .= '/><label for="' . $sOptionId . '">' . $aOptionData["label"] . '</label></div>';
                    }
                    $sFormElement .= "\n";
    
                    if ($sLabelText) {
                        // $sLabelElement.='<span class="help-block">' . $sLabelText . '</span>' . "\n";
                        $sLabelElement = $this->_addLabel($sLabelText, $sId, "col-sm-2");
                    }
    
                    // $sHtmlDefault = $sLabelElement . $sFormElement;
                    $sHtmlDefault = $sLabelElement . '<div class="col-sm-10">' . "\n" . $sFormElement . '</div>' . "\n";
    
                    $sHtmlTable = '<td>' . $sLabelText . '</td><td>' . $sFormElement . '</td>';
                    // $sHtmlDefault = $sLabelElement . $sFormElement;
    
                    // $sReturn.=$this->_addLabel($sFormElement,$sId,"checkbox");
                    break;
    
                case "select":
                    // HINWEIS optgroups werden nicht unterstuezt - nur einfache Listen
                    $this->_checkReqiredKeys($elementData, ["name"]);
                    $sDivClass = (isset($elementData["inline"]) && $elementData["inline"]) ? "form-group" : "col-sm-10";
                    $elementData['class'] .= " form-control" . (isset($this->aFeatures['bootstrap-select']) && $this->aFeatures['bootstrap-select'] ? " selectpicker" : "");
                    $sFormElement .= '<div class="' . $sDivClass . '">' . "\n" . '<select id="' . $sId . '" '
                        . $this->_addHtmlAtrributes(explode(",", "$sDefaultAttributes,name,onchange"), $elementData)
                        . (isset($this->aFeatures['bootstrap-select']) && $this->aFeatures['bootstrap-select'] ? ' data-live-search="true"' : '');
                    $sFormElement .= ">\n";
                    foreach ($elementData["options"] as $idOption => $aOptionData) {
                        $s = preg_replace('/\W/iu', '', $sId . $idOption);
                        $sOptionId = preg_replace('/[äöüß]/i', '', $s);
                        $sFormElement .= '    <option value="' . (isset($aOptionData["value"]) ? $aOptionData["value"] : $idOption) . '" ';
                        $sFormElement .= $this->_addHtmlAtrributes(explode(",", "$sDefaultAttributes,selected"), $aOptionData);
                        $sFormElement .= '>' . $aOptionData["label"] . '</option>' . "\n";
                    }
                    $sFormElement .= "</select></div>\n";
    
                    if ($sLabelText) {
                        // $sLabelElement.='<span class="help-block">' . $sLabelText . '</span>' . "\n";
                        $sLabelClass = (isset($elementData["inline"]) && $elementData["inline"]) ? "" : "col-sm-2";
                        $sLabelElement = $this->_addLabel($sLabelText, $sId, $sLabelClass);
                    }
    
                    $sHtmlTable = '<td>' . $sLabelText . '</td><td>' . $sFormElement . '</td>';
                    $sHtmlDefault = $sLabelElement . $sFormElement;
    
                    // $sReturn.=$this->_addLabel($sFormElement,$sId,"checkbox");
                    break;
    
                case "submit":
                    $this->_checkReqiredKeys($elementData, ["value"]);
                    $sClass = "btn btn-primary ";
                    if (isset($elementData["class"])) {
                        $sClass .= $elementData["class"];
                    }
                    $elementData["class"] = $sClass;
                    $sFormElement .= '    <button id="' . $sId . '" type="submit" ';
                    $sFormElement .= $this->_addHtmlAtrributes(explode(",", "$sDefaultAttributes"), $elementData);
                    $sFormElement .= '>' . $elementData["value"] . '</button>';
                    $sFormElement .= "\n";
    
                    $sHtmlDefault = $sFormElement;
                    break;
    
                case "text":
                case "password":
                    $this->_checkReqiredKeys($elementData, ["name"]);
                    $sFormElement .= '    <input type="' . $elementData["type"] . '" id="' . $sId . '" class="form-control col-sm-10" ';
                    $aAllowedHtmlAttributes["text"] = explode(",", "");
                    $sFormElement .= $this->_addHtmlAtrributes(explode(",", "$sDefaultAttributes,name,autocomplete,autofocus,list,disabled,onchange,pattern,placeholder,required,size,value"), $elementData);
                    // $sFormElement.=$this->_addHtmlAtrributes(["name", "value", "size", "placeholder", "required"], $elementData);
                    // IE: Return abfangen lassen
                    // $sFormElement.=' onkeypress="return checkKey(event);"';
                    $sFormElement .= ' />';
                    $sFormElement .= "\n";
    
                    if (isset($elementData["class"]) && $elementData["inline"]) {
                        $sLabelElement = $this->_addLabel($sLabelText, $sId, "col-sm-2");
                        // $sHtmlDefault = $sLabelElement . "\n" . $sFormElement . "\n";
                        $sHtmlDefault = $sLabelElement . '<div class="col-sm-3">' . "\n" . $sFormElement . '</div>' . "\n";
                    } else {
                        $sLabelElement = $this->_addLabel($sLabelText, $sId, "col-sm-2");
                        // $sHtmlDefault = $sLabelElement . '<div class="controls">' . "\n" . $sFormElement . '</div>' . "\n";                    
                        $sHtmlDefault = $sLabelElement . '<div class="col-sm-10">' . "\n" . $sFormElement . '</div>' . "\n";
                    }
    
                    $sHtmlTable = '<td>' . $sLabelText . '</td><td>' . $sFormElement . '</td>';
    
                    break;
    
                case "textarea":
                    $this->_checkReqiredKeys($elementData, ["name"]);
                    $sFormElement .= '    <textarea id="' . $sId . '" class="form-control col-sm-10" ';
                    $aAllowedHtmlAttributes["text"] = explode(",", "");
                    $sFormElement .= $this->_addHtmlAtrributes(explode(",", "$sDefaultAttributes,name,onchange,placeholder,required,cols,rows"), $elementData);
                    // $sFormElement.=$this->_addHtmlAtrributes(["name", "value", "size", "placeholder", "required"], $elementData);
                    $sFormElement .= '>' . $elementData['value'] . '</textarea>';
                    $sFormElement .= "\n";
    
                    $sLabelElement = $this->_addLabel($sLabelText, $sId, "control-label col-sm-2");
    
                    // $sHtmlDefault = $sLabelElement . '<div class="controls">' . "\n" . $sFormElement . '</div>' . "\n";
                    $sHtmlDefault = $sLabelElement . '<div class=" col-sm-10">' . "\n" . $sFormElement . '</div>' . "\n";
                    $sHtmlTable = '<td>' . $sLabelElement . '</td><td>' . $sFormElement . '</td>';
    
                    break;
    
                default:
                    die("ERROR: " . __CLASS__ . ":" . __FUNCTION__ . " - formelement type " . $elementData["type"] . " ist not supported (yet).");
            }
    
            // Default or table mode?
            if (isset($elementData["mode"]) && $elementData["mode"] == 'table' && $sHtmlTable) {
                $sHtmlDefault = $sHtmlTable;
            } else {
                if (
                    $elementData["type"] != "button"
                    && $elementData["type"] != "fieldset"
                    && $elementData["type"] != "markup"
                    && $elementData["type"] != "hidden"
                ) {
                    if (!isset($elementData["inline"]) || !$elementData["inline"]) {
                        // $sHtmlDefault = "<fieldset>" . $sHtmlDefault . "</fieldset>\n";
                        $sHtmlDefault = '<div class="form-group row">' . $sHtmlDefault . '</div>' . "\n";
                    }
                }
            }
    
            $sReturn .= "<!-- " . $elementData["type"] . " -->\n";
            $sReturn .= $sHtmlDefault . "\n";
    
            return $sReturn;
        }
    
    }