Problem building WordPress Plugin that uses lastRSS

Howard Bash
Howard Bash used Ask the Experts™
on
I have been going through a tutorial and built a plugin for WordPress that uses lastRSS.  When I activate it.  It displays some of the code on the top left corner of the dashboard.

I will attach the code that uses lastRSS for review.  I'm not clear how to go about debugging it.

<?
/*
Plugin Name: RSS Processor
Plugin URI: http://localhost
Description: Plugin to fetch parse and show RSS feeds.
Author: Author
Version: 1.0
Author URI: http://localhost
Feature: So far none to be seen.
*/
?>



<?

add_filter('the_content', 'rss_parse');

/*
RSS PARSE FUNCTION
Sample format for rss tag:
{rss uri=http://rss.groups.yahoo.com/phpexperts/rss count=5}

uri and how many feeds to show

param is content of post
returns none

*/


include './lastRSS.php';


function rss_parse($content)
{
  $rss=new lastRSS();
  
  $pattern="~{rss\s*uri=(.*)\s*limit=(.*)}~iU";

  $matches = "";

  preg_match_all($pattern, $content, $matches);

  $rsses = 0;
  while ($rsses<count($matches[0]))
  {
    $p_content="";

    $uri=$matches[1][$rsses];

    $count=$matches[2][$rsses];

    if (empty($count)) $count=10;

    $rss_content = $rss->Get($uri);
 
    $items = $rss_content['items'];

    $i = 0;
    while ($i < $count)
      {
        $p_content .= "<div id='rss_item'><strong><a href='{$items[$i]['link']}'>".$items[$i]['title']."</a></strong><br/>";
        $p_content .= "".$items[$i]['description']."</div><br/><br/>";

        $i++;

      }
    $content = str_replace($matches[0][$rsses], $p_content, $content);
    $rsses +=1;

  }
  return $content;
 
}

?>

Open in new window

Comment
Watch Question

Do more with

Expert Office
EXPERT OFFICE® is a registered trademark of EXPERTS EXCHANGE®
Most Valuable Expert 2011
Top Expert 2016

Commented:
Start on line 1 by making it say <?php instead of <?
Most Valuable Expert 2011
Top Expert 2016

Commented:
Can you please show us what code gets displayed?  Just copy and paste, or post a screen shot.  Thanks.
Howard BashSenior Software Engineer

Author

Commented:
Made that change.  Now it does not show the code in the dashboard, but the dashboard format is messed up.  The left hand side bar has missing options and the content panel has it's content shifted and begins centered (as it should be), but beginning below the messed up dashboard left side panel.
OWASP: Avoiding Hacker Tricks

Learn to build secure applications from the mindset of the hacker and avoid being exploited.

Howard BashSenior Software Engineer

Author

Commented:
Also,  the content is truncated.  I am including the code for lastRSS (perhaps a defective version).

<?php
/*
 ======================================================================
 lastRSS 0.9.1
 
 Simple yet powerfull PHP class to parse RSS files.
 
 by Vojtech Semecky, webmaster @ webdot . cz
 
 Latest version, features, manual and examples:
 	http://lastrss.webdot.cz/

 ----------------------------------------------------------------------
 LICENSE

 This program is free software; you can redistribute it and/or
 modify it under the terms of the GNU General Public License (GPL)
 as published by the Free Software Foundation; either version 2
 of the License, or (at your option) any later version.

 This program 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 General Public License for more details.

 To read the license please visit http://www.gnu.org/copyleft/gpl.html
 ======================================================================
*/

/**
* lastRSS
* Simple yet powerfull PHP class to parse RSS files.
*/
class lastRSS {
	// -------------------------------------------------------------------
	// Public properties
	// -------------------------------------------------------------------
	var $default_cp = 'UTF-8';
	var $CDATA = 'nochange';
	var $cp = '';
	var $items_limit = 0;
	var $stripHTML = False;
	var $date_format = '';

