function indexRSS() { /* create an RSS feed -------------------------------------------------------------------------------------------------------------- */ $rss = new DOMTemplate(file_get_contents(FORUM_LIB . 'rss-template.xml')); $rss->set(array('/rss/channel/title' => FORUM_NAME . (PATH ? str_replace('/', ' / ', PATH) : ''), '/rss/channel/link' => FORUM_URL . url(PATH_URL)))->remove('/rss/channel/category'); //get list of threads, sort by date; most recently modified first $threads = preg_grep('/\\.rss$/', scandir('.')); array_multisort(array_map('filemtime', $threads), SORT_DESC, $threads); $items = $rss->repeat('/rss/channel/item'); //get the last post made in each thread as an RSS item foreach (array_slice($threads, 0, FORUM_THREADS) as $thread) { if ($xml = @simplexml_load_file($thread)) { //if the RSS feed is valid if ($item = @$xml->channel->item[0]) { //if the feed has any items $items->set(array('./title' => $item->title, './link' => $item->link, './author' => $item->author, './pubDate' => gmdate('r', strtotime($item->pubDate)), './description' => $item->description))->remove(array('./category[.="deleted"]' => !$item->xpath('category[.="deleted"]')))->next(); } } } file_put_contents('index.xml', $rss); /* sitemap -------------------------------------------------------------------------------------------------------------- */ //we’re going to use the RSS files as sitemaps chdir(FORUM_ROOT); //get list of sub-forums and include the root too $folders = array('') + array_filter(preg_grep('/^(\\.|users$|themes$|lib$)/', scandir(FORUM_ROOT . DIRECTORY_SEPARATOR), PREG_GREP_INVERT), 'is_dir'); //start the XML file. this template has an XMLNS, so we have to prefix all our XPath queries :( $xml = new DOMTemplate(file_get_contents(FORUM_LIB . 'sitemap-template.xml'), array('x' => 'http://www.sitemaps.org/schemas/sitemap/0.9')); //generate a sitemap index file, to point to each index RSS file in the forum: //<https://www.google.com/support/webmasters/bin/answer.py?answer=71453> $sitemap = $xml->repeat('//x:sitemap'); foreach ($folders as $folder) { //get the time of the latest item in the RSS feed //(the RSS feed may be missing as they are not generated in new folders until something is posted) if (@($rss = simplexml_load_file(FORUM_ROOT . ($folder ? DIRECTORY_SEPARATOR . $folder : '') . DIRECTORY_SEPARATOR . 'index.xml'))) { //if you delete the last thread in a folder, there won’t be anything in the RSS index file! if (@$rss->channel->item[0]) { $sitemap->set(array('./x:loc' => FORUM_URL . FORUM_PATH . ($folder ? safeURL("{$folder}/", false) : '') . 'index.xml', './x:lastmod' => gmdate('r', strtotime($rss->channel->item[0]->pubDate))))->next(); } } } file_put_contents(FORUM_ROOT . DIRECTORY_SEPARATOR . 'sitemap.xml', $xml); //you saw nothing, right? clearstatcache(); }
//get a read/write lock on the file so that between now and saving, no other posts could slip in //normally we could use a write-only lock 'c', but on Windows you can't read the file when write-locked! $f = fopen("{$FILE}.rss", 'r+'); flock($f, LOCK_EX); //we have to read the XML using the file handle that's locked because in Windows, functions like //`get_file_contents`, or even `simplexml_load_file`, won't work due to the lock $xml = simplexml_load_string(fread($f, filesize("{$FILE}.rss"))) or (require FORUM_LIB . 'error_xml.php'); if (!(NAME == $xml->channel->item[0]->author && formatText(TEXT, $xml) == $xml->channel->item[0]->description && !$xml->channel->xpath('category[.="locked"]'))) { //where to? $page = (count($thread) + 1) % FORUM_POSTS == 1 ? floor((count($thread) + 1) / FORUM_POSTS) : ceil((count($thread) + 1) / FORUM_POSTS); $url = FORUM_URL . url('thread', PATH_URL, $FILE, $page) . '#' . base_convert(microtime(), 10, 36); //re-template the whole thread: $rss = new DOMTemplate(file_get_contents(FORUM_LIB . 'rss-template.xml')); $rss->set(array('/rss/channel/title' => $xml->channel->title, '/rss/channel/link' => FORUM_URL . url('thread', PATH_URL, $FILE)))->remove(array('/rss/channel/category' => !$xml->channel->xpath('category[.="locked"]'))); //template the new reply first $items = $rss->repeat('/rss/channel/item'); $items->set(array('./title' => sprintf(THEME_RE, count($xml->channel->item), $xml->channel->title), './link' => $url, './author' => NAME, './pubDate' => gmdate('r'), './description' => formatText(TEXT, $xml)))->remove('./category')->next(); //copy the remaining replies across foreach ($xml->channel->item as $item) { $items->set(array('./title' => $item->title, './link' => $item->link, './author' => $item->author, './pubDate' => $item->pubDate, './description' => $item->description))->remove(array('./category' => !$item->xpath('./category')))->next(); } //write the file: first move the write-head to 0, remove the file's contents, and then write new one rewind($f); ftruncate($f, 0); fwrite($f, $rss->html()); } else { //if a double-post, link back to the previous post $url = $xml->channel->item[0]->link; } //close the lock / file flock($f, LOCK_UN);