Skip to content

markocupic/rss-feed-generator-bundle

Folders and files

NameName
Last commit message
Last commit date

Latest commit

 

History

47 Commits
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 

Repository files navigation

RSS Feed Generator Bundle

Use this bundle to generate rss feeds inside your Symfony application.

❤ Many thanks to @eko (Vincent Composieux) for giving me the inspiration to program this bundle. https://github.com/eko/FeedBundle.

Installation

composer require markocupic/rss-feed-generator-bundle

Option A: Add this to your config/bundles.php.

<?php

return [
    // ...
    Markocupic\RssFeedGeneratorBundle\MarkocupicRssFeedGeneratorBundle::class => ['all' => true],
];

Option B: In a Contao ❤ environment register the rss feed generator bundle in the Contao Manager Plugin class of your bundle.

<?php

declare(strict_types=1);

namespace Contao\CoreBundle\ContaoManager;
use Contao\CoreBundle\ContaoCoreBundle;
use Contao\ManagerPlugin\Bundle\BundlePluginInterface;
use Contao\ManagerPlugin\Bundle\Config\BundleConfig;
use Contao\ManagerPlugin\Bundle\Parser\ParserInterface;
use Contao\ManagerPlugin\Config\ConfigPluginInterface;
use Contao\ManagerPlugin\Routing\RoutingPluginInterface;
use Symfony\Component\Config\Loader\LoaderInterface;
use Symfony\Component\Config\Loader\LoaderResolverInterface;
use Symfony\Component\HttpKernel\KernelInterface;
use Markocupic\RssFeedGeneratorBundle\MarkocupicRssFeedGeneratorBundle;
use Acme\MyBundle\AcmeMyBundleBundle;

class Plugin implements BundlePluginInterface, RoutingPluginInterface, ConfigPluginInterface
{
    /**
     * {@inheritdoc}
     */
    public function getBundles(ParserInterface $parser)
    {
        return [
            // Register RSS feed generator bundle
            BundleConfig::create(MarkocupicRssFeedGeneratorBundle::class),
            // register other bundles
            BundleConfig::create(AcmeMyBundle::class)
            ->setLoadAfter(MarkocupicRssFeedGeneratorBundle::class)
            ->setLoadAfter(ContaoCoreBundle::class)
        ];
    }

Use dependency injection to require the feed factory in your controller.

# config/services.yml
services:

  Markocupic\DemoBundle\Controller\Feed\FeedController:
    arguments:
      - '@Markocupic\RssFeedGeneratorBundle\Feed\FeedFactory'
      - '@database_connection'
      - '%kernel.project_dir%'
    public: true

Create the feed

// Use the feed factory to generate the feed object
$rss = $this->feedFactory->createFeed(\Markocupic\RssFeedGeneratorBundle\Feed\Feed::ENCODING_UTF8);

 // Add one or more attributes to the root element
$rss->setRootAttributes([
    'xmlns:tourdb' => 'https://acme.com/schema/tourdbrss/1.0',
    'xmlns:atom'=>'http://www.w3.org/2005/Atom',
]);

// Add one or more attributes to the channel element
$rss->setChannelAttributes([
    'foo' => 'bar',
]);

Add feed Channel elements

Use the Item class inside the feed factory method FeedFactory::addChannelField().

The Item::__constructor($elementName, $strValue, $arrOptions, $arrAttributes) takes four arguments:

  1. (string) element name
  2. (string) content
  3. optional: (array) options (at the moment cdata, and filters)
  4. optional: (array) with attributes
$rss->addChannelField(
    new Item('title', 'Demo feed')
);

$rss->addChannelField(
    new Item('link', 'https://foobar.ch')
);

Make cdata elements and insert attributes:

// Add CDATA element and an attribute
$rss->addChannelField(
    new Item('description', 'Check our news feed and have fun!', ['cdata' => true], ['attrName' => 'Here comes the attribute value'])
);

Filter od replace content

// filter or replace values
$arrFilter = ['Ferrari' => 'Italia', 'car' => 'country'] ;
$rss->addChannelField(
    new Item('description', 'Ferrari is my favourite car!', ['filter' => $arrFilter])
);
// Will result in:
// <description>Italia is my favourite country!</description>

Add channel items

Use FeedFactory::addChannelItemField(), ItemGroup() and Item() to generate channel items.

The ItemGroup::__constructor($elementName, $arrItemObjects, $arrAttributes) takes three arguments:

