Follow-up to #16315: added missing mirror push parser (Thanks to Marcus Krause)
[Packages/TYPO3.CMS.git] / typo3 / sysext / em / classes / parser / class.tx_em_parser_mirrorxmlpushparser.php
1 <?php
2 /***************************************************************
3 * Copyright notice
4 *
5 * (c) 2010 Marcus Krause <marcus#exp2010@t3sec.info>
6 * Steffen Kamper <info@sk-typo3.de>
7 * All rights reserved
8 *
9 * This script is part of the TYPO3 project. The TYPO3 project is
10 * free software; you can redistribute it and/or modify
11 * it under the terms of the GNU General Public License as published by
12 * the Free Software Foundation; either version 2 of the License, or
13 * (at your option) any later version.
14 *
15 * The GNU General Public License can be found at
16 * http://www.gnu.org/copyleft/gpl.html.
17 *
18 * This script is distributed in the hope that it will be useful,
19 * but WITHOUT ANY WARRANTY; without even the implied warranty of
20 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
21 * GNU General Public License for more details.
22 *
23 * This copyright notice MUST APPEAR in all copies of the script!
24 ***************************************************************/
25 /**
26 * class.tx_em_parser_mirrorxmlpushparser.php
27 *
28 * Module: Extension manager - mirrors.xml push-parser
29 *
30 * $Id$
31 *
32 * @author Marcus Krause <marcus#exp2010@t3sec.info>
33 * @author Steffen Kamper <info@sk-typo3.de>
34 */
35
36
37 /**
38 * Parser for TYPO3's mirrors.xml file.
39 *
40 * Depends on PHP ext/xml which should be available
41 * with PHP 4+. This is the parser used in TYPO3
42 * Core <= 4.3 (without the "collect all data in one
43 * array" behaviour).
44 * Notice: ext/xml has proven to be buggy with entities.
45 * Use at least PHP 5.2.9+ and libxml2 2.7.3+!
46 *
47 * @author Marcus Krause <marcus#exp2010@t3sec.info>
48 * @author Steffen Kamper <info@sk-typo3.de>
49 *
50 * @since 2010-11-17
51 * @package TYPO3
52 * @subpackage EM
53 */
54 class tx_em_Parser_MirrorXmlPushParser extends tx_em_Parser_MirrorXmlAbstractParser implements SplSubject {
55
56
57 /**
58 * Keeps list of attached observers.
59 *
60 * @var array
61 */
62 protected $observers = array();
63
64
65 /**
66 * Class constructor.
67 *
68 * @return void
69 */
70 function __construct() {
71 $this->requiredPHPExt = 'xml';
72
73 if ($this->isAvailable()) {
74 $this->objXML = xml_parser_create();
75 xml_set_object($this->objXML, $this);
76 }
77 }
78
79 /**
80 * Method parses a mirror.xml file.
81 *
82 * @param string $file: GZIP stream resource
83 * @return void
84 * @throws em_mirrorxml_Exception in case of XML parser errors
85 */
86 public function parseXML($file) {
87
88 if (!is_resource($this->objXML)) {
89 $this->throwException('Unable to create XML parser.');
90 }
91 // keep original character case of XML document
92 xml_parser_set_option($this->objXML, XML_OPTION_CASE_FOLDING, FALSE);
93 xml_parser_set_option($this->objXML, XML_OPTION_SKIP_WHITE, FALSE);
94 xml_parser_set_option($this->objXML, XML_OPTION_TARGET_ENCODING, 'utf-8');
95 xml_set_element_handler($this->objXML, 'startElement', 'endElement');
96 xml_set_character_data_handler($this->objXML, 'characterData');
97
98 if (!($fp = fopen($file, "r"))) {
99 $this->throwException(sprintf('Unable to open file ressource %s.', htmlspecialchars($file)));
100 }
101 while ($data = fread($fp, 4096)) {
102 if (!xml_parse($this->objXML, $data, feof($fp))) {
103 $this->throwException(sprintf('XML error %s in line %u of file ressource %s.',
104 xml_error_string(xml_get_error_code($this->objXML)),
105 xml_get_current_line_number($this->objXML),
106 htmlspecialchars($file)));
107 }
108 }
109 xml_parser_free($this->objXML);
110 }
111
112 /**
113 * Method is invoked when parser accesses start tag of an element.
114 *
115 * @param ressource $parser parser resource
116 * @param string $elementName: element name at parser's current position
117 * @param array $attrs: array of an element's attributes if available
118 * @return void
119 */
120 protected function startElement($parser, $elementName, $attrs) {
121 switch ($elementName) {
122 default:
123 $this->element = $elementName;
124 }
125 }
126
127 /**
128 * Method is invoked when parser accesses end tag of an element.
129 *
130 * @param ressource $parser parser resource
131 * @param string $elementName: element name at parser's current position
132 * @return void
133 */
134 protected function endElement($parser, $elementName) {
135 switch ($elementName) {
136 case 'mirror':
137 $this->notify();
138 $this->resetProperties();
139 break;
140 default:
141 $this->element = NULL;
142 }
143 }
144
145 /**
146 * Method is invoked when parser accesses any character other than elements.
147 *
148 * @param ressource $parser: parser ressource
149 * @param string $data: an element's value
150 * @return void
151 */
152 protected function characterData($parser, $data) {
153 if (isset($this->element)) {
154 switch ($this->element) {
155 case 'title':
156 $this->title = $data;
157 break;
158 case 'host':
159 $this->host = $data;
160 break;
161 case 'path':
162 $this->path = $data;
163 break;
164 case 'country':
165 $this->country = $data;
166 break;
167 case 'name':
168 $this->sponsorname = $data;
169 break;
170 case 'link':
171 $this->sponsorlink = $data;
172 break;
173 case 'logo':
174 $this->sponsorlogo = $data;
175 break;
176 }
177 }
178 }
179
180 /**
181 * Method attaches an observer.
182 *
183 * @access public
184 * @param SplObserver $observer an observer to attach
185 * @return void
186 * @see $observers, detach(), notify()
187 */
188 public function attach(SplObserver $observer) {
189 $this->observers[] = $observer;
190 }
191
192 /**
193 * Method detaches an attached observer
194 *
195 * @access public
196 * @param SplObserver $observer an observer to detach
197 * @return void
198 * @see $observers, attach(), notify()
199 */
200 public function detach(SplObserver $observer) {
201 $key = array_search($observer, $this->observers, true);
202 if (!($key === false)) {
203 unset($this->observers[$key]);
204 }
205 }
206
207 /**
208 * Method notifies attached observers.
209 *
210 * @access public
211 * @return void
212 * @see $observers, attach(), detach()
213 */
214 public function notify() {
215 foreach ($this->observers as $observer) {
216 $observer->update($this);
217 }
218 }
219 }
220
221 ?>