56721801458aa1157eeed618e56a6f390d918791
[Packages/TYPO3.CMS.git] / typo3 / sysext / extensionmanager / Classes / Utility / Parser / ExtensionXmlPullParser.php
1 <?php
2 namespace TYPO3\CMS\Extensionmanager\Utility\Parser;
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 * Parser for TYPO3's extension.xml file.
19 *
20 * Depends on PHP ext/xmlreader which should be available
21 * with PHP >= 5.1.0.
22 */
23 class ExtensionXmlPullParser extends AbstractExtensionXmlParser
24 {
25 /**
26 * Class constructor.
27 */
28 public function __construct()
29 {
30 $this->requiredPhpExtensions = 'xmlreader';
31 }
32
33 /**
34 * Create required parser
35 *
36 * @return void
37 */
38 protected function createParser()
39 {
40 $this->objXml = new \XMLReader();
41 }
42
43 /**
44 * Method parses an extensions.xml file.
45 *
46 * @param string $file GZIP stream resource
47 * @return void
48 * @throws \TYPO3\CMS\Extensionmanager\Exception\ExtensionManagerException in case of parser error
49 */
50 public function parseXml($file)
51 {
52 $this->createParser();
53 if (!(is_object($this->objXml) && get_class($this->objXml) == 'XMLReader')) {
54 throw new \TYPO3\CMS\Extensionmanager\Exception\ExtensionManagerException('Unable to create XML parser.', 1342640540);
55 }
56 if ($this->objXml->xml(file_get_contents($file), 'utf-8') === false) {
57 throw new \TYPO3\CMS\Extensionmanager\Exception\ExtensionManagerException(sprintf('Unable to parse file resource %s.', $file));
58 }
59 while ($this->objXml->read()) {
60 if ($this->objXml->nodeType == \XMLReader::ELEMENT) {
61 $this->startElement($this->objXml->name);
62 } else {
63 if ($this->objXml->nodeType == \XMLReader::END_ELEMENT) {
64 $this->endElement($this->objXml->name);
65 } else {
66 continue;
67 }
68 }
69 }
70 $this->objXml->close();
71 }
72
73 /**
74 * Method is invoked when parser accesses start tag of an element.
75 *
76 * @param string $elementName element name at parser's current position
77 * @return void
78 */
79 protected function startElement($elementName)
80 {
81 switch ($elementName) {
82 case 'extension':
83 $this->extensionKey = $this->objXml->getAttribute('extensionkey');
84 break;
85 case 'version':
86 $this->version = $this->objXml->getAttribute('version');
87 break;
88 case 'downloadcounter':
89 // downloadcounter could be a child node of
90 // extension or version
91 if ($this->version == null) {
92 $this->extensionDownloadCounter = $this->getElementValue($elementName);
93 } else {
94 $this->versionDownloadCounter = $this->getElementValue($elementName);
95 }
96 break;
97 case 'title':
98 $this->title = $this->getElementValue($elementName);
99 break;
100 case 'description':
101 $this->description = $this->getElementValue($elementName);
102 break;
103 case 'state':
104 $this->state = $this->getElementValue($elementName);
105 break;
106 case 'reviewstate':
107 $this->reviewstate = $this->getElementValue($elementName);
108 break;
109 case 'category':
110 $this->category = $this->getElementValue($elementName);
111 break;
112 case 'lastuploaddate':
113 $this->lastuploaddate = $this->getElementValue($elementName);
114 break;
115 case 'uploadcomment':
116 $this->uploadcomment = $this->getElementValue($elementName);
117 break;
118 case 'dependencies':
119 $this->dependencies = $this->convertDependencies($this->getElementValue($elementName));
120 break;
121 case 'authorname':
122 $this->authorname = $this->getElementValue($elementName);
123 break;
124 case 'authoremail':
125 $this->authoremail = $this->getElementValue($elementName);
126 break;
127 case 'authorcompany':
128 $this->authorcompany = $this->getElementValue($elementName);
129 break;
130 case 'ownerusername':
131 $this->ownerusername = $this->getElementValue($elementName);
132 break;
133 case 't3xfilemd5':
134 $this->t3xfilemd5 = $this->getElementValue($elementName);
135 break;
136 }
137 }
138
139 /**
140 * Method is invoked when parser accesses end tag of an element.
141 *
142 * @param string $elementName: element name at parser's current position
143 * @return void
144 */
145 protected function endElement($elementName)
146 {
147 switch ($elementName) {
148 case 'extension':
149 $this->resetProperties(true);
150 break;
151 case 'version':
152 $this->notify();
153 $this->resetProperties();
154 break;
155 }
156 }
157
158 /**
159 * Method returns the value of an element at XMLReader's current
160 * position.
161 *
162 * Method will read until it finds the end of the given element.
163 * If element has no value, method returns NULL.
164 *
165 * @param string $elementName: name of element to retrieve it's value from
166 * @return string an element's value if it has a value, otherwise NULL
167 */
168 protected function getElementValue(&$elementName)
169 {
170 $value = null;
171 if (!$this->objXml->isEmptyElement) {
172 $value = '';
173 while ($this->objXml->read()) {
174 if ($this->objXml->nodeType == \XMLReader::TEXT || $this->objXml->nodeType == \XMLReader::CDATA || $this->objXml->nodeType == \XMLReader::WHITESPACE || $this->objXml->nodeType == \XMLReader::SIGNIFICANT_WHITESPACE) {
175 $value .= $this->objXml->value;
176 } else {
177 if ($this->objXml->nodeType == \XMLReader::END_ELEMENT && $this->objXml->name === $elementName) {
178 break;
179 }
180 }
181 }
182 }
183 return $value;
184 }
185 }