Passed
Pull Request — master (#119)
by
unknown
05:26 queued 01:12
created

XPathXMLGenerator   A

Complexity

Total Complexity 28

Size/Duplication

Total Lines 147
Duplicated Lines 0 %

Importance

Changes 0
Metric Value
eloc 54
dl 0
loc 147
rs 10
c 0
b 0
f 0
wmc 28

9 Methods

Rating   Name   Duplication   Size   Complexity  
A endToken() 0 3 1
A getXML() 0 3 1
A setText() 0 3 1
A __construct() 0 4 1
A startToken() 0 3 1
D loop() 0 69 20
A addAttribute() 0 3 1
A startAttribute() 0 3 1
A endAttribute() 0 3 1
1
<?php
2
namespace EWW\Dpf\Services;
3
4
/*
5
 * This file is part of the TYPO3 CMS project.
6
 *
7
 * It is free software; you can redistribute it and/or modify it under
8
 * the terms of the GNU General Public License, either version 2
9
 * of the License, or any later version.
10
 *
11
 * For the full copyright and license information, please read the
12
 * LICENSE.txt file that was distributed with this source code.
13
 *
14
 * The TYPO3 project - inspiring people to share!
15
 */
16
17
/**
18
 * Class XPathXMLGenerator
19
 * Generates XML elements for a given xpath
20
 * Notice: Not all sytax from the original xpath is implemented
21
 */
22
class XPathXMLGenerator
23
{
24
    protected $regex = '/[a-zA-Z:]+|[<=>]|[@][a-z][a-z0-9_\-\:\.]*|\[|\'.*?\'|".*?"|\]|\//';
25
26
    private $xmlWriter;
27
28
    public function __construct()
29
    {
30
        $this->xmlWriter = new \XMLWriter();
31
        $this->xmlWriter->openMemory();
32
    }
33
34
    function loop($xpath)
0 ignored issues
show
Best Practice introduced by
It is generally recommended to explicitly declare the visibility for methods.

Adding explicit visibility (private, protected, or public) is generally recommend to communicate to other developers how, and from where this method is intended to be used.

Loading history...
35
    {
36
        // split xpath to find predicates, attributes and texts
37
        preg_match_all($this->regex, $xpath, $matches);
38
        $i = 0;
39
        $predicateStack = 0;
40
        $tokenStack = 0;
41
        $insidePredicate = false;
42
        $predicateString = "";
43
        $loopStack = array();
44
45
        foreach ($matches[0] as $key => $value) {
46
            $firstChar = substr($value, 0, 1);
47
48
            if ($firstChar === '[' || $insidePredicate) {
49
                // get corresponding bracket
50
                $insidePredicate = true;
51
52
                $predicateString .= $value;
53
54
                if ($value === "]") {
55
                    $predicateStack--;
56
57
                    if ($predicateStack === 0) {
58
                        // corresponding bracket found
59
                        $insidePredicate = false;
60
61
                        if (!empty($predicateString)) {
62
                            // recursive call with predicate string
63
                            $this->loop(trim($predicateString, "[]"));
64
                            $predicateString = "";
65
                        }
66
                    }
67
                } else if ($value === "[") {
68
                    $predicateStack++;
69
                }
70
71
            } else if ($firstChar === '@') {
72
                // attribute found
73
                $this->startAttribute(substr($value, 1, strlen($value)));
74
                $loopStack[] = 'attribute';
75
76
            } else if ($firstChar === '"' || $firstChar === "'") {
77
                // string found
78
                $this->setText(trim($value, "'\""));
79
            } else if ($firstChar === ']') {
80
                $this->endAttribute();
81
                array_pop($loopStack);
82
                $predicateStack--;
83
84
            } else if ($firstChar !== '=' && $firstChar !== '[' && $firstChar !== '@' && $firstChar !== '/') {
85
                $this->startToken($value);
86
                $loopStack[] = 'token';
87
                if ($predicateStack > 0) {
88
                    $tokenStack++;
89
                }
90
            }
91
            $i++;
92
        }
93
94
        // end all open token and attributes in stacked order
95
        foreach (array_reverse($loopStack) as $key => $value) {
96
            if ($value === "attribute") {
97
                $this->endAttribute();
98
            } else if ($value === "token") {
99
                $this->endToken();
100
            }
101
        }
102
        $this->stack = array();
0 ignored issues
show
Bug Best Practice introduced by
The property stack does not exist. Although not strictly required by PHP, it is generally a best practice to declare properties explicitly.
Loading history...
103
104
    }
105
106
    /**
107
     * @param $value
108
     * Starts an XML element
109
     * <$value>
110
     */
111
    function startToken($value)
0 ignored issues
show
Best Practice introduced by
It is generally recommended to explicitly declare the visibility for methods.

Adding explicit visibility (private, protected, or public) is generally recommend to communicate to other developers how, and from where this method is intended to be used.

Loading history...
112
    {
113
        $this->xmlWriter->startElement($value);
114
    }
115
116
    /**
117
     * Ends the last token
118
     */
119
    function endToken()
0 ignored issues
show
Best Practice introduced by
It is generally recommended to explicitly declare the visibility for methods.

Adding explicit visibility (private, protected, or public) is generally recommend to communicate to other developers how, and from where this method is intended to be used.

Loading history...
120
    {
121
        $this->xmlWriter->endElement();
122
    }
123
124
    /**
125
     * @param $value
126
     * Adds content to an XML element or attribute
127
     * <mods:mods>$value</mods:mods>
128
     */
129
    function setText($value)
0 ignored issues
show
Best Practice introduced by
It is generally recommended to explicitly declare the visibility for methods.

Adding explicit visibility (private, protected, or public) is generally recommend to communicate to other developers how, and from where this method is intended to be used.

Loading history...
130
    {
131
        $this->xmlWriter->text($value);
132
    }
133
134
    /**
135
     * @param $name
136
     * @param $value
137
     * It adds an attribute with name and value to an XML element
138
     * <mods:mods $name=$value>
139
     */
140
    function addAttribute($name, $value)
0 ignored issues
show
Best Practice introduced by
It is generally recommended to explicitly declare the visibility for methods.

Adding explicit visibility (private, protected, or public) is generally recommend to communicate to other developers how, and from where this method is intended to be used.

Loading history...
141
    {
142
        $this->xmlWriter->writeAttribute($name, $value);
143
    }
144
145
    /**
146
     * @param $name
147
     * Starts an attribute
148
     */
149
    function startAttribute($name)
0 ignored issues
show
Best Practice introduced by
It is generally recommended to explicitly declare the visibility for methods.

Adding explicit visibility (private, protected, or public) is generally recommend to communicate to other developers how, and from where this method is intended to be used.

Loading history...
150
    {
151
        $this->xmlWriter->startAttribute($name);
152
    }
153
154
    /**
155
     * Ends the last started attribute
156
     */
157
    function endAttribute()
0 ignored issues
show
Best Practice introduced by
It is generally recommended to explicitly declare the visibility for methods.

Adding explicit visibility (private, protected, or public) is generally recommend to communicate to other developers how, and from where this method is intended to be used.

Loading history...
158
    {
159
        $this->xmlWriter->endAttribute();
160
    }
161
162
    /**
163
     * @return string
164
     * Returns the created XML
165
     */
166
    function getXML()
0 ignored issues
show
Best Practice introduced by
It is generally recommended to explicitly declare the visibility for methods.

Adding explicit visibility (private, protected, or public) is generally recommend to communicate to other developers how, and from where this method is intended to be used.

Loading history...
167
    {
168
        return $this->xmlWriter->outputMemory();
169
    }
170
}
171