I am developing a website for the lacrosse club I am part of. As part of the site, it should display fixtures direct from the governing bodies website using rest.
this has worked on previous sites and worked when i was initially developing the modx based site.
Here is my snippet:
<?php
require_once('rest.inc');
$xmlfile = 'mens-fixtures-East+Coast.xml'; // local file name to store XML data
$xmlurl = 'http://www.southlacrosse.org.uk/rest/fixtures/mens/East+Coast'; // URL of data on South Lacrosse site
$httpCache = new httpCache($xmlurl,$xmlfile);
$httpCache->fetch();
// parse XML data into arrays for easier processing
if (!$httpCache->isError()) {
$parser = new simpleParser();
$xml = &$parser->parseString($httpCache->getXml());
}
// output page heading
?>
<?
if ($httpCache->isError()) {
echo '<p style="color: red;"><b>Error retrieving data : ' . $httpCache->getError()
. "</b></p>\n";
} elseif (!$xml) {
echo '<p style="color: red;"><b>Error converting data : ' . $parser->getError()
. "</b></p>\n";
} else {
?>
<table style="text-align: center;" cellpadding="3" cellspacing="2" border="0" width="100%">
<thead>
<tr>
<th>Date</th>
<th>Home</th>
<th/>
<th/>
<th/>
<th>Away</th>
<th>Competition</th>
</tr>
</thead>
<tbody>
<?
// Loop thru all the fixtures in the XML document
foreach ($xml->fixture as $fixture) {
$date = date('j M y',strtotime($fixture->date));
// note: competition is wrapped in htmlspecialchars() as it
// may contain &
?>
<tr>
<td><? echo $date; ?></td>
<td><? echo $fixture->{'home-team'}; ?></td>
<td><? echo $fixture->{'home-goals'}; ?></td>
<td><? if ($fixture->{'home-team'} || $fixture->{'away-team'}) echo 'v'; ?></td>
<td><? echo $fixture->{'away-goals'}; ?></td>
<td><? echo $fixture->{'away-team'}; ?></td>
<td><? echo htmlspecialchars($fixture->competition); ?></td>
</tr>
<? } // end of fixtures loop ?>
</tbody>
</table>
<?
} // end of else
// finish off page
?>
Here is the error when I try to call that snippet:
« MODx Parse Error »
MODx encountered the following error while attempting to parse the requested resource:
« PHP Parse Error »
PHP error debug
Error: touch() [function.touch]: Utime failed: Operation not permitted
Error type/ Nr.: Warning - 2
File: /home/x0149128/public_html/playlacrosse.co.uk/rest.inc
Line: 337
Line 337 source: touch($this->destCacheInfoFile, time(), $remoteDate);
Parser timing
MySQL: 0.0009 s (5 Requests)
PHP: 0.5093 s
Total: 0.5102 s
Here is the full rest.ini file
<?php
////////////////////////////////////////////////////
// Support for accessing REST services. Includes:
//
// simpleParser - XML parsing for PHP4/5
// cacheHeaders - allow dynamic pages to be cached in the browser
// httpCache - cache http requests (in this case REST xml pages)
//
// Copyright (C) 2006 Dave Slaughter [email protected]
//
// This library is free software; you can redistribute it and/or
// modify it under the terms of the GNU Lesser General Public
// License as published by the Free Software Foundation; either
// version 2.1 of the License, or (at your option) any later version.
//
// This library is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
// Lesser General Public License for more details.
//
// See http://www.gnu.org/copyleft/lesser.html
////////////////////////////////////////////////////
// simpleParser/simpleNode
//
// Classes for parsing XML into an array of objects in a similar
// fashion to SimpleXml in PHP5, but will also work in PHP4.
//
// If a node has attributes or children then it will be a simpleNode,
// otherwise a string. The root node will always be a simpleNode,
// and have a field "tag" to indicate the name of the root tag.
// Child nodes are added as fields of the same name to their parent node. If there
// are multiple child nodes with the same name then they will be defined as
// an array. Attributes are added as an array called "attributes".
//
// You can check if the node you have got is a simpleNode by using is_object().
//
// e.g. xml file
// <a>
// <b>B text</b>
// <c attr="c-attr">C text</c>
// <d>d one</d>
// <d>d two</d>
// </a>
// will parse to
// simpleNode {
// tag ="a",
// b = "B text"
// c = simplenode {
// attributes = array(1) { attr->"c-attr" }
// cdata = "C text"
// }
// d = array(2) { "d one", "d two" }
// }
//
// Simple example is
//
// $parser = new simpleParser();
// $xml = $parser.parseFile("somefile");
// echo "b=" . $xml->b . "\n"; // <b> node text, i.e. "B text"
// echo echo "c=" . $xml->c->cdata . "\n"; // <c> node text, i.e. "C text"
// foreach ($xml->d as $d) { // loop thru all <d> nodes
// echo "d=$d\n";
// }
class simpleNode {
var $tag;
var $cdata = '';
function simpleNode($tag, $attributes) {
$this->tag = $tag;
if (count($attributes) != 0) {
$this->attributes = $attributes;
}
}
// PHP5 will return cdata for this node
function __toString() {
return cdata;
}
function debugString() {
return $str = '[' . $this->tag
. ', attrCount=' . count($this->attributes)
. ', haschildren='.$this->hasChildren . ']';
}
} // end of class simpleNode
class simpleParser {
var $parser;
var $nodeStack;
var $currentNode;
function simpleParser() { }
/**
* Parse XML within a file into an array
* @return the parsed array, or FALSE for failure
*/
function parseFile($file) {
$this->_createParser();
if (!($fp = fopen($file, "r"))) {
die ("Cannot locate XML file : $xmlFile");
}
// read & parse
while ($data = fread($fp, 4096)) {
if (!xml_parse($this->parser, $data, feof($fp))) {
$this->error = sprintf("XML error: %s at line %d",
xml_error_string(xml_get_error_code($this->parser)),
xml_get_current_line_number($this->parser));
}
}
return $this->_freeParser();
}
/**
* Parse XML in a string into an array
* @return the parsed array, or FALSE for failure
*/
function parseString(&$data) {
$this->_createParser();
if (!xml_parse($this->parser, $data, TRUE)) {
$this->error = sprintf("XML error: %s at line %d",
xml_error_string(xml_get_error_code($this->parser)),
xml_get_current_line_number($this->parser));
}
return $this->_freeParser();
}
function getError() {
return $this->error;
}
function _createParser() {
$this->nodeStack = array();
$this->currentNode = -1;
unset($this->error);
$this->parser = xml_parser_create();
xml_parser_set_option($this->parser, XML_OPTION_CASE_FOLDING, 0);
xml_parser_set_option($this->parser, XML_OPTION_SKIP_WHITE, 1);
xml_set_object($this->parser, $this);
xml_set_element_handler($this->parser, "_tag_open", "_tag_close");
xml_set_character_data_handler($this->parser, "_cdata");
}
function _freeParser() {
xml_parser_free($this->parser);
if (isset($this->error)) {
unset($this->nodeStack);
return false;
}
$root =& $this->nodeStack[0];
unset($this->nodeStack);
return $root;
}
function _tag_open($parser, $tag, $attributes) {
// just pop the new node onto the stack
$this->nodeStack[] =& new simpleNode($tag,$attributes);
$this->currentNode++;
}
function _cdata($parser, $cdata) {
// add characrer data to the current node
$this->nodeStack[$this->currentNode]->cdata .= $cdata;
}
function _tag_close($parser, $tag) {
// get current node and tidy it up
$node =& $this->nodeStack[$this->currentNode];
$node->cdata = trim($node->cdata);
if ($node->cdata == '') {
unset($node->cdata);
}
// don't do anything to the root node, and also make sure we keep it
// to return from the parse functions
if ($this->currentNode > 0) {
$tag = $node->tag;
// if current node only has character data then add it as a
// string to the parent, but if it has children or attributes
// then add it as a simpleNode
if (!$node->hasChildren && count($node->attributes) == 0) {
$node = $node->cdata;
} else {
unset($node->hasChildren);
}
// get field "$node->tag" from parent (i.e. the field with the same name
// as this nodes tag), so we can add this node to it.
// need to decide if it was unset, a single value, or an array
$parent =& $this->nodeStack[$this->currentNode - 1];
if (!isset($parent->{$tag})) { // no field
$parent->{$tag} = $node;
$parent->hasChildren = true;
} elseif (count($parent->{$tag}) > 1) { // field is array
$parent->{$tag}[] = $node;
} else { // single field, so make array
$parent->{$tag} = array($parent->{$tag}, $node);
}
array_pop($this->nodeStack);
} else {
// tidy up root node
unset($node->hasChildren);
}
$this->currentNode--;
}
} // end of class simpleParser
// cacheHeaders - send "Not Modified" response, or set Last-Modified header
// $depends should be an array of dependant files
function cacheHeaders($depends) {
$modDate = getlastmod();
// check for extra dependancies from script
if (!empty($depends) && is_array($depends)) {
while (list($key,$item) = each ($depends)) {
$fileModDate = filemtime($item);
if ($fileModDate > $modDate) {
$modDate = $fileModDate;
}
}
}
$fileModDate = filemtime(__FILE__);
if ($fileModDate > $modDate) {
$modDate = $fileModDate;
}
// send HTTP 304 if possible
if (isset($_SERVER['HTTP_IF_MODIFIED_SINCE']) && strtotime($_SERVER['HTTP_IF_MODIFIED_SINCE']) >= $modDate) {
if (substr(php_sapi_name(), 0, 3) == 'cgi') {
header('Status: 304 Not Modified');
} else {
header('HTTP/1.1 304 Not Modified');
}
exit;
}
header('Last-Modified: '.gmdate('D, d M Y H:i:s', $modDate).' GMT');
}
// httpCache - cache an HTTP request for a REST service
class httpCache {
var $url;
var $destFile;
// Keep time we last asked the server for the XML file. Don't set the
// modified date on $destFile as 304 processing in cacheHeaders won't work
// correctly.
// Stores the remote server time in accessTime, so when we send the
// If-Modified-Since header it is the correct date. However, we also use
// this for checking if the cache is stale, so the local time is stored in
// the modifiedTime.
var $destCacheInfoFile;
var $timeout;
var $xml = null;
function httpCache($url, $destFile, $timeout=7200) {
$this->url = $url;
$this->destFile = $destFile;
$this->destCacheInfoFile = $destFile . '.cacheinfo';
$this->timeout = $timeout;
}
// remove the file from the cache
function delete() {
unlink($this->destFile);
unlink($this->destCacheInfoFile);
}
// Fetch the file from the remote server and cache it locally.
function fetch() {
if (file_exists($this->destFile) && file_exists($this->destCacheInfoFile)) {
$lastChecked = filemtime($this->destCacheInfoFile);
} else {
$lastChecked = 0;
}
if($lastChecked < (time() - $this->timeout)) {
// Initialize the session
$session = curl_init($this->url);
// Set curl options
curl_setopt($session, CURLOPT_HEADER, true);
curl_setopt($session, CURLOPT_RETURNTRANSFER, true);
// send the If-Modified-Since header with the last accessed time
if ($lastChecked != 0) {
$fileModGMT = gmdate('D, d M Y H:i:s', fileatime($this->destCacheInfoFile)).' GMT';
curl_setopt($session, CURLOPT_HTTPHEADER, array("If-Modified-Since: $fileModGMT"));
}
// Make the request
$response = curl_exec($session);
// Close the curl session
curl_close($session);
// Get HTTP Status code from the response
$statusCode = array();
if (!preg_match('/\d\d\d/', $response, $statusCode)) {
$this->error = 'Invalid response from '+$this->url;
}
// Check the HTTP Status code
switch( $statusCode[0] ) {
case 200:
// Success
break;
case 304:
// file on server was not modified - so update the file with the current date
// from the server (otherwise on the next view of this page we will try to
// fetch it again), and return the cached file contents (since the request
// returns no data)
$this->_setCacheInfoDate($response);
return;
default:
$this-> error = 'Retrieving data from '.$this->url.' failed, and returned an unexpected HTTP status of:' . $statusCode[0];
return;
}
// Get the XML from the response, bypassing the header
if (!($this->xml = strstr($response, '<?xml'))) {
$this->error = 'Cannot find XML in response from '.$this->url;
return;
}
$tmpf = tempnam('/tmp','YWS');
$fp = fopen($tmpf,"w");
fwrite($fp, $this->xml);
fclose($fp);
rename($tmpf, $this->destFile);
$this->_setCacheInfoDate($response);
}
}
// Return the actual XML data
function getXml() {
if ($this->xml) {
return $this->xml;
}
return file_get_contents($this->destFile);
}
function isError() {
return isset($this->error);
}
function getError() {
return $this->error;
}
// internal function to update modified/accessed date on cacheinfo file.
function _setCacheInfoDate($response) {
$modDate = array();
if (preg_match('/^Date: (.*)$/m', $response, $modDate)) {
$remoteDate = strtotime($modDate[1]);
touch($this->destCacheInfoFile, time(), $remoteDate);
} else {
touch($this->destCacheInfoFile);
}
}
} // end of class HttpCache
?>
Does anyone know what the problem is at all?