markocupic / rss-feed-generator-bundle
Simple RSS feed generator. Generate RSS feeds inside a symfony controller.
Installs: 6 612
Dependents: 2
Suggesters: 0
Security: 0
Stars: 1
Watchers: 2
Forks: 0
Open Issues: 1
Type:symfony-bundle
Requires
- php: ^7.4 || ^8.0
- symfony/framework-bundle: ^4.4 || ^5.2 || ^6.0
Requires (Dev)
README
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:
- (string) element name
- (string) content
- optional: (array) options (at the moment cdata, and filters)
- 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:
- (string) element name
- (array) with Item objects
- 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: '/</': '<' '/[\n\r]+/': ' ' '/(/': '(' '/)/': ')' '/\[-\]/': '' '/\­/': '' '/\[nbsp\]/': ' ' '/ /': ' ' '/&/': '&'