[BUGFIX] Remote extensions aren't displayed
[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 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 * @package TYPO3
40 * @subpackage EM
41 */
42 class ExtensionXmlPullParser extends \TYPO3\CMS\Extensionmanager\Utility\Parser\ExtensionXmlAbstractParser implements \SplSubject {
43
44 /**
45 * Keeps list of attached observers.
46 *
47 * @var SplObserver[]
48 */
49 protected $observers = array();
50
51 /**
52 * Class constructor.
53 */
54 public function __construct() {
55 $this->requiredPhpExtensions = 'xmlreader';
56 if ($this->isAvailable()) {
57 $this->objXml = new \XMLReader();
58 }
59 }
60
61 /**
62 * Method parses an extensions.xml file.
63 *
64 * @param string $file GZIP stream resource
65 * @return void
66 * @throws \TYPO3\CMS\Extensionmanager\Exception\ExtensionManagerException in case of parser error
67 */
68 public function parseXml($file) {
69 if (!(is_object($this->objXml) && get_class($this->objXml) == 'XMLReader')) {
70 throw new \TYPO3\CMS\Extensionmanager\Exception\ExtensionManagerException('Unable to create XML parser.', 1342640540);
71 }
72 if ($this->objXml->open($file, 'utf-8') === FALSE) {
73 throw new \TYPO3\CMS\Extensionmanager\Exception\ExtensionManagerException(sprintf('Unable to open file resource %s.', htmlspecialchars($file)));
74 }
75 while ($this->objXml->read()) {
76 if ($this->objXml->nodeType == \XMLReader::ELEMENT) {
77 $this->startElement($this->objXml->name);
78 } else {
79 if ($this->objXml->nodeType == \XMLReader::END_ELEMENT) {
80 $this->endElement($this->objXml->name);
81 } else {
82 continue;
83 }
84 }
85 }
86 $this->objXml->close();
87 }
88
89 /**
90 * Method is invoked when parser accesses start tag of an element.
91 *
92 * @param string $elementName element name at parser's current position
93 * @return void
94 */
95 protected function startElement($elementName) {
96 switch ($elementName) {
97 case 'extension':
98 $this->extensionKey = $this->objXml->getAttribute('extensionkey');
99 break;
100 case 'version':
101 $this->version = $this->objXml->getAttribute('version');
102 break;
103 case 'downloadcounter':
104 // downloadcounter could be a child node of
105 // extension or version
106 if ($this->version == NULL) {
107 $this->extensionDownloadCounter = $this->getElementValue($elementName);
108 } else {
109 $this->versionDownloadCounter = $this->getElementValue($elementName);
110 }
111 break;
112 case 'title':
113 $this->title = $this->getElementValue($elementName);
114 break;
115 case 'description':
116 $this->description = $this->getElementValue($elementName);
117 break;
118 case 'state':
119 $this->state = $this->getElementValue($elementName);
120 break;
121 case 'reviewstate':
122 $this->reviewstate = $this->getElementValue($elementName);
123 break;
124 case 'category':
125 $this->category = $this->getElementValue($elementName);
126 break;
127 case 'lastuploaddate':
128 $this->lastuploaddate = $this->getElementValue($elementName);
129 break;
130 case 'uploadcomment':
131 $this->uploadcomment = $this->getElementValue($elementName);
132 break;
133 case 'dependencies':
134 $this->dependencies = $this->convertDependencies($this->getElementValue($elementName));
135 break;
136 case 'authorname':
137 $this->authorname = $this->getElementValue($elementName);
138 break;
139 case 'authoremail':
140 $this->authoremail = $this->getElementValue($elementName);
141 break;
142 case 'authorcompany':
143 $this->authorcompany = $this->getElementValue($elementName);
144 break;
145 case 'ownerusername':
146 $this->ownerusername = $this->getElementValue($elementName);
147 break;
148 case 't3xfilemd5':
149 $this->t3xfilemd5 = $this->getElementValue($elementName);
150 break;
151 }
152 }
153
154 /**
155 * Method is invoked when parser accesses end tag of an element.
156 *
157 * @param string $elementName: element name at parser's current position
158 * @return void
159 */
160 protected function endElement($elementName) {
161 switch ($elementName) {
162 case 'extension':
163 $this->resetProperties(TRUE);
164 break;
165 case 'version':
166 $this->notify();
167 $this->resetProperties();
168 break;
169 }
170 }
171
172 /**
173 * Method returns the value of an element at XMLReader's current
174 * position.
175 *
176 * Method will read until it finds the end of the given element.
177 * If element has no value, method returns NULL.
178 *
179 * @param string $elementName: name of element to retrieve it's value from
180 * @return string an element's value if it has a value, otherwise NULL
181 */
182 protected function getElementValue(&$elementName) {
183 $value = NULL;
184 if (!$this->objXml->isEmptyElement) {
185 $value = '';
186 while ($this->objXml->read()) {
187 if ((($this->objXml->nodeType == \XMLReader::TEXT || $this->objXml->nodeType == \XMLReader::CDATA) || $this->objXml->nodeType == \XMLReader::WHITESPACE) || $this->objXml->nodeType == \XMLReader::SIGNIFICANT_WHITESPACE) {
188 $value .= $this->objXml->value;
189 } else {
190 if ($this->objXml->nodeType == \XMLReader::END_ELEMENT && $this->objXml->name === $elementName) {
191 break;
192 }
193 }
194 }
195 }
196 return $value;
197 }
198
199 /**
200 * Method attaches an observer.
201 *
202 * @param SplObserver $observer: an observer to attach
203 * @return void
204 */
205 public function attach(\SplObserver $observer) {
206 $this->observers[] = $observer;
207 }
208
209 /**
210 * Method detaches an attached observer
211 *
212 * @param SplObserver $observer: an observer to detach
213 * @return void
214 */
215 public function detach(\SplObserver $observer) {
216 $key = array_search($observer, $this->observers, TRUE);
217 if (!($key === FALSE)) {
218 unset($this->observers[$key]);
219 }
220 }
221
222 /**
223 * Method notifies attached observers.
224 *
225 * @return void
226 */
227 public function notify() {
228 foreach ($this->observers as $observer) {
229 $observer->update($this);
230 }
231 }
232
233 }
234
235
236 ?>