RSS feed aggregator/combiner in PHP with Magpie RSS (v2)

I have recently upgraded the code to combine multiple RSS feeds, for the original version see this post.

To install, extract the following zip file to a directory where you want your combined feeds to be displayed, I use thydzik.com/combinedfeed as thydizk.com/feed is already used by WordPress.

Edit index.php for your site, and make sure the temp directory has write permissions (mod 755). That should be it. Enjoy.

thydzik RSS feed aggregator v2.zip

Thanks to Magpie RSS and Feedcreator.

<?php
	$TMP_ROOT = "temp/"; //a atempory folder for storing the cached feeds, need to have write access (mod755)
	$DOMAIN_NAME = "http://thydzik.com/";
	$SITE_TITLE = "Travis Hydzik's blog feeds";
	$SITE_DESRIPTION = "A collection of Travis Hydzik's blog feeds";
	$SITE_AUTHOR = "Travis Hydzik";

	$FEEDS_ARRAY  = array( //the collection of urls linking to individual feeds
		"http://hydzik.com/feed/",
		"http://sonyaandtravis.com/feed",
		"http://thydzik.com/feed/"
	);

	$MAX_ITEMS = 10;
	$SHOW_FULL_FEED = FALSE;

	//stop editing from here onwards

	define('MAGPIE_DIR', '');
	define('MAGPIE_CACHE_DIR', $TMP_ROOT);

	//include magpie rss http://magpierss.sourceforge.net/
	@require_once(MAGPIE_DIR.'rss_fetch.inc');

	//include universal feed creator http://sourceforge.net/projects/feedcreator/
	@include(MAGPIE_DIR.'feedcreator.class.php');

	//create the basic rss feed
	$rss = new UniversalFeedCreator();
	$rss->useCached();
	$rss->title = $SITE_TITLE;
	$rss->description = $SITE_DESRIPTION;
	$rss->link = $DOMAIN_NAME;
	$rss->syndicationURL = curPageURL();

	//get all items is all feeds
	$total_temp = 0; //temp total number of posts in all rss feeds
	foreach ($FEEDS_ARRAY as $single_url) {
		$array_temp[$single_url]['page_title'] = url_grab_title($single_url); //grab the page title

		$rss_temp = fetch_rss($single_url);
		$items = array_slice($rss_temp->items, 0, $MAX_ITEMS);
		$array_temp[$single_url]['rss_data'] = $items;
		$total_temp += count($items);

		$array_temp[$single_url]['rss_pointer'] = 0;

		preg_match('@^(?:http://)?([^/]+)@i', $single_url, $matches);
		$array_temp[$single_url]['site_url'] = $matches[0];
	}

	while ($total_temp <> 0 && $MAX_ITEMS > 0){// loop while there are remaining posts to process
		$date_timestamp_temp = 0; //initialise to 0
		foreach ($FEEDS_ARRAY as $single_url) {
			$this_date_timestamp = $array_temp[$single_url]['rss_data'][$array_temp[$single_url]['rss_pointer']]['date_timestamp']; //get the date stamp of this post
			if ($this_date_timestamp > $date_timestamp_temp) { //if this date stamp is the newest, save where it came from
				$date_timestamp_temp = $this_date_timestamp; //update with this date stamp
				$temp_url = $single_url; //save the url feed
				$pointer_temp = $array_temp[$single_url]['rss_pointer']; //save the item number
			}
		}

		$total_temp --; //decrement total remaining posts to process
		$MAX_ITEMS --; //decrement number of posts to display
		$array_temp[$temp_url]['rss_pointer'] ++; //increment post index of used post rss

		//get the saved item
		$item = $array_temp[$temp_url]['rss_data'][$pointer_temp];

		//create the new item
		$item_new = new FeedItem();

		//add all the copied basics
		$item_new->title = $item['title'];
		$item_new->link = $item['link'];
		$item_new->date = $item['pubdate'];
		$item_new->author = $item['author'];
		$item_new->source = $temp_url;

		//to show full feed or blurb
		if ($SHOW_FULL_FEED) {
			$item_new->description = $item['content']['encoded'].'<p>Copyright &copy; <a href="'.$array_temp[$temp_url]['site_url'].'">'.$array_temp[$temp_url]['page_title'].'</a>. All Rights Reserved.</p>';
		} else {
			$item_new->description = $item['description']       .'<p>Copyright &copy; <a href="'.$array_temp[$temp_url]['site_url'].'">'.$array_temp[$temp_url]['page_title'].'</a>. All Rights Reserved.</p>';
		}

		$rss->addItem($item_new);
	}

	// a quick function the grab a pages title
	function url_grab_title($rss_url) {
  		$contents = file_get_contents($rss_url, TRUE, NULL, 0, 3072);
  		$contents = preg_replace("/(\n|\r)/", '', $contents);
		preg_match('/<title>(.*?)<\/title>/i', $contents, $matches);
		return $matches[1];
	}

	//get page url (for syndication), source http://www.webcheatsheet.com/PHP/get_current_page_url.php
	function curPageURL() {
		$pageURL = 'http';
		if ($_SERVER["HTTPS"] == "on") {$pageURL .= "s";}
		$pageURL .= "://";
		if ($_SERVER["SERVER_PORT"] != "80") {
			$pageURL .= $_SERVER["SERVER_NAME"].":".$_SERVER["SERVER_PORT"].$_SERVER["REQUEST_URI"];
		} else {
			$pageURL .= $_SERVER["SERVER_NAME"].$_SERVER["REQUEST_URI"];
		}
		return $pageURL;
	}

	// get your news items from other feed and display back
	$rss->saveFeed("RSS2.0", $TMP_ROOT."feed.xml");