	// -------------------------------------------------------------------
	// Private variables
	// -------------------------------------------------------------------
	var $channeltags = array ('title', 'link', 'description', 'language', 'copyright', 'managingEditor', 'webMaster', 'lastBuildDate', 'rating', 'docs');
	var $itemtags = array('title', 'link', 'description', 'author', 'category', 'comments', 'enclosure', 'guid', 'pubDate', 'source');
	var $imagetags = array('title', 'url', 'link', 'width', 'height');
	var $textinputtags = array('title', 'description', 'name', 'link');

	// -------------------------------------------------------------------
	// Parse RSS file and returns associative array.
	// -------------------------------------------------------------------
	function Get ($rss_url) {
		// If CACHE ENABLED
		if ($this->cache_dir != '') {
			$cache_file = $this->cache_dir . '/rsscache_' . md5($rss_url);
			$timedif = @(time() - filemtime($cache_file));
			if ($timedif < $this->cache_time) {
				// cached file is fresh enough, return cached array
				$result = unserialize(join('', file($cache_file)));
				// set 'cached' to 1 only if cached file is correct
				if ($result) $result['cached'] = 1;
			} else {
				// cached file is too old, create new
				$result = $this->Parse($rss_url);
				$serialized = serialize($result);
				if ($f = @fopen($cache_file, 'w')) {
					fwrite ($f, $serialized, strlen($serialized));
					fclose($f);
				}
				if ($result) $result['cached'] = 0;
			}
		}
		// If CACHE DISABLED >> load and parse the file directly
		else {
			$result = $this->Parse($rss_url);
			if ($result) $result['cached'] = 0;
		}
		// return result
		return $result;
	}
	
	// -------------------------------------------------------------------
	// Modification of preg_match(); return trimed field with index 1
	// from 'classic' preg_match() array output
	// -------------------------------------------------------------------
	function my_preg_match ($pattern, $subject) {
		// start regullar expression
		preg_match($pattern, $subject, $out);

		// if there is some result... process it and return it
		if(isset($out[1])) {
			// Process CDATA (if present)
			if ($this->CDATA == 'content') { // Get CDATA content (without CDATA tag)
				$out[1] = strtr($out[1], array('<![CDATA['=>'', ']]>'=>''));
			} elseif ($this->CDATA == 'strip') { // Strip CDATA
				$out[1] = strtr($out[1], array('<![CDATA['=>'', ']]>'=>''));
			}

			// If code page is set convert character encoding to required
			if ($this->cp != '')
				//$out[1] = $this->MyConvertEncoding($this->rsscp, $this->cp, $out[1]);
				$out[1] = iconv($this->rsscp, $this->cp.'//TRANSLIT', $out[1]);
			// Return result
			return trim($out[1]);
		} else {
		// if there is NO result, return empty string
			return '';
		}
	}

	// -------------------------------------------------------------------
	// Replace HTML entities &something; by real characters
	// -------------------------------------------------------------------
	function unhtmlentities ($string) {
		// Get HTML entities table
		$trans_tbl = get_html_translation_table (HTML_ENTITIES, ENT_QUOTES);
		// Flip keys<==>values
		$trans_tbl = array_flip ($trans_tbl);
		// Add support for &apos; entity (missing in HTML_ENTITIES)
		$trans_tbl += array('&apos;' => "'");
		// Replace entities by values
		return strtr ($string, $trans_tbl);
	}

