Jump to content

RSS Feed Module


ryan

Recommended Posts

error on line 1 at column 2: StartTag: invalid element name

What is on line 1 column 2? That sounds like the first element in the file. I am guessing that a PHP error message is appearing where the start of the RSS should be. Either that or you have whitespace before the <?php tag in your template file. Viewing the source of the RSS feed should reveal what the issue is. 

Link to comment
Share on other sites

Looks like a php error, but I really can't find it. 
Its exactly the code from above, without whitespace before the <?php opening tag and in my point of view there is no column 2 on line 1. 
What do you mean with the source of the RSS feed? My rss template file or something else? 

Link to comment
Share on other sites

When you are viewing your RSS feed in your browser - something like www.mysite.com/rss/ - do a View Source in your browser. Paste the content of the source here and I am sure we can figure out the problem.

Link to comment
Share on other sites

Heres what I get:

Question: Is it possible to make the code collapsable, in order to make the post not so long?

<!doctype html>
<!-- paulirish.com/2008/conditional-stylesheets-vs-css-hacks-answer-neither/ -->
<!--[if lt IE 7]> <html class="no-js ie6 oldie" lang="en"> <![endif]-->
<!--[if IE 7]>    <html class="no-js ie7 oldie" lang="en"> <![endif]-->
<!--[if IE 8]>    <html class="no-js ie8 oldie" lang="en"> <![endif]-->
<!--[if IE 9]>    <html class="no-js ie9" lang="en"> <![endif]-->
<!-- Consider adding an manifest.appcache: h5bp.com/d/Offline -->
<!--[if gt IE 8]><!--> 
<html class="no-js" lang="en" itemscope itemtype="http://schema.org/Product"> <!--<![endif]-->
<head>
  <meta charset="utf-8">

  <!-- Use the .htaccess and remove these lines to avoid edge case issues.
       More info: h5bp.com/b/378 -->
  <meta http-equiv="X-UA-Compatible" content="IE=edge,chrome=1">

  <title>rss</title>
  <meta name="description" content="" />
  <meta name="generator" content="ProcssWire 2.3.0" />
  <meta name="keywords" content="" />
  <meta name="author" content="/livio/site/templates/humans.txt">
  <link rel="icon" type="image/png" href="/livio/site/templates//img/favicon.png" />

  <!-- Facebook Metadata /-->
  <meta property="fb:page_id" content="" />
  <meta property="og:image" content="" />
  <meta property="og:description" content=""/>
  <meta property="og:title" content=""/>

  <!-- Google+ Metadata /-->
  <meta itemprop="name" content="">
  <meta itemprop="description" content="">
  <meta itemprop="image" content="">

  <meta name="viewport" content="width=device-width, initial-scale=1.0, maximum-scale=1">

  <!-- We highly recommend you use SASS and write your custom styles in sass/_custom.scss.
       However, there is a blank style.css in the css directory should you prefer -->
  <link rel="stylesheet" href="/livio/site/templates/css/gumby.css">
  <!-- <link rel="stylesheet" href="css/style.css"> -->
  <link rel="stylesheet" href="/livio/site/templates/css/style.css">

  <script src="/livio/site/templates/js/libs/modernizr-2.0.6.min.js"></script>
</head>

