| 1 |  |  | <?php | 
            
                                                                                                            
                            
            
                                    
            
            
                | 2 |  |  | declare(strict_types=1); | 
            
                                                                                                            
                            
            
                                    
            
            
                | 3 |  |  |  | 
            
                                                                                                            
                            
            
                                    
            
            
                | 4 |  |  | namespace SKien\Formgenerator; | 
            
                                                                                                            
                            
            
                                    
            
            
                | 5 |  |  |  | 
            
                                                                                                            
                            
            
                                    
            
            
                | 6 |  |  |  | 
            
                                                                                                            
                            
            
                                    
            
            
                | 7 |  |  | /** | 
            
                                                                                                            
                            
            
                                    
            
            
                | 8 |  |  |  * | 
            
                                                                                                            
                            
            
                                    
            
            
                | 9 |  |  |  * | 
            
                                                                                                            
                            
            
                                    
            
            
                | 10 |  |  |  * @package Formgenerator | 
            
                                                                                                            
                            
            
                                    
            
            
                | 11 |  |  |  * @author Stefanius <[email protected]> | 
            
                                                                                                            
                            
            
                                    
            
            
                | 12 |  |  |  * @copyright MIT License - see the LICENSE file for details | 
            
                                                                                                            
                            
            
                                    
            
            
                | 13 |  |  |  */ | 
            
                                                                                                            
                            
            
                                    
            
            
                | 14 |  |  | class XMLForm extends FormGenerator | 
            
                                                                                                            
                            
            
                                    
            
            
                | 15 |  |  | { | 
            
                                                                                                            
                            
            
                                    
            
            
                | 16 |  |  |     const E_OK = 0; | 
            
                                                                                                            
                            
            
                                    
            
            
                | 17 |  |  |     const E_FILE_NOT_EXIST = 1; | 
            
                                                                                                            
                            
            
                                    
            
            
                | 18 |  |  |     const E_XML_ERROR = 2; | 
            
                                                                                                            
                            
            
                                    
            
            
                | 19 |  |  |     const E_XSD_ERROR = 3; | 
            
                                                                                                            
                            
            
                                    
            
            
                | 20 |  |  |     const E_MISSING_ROOT = 4; | 
            
                                                                                                            
                            
            
                                    
            
            
                | 21 |  |  |     const E_MISSING_FORM = 5; | 
            
                                                                                                            
                            
            
                                    
            
            
                | 22 |  |  |     const E_UNKNOWN_FORM_ELEMENT = 5; | 
            
                                                                                                            
                            
            
                                    
            
            
                | 23 |  |  |  | 
            
                                                                                                            
                            
            
                                    
            
            
                | 24 |  |  |     const XML_SCHEMA = 'FormGenerator.xsd'; | 
            
                                                                                                            
                            
            
                                    
            
            
                | 25 |  |  |  | 
            
                                                                                                            
                            
            
                                    
            
            
                | 26 |  |  |     /** @var string error message     */ | 
            
                                                                                                            
                            
            
                                    
            
            
                | 27 |  |  |     protected string $strErrorMsg = ''; | 
            
                                                                                                            
                            
            
                                    
            
            
                | 28 |  |  |     /** @var bool error message as plain text (\n instead of <br/>) */ | 
            
                                                                                                            
                            
            
                                    
            
            
                | 29 |  |  |     protected bool $bPlainError = false; | 
            
                                                                                                            
                            
            
                                    
            
            
                | 30 |  |  |     /** @var bool check xml file against the FormGenerator XSD schema */ | 
            
                                                                                                            
                            
            
                                    
            
            
                | 31 |  |  |     protected bool $bSchemaValidate = true; | 
            
                                                                                                            
                            
            
                                    
            
            
                | 32 |  |  |  | 
            
                                                                                                            
                            
            
                                    
            
            
                | 33 |  |  |     /** | 
            
                                                                                                            
                            
            
                                    
            
            
                | 34 |  |  |      * no constructor - always use the constructor of the parent! | 
            
                                                                                                            
                            
            
                                    
            
            
                | 35 |  |  |      */ | 
            
                                                                                                            
                            
            
                                    
            
            
                | 36 |  |  |  | 
            
                                                                                                            
                            
            
                                    
            
            
                | 37 |  |  |     /** | 
            
                                                                                                            
                            
            
                                    
            
            
                | 38 |  |  |      * Load form from the given XML file. | 
            
                                                                                                            
                            
            
                                    
            
            
                | 39 |  |  |      * @param string $strXMLFile | 
            
                                                                                                            
                            
            
                                    
            
            
                | 40 |  |  |      * @return int | 
            
                                                                                                            
                            
            
                                    
            
            
                | 41 |  |  |      */ | 
            
                                                                                                            
                            
            
                                    
            
            
                | 42 |  |  |     public function loadXML(string $strXMLFile) : int | 
            
                                                                                                            
                            
            
                                    
            
            
                | 43 |  |  |     { | 
            
                                                                                                            
                            
            
                                    
            
            
                | 44 |  |  |         if (!file_exists($strXMLFile)) { | 
            
                                                                                                            
                            
            
                                    
            
            
                | 45 |  |  |             // if file not exist, there is nothing more to do... | 
            
                                                                                                            
                            
            
                                    
            
            
                | 46 |  |  |             $this->strErrorMsg = 'Missing form file: ' . $strXMLFile; | 
            
                                                                                                            
                            
            
                                    
            
            
                | 47 |  |  |             return self::E_FILE_NOT_EXIST; | 
            
                                                                                                            
                            
            
                                    
            
            
                | 48 |  |  |         } | 
            
                                                                                                            
                            
            
                                    
            
            
                | 49 |  |  |         // to get more detailed information about XML errors and XML schema validation | 
            
                                                                                                            
                            
            
                                    
            
            
                | 50 |  |  |         libxml_use_internal_errors(true); | 
            
                                                                                                            
                            
            
                                    
            
            
                | 51 |  |  |         $iResult = self::E_XML_ERROR; | 
            
                                                                                                            
                            
            
                                    
            
            
                | 52 |  |  |         $oXMLForm = new \DOMDocument(); | 
            
                                                                                                            
                            
            
                                    
            
            
                | 53 |  |  |         if ($oXMLForm->load($strXMLFile)) { | 
            
                                                                                                            
                            
            
                                    
            
            
                | 54 |  |  |             $iResult = self::E_OK; | 
                            
                    |  |  |  | 
                                                                                        
                                                                                     | 
            
                                                                                                            
                            
            
                                    
            
            
                | 55 |  |  |             // the XML schema is allways expected in the same directory as the XML file itself | 
            
                                                                                                            
                            
            
                                    
            
            
                | 56 |  |  |             $strXSDFile = pathinfo($strXMLFile, PATHINFO_DIRNAME) . DIRECTORY_SEPARATOR . self::XML_SCHEMA; | 
                            
                    |  |  |  | 
                                                                                        
                                                                                     | 
            
                                                                                                            
                            
            
                                    
            
            
                | 57 |  |  |             $oRoot = $oXMLForm->documentElement; | 
            
                                                                                                            
                            
            
                                    
            
            
                | 58 |  |  |             if ($this->bSchemaValidate && !$oXMLForm->schemaValidate($strXSDFile)) { | 
            
                                                                                                            
                            
            
                                    
            
            
                | 59 |  |  |                 $iResult = self::E_XSD_ERROR; | 
            
                                                                                                            
                            
            
                                    
            
            
                | 60 |  |  |             } elseif ($oRoot->nodeName != 'FormGenerator') { | 
            
                                                                                                            
                            
            
                                    
            
            
                | 61 |  |  |                 $this->strErrorMsg = 'Missing document root <FormGenerator> in form file: ' . $strXMLFile; | 
            
                                                                                                            
                            
            
                                    
            
            
                | 62 |  |  |                 $iResult = self::E_MISSING_ROOT; | 
            
                                                                                                            
                            
            
                                    
            
            
                | 63 |  |  |             } elseif (($oForm = $this->getXMLChild($oRoot, 'Form')) === null) { | 
            
                                                                                                            
                            
            
                                    
            
            
                | 64 |  |  |                 $this->strErrorMsg = 'Missing form elemnt <Form> as first child of the root: ' . $strXMLFile; | 
            
                                                                                                            
                            
            
                                    
            
            
                | 65 |  |  |                 $iResult = self::E_MISSING_FORM; | 
            
                                                                                                            
                            
            
                                    
            
            
                | 66 |  |  |             } else { | 
            
                                                                                                            
                            
            
                                    
            
            
                | 67 |  |  |                 // First we read some general infos for the form | 
            
                                                                                                            
                            
            
                                    
            
            
                | 68 |  |  |                 $this->readAdditionalXML($oForm); | 
            
                                                                                                            
                            
            
                                    
            
            
                | 69 |  |  |  | 
            
                                                                                                            
                            
            
                                    
            
            
                | 70 |  |  |                 // and iterate recursive through the child elements | 
            
                                                                                                            
                            
            
                                    
            
            
                | 71 |  |  |                 $iResult = $this->createChildElements($oForm, $this); | 
            
                                                                                                            
                            
            
                                    
            
            
                | 72 |  |  |             } | 
            
                                                                                                            
                            
            
                                    
            
            
                | 73 |  |  |         } | 
            
                                                                                                            
                            
            
                                    
            
            
                | 74 |  |  |         if ($iResult != self::E_OK && strlen($this->strErrorMsg) == 0) { | 
            
                                                                                                            
                            
            
                                    
            
            
                | 75 |  |  |             $this->strErrorMsg = ($iResult != self::E_XSD_ERROR ? 'XML error: ' : 'XSD Schema validation error: '); | 
            
                                                                                                            
                            
            
                                    
            
            
                | 76 |  |  |             $this->strErrorMsg .= $this->getFormatedXMLError($this->bPlainError); | 
            
                                                                                                            
                            
            
                                    
            
            
                | 77 |  |  |         } | 
            
                                                                                                            
                            
            
                                    
            
            
                | 78 |  |  |         libxml_clear_errors(); | 
            
                                                                                                            
                            
            
                                    
            
            
                | 79 |  |  |         return $iResult; | 
            
                                                                                                            
                            
            
                                    
            
            
                | 80 |  |  |     } | 
            
                                                                                                            
                            
            
                                    
            
            
                | 81 |  |  |  | 
            
                                                                                                            
                            
            
                                    
            
            
                | 82 |  |  |     /** | 
            
                                                                                                            
                            
            
                                    
            
            
                | 83 |  |  |      * Iterate through all childs of the given parent node and create the according element. | 
            
                                                                                                            
                            
            
                                    
            
            
                | 84 |  |  |      * This method cals itself recursive for all collection elements. | 
            
                                                                                                            
                            
            
                                    
            
            
                | 85 |  |  |      * @param \DOMElement $oXMLParent the DOM Element containing the infos for the formelement to create | 
            
                                                                                                            
                            
            
                                    
            
            
                | 86 |  |  |      * @param FormCollection $oFormParent the parent element in the form | 
            
                                                                                                            
                            
            
                                    
            
            
                | 87 |  |  |      * @return int | 
            
                                                                                                            
                            
            
                                    
            
            
                | 88 |  |  |      */ | 
            
                                                                                                            
                            
            
                                    
            
            
                | 89 |  |  |     protected function createChildElements(\DOMElement $oXMLParent, FormCollection $oFormParent) : int | 
            
                                                                                                            
                            
            
                                    
            
            
                | 90 |  |  |     { | 
            
                                                                                                            
                            
            
                                    
            
            
                | 91 |  |  |         $iResult = self::E_OK; | 
            
                                                                                                            
                            
            
                                    
            
            
                | 92 |  |  |         if (!$oXMLParent->hasChildNodes()) { | 
            
                                                                                                            
                            
            
                                    
            
            
                | 93 |  |  |             return $iResult; | 
            
                                                                                                            
                            
            
                                    
            
            
                | 94 |  |  |         } | 
            
                                                                                                            
                            
            
                                    
            
            
                | 95 |  |  |         foreach ($oXMLParent->childNodes as $oXMLChild) { | 
            
                                                                                                            
                            
            
                                    
            
            
                | 96 |  |  |             if (strtolower($oXMLChild->nodeName) == '#text') { | 
            
                                                                                                            
                            
            
                                    
            
            
                | 97 |  |  |                 continue; | 
            
                                                                                                            
                            
            
                                    
            
            
                | 98 |  |  |             } | 
            
                                                                                                            
                            
            
                                    
            
            
                | 99 |  |  |             $strClassname = __NAMESPACE__ . '\Form' . $oXMLChild->nodeName; | 
            
                                                                                                            
                            
            
                                    
            
            
                | 100 |  |  |             if (class_exists($strClassname) && is_subclass_of($strClassname, __NAMESPACE__ . '\FormElement')) { | 
            
                                                                                                            
                            
            
                                    
            
            
                | 101 |  |  |                 $oFormElement = $strClassname::fromXML($oXMLChild, $oFormParent); | 
            
                                                                                                            
                            
            
                                    
            
            
                | 102 |  |  |                 // recursive call for collection element (div, fieldset, line) | 
            
                                                                                                            
                            
            
                                    
            
            
                | 103 |  |  |                 if ($oFormElement instanceof FormCollection) { | 
            
                                                                                                            
                            
            
                                    
            
            
                | 104 |  |  |                     $iResult = $this->createChildElements($oXMLChild, $oFormElement); | 
            
                                                                                                            
                            
            
                                    
            
            
                | 105 |  |  |                 } | 
            
                                                                                                            
                            
            
                                    
            
            
                | 106 |  |  |             } else { | 
            
                                                                                                            
                            
            
                                    
            
            
                | 107 |  |  |                 $this->strErrorMsg = 'Unknown form element: ' . $oXMLChild->nodeName; | 
            
                                                                                                            
                            
            
                                    
            
            
                | 108 |  |  |                 $iResult = self::E_UNKNOWN_FORM_ELEMENT; | 
            
                                                                                                            
                            
            
                                    
            
            
                | 109 |  |  |             } | 
            
                                                                                                            
                            
            
                                    
            
            
                | 110 |  |  |             if ($iResult != self::E_OK) { | 
            
                                                                                                            
                            
            
                                    
            
            
                | 111 |  |  |                 break; | 
            
                                                                                                            
                            
            
                                    
            
            
                | 112 |  |  |             } | 
            
                                                                                                            
                            
            
                                    
            
            
                | 113 |  |  |         } | 
            
                                                                                                            
                            
            
                                    
            
            
                | 114 |  |  |         return $iResult; | 
            
                                                                                                            
                            
            
                                    
            
            
                | 115 |  |  |     } | 
            
                                                                                                            
                            
            
                                    
            
            
                | 116 |  |  |  | 
            
                                                                                                            
                            
            
                                    
            
            
                | 117 |  |  |     /** | 
            
                                                                                                            
                            
            
                                    
            
            
                | 118 |  |  |      * Get message to error occured. | 
            
                                                                                                            
                            
            
                                    
            
            
                | 119 |  |  |      * May contain multiple lines in case of any XML formating errors. | 
            
                                                                                                            
                            
            
                                    
            
            
                | 120 |  |  |      * @return string | 
            
                                                                                                            
                            
            
                                    
            
            
                | 121 |  |  |      */ | 
            
                                                                                                            
                            
            
                                    
            
            
                | 122 |  |  |     public function getErrorMsg() : string | 
            
                                                                                                            
                            
            
                                    
            
            
                | 123 |  |  |     { | 
            
                                                                                                            
                            
            
                                    
            
            
                | 124 |  |  |         return $this->strErrorMsg; | 
            
                                                                                                            
                            
            
                                    
            
            
                | 125 |  |  |     } | 
            
                                                                                                            
                            
            
                                    
            
            
                | 126 |  |  |  | 
            
                                                                                                            
                            
            
                                    
            
            
                | 127 |  |  |     /** | 
            
                                                                                                            
                            
            
                                    
            
            
                | 128 |  |  |      * Format error message as plain text (\n instead of <br/> for multiline errors) | 
            
                                                                                                            
                            
            
                                    
            
            
                | 129 |  |  |      * @param bool $bPlainError | 
            
                                                                                                            
                                                                
            
                                    
            
            
                | 130 |  |  |      */ | 
            
                                                                        
                            
            
                                    
            
            
                | 131 |  |  |     public function setPlainError(bool $bPlainError) : void | 
            
                                                                        
                            
            
                                    
            
            
                | 132 |  |  |     { | 
            
                                                                        
                            
            
                                    
            
            
                | 133 |  |  |         $this->bPlainError = $bPlainError; | 
            
                                                                                                            
                            
            
                                    
            
            
                | 134 |  |  |     } | 
            
                                                                                                            
                            
            
                                    
            
            
                | 135 |  |  |  | 
            
                                                                                                            
                            
            
                                    
            
            
                | 136 |  |  |     /** | 
            
                                                                                                            
                            
            
                                    
            
            
                | 137 |  |  |      * enable/disable the schema validation (default set to true) | 
            
                                                                                                            
                            
            
                                    
            
            
                | 138 |  |  |      * @param bool $bSchemaValidate | 
            
                                                                                                            
                            
            
                                    
            
            
                | 139 |  |  |      */ | 
            
                                                                                                            
                            
            
                                    
            
            
                | 140 |  |  |     public function setSchemaValidation(bool $bSchemaValidate) : void | 
            
                                                                                                            
                            
            
                                    
            
            
                | 141 |  |  |     { | 
            
                                                                                                            
                            
            
                                    
            
            
                | 142 |  |  |         $this->bSchemaValidate = $bSchemaValidate; | 
            
                                                                                                            
                            
            
                                    
            
            
                | 143 |  |  |     } | 
            
                                                                                                            
                                                                
            
                                    
            
            
                | 144 |  |  | } | 
            
                                                        
            
                                    
            
            
                | 145 |  |  |  |