Set default captcha type to none
[GitHub/WoltLab/WCF.git] / wcfsetup / install / files / lib / util / XMLWriter.class.php
CommitLineData
6f5d6b49 1<?php
a9229942 2
6f5d6b49 3namespace wcf\util;
a9229942 4
6f5d6b49
AE
5use wcf\system\exception\SystemException;
6
7/**
8 * Writes XML documents.
a9229942
TD
9 *
10 * @author Alexander Ebert
11 * @copyright 2001-2019 WoltLab GmbH
12 * @license GNU Lesser General Public License <http://opensource.org/licenses/lgpl-license.php>
6f5d6b49 13 */
a9229942
TD
14class XMLWriter
15{
16 /**
17 * true, if a document is still processed
18 * @var bool
19 */
20 protected $activeDocument = false;
21
22 /**
23 * number of open elements
24 * @var int
25 */
26 protected $openElements = 0;
27
28 /**
29 * XMLWriter object
30 * @var \XMLWriter
31 */
32 protected $xml;
33
34 /**
35 * Creates a new XML document.
36 *
37 * @param string $rootElement
38 * @param string $namespace
39 * @param string $schemaLocation
40 * @param string[] $attributes
41 * @throws SystemException
42 */
43 public function beginDocument($rootElement, $namespace, $schemaLocation, array $attributes = [])
44 {
45 if ($this->activeDocument) {
46 throw new SystemException("Could not begin a new document unless the previous is finished");
47 }
48
49 if ($this->xml === null) {
50 $this->xml = new \XMLWriter();
51 $this->xml->openMemory();
52 $this->xml->setIndent(true);
53 $this->xml->setIndentString("\t");
54 }
55
56 $this->xml->startDocument('1.0', 'UTF-8');
57 $this->startElement($rootElement);
58 $attributes = \array_merge(
59 [
60 'xmlns' => $namespace,
61 'xmlns:xsi' => 'http://www.w3.org/2001/XMLSchema-instance',
62 'xsi:schemaLocation' => $namespace . ' ' . $schemaLocation,
63 ],
64 // `xmlns`, `xmlns:xsi`, and `xsi:schemaLocation` are explicitly set
65 // as first attributes in that order
66 \array_filter($attributes, static function ($attributeName) {
67 return !\in_array($attributeName, ['xmlns', 'xmlns:xsi', 'xsi:schemaLocation']);
68 }, \ARRAY_FILTER_USE_KEY)
69 );
70 $this->writeAttributes($attributes);
71
72 $this->activeDocument = true;
73 }
74
75 /**
76 * Returns the generated XML document or writes it to given filename. All open
77 * elements will be automatically closed before flushing.
78 *
79 * @param string $filename
80 * @return mixed
81 */
82 public function endDocument($filename = '')
83 {
84 // mark document as done
85 $this->activeDocument = false;
86
87 // close all open tags
88 while ($this->openElements) {
89 $this->endElement();
90 }
91
92 if (empty($filename)) {
93 // return XML as string
94 return $this->xml->flush(true);
95 } else {
96 // write to file
97 \file_put_contents($filename, $this->xml->flush(true));
98 }
99 }
100
101 /**
102 * Begins a new element.
103 *
104 * @param string $element
105 * @param string[] $attributes
106 */
107 public function startElement($element, array $attributes = [])
108 {
109 $this->xml->startElement($element);
110 $this->openElements++;
111
112 if (!empty($attributes)) {
113 $this->writeAttributes($attributes);
114 }
115 }
116
117 /**
118 * Ends the last opened element.
119 */
120 public function endElement()
121 {
122 if ($this->openElements) {
123 $this->xml->endElement();
124 $this->openElements--;
125 }
126 }
127
128 /**
129 * Writes an element directly.
130 *
131 * @param string $element
132 * @param string $cdata
133 * @param string[] $attributes
134 * @param bool $writeAsCdata
135 */
136 public function writeElement($element, $cdata, array $attributes = [], $writeAsCdata = true)
137 {
138 $this->startElement($element);
139
140 // write attributes
141 if (!empty($attributes)) {
142 $this->writeAttributes($attributes);
143 }
144
145 // content
146 if ($cdata !== '') {
147 if ($writeAsCdata) {
148 $this->xml->writeCdata(StringUtil::escapeCDATA($cdata));
149 } else {
150 $this->xml->text($cdata);
151 }
152 }
153
154 $this->endElement();
155 }
156
157 /**
158 * Writes a comment.
159 *
160 * @param string $comment
161 * @since 5.2
162 */
163 public function writeComment($comment)
164 {
165 $this->xml->writeComment($comment);
166 }
167
168 /**
169 * Writes an attribute to last opened element.
170 *
171 * @param string $attribute
172 * @param string $value
173 */
174 public function writeAttribute($attribute, $value)
175 {
176 $this->writeAttributes([$attribute => $value]);
177 }
178
179 /**
180 * Writes a list of attributes to last opened element.
181 *
182 * @param string[] $attributes
183 */
184 public function writeAttributes(array $attributes)
185 {
186 foreach ($attributes as $attribute => $value) {
187 $this->xml->writeAttribute($attribute, $value);
188 }
189 }
6f5d6b49 190}