Passed
Pull Request — master (#119)
by
unknown
07:31
created

XPathXMLGenerator::endToken()   A

Complexity

Conditions 1
Paths 1

Size

Total Lines 3
Code Lines 1

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
cc 1
eloc 1
nc 1
nop 0
dl 0
loc 3
rs 10
c 0
b 0
f 0
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-zA-Z][a-zA-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 replaceLineBreaks($string) {
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
        return str_replace("\n", "%%nl%%", $string);
36
    }
37
38
    function undoReplaceLineBreaks($string) {
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...
39
        return str_replace("%%nl%%", "\n", $string);
40
    }
41
42
    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...
43
    {
44
        // split xpath to find predicates, attributes and texts
45
        preg_match_all($this->regex, $this->replaceLineBreaks($xpath), $matches);
46
        $i = 0;
47
        $predicateStack = 0;
48
        $tokenStack = 0;
49
        $insidePredicate = false;
50
        $predicateString = "";
51
        $loopStack = array();
52
53
        foreach ($matches[0] as $key => $value) {
54
            $firstChar = substr($value, 0, 1);
55
56
            if ($firstChar === '[' || $insidePredicate) {
57
                // get corresponding bracket
58
                $insidePredicate = true;
59
60
                $predicateString .= $value;
61
62
                if ($value === "]") {
63
                    $predicateStack--;
64
65
                    if ($predicateStack === 0) {
66
                        // corresponding bracket found
67
                        $insidePredicate = false;
68
69
                        if (!empty($predicateString)) {
70
                            // recursive call with predicate string
71
                            $this->loop(trim($predicateString, "[]"));
72
                            $predicateString = "";
73
                        }
74
                    }
75
                } else if ($value === "[") {
76
                    $predicateStack++;
77
                }
78
79
            } else if ($firstChar === '@') {
80
                // attribute found
81
                $this->startAttribute(substr($value, 1, strlen($value)));
82
                $loopStack[] = 'attribute';
83
84
            } else if ($firstChar === '"' || $firstChar === "'") {
85
                // string found
86
                $this->setText(trim($this->undoReplaceLineBreaks($value), "'\""));
87
            } else if ($firstChar === ']') {
88
                $this->endAttribute();
89
                array_pop($loopStack);
90
                $predicateStack--;
91
            } else if ($firstChar !== '=' && $firstChar !== '[' && $firstChar !== '@' && $firstChar !== '/' && $firstChar!== '.') {
92
                $this->startToken($value);
93
                $loopStack[] = 'token';
94
                if ($predicateStack > 0) {
95
                    $tokenStack++;
96
                }
97
            }
98
            $i++;
99
        }
100
101
        // end all open token and attributes in stacked order
102
        foreach (array_reverse($loopStack) as $key => $value) {
103
            if ($value === "attribute") {
104
                $this->endAttribute();
105
            } else if ($value === "token") {
106
                $this->endToken();
107
            }
108
        }
109
        $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...
110
111
    }
112
113
    /**
114
     * @param $value
115
     * Starts an XML element
116
     * <$value>
117
     */
118
    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...
119
    {
120
        $this->xmlWriter->startElement($value);
121
    }
122
123
    /**
124
     * Ends the last token
125
     */
126
    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...
127
    {
128
        $this->xmlWriter->endElement();
129
    }
130
131
    /**
132
     * @param $value
133
     * Adds content to an XML element or attribute
134
     * <mods:mods>$value</mods:mods>
135
     */
136
    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...
137
    {
138
        $this->xmlWriter->text($value);
139
    }
140
141
    /**
142
     * @param $name
143
     * @param $value
144
     * It adds an attribute with name and value to an XML element
145
     * <mods:mods $name=$value>
146
     */
147
    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...
148
    {
149
        $this->xmlWriter->writeAttribute($name, $value);
150
    }
151
152
    /**
153
     * @param $name
154
     * Starts an attribute
155
     */
156
    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...
157
    {
158
        $this->xmlWriter->startAttribute($name);
159
    }
160
161
    /**
162
     * Ends the last started attribute
163
     */
164
    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...
165
    {
166
        $this->xmlWriter->endAttribute();
167
    }
168
169
    /**
170
     * @return string
171
     * Returns the created XML
172
     */
173
    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...
174
    {
175
        return $this->xmlWriter->outputMemory();
176
    }
177
}
178