?>

thydzik Google Map v1.4.7 – inline WordPress Google Maps

I have released an updated version of thydzik Google Map which allows for coloured and variable text markers, see the example below.

thydzikGoogleMap(example.xml)

Unfortunately, it now requires FreeType being compiled into PHP. If FreeType is not installed only the default marker and markers A-Z will be usable, with anything else being replaced with the default marker.

Download the latest from the WordPress Plugin Directory.

Dynamic Google Maps markers/icons with PHP

I am a avid fan of Google’s Map API, have even have created my own WordPress Google Maps plug-in (thydzikGoogleMap), but one feature that I find lacking are customisable markers, with the need to include an image file for every customisable marker, now if you want a selection of colours and labels this creates a huge image database.

Google has gone in the right step their MapIconMaker allowing very customisable markers using the Charts API marker output. But why not take this a step further and add dynamically generated text as well.

Hence, I provide a little demo of some PHP code that does this that I quickly whipped up. Here are some example markers:
DefaultAZ110PQ69%BEΩ$
(Have a look at the image name)

Now that gets a little boring, how about some color:
DefaultAZ110PQ69%BEΩ$
(Again, have a look at the image name)

Unfortunately, not all symbols work (not sure why, even though they are in the font) and if the symbol doesn’t work it will default to the default bullet (this is done with a modified font file).

Also there may be an issue with alignment. All main characters 0-9 and A-Z; I have added manual offsets, this could be improved.

You will need to download the modified arial font and host it in the same directory.

Update: it looks like in Internet Explorer the transparencies are incorrectly displayed, this is not the case when displayed on a Google Map.

Have a look at the PHP source code below:

<?php
	 $color = $_GET['color'];
	 if (!$color) {$color = "ff776b";} //default google map color
	 $color = str_replace("#", "", $color);
	 $string = $_GET['text'];

	 //some smarts to prevent hotlinking
	 if (!stristr($_SERVER['HTTP_REFERER'], "thydzik.com")) {
		$string = chr(169);
	 }
	 $font = 'arial';

	 //unfortunately we still must do some offsetting
	 switch (ord(substr($string,0,1))) {
		 case 49: //1
			$offset = -2;
			break;
		 case 55: //7
			$offset = -1;
			break;
		 case 65: //A
			$offset = 1;
			break;
		 case 74: //J
			$offset = -1;
			break;
		 case 84: //T
			$offset = 1;
			break;
		 case 99: //c
			$offset = -1;
			break;
		 case 106: //j
			$offset = 1;
			break;
	 }
	 if (strlen($string) == 1) {
		$fontsize = 10.5;
	 } else if (strlen($string) == 2) {
		$fontsize = 9;
	 } else {
		$fontsize = 10.5;
		$offset = 0; //reset offset
		$string = chr(149);
	 }

	 $bbox = imagettfbbox($fontsize, 0, $font, $string);
	 $width = $bbox[2] - $bbox[0] + 1;
	 $height = $bbox[1] - $bbox[7] + 1;

	 $image_name = "http://chart.apis.google.com/chart?cht=mm&chs=20x34&chco=$color,$color,000000&ext=.png";
	 $im = imagecreatefrompng($image_name);
	 imageAlphaBlending($im, true);
	 imageSaveAlpha($im, true);
	 $black = imagecolorallocate($im, 0, 0, 0);

	 imagettftext($im, $fontsize, 0, 11 - $width/2 + $offset, 9 + $height/2, $black, $font, $string);

	 header("Content-type: image/png");
	 imagepng($im);
	 imagedestroy($im);