	// -------------------------------------------------------------------
	// Parse() is private method used by Get() to load and parse RSS file.
	// Don't use Parse() in your scripts - use Get($rss_file) instead.
	// -------------------------------------------------------------------
	function Parse ($rss_url) {
		// Open and load RSS file
		if ($f = @fopen($rss_url, 'r')) {
			$rss_content = '';
			while (!feof($f)) {
				$rss_content .= fgets($f, 4096);
			}
			fclose($f);

			// Parse document encoding
			$result['encoding'] = $this->my_preg_match("'encoding=[\'\"](.*?)[\'\"]'si", $rss_content);
			// if document codepage is specified, use it
			if ($result['encoding'] != '')
				{ $this->rsscp = $result['encoding']; } // This is used in my_preg_match()
			// otherwise use the default codepage
			else
				{ $this->rsscp = $this->default_cp; } // This is used in my_preg_match()

			// Parse CHANNEL info
			preg_match("'<channel.*?>(.*?)</channel>'si", $rss_content, $out_channel);
			foreach($this->channeltags as $channeltag)
			{
				$temp = $this->my_preg_match("'<$channeltag.*?>(.*?)</$channeltag>'si", $out_channel[1]);
				if ($temp != '') $result[$channeltag] = $temp; // Set only if not empty
			}
			// If date_format is specified and lastBuildDate is valid
			if ($this->date_format != '' && ($timestamp = strtotime($result['lastBuildDate'])) !==-1) {
						// convert lastBuildDate to specified date format
						$result['lastBuildDate'] = date($this->date_format, $timestamp);
			}

			// Parse TEXTINPUT info
			preg_match("'<textinput(|[^>]*[^/])>(.*?)</textinput>'si", $rss_content, $out_textinfo);
				// This a little strange regexp means:
				// Look for tag <textinput> with or without any attributes, but skip truncated version <textinput /> (it's not beggining tag)
			if (isset($out_textinfo[2])) {
				foreach($this->textinputtags as $textinputtag) {
					$temp = $this->my_preg_match("'<$textinputtag.*?>(.*?)</$textinputtag>'si", $out_textinfo[2]);
					if ($temp != '') $result['textinput_'.$textinputtag] = $temp; // Set only if not empty
				}
			}
			// Parse IMAGE info
			preg_match("'<image.*?>(.*?)</image>'si", $rss_content, $out_imageinfo);
			if (isset($out_imageinfo[1])) {
				foreach($this->imagetags as $imagetag) {
					$temp = $this->my_preg_match("'<$imagetag.*?>(.*?)</$imagetag>'si", $out_imageinfo[1]);
					if ($temp != '') $result['image_'.$imagetag] = $temp; // Set only if not empty
				}
			}
			// Parse ITEMS
			preg_match_all("'<item(| .*?)>(.*?)</item>'si", $rss_content, $items);
			$rss_items = $items[2];
			$i = 0;
			$result['items'] = array(); // create array even if there are no items
			foreach($rss_items as $rss_item) {
				// If number of items is lower then limit: Parse one item
				if ($i < $this->items_limit || $this->items_limit == 0) {
					foreach($this->itemtags as $itemtag) {
						$temp = $this->my_preg_match("'<$itemtag.*?>(.*?)</$itemtag>'si", $rss_item);
						if ($temp != '') $result['items'][$i][$itemtag] = $temp; // Set only if not empty
					}
					// Strip HTML tags and other bullshit from DESCRIPTION
					if ($this->stripHTML && $result['items'][$i]['description'])
						$result['items'][$i]['description'] = strip_tags($this->unhtmlentities(strip_tags($result['items'][$i]['description'])));
					// Strip HTML tags and other bullshit from TITLE
					if ($this->stripHTML && $result['items'][$i]['title'])
						$result['items'][$i]['title'] = strip_tags($this->unhtmlentities(strip_tags($result['items'][$i]['title'])));
					// If date_format is specified and pubDate is valid
					if ($this->date_format != '' && ($timestamp = strtotime($result['items'][$i]['pubDate'])) !==-1) {
						// convert pubDate to specified date format
						$result['items'][$i]['pubDate'] = date($this->date_format, $timestamp);
					}
					// Item counter
					$i++;
				}
			}

			$result['items_count'] = $i;
			return $result;
		}
		else // Error in opening return False
		{
			return False;
		}
	}
}

?>

Open in new window

Howard BashSenior Software Engineer

