Passed
Push — main ( 42d660...97d8d6 )
by Stefan
02:38
created

XMLForm::loadXML()   B

Complexity

Conditions 6
Paths 5

Size

Total Lines 34
Code Lines 25

Duplication

Lines 0
Ratio 0 %

Importance

Changes 1
Bugs 0 Features 0
Metric Value
cc 6
eloc 25
nc 5
nop 1
dl 0
loc 34
rs 8.8977
c 1
b 0
f 0
1
<?php
2
declare(strict_types=1);
3
4
namespace SKien\Formgenerator;
5
6
/**
7
 * 
8
 *
9
 * @package Formgenerator
10
 * @author Stefanius <[email protected]>
11
 * @copyright MIT License - see the LICENSE file for details
12
 */
13
class XMLForm extends FormGenerator
14
{
15
    const E_OK = 0;
16
    const E_FILE_NOT_EXIST = 1;
17
    const E_INVALID_FORM = 2;
18
    const E_INVALID_FORM_ELEMENT = 3;
19
    
20
    /** @var string error message     */
21
    protected string $strErrorMsg = '';
22
    /** @var bool error message as plain text (\n instead of &lt;br/&gt;) */
23
    protected bool $bPlainError = false;
24
    
25
    /**
26
     * no constructor - always use the constructor of the parent! 
27
     */
28
29
    /**
30
     * Load form from the given XML file. 
31
     * @param string $strXMLFile
32
     * @return int
33
     */
34
    public function loadXML(string $strXMLFile) : int
35
    {
36
        $iResult = self::E_OK;
37
        if (!file_exists($strXMLFile)) {
38
            $this->strErrorMsg = 'Missing form file: ' . $strXMLFile;
39
            return self::E_FILE_NOT_EXIST;
40
        }
41
        libxml_use_internal_errors(true);
42
        $oXMLForm = new \DOMDocument();
43
        if ($oXMLForm->load($strXMLFile)) {
44
            $oRoot = $oXMLForm->documentElement;
45
            if ($oRoot->nodeName != 'Form') {
46
                $this->strErrorMsg = 'Missing document root &lt;Form&gt; in form file: ' . $strXMLFile;
47
                return self::E_INVALID_FORM;
48
            }
49
            // First we read some general infos for the form
50
            $this->readAdditionalXML($oRoot);
51
            
52
            // and iterate recursive through the child elements
53
            $this->createChildElements($oRoot, $this);
54
        } else {
55
            $this->strErrorMsg = 'XML Parser Error: ';
56
            $errors = libxml_get_errors();
57
            $aLevel = [LIBXML_ERR_WARNING => 'Warning ', LIBXML_ERR_ERROR => 'Error ', LIBXML_ERR_FATAL => 'Fatal Error '];
58
            $strCR = ($this->bPlainError ? PHP_EOL : '<br/>');
59
            foreach ($errors as $error) {
60
                $this->strErrorMsg .= $strCR . $aLevel[$error->level] . $error->code;
61
                $this->strErrorMsg .= ' (Line ' . $error->line . ', Col ' . $error->column . ') ';
62
                $this->strErrorMsg .= trim($error->message);
63
            }
64
            $iResult = self::E_INVALID_FORM;
65
        }
66
        libxml_clear_errors();
67
        return $iResult;
68
    }
69
70
    /**
71
     * Iterate through all childs of the given parent node and create the according element.
72
     * This method cals itself recursive for all collection elements. 
73
     * @param \DOMElement $oXMLParent the DOM Element containing the infos for the formelement to create
74
     * @param FormCollection $oFormParent the parent element in the form
75
     * @return int
76
     */
77
    protected function createChildElements(\DOMElement $oXMLParent, FormCollection $oFormParent) : int
78
    {
79
        $iResult = self::E_OK;
80
        if (!$oXMLParent->hasChildNodes()) {
81
            return $iResult;
82
        }
83
        foreach ($oXMLParent->childNodes as $oXMLChild) {
84
            if (strtolower($oXMLChild->nodeName) == '#text') {
85
                continue;
86
            }
87
            $strClassname = __NAMESPACE__ . '\Form' . $oXMLChild->nodeName;
88
            if (class_exists($strClassname) && is_subclass_of($strClassname, __NAMESPACE__ . '\FormElement')) {
89
                $oFormElement = $strClassname::fromXML($oXMLChild, $oFormParent);
90
                // recursive call for collection element (div, fieldset, line)
91
                if ($oFormElement instanceof FormCollection) {
92
                    $iResult = $this->createChildElements($oXMLChild, $oFormElement);
93
                }
94
            } else {
95
                $iResult = self::E_INVALID_FORM_ELEMENT;
96
            }
97
            if ($iResult != self::E_OK) {
98
                break;
99
            }
100
        }
101
        return $iResult;
102
    }
103
    
104
    /**
105
     * Get message to error occured.
106
     * May contain multiple lines in case of any XML formating errors. 
107
     * @return string
108
     */
109
    public function getErrorMsg() : string
110
    {
111
        return $this->strErrorMsg;
112
    }
113
    
114
    /**
115
     * Format error message as plain text (\n instead of <br/> for multiline errors)
116
     * @param bool $bPlainError
117
     */
118
    public function setPlainError(bool $bPlainError) : void
119
    {
120
        $this->bPlainError = $bPlainError;
121
    }
122
}
123