?>

EDIT: 27th January 2010

I have experienced some users with errors produced by the imagecreatefrompng, either due to versions <4.3.0 disabling remote file access or allow_url_fopen being disabled.

A greater supported alternative is to use curl to fetch the Google marker. Replace the above with the below modification;

	$image_name = "http://chart.apis.google.com/chart?cht=mm&chs=20x34&chco=$color,$color,000000&ext=.png";

	$ch = curl_init();
	curl_setopt ($ch, CURLOPT_URL, $image_name);
	curl_setopt ($ch, CURLOPT_CONNECTTIMEOUT, 0);

	// Getting binary data
	curl_setopt($ch, CURLOPT_RETURNTRANSFER, 1);
	curl_setopt($ch, CURLOPT_BINARYTRANSFER, 1);

	$image_string = curl_exec($ch);
	curl_close($ch);

	$im = imagecreatefromstring ($image_string);

EDIT: 30th November 2011

Hosting of these dynamic markers, linked on NumericIcons is using all my allocated hosting server resources. I have modified the script to redirect to Google’s dynamic markers (yes, Google has the equivalent) hopefully that will take some of the load off, and I won’t need to remove it totally.

They look slightly different to mine;
DefaultAZ110PQ69%BEO$

DefaultAZ110PQ69%BEO$

	if (!$color = $_GET['color']) {
		$color = "ff776b"; //default google map color
	}
	$color = str_replace("#", "", $color);
	
	if (!$text = $_GET['text']) {
		$text = "%e2%bc%80"; //default google map icon
	}
	
	header("Location: http://chart.googleapis.com/chart?chst=d_map_pin_letter&chld={$text}|{$color}|000000&.png");

EDIT: 6 December 2011
I now have implemented an Apache Mod_Rewrite solution, which will take all load off the php processing, existing users should see no difference.

RewriteCond %{QUERY_STRING} ^text=([^&]*)$
RewriteRule ^thydzikGoogleMap/markerlink\.php$ http://chart.googleapis.com/chart?chst=d_map_pin_letter&chld=%1|ff776b|000000&.png? [R,L]

RewriteCond %{QUERY_STRING} ^color=([^&]*)$
RewriteRule ^thydzikGoogleMap/markerlink\.php$ http://chart.googleapis.com/chart?chst=d_map_pin_letter&chld=â¼€|%1|000000&.png? [R,L]

RewriteCond %{QUERY_STRING} ^text=(.*)\&color=(.*)$
RewriteRule ^thydzikGoogleMap/markerlink\.php$ http://chart.googleapis.com/chart?chst=d_map_pin_letter&chld=%1|%2|000000&.png? [R,L]

RewriteCond %{QUERY_STRING} ^color=(.*)\&text=(.*)$
RewriteRule ^thydzikGoogleMap/markerlink\.php$ http://chart.googleapis.com/chart?chst=d_map_pin_letter&chld=%2|%1|000000&.png? [R,L]

RewriteCond %{QUERY_STRING} =""
RewriteRule ^thydzikGoogleMap/markerlink\.php$ http://chart.googleapis.com/chart?chst=d_map_pin_letter&chld=â¼€|ff776b|000000&.png? [R,L]

EDIT: 14 September 2014
Unfortunately I have had to remove all working examples, as those that were hot-linking to the markers directly were causing server loading, which Hostgator doesn’t like.

RSS feed aggregator/combiner in PHP

Having also a second blog, I needed a way to combine the RSS feeds into one, hence, the following code was written (well, modified from this code).

The code uses MagpieRSS to read and FeedCreator to write. Thanks to Scott Hurring for code to grab the RSS feed title.

The code has been tested with my 2 WordPress blogs (view example combined RSS feed). To install, extract and upload the feed directory and modify the settings in index.php.

Download all files and folders

Update: 1 April 2009, improved code speed up the slow response of the url_grab_title function.

Update: 3 March 2010, I have further improved the code and made it easier to intergrate into another site.
Refer to this post.