  1. (string) element name
  2. (array) with Item objects
  3. optional: (array) with attributes
// Retrieve data from database and add items
$results = $this->getEvents($section);

if (null !== $results) {
    while (false !== ($arrEvent = $results->fetch())) {
        // Use a new instance of ItemGroup to add a collection of items all of the same level.
        $rss->addChannelItemField(
            new ItemGroup('item', [
                new Item('title', $arrEvent['title']),
                new Item('link', $arrEvent['link']),
                new Item('description', $arrEvent['description'], ['cdata' => true]),
                new Item('pubDate', date('r',(int) $arrEvent['tstamp'])),
                new Item('author', $arrEvent['author']),
                new Item('guid', $arrEvent['uuid']),
                new Item('tourdb:startdate', date('Y-m-d', (int) $arrEvent['startDate'])),
                new Item('tourdb:enddate', date('Y-m-d', (int) $arrEvent['endDate'])),
            ])
        );
    }
}

Nested items

// Append nested items with ItemGroup.
$rss->addChannelItemField(
    new ItemGroup('item', [
        new Item('title', 'Title'),
        new Item('link', 'https://foo.bar'),
        new ItemGroup('nestedItems', [
            new Item('subitem', 'Some content'),
            new Item('subitem', 'Some content'),
        ], ['foo'=> 'bar']),
    ])
);

Result:

<item>
    <title>Title</title>
    <link>https://foo.bar</link>
    <nestedItem foo="bar">
        <subitem>Some content</subitem>
        <subitem>Some content</subitem>
    </nestedItem>
</item>

Render and send content to the browser.

return $rss->render();

Render and save content to the filesystem.

return $rss->render('public/share/myfeed.xml);

Generate RSS 2.0 feed inside a controller in a Symfony bundle

<?php

declare(strict_types=1);

namespace Acme\DemoBundle\Controller\Feed;

use Doctrine\DBAL\Connection;
use Doctrine\DBAL\Query\QueryBuilder;
use Markocupic\RssFeedGeneratorBundle\Feed\FeedFactory;
use Markocupic\RssFeedGeneratorBundle\Item\Item;
use Markocupic\RssFeedGeneratorBundle\Feed\ItemGroup;
use Symfony\Bundle\FrameworkBundle\Controller\AbstractController;
use Symfony\Component\HttpFoundation\Response;
use Symfony\Component\Routing\Annotation\Route;

class FeedController extends AbstractController
{
    /**
     * @var FeedFactory
     */
    private $feedFactory;

    /**
     * @var Connection
     */
    private $connection;

    /**
     * @var string
     */
    private $projectDir;

    /**
     * @Route("/_rssfeed", name="rss_feed")
     */
    public function printLatestEvents(): Response
    {

        $rss = $this->feedFactory->createFeed('utf-8');

        $rss->addChannelField(
            new Item('title', 'Acme news')
        );

        $rss->addChannelField(
            new Item('description', 'Enjoj our news.')
        );

        $rss->addChannelField(
            new Item('link', 'https://acme.com')
        );

        $rss->addChannelField(
            new Item('language', 'de')
        );

        $rss->addChannelField(
            new Item('pubDate', date('r', (time() - 3600)))
        );

        // Retrieve data from db
        $results = $this->getEvents($section);

        // Add some channel items
        if (null !== $results) {
            while (false !== ($arrEvent = $results->fetch())) {
                $eventsModel = $calendarEventsModelAdapter->findByPk($arrEvent['id']);

                $rss->addChannelItemField(
                    new ItemGroup('item', [
                        new Item('title', $arrEvent['title']),
                        new Item('link', $arrEvent['link']),
                        new Item('description', $arrEvent['description'], ['cdata' => true]),
                        new Item('pubDate', date('r', (int) $eventsModel->tstamp)),
                    ])
                );
            }
        }

        return $rss->render($this->projectDir.'/public/share/rss.xml');
    }
}

Filter & search and replace strings

The extension will filter by default some characters. Linebreaks will be replaced with a whitespace, etc. Please have a look at the Plugin Configuration.

Overriding these defaults is pretty easy and can be done in config/parameters.yml. Please use regular expressions for the search patterns.

# config/parameters.yml
markocupic_rss_feed_generator:
  filter:
    '/</': '&lt;'
    '/[\n\r]+/': ' '
    '/&#40;/': '('
    '/&#41;/': ')'
    '/\[-\]/': ''
    '/\&shy;/': ''
    '/\[nbsp\]/': ' '
    '/&nbsp;/': ' '
    '/&/': '&amp;'

About

simple rss feed generator

Resources

License

Stars

Watchers

Forks

Packages

No packages published