Author

Commented:
The dashboard message on activating has the following message along with that it has activated it:

The plugin generated 6 characters of unexpected output during activation. If you notice “headers already sent” messages, problems with syndication feeds or other issues, try deactivating or removing this plugin.
Most Valuable Expert 2011
Top Expert 2016

Commented:
Made that change.  Now it does not show the code in the dashboard...

That's good.  It means that PHP did not have the short-open-tags enabled.

But as I look at the code for lastRSS, it looks to me like a PHP4 setup, and since PHP4 is not supported any more, it might be time to bring this thing into the 21st century.  Modern technology would probably use SimpleXML to parse an RSS string.

Have you asked Vojtech Semecky if this is expected to work with your version of WP and your version of PHP?
Jason C. LevineDon't talk to me.

Commented:
Agree with Ray.  That plugin is ancient and probably not fully compatible with modern WP.  If it was a dog, it would be ready to be put to sleep.

There are newer RSS plugins out there, or if you are using a tutorial to learn to write your own, the current method to deal with an RSS file is fetch_feed()

http://codex.wordpress.org/Function_Reference/fetch_feed
Howard BashSenior Software Engineer

Author

Commented:
i build the page from the fetch_feed example and placed it in the root of a working blog.  When I call it,  it fails that it can't be displayed with a 500 and an internal error.

I have installed NetBeans 7 IDE with php support and would like to use this IDE to debug this.  Is that possible?  So far,  I have loaded the page into the IDE and run it and it doesn't break where I added a breakpoint.  I think that I may need xDebug for Windows 2008 R2 and have not been able to locate such and install.
Jason C. LevineDon't talk to me.

Commented:
I don't know if NetBeans respects the WordPress internal functions or not.  If so, you can use it for debugging.
Howard BashSenior Software Engineer

Author

Commented:
Do you have a different recommendation for debugging?
Jason C. LevineDon't talk to me.

Commented:
Not really. Your best bet for checking code syntax might be Aptana with the older PHP plugin.  There seems to be some user activity to create a WordPress-friendly code library for that platform:

http://www.ilovecolors.com.ar/wordpress-code-templates-for-aptana/
Howard BashSenior Software Engineer

Author

Commented:
I have added a net-beans ide and aptana.  Both may be nice and their interfacese are,  but I have not yet been able to execute php within either that will allow me to break on a line of code and then inspect.
Jason C. LevineDon't talk to me.

Commented:
Not sure of what would be required in either IDE to do line-by-line debugging, or if that's even possible.  Sounds like a new question for the PHP Zone...those top guys are way beyond me in ability and probably know something I don't.

Ray, you still reading?


I found a few articles on debugging WordPress while browsing for something else,now a few days later I can't seem to find the page. I actually used a few of them which worked great. It was on a theme I created for a client, but before going live I removed them thinking I would just re-visit the site for future uses. One that I know works is enabling wp_debug in the config.php file of WordPress:

Here are links to WordPress debugging procedures from respectable developers:

WordPress Codex:
http://codex.wordpress.org/Editing_wp-config.php#Increasing_memory_allocated_to_PHP

Andrew Niacin has a good post on debugging WordPress:
http://andrewnacin.com/2010/04/23/5-ways-to-debug-wordpress/
Jason C. LevineDon't talk to me.

Commented:
Heh.  Nacin used to be a Moderator here, back in the day.
Really, I guess he is too busy to participate now. I've learned some useful things from his blog.
Andrew Nacin and Justin Tadlock are two WP Developers that I think WordPress beginners can learn a lot from. I can trust what I've read from them, unlike many blogs and websites that just copy and paste something from somewhere on the internet without even testing it.
Howard BashSenior Software Engineer

Author

Commented:
Great developer link.

Do more with

Expert Office
Submit tech questions to Ask the Experts™ at any time to receive solutions, advice, and new ideas from leading industry professionals.

Start 7-Day Free Trial