&lt;?php
	$TMP_ROOT = &quot;tmp/&quot;;
	$DOMAIN_NAME = &quot;http://thydzik.com/&quot;;
	$SITE_TITLE = &quot;thydzik&quot;;
	$SITE_DESRIPTION = &quot;thydzik's blog feeds&quot;;
	$SITE_AUTHOR = &quot;thydzik&quot;;
	$RSS_DIR = &quot;../&quot;;

	$array = array(
		&quot;http://blog.thydzik.com/feed/&quot;,
		&quot;http://sonyaandtravis.com/feed/&quot;
	);
	$num = 10;
	$showfullfeed = FALSE;

	define('MAGPIE_DIR', $RSS_DIR.'feed/');
	define('MAGPIE_CACHE_DIR','/'.$TMP_ROOT.'rsscache');

	/* include required files */
	@require_once(MAGPIE_DIR.'rss_fetch.inc');
	@include(MAGPIE_DIR.'feedcreator.class.php');

	/* Set RSS properties */
	$rss = new UniversalFeedCreator();
	$rss-&gt;useCached();
	$rss-&gt;title = $SITE_TITLE;
	$rss-&gt;description = $SITE_DESRIPTION;
	$rss-&gt;link = $DOMAIN_NAME;
	$rss-&gt;syndicationURL = $DOMAIN_NAME.&quot;feed/index.php&quot;;

	$i_temp = 0; //temp i variable
	$j_temp = 0; //temp j variable
	$total_temp = 0; //temp total number of posts in all rss feeds

	$array_count = count($array); //number of rss feeds

	/* code to determine which post to display */
	for ($i = 0; $i &lt; $array_count; $i++) {
		$rss1 = fetch_rss($array[$i]);
		if ($rss1) {
			$array_temp[$i]['page_title'] = url_grab_title($array[$i]);
			$items = array_slice($rss1-&gt;items, 0);
			$array_temp[$i]['rss_data'] = $items;
			$total_temp += count($items);
			$array_temp[$i]['rss_pointer'] = 0;
			preg_match('@^(?:http://)?([^/]+)@i', $array[$i], $matches);
			$array_temp[$i]['site_url'] = $matches[0];
		}
	}
	while ($total_temp &lt;&gt; 0 &amp;&amp; $num &gt; 0){// loop while there are remaining posts to process
		$date_timestamp_temp = 0; //initialise to 0
		for ($i = 0; $i &lt; $array_count; $i++) {
			$date_timestamp_temp = max($date_timestamp_temp, $array_temp[$i]['rss_data'][$array_temp[$i]['rss_pointer']]['date_timestamp']); //determine latest post from rss feeds
			if ($date_timestamp_temp == $array_temp[$i]['rss_data'][$array_temp[$i]['rss_pointer']]['date_timestamp']) { //latest post is found so save where it came from
				$i_temp = $i;
				$j_temp = $array_temp[$i]['rss_pointer'];
			}
		}
		$total_temp --; //decrement total remaining posts to process
		$num --; //decrement number of posts to display
		$array_temp[$i_temp]['rss_pointer'] ++; //increment post index of used post rss

		/* code to display post */
		$item = $array_temp[$i_temp]['rss_data'][$j_temp];
		$href = $item['link'];
		$title = $item['title'];
		if (!$showfullfeed) {
			$desc = $item['description'];
		}else{
			$desc =  $item['content']['encoded'];
		}
		$desc .=  '
Copyright &amp;copy; &lt;a href=&quot;'.$array_temp[$i_temp]['site_url'].'&quot;&gt;'.$array_temp[$i_temp]['page_title'].'&lt;/a&gt;.  All Rights Reserved.
';
		$pdate = $item['pubdate'];
		$item = new FeedItem();
		$item-&gt;title = $title;
		$item-&gt;link = $href;
		$item-&gt;description = $desc;
		$item-&gt;date = $pdate;
		$item-&gt;source = $DOMAIN_NAME;
		$item-&gt;author = $SITE_AUTHOR;
		$rss-&gt;addItem($item);
	}

	function url_grab_title($rss_url) {
		$contents = file_get_contents($rss_url, TRUE, NULL, 0, 3072);
		$contents = preg_replace(&quot;/(\n|\r)/&quot;, '', $contents);
		preg_match('/&lt;title&gt;(.*?)&lt;\/title&gt;/i', $contents, $matches);
		return $matches[1];
	}

	// get your news items from other feed and display back
	$rss-&gt;saveFeed(&quot;RSS2.0&quot;, '/'.$TMP_ROOT.&quot;rsscache/feed.xml&quot;);
?&gt;