771f1b721f4ac4a81aeb1e31f6b882c80ac9d849
[Packages/TYPO3.CMS.git] / typo3 / sysext / extensionmanager / Classes / Utility / Parser / ExtensionXmlPullParser.php
1 <?php
2 namespace TYPO3\CMS\Extensionmanager\Utility\Parser;
3
4 /***************************************************************
5 * Copyright notice
6 *
7 * (c) 2010-2013 Marcus Krause <marcus#exp2010@t3sec.info>
8 * Steffen Kamper <info@sk-typo3.de>
9 * All rights reserved
10 *
11 * This script is part of the TYPO3 project. The TYPO3 project is
12 * free software; you can redistribute it and/or modify
13 * it under the terms of the GNU General Public License as published by
14 * the Free Software Foundation; either version 2 of the License, or
15 * (at your option) any later version.
16 *
17 * The GNU General Public License can be found at
18 * http://www.gnu.org/copyleft/gpl.html.
19 *
20 * This script is distributed in the hope that it will be useful,
21 * but WITHOUT ANY WARRANTY; without even the implied warranty of
22 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
23 * GNU General Public License for more details.
24 *
25 * This copyright notice MUST APPEAR in all copies of the script!
26 ***************************************************************/
27 /**
28 * Module: Extension manager - Extension.xml pull-parser
29 */
30 /**
31 * Parser for TYPO3's extension.xml file.
32 *
33 * Depends on PHP ext/xmlreader which should be available
34 * with PHP >= 5.1.0.
35 *
36 * @author Marcus Krause <marcus#exp2010@t3sec.info>
37 * @author Steffen Kamper <info@sk-typo3.de>
38 * @since 2010-02-09
39 */
40 class ExtensionXmlPullParser extends AbstractExtensionXmlParser {
41
42 /**
43 * Class constructor.
44 */
45 public function __construct() {
46 $this->requiredPhpExtensions = 'xmlreader';
47 }
48
49 /**
50 * Create required parser
51 *
52 * @return void
53 */
54 protected function createParser() {
55 $this->objXml = new \XMLReader();
56 }
57
58 /**
59 * Method parses an extensions.xml file.
60 *
61 * @param string $file GZIP stream resource
62 * @return void
63 * @throws \TYPO3\CMS\Extensionmanager\Exception\ExtensionManagerException in case of parser error
64 */
65 public function parseXml($file) {
66 $this->createParser();
67 if (!(is_object($this->objXml) && get_class($this->objXml) == 'XMLReader')) {
68 throw new \TYPO3\CMS\Extensionmanager\Exception\ExtensionManagerException('Unable to create XML parser.', 1342640540);
69 }
70 if ($this->objXml->open($file, 'utf-8') === FALSE) {
71 throw new \TYPO3\CMS\Extensionmanager\Exception\ExtensionManagerException(sprintf('Unable to open file resource %s.', htmlspecialchars($file)));
72 }
73 while ($this->objXml->read()) {
74 if ($this->objXml->nodeType == \XMLReader::ELEMENT) {
75 $this->startElement($this->objXml->name);
76 } else {
77 if ($this->objXml->nodeType == \XMLReader::END_ELEMENT) {
78 $this->endElement($this->objXml->name);
79 } else {
80 continue;
81 }
82 }
83 }
84 $this->objXml->close();
85 }
86
87 /**
88 * Method is invoked when parser accesses start tag of an element.
89 *
90 * @param string $elementName element name at parser's current position
91 * @return void
92 */
93 protected function startElement($elementName) {
94 switch ($elementName) {
95 case 'extension':
96 $this->extensionKey = $this->objXml->getAttribute('extensionkey');
97 break;
98 case 'version':
99 $this->version = $this->objXml->getAttribute('version');
100 break;
101 case 'downloadcounter':
102 // downloadcounter could be a child node of
103 // extension or version
104 if ($this->version == NULL) {
105 $this->extensionDownloadCounter = $this->getElementValue($elementName);
106 } else {
107 $this->versionDownloadCounter = $this->getElementValue($elementName);
108 }
109 break;
110 case 'title':
111 $this->title = $this->getElementValue($elementName);
112 break;
113 case 'description':
114 $this->description = $this->getElementValue($elementName);
115 break;
116 case 'state':
117 $this->state = $this->getElementValue($elementName);
118 break;
119 case 'reviewstate':
120 $this->reviewstate = $this->getElementValue($elementName);
121 break;
122 case 'category':
123 $this->category = $this->getElementValue($elementName);
124 break;
125 case 'lastuploaddate':
126 $this->lastuploaddate = $this->getElementValue($elementName);
127 break;
128 case 'uploadcomment':
129 $this->uploadcomment = $this->getElementValue($elementName);
130 break;
131 case 'dependencies':
132 $this->dependencies = $this->convertDependencies($this->getElementValue($elementName));
133 break;
134 case 'authorname':
135 $this->authorname = $this->getElementValue($elementName);
136 break;
137 case 'authoremail':
138 $this->authoremail = $this->getElementValue($elementName);
139 break;
140 case 'authorcompany':
141 $this->authorcompany = $this->getElementValue($elementName);
142 break;
143 case 'ownerusername':
144 $this->ownerusername = $this->getElementValue($elementName);
145 break;
146 case 't3xfilemd5':
147 $this->t3xfilemd5 = $this->getElementValue($elementName);
148 break;
149 }
150 }
151
152 /**
153 * Method is invoked when parser accesses end tag of an element.
154 *
155 * @param string $elementName: element name at parser's current position
156 * @return void
157 */
158 protected function endElement($elementName) {
159 switch ($elementName) {
160 case 'extension':
161 $this->resetProperties(TRUE);
162 break;
163 case 'version':
164 $this->notify();
165 $this->resetProperties();
166 break;
167 }
168 }
169
170 /**
171 * Method returns the value of an element at XMLReader's current
172 * position.
173 *
174 * Method will read until it finds the end of the given element.
175 * If element has no value, method returns NULL.
176 *
177 * @param string $elementName: name of element to retrieve it's value from
178 * @return string an element's value if it has a value, otherwise NULL
179 */
180 protected function getElementValue(&$elementName) {
181 $value = NULL;
182 if (!$this->objXml->isEmptyElement) {
183 $value = '';
184 while ($this->objXml->read()) {
185 if ($this->objXml->nodeType == \XMLReader::TEXT || $this->objXml->nodeType == \XMLReader::CDATA || $this->objXml->nodeType == \XMLReader::WHITESPACE || $this->objXml->nodeType == \XMLReader::SIGNIFICANT_WHITESPACE) {
186 $value .= $this->objXml->value;
187 } else {
188 if ($this->objXml->nodeType == \XMLReader::END_ELEMENT && $this->objXml->name === $elementName) {
189 break;
190 }
191 }
192 }
193 }
194 return $value;
195 }
196 }