RSS Feed for an image collection

Hello everyone. I was wondering if it would be possible to create a RSS Feed for a collection of images? I’ve tried to edit the feed.php with the same method I’m using in my template, but that seems to break the whole feed, resulting in an empty <body>. Not shure what I’m doing wrong, or if this is even the right approach, so any help would be greatly appreciated. Here’s how it currently looks:

<?php
  $screenshots = page('screenshots')->children()->visible();
  $images = new Collection();
    foreach ($screenshots as $project) {
      foreach ($project->images() as $i) {
        $images->data[] = $i;
      }
    }
  $images = $images->sortBy('modified', 'desc');

  echo $images->limit(10)->feed(array(
    'title'       => $page->title(),
    'description' => $page->description(),
    'link'        => 'blog',
  ));
?>

The main goal is to create an entry for each new image added to the collection and add the title and caption underneath it as well.

Hello,
As far as I can tell, the feed plugin is meant to loop through pages not images.You could loop through the pages:

<?php
  $screenshots = page('screenshots')->children()->visible()->sortBy('modified', 'desc');

  echo $screenshots->limit(10)->feed(array(
    'title'       => $page->title(),
    'description' => $page->description(),
    'link'        => 'screenshots',
  ));
?>

Now that you have your pages listed, let’s talk about adding images. The feed plugin doesn’t have this built-in. Let’s add it! Edit template.php in site/plugins/feed

  • Add `the following on line 22 (just below the description)
<enclosure url="<?= $item->image()->url(); ?>" length="<?= $item->image()->size(); ?>" type="image/<?= $item->image()->extension(); ?>" />

This may not cover your needs if you have several images per child page of screenshots. Not knowing your content structure, I can only hope this works :wink:

You could also modifiy the code I gave you to fetch the last modified image from each page:
Change $item->image() to $item->images()->sortBy('modified', 'desc')->first();

You may also want to modify where the title and description in the template.php file are taken from. Right now, it will be from the page containing the image and not from the image itself.

NB: I have no way of testing any of the code I’m giving you right now. Please double-check everything works right for you!

1 Like

Wow, what a detailed answer, thank you! Sadly (as you have already guessed), there are several images in the child pages and I would like to have an entry for each of them, so looping through the pages alone isn’t going to work. :sweat_smile: My content structure looks somewhat like this:

- Screenshots 
  - Project a
    - image1.jpg
    - image2.jpg
  - Project B
    - image3.jpg
    - image4.jpg
  - Project C
    - image5.jpg
    - image6.jpg
    - image7.jpg

Your code is perfect for a Blogfeed though, and I’ll probably use it for that, since it works fine. It’s just not working for my initial idea. And I’m aware that my structure may be pushing the plugin a bit, so if it really isn’t meant for looping through images, I guess there isn’t much I can do to achieve this?

There’s always something you can do and the flexibility of Kirby is amazing :slight_smile:

What would your XML entry look like? Can you look at the template.php and list the fields you’d need? You mentioned wanting to get the title and caption from the image. Are those custom file fields?

I’m sure we’ll find a solution for you! If it leaves the reach of my skillset, there are many way more talented devs here that’ll know just the perfect way to do this!

1 Like

Check out this post: RSS Feed with images

2 Likes

That’s one way of doing it but it would result in all the images of a page being listed for the 10 most recent pages.
If I understand what @Swissendo wants, it’s the 10 most recent images, regardless of the page it’s from.
Is that a correct assumption?

Yes, that is a correct assumption. As far as I can understand, the solution from @texnixe would list the ten most recent pages, each containing all images of them, just like you’ve said. What I want is to bundle all images together, sort them by the modified date and output the 10 most recent images. I want something similar to a Flickr RSS Feed, to give an example.

As for the XML: The caption and title are custom file fields, yes. At first I thought I could just use $item->caption() and $item->title() inside the <description>, if the plugin recognizes the images as an $item, but it seems that’s exactly where the main problem is. Either way, thank you both for your answers and support so far!

It should not be too difficult to rewrite the plugin so that it supports images instead of pages. Currently, it creates a new pages method, so you would have to create a new files method “feed”.

A series of questions:

  • Have you turned on debugging? c::set('debug',true); in the file site/config/config.php
  • Can you share your blueprint for the children of screenshots? I’m only interested in the “files” part.
  • Have you set a title and caption for all of your images?
  • What do you want the <uri> to link to? Flickr example: <uri>https://www.flickr.com/people/someuser/</uri>

I’m sure it’s going to be easy fixing this :wink:

@Thiousi: As I said above, with the current way the plugin works, it is page based, so there is no feed method on images. It simply won’t work. So this code:

echo $images->limit(10)->feed(array(
    'title'       => $page->title(),
    'description' => $page->description(),
    'link'        => 'blog',
  ));

will throw an error.

I’m well aware :wink: It was the first thing I said in this thread :smiley:

@Thiousi. Well, sorry, I was set on the wrong track by your last post, because the problem is not related to the blueprint with the titles and captions.

Anyway, @swissendo, I think it is worth a try to adapt the feed plugin by using a files method instead:

Instead of this:

Pages::$methods['feed'] = function($pages, $params = array()) {
}

use

Files::$methods['feed'] = function($files, $params = array()) {
}

and change the defaults and all the rest where necessary. You will have to adapt the template as well.

https://getkirby.com/docs/developer-guide/objects/files

@texnixe: I’ve tried to adapt the files to the best to my knowledge (which probably means I’ve made a ton of mistakes), yet nothing changed. Here’s how my files look so far:

/templates/feed.php

<?php
  $screenshots = page('screenshots')->children()->visible();
  $images = new Collection();
    foreach ($screenshots as $project) {
      foreach ($project->images() as $i) {
        $images->data[] = $i;
      }
    }
  $images = $images->sortBy('modified', 'desc');

  echo $images->limit(10)->feed(array(
    'title'       => 'Test',
    'description' => 'Test',
    'link'        => 'blog',
  ));
?>

template.php

  <channel>
    <title><?php echo xml($title) ?></title>
    <link><?php echo xml($link) ?></link>
    <generator><?php echo c::get('feed.generator', 'Kirby') ?></generator>
    <lastBuildDate><?php echo date('r', $modified) ?></lastBuildDate>
    <atom:link href="<?php echo xml($url) ?>" rel="self" type="application/rss+xml" />

    <?php if(!empty($description)): ?>
    <description><?php echo xml($description) ?></description>
    <?php endif ?>

    <?php foreach($items as $item): ?>
    <item>
      <title><?php echo xml($item->title()) ?></title>
      <link><?php echo xml($item->url()) ?></link>
      <guid><?php echo xml($item->id()) ?></guid>
      <pubDate><?php echo $datefield == 'modified' ? $item->modified('r') : $item->date('r', $datefield) ?></pubDate>
      <description>
        <enclosure url="<?= $item->image()->url(); ?>" length="<?= $item->image()->size(); ?>" type="image/<?= $item->image()->extension(); ?>" />
        <![CDATA[<?php echo $item->{$textfield}()->kirbytext() ?>]]>
      </description>
    </item>
    <?php endforeach ?>
  </channel>
</rss>

feed.php

<?php

/**
 * Feed Plugin
 *
 * @author Bastian Allgeier <bastian@getkirby.com>
 * @version 2.0.0
 */
Files::$methods['feed'] = function($files, $params = array()) {

  // set all default values
  $defaults = array(
    'url'         => url(),
    'title'       => 'Feed',
    'description' => '',
    'link'        => url(),
    'datefield'   => time(),
    'textfield'   => 'caption',
    'modified'    => time(),
    'excerpt'     => false,
    'generator'   => kirby()->option('feed.generator', 'Kirby'),
    'header'      => true,
    'snippet'     => false,
  );

  // merge them with the user input
  $options = array_merge($defaults, $params);

  // sort by date
  $items = $files->sortBy($options['modified'], 'desc');

  // add the items
  $options['items'] = $items;
  $options['link']  = url($options['link']);

  // fetch the modification date
  if($options['datefield'] == 'modified') {
    $options['modified'] = $items->first()->modified();
  } else {
    $options['modified'] = $items->first()->date(null, $options['datefield']);
  }

  // send the xml header
  if($options['header']) header::type('text/xml');

  // echo the doctype
  $html  = '<?xml version="1.0" encoding="utf-8"?>' . PHP_EOL;

  // custom snippet
  if($options['snippet']) {
    $html .= snippet($options['snippet'], $options, true);
  } else {
    $html .= tpl::load(__DIR__ . DS . 'template.php', $options);
  }

  return $html;

};

I’ll continue to fiddle around with it, thank you for the starting point.

@Thiousi

  • Yes, I have. I’ll probably need to change something in my xampp first though, because php_error_log doesn’t seem to exist.
  • Do you mean the blueprint for the panel? There isn’t much to it, the only fields of interest are title and caption, plus some other stuff that isn’t relevant to this question.
  • No, I haven’t. But some of them have both, so at least these should show up, I think?

What do you get as a result?

Your items should now be your images, but you are trying to use an enclosure tag where you call the image method on a file, that’s not possible.

Oh, btw, you can get your image collection with only one line of code:

$images = page('screenshots')->children()->visible()->images();

I still get an empty <body>, with and without the enclosure and the line of code. So nothing really changed.

Pls. try to enable debugging or check where your php_error_log is located, there should be a folder called logs somewhere. What version of XAMPP is that? Are you on Windows?

Debugging is enabled, it just doesn’t seem to output anything regarding the RSS Feed. If I purposely create an error by changing $page to $pagee or something similar, it shows up in my php_error_log.txt. Visiting the Feed URL doesn’t ouput anything.

Edit: Windows, XAMPP 3.2.2 5.6.19

I’ll try to look into this later today or tomorrow.

1 Like

Sorry, there never was a “XAMPP” version like

This number may be the version of the “XAMPP Control Panel”!

Please look in line 3 of the logged text.

1 Like