<body>



			
<?xml version='1.0' encoding='utf-8' ?>
<rss version='2.0'>
<channel>
	<title>Latest updates</title>
	<link>http://localhost:8888/livio/rss/</link>
	<description>The most recent pages updated on my site</description>
	<pubDate>Thu, 18 Apr 2013 16:24:55 +0200</pubDate>
	<ttl>60</ttl>
	<item>
		<title>Sintel</title>
		<description><![CDATA[InfoPassepartout had a moist sensation about the eyes; his master's action touched his susceptible heart. Two first-class tickets for Paris having been speedily purchased, Mr. Fogg was crossing the station to the train, when he perceived his five friends of the Reform. "Well, gentlemen," said he, "I'm off, you see; and, if you will examine my passport when I get back, you will be able to judge whether I have accomplished the journey agreed upon." "Oh, that would be quite unnecessary, Mr. Fogg," said Ralph politely. "We will trust your word, as a gentleman of honour." "You do not forget when you are due in London again?" asked Stuart. "In eighty days; on Saturday, the 21st of December, 1872, at a quarter before nine p.m. Good-bye, gentlemen." Phileas Fogg and his servant seated themselves in a first-class carriage at twenty minutes before nine; five minutes later the whistle screamed, and the train slowly glided out of the station. The night was dark, and a fine, steady rain was falling. Phileas Fogg,]]></description>
		<pubDate>Wed, 03 Apr 2013 13:54:47 +0200</pubDate>
		<link>http://localhost:8888/livio/movies/sintel/</link>

	<guid>http://localhost:8888/livio/movies/sintel/</guid>
	</item>
	<item>
		<title>Big Buck Bunny</title>
		<description><![CDATA[]]></description>
		<pubDate>Thu, 04 Apr 2013 14:25:48 +0200</pubDate>
		<link>http://localhost:8888/livio/movies/big-buck-bunny/</link>

	<guid>http://localhost:8888/livio/movies/big-buck-bunny/</guid>
	</item>
	<item>
		<title>Tears of steel</title>
		<description><![CDATA[]]></description>
		<pubDate>Thu, 04 Apr 2013 15:41:36 +0200</pubDate>
		<link>http://localhost:8888/livio/movies/tears-of-steel/</link>

	<guid>http://localhost:8888/livio/movies/tears-of-steel/</guid>
	</item>
</channel>
</rss>
<!-- JavaScript at the bottom for fast page loading -->

  <!-- Grab Google CDN's jQuery, with a protocol relative URL; fall back to local if offline -->
  <script src="http://ajax.googleapis.com/ajax/libs/jquery/1.7.2/jquery.min.js"></script>
  <script>window.jQuery || document.write('<script src="/livio/site/templates/js/libs/jquery-1.7.2.min.js"><\/script>')</script>
  <script src="/livio/site/templates/js/libs/gumby.min.js"></script>
  <script src="/livio/site/templates/js/plugins.js"></script>
  <script src="/livio/site/templates/js/main.js"></script>
  <script src="/livio/site/templates/js/libs/jquery.easing.1.3.js"></script>

	</body>
</html>
Edited by Samuel
Link to comment
Share on other sites

Not sure about collapsing the code window - don't think I've seen that option in this forum.

But, back to your problem - all that your RSS page should be outputting is:

<?xml version='1.0' encoding='utf-8' ?>
<rss version='2.0'>
<channel>
	<title>Latest updates</title>
	<link>http://localhost:8888/livio/rss/</link>
	<description>The most recent pages updated on my site</description>
	<pubDate>Thu, 18 Apr 2013 16:24:55 +0200</pubDate>
	<ttl>60</ttl>
	<item>
		<title>Sintel</title>
		<description><![CDATA[InfoPassepartout had a moist sensation about the eyes; his master's action touched his susceptible heart. Two first-class tickets for Paris having been speedily purchased, Mr. Fogg was crossing the station to the train, when he perceived his five friends of the Reform. "Well, gentlemen," said he, "I'm off, you see; and, if you will examine my passport when I get back, you will be able to judge whether I have accomplished the journey agreed upon." "Oh, that would be quite unnecessary, Mr. Fogg," said Ralph politely. "We will trust your word, as a gentleman of honour." "You do not forget when you are due in London again?" asked Stuart. "In eighty days; on Saturday, the 21st of December, 1872, at a quarter before nine p.m. Good-bye, gentlemen." Phileas Fogg and his servant seated themselves in a first-class carriage at twenty minutes before nine; five minutes later the whistle screamed, and the train slowly glided out of the station. The night was dark, and a fine, steady rain was falling. Phileas Fogg,]]></description>
		<pubDate>Wed, 03 Apr 2013 13:54:47 +0200</pubDate>
		<link>http://localhost:8888/livio/movies/sintel/</link>

	<guid>http://localhost:8888/livio/movies/sintel/</guid>
	</item>
	<item>
		<title>Big Buck Bunny</title>
		<description><![CDATA[]]></description>
		<pubDate>Thu, 04 Apr 2013 14:25:48 +0200</pubDate>
		<link>http://localhost:8888/livio/movies/big-buck-bunny/</link>

	<guid>http://localhost:8888/livio/movies/big-buck-bunny/</guid>
	</item>
	<item>
		<title>Tears of steel</title>
		<description><![CDATA[]]></description>
		<pubDate>Thu, 04 Apr 2013 15:41:36 +0200</pubDate>
		<link>http://localhost:8888/livio/movies/tears-of-steel/</link>

	<guid>http://localhost:8888/livio/movies/tears-of-steel/</guid>
	</item>
</channel>
</rss>

Seems to me that your rss.php template has your header and footer includes in place. That file should just have the code you posted in your first post, and nothing else. Try that and let us know how you go.

  • Like 2
Link to comment
Share on other sites

That did it perfectly. Thanks!
Therefore it would be interesting if it is possible to exclude the prepend and append template files from the config.php for specific pages like in this case, for rss pages.

Link to comment
Share on other sites

  • 4 weeks later...

Dear Ryan,

I installed the RSS Feed module tonight, and it works very well -- now. :-)

I had to dig and dig because the feed was only showing the page title and description, but no articles.

I finally found out that the default copyright element in the module was pulling in a copyright line from somewhere -- I know not where, with this line:

<copyright>© 2013 The World Community Press</copyright>

The feed was choking on the © entity, since that's not legal xml.

I then added this to my template:

$rss->copyright            = '';
 

and the feed worked. It also worked when I used this: © for the copyright symbol, but I didn't see where the copyright appeared on the feed anyway, so I went back to a blank value.

I've searched in the database and in my template files, and even in your module code, and I can't for the life of me figure out where your module was pulling that value from. That company name is inside a page item called 'footer', but it has more than just that in the footer.

This is my code in the rss.php template file:

<?php

$rss                       = $modules->get("MarkupRSS");
$rss->title                = "RSS Feed";
$rss->description          = "This feed shows the most recent items that have been published.";

$rss->itemTitleField       = 'headline';
$rss->itemDescriptionField = 'summary';
$rss->itemDateField        = 'publish_date';
$rss->copyright            = '';

$now       = time();

$selectors = "custom_template_file.select_value=article_page.html," .
             "sort=-publish_date," .
             "publish_date<=$now," .
             "limit=20";

$items     = $pages->get("/")->find("$selectors");

$rss->render($items);

 

When I comment out the copyright line, I get the error again. I'm stumped. Any ideas?

Thanks!

Peter

Link to comment
Share on other sites

Dear Ryan,

I found another wrinkle.

When I'm not logged in, the RSS page just shows the title, but no content.

When I log in, the content appears.

However, on the main pages of my site, the content appears whether I'm logged in or not.

The rss template has permissions set for the guest to view.

I'm stumped.

Thanks for your help.

Peter

Link to comment
Share on other sites

Dear Soma,

No, I haven't enabled the cache on any of my templates.

To run a test, I created a 'test' template, with just the title field, and full guest permissions.

I then created a page off the Home page, called /test/.

In the test.php file, I placed this code, which, when I'm logged in, shows the data, but when I'm not, the

header (Test Page) shows up, but the selected articles do not. So, I've isolated the fact that this has nothing to do with the RSS module.

(At least *this* problem. The copyright issue above is different.)

Here's the code in test.php:

<?php

echo "Test Page<hr>";

$now       = time();

$selectors = "custom_template_file.select_value=article_page.html," .
             "sort=-publish_date," .
             "publish_date<=$now," .
             "limit=20";

$items     = $pages->get("/")->find("$selectors");

foreach($items as $item)
      {
      echo "$item->headline<br>$item->summary<br><br>";
      }

 

What's weird is that I run this code in the home page template, and it works fine.

I'm missing something; probably something ridiculous, but I'm stumped.

Thanks for any advice!

Peter

Link to comment
Share on other sites

Dear Soma,

I've solved it.

It was related to permissions with this line:

$selectors = "custom_template_file.select_value=article_page.html," .
 

When I commented that criteria out, it worked.

So, I looked at the template and pages that I had created to assemble a list of custom templates.

I had used a template called 'custom_data_selects', and had set it to not have guest permissions.

Once I gave that template guest permissions, it worked.

I have to figure out the permission system, because I had thought that it wouldn't be good to have those

"pages" which just have data elements, available to the public.

Between template permissions and hidden pages, I'm a little unclear.

In MODX, you could create chunks that were not available for public viewing.

Do you have any permission tips for that type of thing?

So, with the RSS feed, I think I just have the copyright issue to figure out.

Thanks, Soma!

Peter

Link to comment
Share on other sites

Peter, check your module settings for MarkupRSS (Admin > Modules > Markup > RSS). It sounds like there are some default settings that the values may be coming from. Regarding the copyright symbol, I'm not sure about that one but isn't a copyright symbol redundant since the field is a dedicated copyright field? I think the right thing to do there would be to not have any copyright symbols in there since the field already implies that.  

I have to figure out the permission system, because I had thought that it wouldn't be good to have those

"pages" which just have data elements, available to the public.

If it's data going into an RSS feed, then that would be public, right? You could always bypass that by adding "include=all" to your selector while keeping your pages inaccessible, but I think it's more secure to keep public data public and private data private, regardless of whether something maps to a viewable page or not. Another option is to use "hidden", and have "include=hidden" in your selector. For data container pages, you can always choose not to implement a template file too. Or you can have a template file that does something like this:

if(!$user->isLoggedin()) throw new Wire404Exception(); 

Link to comment
Share on other sites

Dear Ryan,

* About the copyright:

Boy, do I feel silly! I had completely forgotten that the module had a settings page; a page in which I had added the © symbol and that copyright line. Oy vey! Sorry to have wasted time and bandwidth! Although I guess I can say that I learned that one can't use the © symbol in the RSS XML.

It's truly amazing how many hours one can spend debugging something that was caused by a stupid little typo, or the equivalent, like the above. Oy, oy!

Of course, this once again demonstrates that ProcessWire, and your code, is excellent.

* About the permissions:

I created a list of template values, using a data page for each, so I would normally think that even though the article pages that used those template values were public, the actual selection list of templates would not normally be public. I think I'll try the hidden flag, plus the lack of the template file to control them, while leaving the permissions to view them open to the public. I guess. Or maybe I can lock all of them down, and use the selectors you mention.

Sounds like there are a variety of options that one could use. Since ProcessWire specifically uses data pages for lists of values that might otherwise be in non-public areas of the database, it might be good to come up with a tutorial on best practices for the variety of privacy settings, for data pages like that.

I've created a variety of "internal" data pages that I don't want to be public web pages. Here's a graphic of them, with some of them expanded.

post-1176-0-59300400-1369004373_thumb.jp

I'd be curious to get your take on the method I've used above; if you recommend it, or not, or if you've done things differently, in your sites.

Thanks for your help!

Yours,

Peter

Link to comment
Share on other sites

XML needs numeric character references, rather than named entities. 

I wonder if a nice addition to the RSS module might be to convert an named entities to numeric automatically. This would take care of preventing any errors when body/summary etc fields are included in the RSS output.

Link to comment
Share on other sites

Dear Ryan,

I've been playing around with the combinations that affect permissions. For my 'data pages', I'm looking for this functionality:

- not viewable by the public, in searches, site-maps, or url pages.

- however, they should be accessible via the api for output in blocks, or pages, like the rss page.

I'm still trying to figure out the right combination, between:

- the template access setting (i.e. no guest access)

- the unpublished setting

- the hidden setting

Haven't gotten clarity in my wee brain yet, but I'm working on it.

[edit: I see that I can't use 'unpublished' because then the selects aren't available to use in the edit pages.]

Peter

Link to comment
Share on other sites

Hi Peter,

  • Set your pages to 'hidden'. This way they won't show up in searches unless you add include=hidden into your selector.
  • Do your data pages have a template file associated or just hold data? If there's no template file, then the pages are not accessible in the frontend anyway because Pw will throw a Wire404Exception (page not found).
  • If the data pages have a template file, then you could check on top of that if the user is SuperUser or has a certain role:
// In your template file
if (!$user->isSuperUser()) {
  throw new Wire404Exception();
}

// OR
if (!$user->hasRole('superAdmin')) //...
  • Like 1
Link to comment
Share on other sites

I agree with Wanze. But if you have a need to make the pages completely inaccessible (via access control), you can always remove guest access at the template level and use "include=all" or "check_access=0" when you need to retrieve them. But if "hidden" will accomplish what you are trying to do, I would use that, as it's more in-line with what it was designed for. Also, minor corrections to Wanze's code:

// In your template file
if (!$user->isSuperuser()) { // Changed from SuperUser to Superuser (case)
  throw new Wire404Exception();
}

// OR
if (!$user->hasRole('superuser')) // changed superAdmin to superuser
Link to comment
Share on other sites

Dear Ryan,

I set my template to not have guest permissions, and also set the templates to not be searchable:

  • No - Pages may NOT not appear in searches/lists unless the user has access to view them

API Note: This setting affects the results returned by $pages->find(), $page->children() and other functions that return PageArrays.

I added:

             "include=all,"        .
             "check_access=0,"     .
 

to my params, but even with check_access=0, the results don't return unless I unselect the above search setting.

Is it correct that check_access=0 does not affect that search setting?

This is the setting that confused me before.

Thanks,

Peter

Link to comment
Share on other sites

Dear Ryan,

I've done some testing, and I can't get things to work properly.

I've used Waynze's excellent Batcher program (thanks, Waynze!) to set all of my element data pages to 'hidden'.

I set the custom_selects template to 'no access for guests', but didn't check the 'block search' radio button.

The net result is that my rss items appear when I do NOT use the params:

             "include=all,"        .
             "check_access=0,"     .

which means that the data pages are not protected.

The pages appear in IE (not logged in) and in Firefox, after I log out.

I'm not using caching at all.

The only thing that really locks the pages down is checking the template - not searchable option, but then I can't get in at all, even when I use the check_access=0 param.

I'm probably doing something wrong, but I can't see it.

[edit: what's really weird is that the hidden flag seems to be working inside a function, where I access a 'chunk' element. I've set the element chunks to hidden, and a non-logged in browser couldn't access them with this code until I added the include=all parameter:

$field_chunk_id_array = wire(pages)->find("parent=1052, include=all");
 

The 1052 id is the parent of the chunk pages. I do a replace of chunk tags in the body field.

====

Here's my code in 'rss.php':

<?php

$rss                       = $modules->get("MarkupRSS");
$rss->title                = "RSS Feed";
$rss->description          = "This feed shows the most recent items that have been published.";
$rss->itemTitleField       = 'headline';
$rss->itemDescriptionField = 'summary';
$rss->itemDateField        = 'publish_date';
$rss->copyright            = '';

$now       = time();

#             "include=hidden,"     .
#             "include=all,"        .
#             "check_access=0,"     .

$selectors = "custom_template_file.select_value=article_page.html," .
             "sort=-publish_date," .
             "publish_date<=$now," .
             "limit=20";

$items     = $pages->get("/")->find("$selectors");

$rss->render($items);

 

Peter

Link to comment
Share on other sites

Dear Ryan,

I've done some more testing, so let me revise my statement above.

Everything is working, in the sense that I can view what I need to view, search, etc.

I confirmed that the hidden setting is preventing search results in a variety of places.

I think the two questions left are:

- the item above, about the template permissions, where it's set to not allow searches for guest users. I haven't been able to unlock that in my code, with the params mentioned above. So, I unchecked it. I'm wondering what the value of that is, if one can't access the data via code?

- with the hidden data pages: although the other code searches and page searches correctly hide the hidden data pages, the rss page mentioned above did not require the 'include=all' parameter, which I found disconcerting, since the data elements were all marked as hidden.

I'm wondering if it's because of the type of selector?

custom_template_file.select_value=article_page.html

"custom_template_file" is a field in my template field sets, which contains an id, which then links to an 'element' data page, with the select value of 'article_page.html'.

Does that type of relational look up get searched, even when the corresponding data page is hidden?

It seems so, from the behavior that I'm seeing.

I think my bottom line is that my site is functional. I do hope to get more technical clarity about the above, to fill in my knowledge gaps.

I must assume it's a knowledge gap, rather than a quirk or bug in your great program! :-)

Although I do think that the permissions system could perhaps be presented in a clearer and more intuitive manner. I've been going 'round and 'round in circles about it, for quite a while.

Thanks,

Peter

Link to comment
Share on other sites

Is it correct that check_access=0 does not affect that search setting?

You don't need "check_access=0" if you are using "include=all", because "all" implies everything. You'd only use "check_access=0" if you wanted it to include pages that the user didn't have permission to view, but still wanted to exclude hidden pages. I think what you are probably looking for is "include=all". 

wire(pages)->find("parent=1052, include=all");

You need quotes around "pages", i.e. wire("pages")

"custom_template_file.select_value=article_page.html," .

I don't understand this line–it looks a bit unusual for a selector, so wondering if there might be a problem there.

$pages->get("/")->find("$selectors");

This should be: $pages->find($selectors); 

Link to comment
Share on other sites

Dear Ryan,

Thanks for your syntax clarifications.

"custom_template_file.select_value=article_page.html," .

> I don't understand this line–it looks a bit unusual for a selector, so wondering if there might be a problem there.

In the template, there's a page_id field to select a value from a drop down. So, if I did a $custom_template_file = $page->custom_template_file, I would get an ID value that points to the select value of 'article_page.html'.

Thus, when I used the above syntax as a selector, it looks for all pages that have that long textual value. This way, I don't have to use the ID as a selector.

But, the 'hidden' attribute doesn't seem to hide that value from being searched.
 

$pages->get("/")->find("$selectors");

> This should be: $pages->find($selectors);

I thought I saw this syntax somewhere in the PW site. I thought it meant that you could specify the parent (e.g. /) in the get, and then chain the selectors off that.

Is that incorrect?

Thanks for all your help!

Peter

Link to comment
Share on other sites

Thus, when I used the above syntax as a selector, it looks for all pages that have that long textual value. This way, I don't have to use the ID as a selector.

I think I understand now. This should work so long as "custom_template_file" is the name of a Page reference field, and "select_value" is the name of the field that contains the exact text "article_page.html" among your page references. 

But, the 'hidden' attribute doesn't seem to hide that value from being searched.

None of the pages returned in your results should be "hidden" unless you specify an "include=hidden" or "include=all". Now if the page pointed to by "custom_template_file" is hidden, that doesn't matter, because that's a page you are using to match, not one of the pages being returned by find(). However, if you want that behavior, you may be able to do it like this:

"custom_template_file.select_value=article_page.html, custom_template_file.status<" . Page::statusHidden; 

You can also check if an individual page is hidden by calling it's $page->isHidden() method, or $page->is(Page::statusHidden); -- both do the same thing. 

Link to comment
Share on other sites

Create an account or sign in to comment

You need to be a member in order to leave a comment

Create an account

Sign up for a new account in our community. It's easy!

Register a new account

Sign in

Already have an account? Sign in here.

Sign In Now
  • Recently Browsing   0 members

    • No registered users viewing this page.
×
×
  • Create New...