Updated for better reporting when loading from remote url fails. Now displays error...
[moodle.git] / rss / class.Atom.php
CommitLineData
0eb35827 1<?php
2/*
3 * Project: phAnTOM: a simple Atom parsing class
4 * File: atom_parse.php includes code for parsing
5 * Atom feeds, and returning an Atom object
6 * Author: Jeremy Ashcraft <ashcraft@13monkeys.com>
7 * Version: 0.1
8 * License: GPL
9 *
10 * The lastest version of phAnTOM can be obtained from:
11 * http://www.simplog.org
12 *
13 * For questions, help, comments, discussion, etc., please join the
14 * Simplog Atom mailing list:
15 * simplog-atom@lists.sourceforge.net
16 *
17 * This code is based on the MagpieRSS parser v0.52 written
18 * by Kellan Elliott-McCrea <kellan@protest.net> and released under the GPL
19 */
20
21
22/*
23 * The lastest Atom feed spec is at http://diveintomark.org/public/2003/08/atom02spec.txt
24 *
25 *
26 * RSS/Atom validators are readily available on the web at:
27 * http://feeds.archive.org/validator/
28 *
29 */
30
31class Atom {
32 /*
33 * Useage Example:
34 *
35 * $xml = "<?xml version="1.0"......
36 *
37 * $atom = new atom( $xml );
38 *
39 * // print feed title
40 * print $atom->feed['title'];
41 *
42 * // print the title of each entry
43 * foreach ($atom->entries as $entry ) {
44 * print $entry[title];
45 * }
46 *
47 */
48
49 var $parser;
50
51 var $current_item = array(); // item currently being parsed
52 var $entries = array(); // collection of parsed items
53 var $feed = array(); // hash of channel fields
54
55 var $parent_field = array('RDF');
56 var $author = array();
57 var $contributor = array();
58 var $current_field = '';
59 var $current_namespace = false;
60
61 var $ERROR = '';
62
63/*======================================================================*\
64 Function: MagpieRSS
65 Purpose: Constructor, sets up XML parser,parses source,
66 and populates object..
67 Input: String containing the RSS to be parsed
68\*======================================================================*/
69 function Atom ($source) {
70
71 # if PHP xml isn't compiled in, die
72 #
73 if (!function_exists('xml_parser_create')) {
74 $this->error( 'Failed to load PHP\'s XML Extension. ' .
75 'http://www.php.net/manual/en/ref.xml.php',
76 E_USER_ERROR );
77 }
78
79 $parser = @xml_parser_create();
80
81 if (!is_resource($parser))
82 {
83 $this->error( 'Failed to create an instance of PHP\'s XML parser. ' .
84 'http://www.php.net/manual/en/ref.xml.php',
85 E_USER_ERROR );
86 }
87
88
89 $this->parser = $parser;
90
91 # pass in parser, and a reference to this object
92 # setup handlers
93 #
94 xml_set_object( $this->parser, $this );
95 xml_set_element_handler($this->parser, 'start_element', 'end_element');
96 xml_set_character_data_handler( $this->parser, 'cdata' );
97
98
99 $status = xml_parse( $this->parser, $source );
100
101 if (! $status ) {
102 $errorcode = xml_get_error_code( $this->parser );
103 if ( $errorcode != XML_ERROR_NONE ) {
104 $xml_error = xml_error_string( $errorcode );
105 $error_line = xml_get_current_line_number($this->parser);
106 $error_col = xml_get_current_column_number($this->parser);
107 $errormsg = $xml_error .' at line '. $error_line .', column '. $error_col;
108
109 $this->error( $errormsg );
110 }
111 }
112
113 xml_parser_free( $this->parser );
114 }
115
116 function start_element ($p, $element, &$attrs) {
117 $element = strtolower( $element );
118 # check for a namespace, and split if found
119 #
120 $namespace = false;
121 if ( strpos( $element, ':' ) ) {
122 list($namespace, $element) = split( ':', $element, 2);
123 }
124 $this->current_field = $element;
125 if ( $namespace ) {
126 $this->current_namespace = $namespace;
127 }
128
129 if ( $element == 'feed' ) {
130 array_unshift( $this->parent_field, 'feed' );
131 } else if ( $element == 'items' ) {
132 array_unshift( $this->parent_field, 'items' );
133 } else if ( $element == 'entry' ) {
134 array_unshift( $this->parent_field, 'entry' );
135 } else if ( $element == 'author' ) {
136 array_unshift( $this->parent_field, 'author' );
137 } else if ( $element == 'contributor' ) {
138 array_unshift( $this->parent_field, 'contributor' );
139 }
140 }
141
142 function end_element ($p, $element) {
143 $element = strtolower($element);
144
145 if ( $element == 'entry' ) {
146 $this->entries[] = $this->current_item;
147 $this->current_item = array();
148 array_shift( $this->parent_field );
149 } else if ( $element == 'feed' or $element == 'items' or
150 $element == 'author' or $element == 'contributor') {
151 array_shift( $this->parent_field );
152 }
153
154 $this->current_field = '';
155 $this->current_namespace = false;
156 }
157
158 function cdata ($p, $text) {
159 # skip item, channel, items first time we see them
160 #
161 if ( $this->parent_field[0] == $this->current_field or
162 ! $this->current_field ) {
163 return;
164 } else if ( $this->parent_field[0] == 'feed') {
165 if ( $this->current_namespace ) {
166 $this->append(
167 $this->feed[ $this->current_namespace ][ $this->current_field ],
168 $text);
169 } else {
170 $this->append($this->feed[ $this->current_field ], $text);
171 }
172
173 } else if ( $this->parent_field[0] == 'entry' ) {
174 if ( $this->current_namespace ) {
175 $this->append(
176 $this->current_item[ $this->current_namespace ][$this->current_field ],
177 $text);
178 } else {
179 $this->append(
180 $this->current_item[ $this->current_field ],
181 $text );
182 }
183 } else if ( $this->parent_field[0] == 'author' ) {
184 if ( $this->current_namespace ) {
185 $this->append(
186 $this->author[ $this->current_namespace ][ $this->current_field ],
187 $text );
188 } else {
189 $this->append(
190 $this->author[ $this->current_field ],
191 $text );
192 }
193 } else if ( $this->parent_field[0] == 'contributor' ) {
194 if ( $this->current_namespace ) {
195 $this->append(
196 $this->contributor[ $this->current_namespace ][ $this->current_field ],
197 $text );
198 } else {
199 $this->append(
200 $this->contributor[ $this->current_field ],
201 $text );
202 }
203 }
204 }
205
206 function append (&$str1, $str2='') {
207 if (!isset($str1) ) {
208 $str1='';
209 }
210 $str1 .= $str2;
211 }
212
213 function error ($errormsg, $lvl=E_USER_WARNING) {
214 // append PHP's error message if track_errors enabled
215 if ( $php_errormsg ) {
216 $errormsg .= ' ('. $php_errormsg .')';
217 }
218 $this->ERROR = $errormsg;
219 if ( ATOM_DEBUG ) {
220 trigger_error( $errormsg, $lvl);
221 } else {
222 error_log( $errormsg, 0);
223 }
224 }
225
226
227/*======================================================================*\
228 EVERYTHING BELOW HERE IS FOR DEBUGGING PURPOSES
229\*======================================================================*/
230 function show_list () {
231 print '<ol>'."\n";
232 foreach ($this->entries as $item) {
233 print '<li>'. $this->show_entry( $item );
234 }
235 print '</ol>';
236 }
237
238 function show_feed () {
239 print 'feed:<br />';
240 print '<ul>';
241 while ( list($key, $value) = each( $this->feed ) ) {
242 print '<li> '. $key .': '. $value;
243 }
244 print '</ul>';
245 }
246
247 function show_entry ($item) {
248 print 'entry: '. $item[title];
249 print '<ul>';
250 while ( list($key, $value) = each($item) ) {
251 if ( is_array($value) ) {
252 print '<br /><strong>'. $key .'</strong>';
253 print '<ul>';
254 while ( list( $ns_key, $ns_value) = each( $value ) ) {
255 print '<li>'. $ns_key .': '. $ns_value;
256 }
257 print '</ul>';
258 } else {
259 print '<li> '. $key .': '. $value;
260 }
261 }
262 print '</ul>';
263 }
264
265/*======================================================================*\
266 END DEBUGGING FUNCTIONS
267\*======================================================================*/
268
269} # end class Atom
270?>