Ecosyste.ms: Awesome
An open API service indexing awesome lists of open source software.
https://github.com/alexdebril/rss-atom-bundle
RSS and Atom Bundle for Symfony
https://github.com/alexdebril/rss-atom-bundle
atom atom-feed feed feed-io feed-reading jsonfeed rss rss-atom-bundle symfony
Last synced: 8 days ago
JSON representation
RSS and Atom Bundle for Symfony
- Host: GitHub
- URL: https://github.com/alexdebril/rss-atom-bundle
- Owner: alexdebril
- License: mit
- Created: 2013-01-30T18:42:39.000Z (almost 12 years ago)
- Default Branch: master
- Last Pushed: 2024-01-30T13:37:49.000Z (9 months ago)
- Last Synced: 2024-09-07T21:15:08.151Z (2 months ago)
- Topics: atom, atom-feed, feed, feed-io, feed-reading, jsonfeed, rss, rss-atom-bundle, symfony
- Language: PHP
- Homepage:
- Size: 1.08 MB
- Stars: 139
- Watchers: 7
- Forks: 49
- Open Issues: 4
-
Metadata Files:
- Readme: README.md
- License: LICENSE
- Codeowners: CODEOWNERS
Awesome Lists containing this project
README
# RssAtomBundle - Read and Build Atom/RSS feeds
[![SensioLabsInsight](https://insight.sensiolabs.com/projects/9e0b1301-d7a5-49fd-916b-49da544389ac/big.png)](https://insight.sensiolabs.com/projects/9e0b1301-d7a5-49fd-916b-49da544389ac)
[![Latest Stable Version](https://poser.pugx.org/debril/rss-atom-bundle/v/stable.png)](https://packagist.org/packages/debril/rss-atom-bundle)
[![Download Count](https://poser.pugx.org/debril/rss-atom-bundle/d/total)](https://packagist.org/packages/debril/rss-atom-bundle)
[![Build Status](https://secure.travis-ci.org/alexdebril/rss-atom-bundle.png?branch=master)](http://travis-ci.org/alexdebril/rss-atom-bundle)
[![Scrutinizer Code Quality](https://scrutinizer-ci.com/g/alexdebril/rss-atom-bundle/badges/quality-score.png?s=6e4cc3b9368ddbf14b1066114b6af6d9011894d9)](https://scrutinizer-ci.com/g/alexdebril/rss-atom-bundle/)
[![Code Coverage](https://scrutinizer-ci.com/g/alexdebril/rss-atom-bundle/badges/coverage.png?s=5bbd191f3b9364b8c31d8f1881f4c1fd06829fc3)](https://scrutinizer-ci.com/g/alexdebril/rss-atom-bundle/)RssAtomBundle is a Bundle for Symfony made to easily access and deliver JSON / RSS / Atom feeds. It is built on top of [feed-io](https://github.com/alexdebril/feed-io) and features:
- Detection of the feed format (JSON / RSS / Atom)
- enclosures support
- A generic StreamController built to write all your feeds. This controller is able to send a 304 HTTP Code if the feed didn't change since the last visit
- HTTP Headers support when reading feeds in order to save network traffic
- Content filtering to fetch only the newest items
- multiple feeds writing
- Ability to use doctrine as a data source
- PSR compliant logging
- DateTime detection and conversion
- Guzzle Client integrationKeep informed about new releases and incoming features : http://debril.org/category/rss-atom-bundle
You can try rss-atom-bundle through its [Demo](https://rss-atom-demo.herokuapp.com/).
## Installation
### Dependencies
As a Symfony Bundle, RssAtomBundle must be installed using Composer. If you do not know Composer, please refer to its website: http://getcomposer.org/
### Your application uses Symfony 3.3 or later
Activate Symfony's [contrib recipes](https://github.com/symfony/recipes-contrib) and use Composer to require the bundle :
```shell
composer config extra.symfony.allow-contrib true
composer require debril/rss-atom-bundle
```That's it. To check the installation, you can start your application and hit http://localhost:8000/rss in your browser. You should see a mock RSS stream.
### If your application uses Symfony < 3.3
Install the bundle using Composer :
```shell
composer require debril/rss-atom-bundle
```Add the bundle's routing configuration in app/config/routing.yml :
```yaml
rssatom:
resource: "@DebrilRssAtomBundle/Resources/config/routing.yml"```
Edit your app/AppKernel.php to register the bundle in the registerBundles() method as above:
```php
class AppKernel extends Kernel
{public function registerBundles()
{
$bundles = array(
new Symfony\Bundle\FrameworkBundle\FrameworkBundle(),
// ...
// register the bundle here
new Debril\RssAtomBundle\DebrilRssAtomBundle(),
```## Usage
rss-atom-bundle is designed to read feeds across the internet and to publish your own using [feed-io](https://github.com/alexdebril/feed-io)
feed-io provides two interfaces, each one being dedicated to feed's consuming and publishing :- [FeedInterface](https://github.com/alexdebril/feed-io/blob/master/src/FeedIo/FeedInterface.php) to handle the feed
- [ItemInterface](https://github.com/alexdebril/feed-io/blob/master/src/FeedIo/Feed/ItemInterface.php) to handle feed's items### Getting a FeedIo instance
You can fetch a `FeedIo\FeedIo` instance through dependency injection or the service container.
#### Dependency injection (highly recommended)
```php
namespace App\Feed;
class Consumer
{/**
* @type \FeedIo\FeedIo
*/
private $feedIo;public function __construct(FeedIo $feedIo)
{
$this->feedIo = $feedIo;
}
}```
#### Service Container
Wherever you have access to the service container :
```php
container->get('feedio');
```### Feed Reading
To read a feed you need to use the `feedio` service which provides two methods for that : `read()` and `readSince()`. This service is based upon [FeedIo](https://github.com/alexdebril/feed-io/blob/master/src/FeedIo/FeedIo.php).
#### using read()
`read()` is designed to give a brand new Feed instance or any object of your own, as long as it implements the [FeedInterface](https://github.com/alexdebril/feed-io/blob/master/src/FeedIo/FeedInterface.php) interface. It takes three arguments :
- `$url` : URL of the RSS/Atom feed you want to read (eg: http://php.net/feed.atom)
- `$feed` (optional) : a FeedInterface instance. The default is a new `\FeedIo\Feed` instance
- `$modifiedSince` (optional) : the last time you read this feed. This is useful to fetch only the articles which were published after your last hit.With a `\FeedIo\FeedIo` instance called `$feedIo` :
```php
read($url, new \Acme\Entity\Feed, $modifiedSince)->getFeed();foreach ( $feed as $item ) {
echo "item title : {$item->getTitle()} \n ";
// getMedias() returns enclosures if any
$medias = $item->getMedias();
}?>
```
`read()` fetches the feed hosted at `$url` and removes items prior to `$modifiedSince`. If it is the first time you read this feed, then you must specify a date far enough in the past to keep all the items. This method does not loop until the `$modifiedSince` is reached, it justs performs one hit and filters the response to keep only the fresh articles.#### using readSince()
`readSince()` helps you get a `\FeedIo\Feed` without creating its instance :
```php
container->get('feedio');// this date is used to fetch only the latest items
$modifiedSince = new \DateTime($date);// the feed you want to read
$url = 'http://host.tld/feed';// now fetch its (fresh) content
$feed = $feedIo->readSince($url, $modifiedSince)->getFeed();
?>
```### Providing feeds
RssAtomBundle offers the ability to provide JSON/RSS/Atom feeds. The route will match the following pattern : /{format}/{contentId}
- {format} must be "rss" or "atom" (or whatever you want if you add the good routing rule in routing.yml)
- {contentId} is an optional argument. Use it you have several feedsThe request will be handled by `StreamController`, according to the following steps :
- 1 : grabs the ModifiedSince header if it exists
- 2 : creates an `Options` instance holding the request's parameters (contentId if it exists)
- 3 : gets the provider defined in services.yml and calls the `getFeedContent(Options $options)` method
- 4 : compare the feed's LastModified property with the ModifiedSince header
- 5 : if LastModified is prior or equal to ModifiedSince then the response contains only a "NotModified" header and the 304 code. Otherwise, the stream is built and sent to the client#### Defining you own provider
You must give to RssAtomBundle the content you want it to display in the feed. For that, two steps :
- write a class that implements `FeedProviderInterface`. This class that we call a 'provider' will be in charge of building the feed.
- configure the dependency injection to make RssAtomBundle use it##### FeedContentProviderInterface implementation
Your class just needs to implement the `Debril\RssAtomBundle\Provider\FeedProviderInterface` interface, for instance :
```php
setTitle('your title');
foreach($this->getItems() as $item ) {
$feed->add($item);
}return $feed;
}protected function getItems()
{
foreach($this->fetchFromStorage() as $storedItem) {
$item = new Item;
$item->setTitle($storedItem->getTitle());
// ...
yield $item;
}
}
protected function fetchFromStorage()
{
// query the database to fetch items
}
}
```StreamController expects the getFeed()'s return value to be a `FeedIo\FeedInterface` instance. It can be a `FeedIo\Feed` or a class of your own and if so, your class MUST implement `\FeedIo\FeedInterface`.
You can also start from this class to save some time : [App\Feed\Provider.php](/Resources/sample/Provider.php)
```php
```
##### configurationNow, you need to configure the `debril.rss_atom.provider` service with the provider's class in your project's services.yml :
```yml
# config/services.yaml
parameters:
debril.rss_atom.provider.class: 'App\Feed\Provider'
```Or, if you need to build it with arguments, you can override `debril.rss_atom.provider`'s declaration :
```yml
# config/services.yaml
services:
debril.rss_atom.provider:
class: App\Feed\Provider
arguments: ["@logger", "@doctrine"]
```That's it. Go to http://localhost:8000/atom, it should display your feed.
##### Make the StreamController answer with a 404
If the reclaimed feed does not exist, you just need to throw a FeedNotFoundException to make the StreamController answer with a 404 error. Otherwise, `getFeedContent(Options $options)` must return a `\FeedIo\FeedInterface` instance. Then, the controller properly turns the object into a XML stream.
More information on the FeedContentProviderInterface interface and how to interface rss-atom-bundle directly with doctrine can be found in the [Providing Feeds section](https://github.com/alexdebril/rss-atom-bundle/wiki/Providing-feeds)
## Useful Tips
### Skipping 304 HTTP Code
The HTTP cache handling can be annoying during development process, you can skip it through configuration in your app/config/config.yml file :
```yml
# config/packages/rss_atom.yaml
debril_rss_atom:
force_refresh: true
```This way, the `StreamController` will always display your feed's content and return a 200 HTTP code.
### Private feeds
You may have private feeds, user-specific or behind some authentication.
In that case, you don't want to `Cache-Control: public` header to be added, not to have your feed cached by a reverse-proxy (such as Symfony AppCache or Varnish).
You can do so by setting `private` parameter to `true` in config:```yml
# config/packages/rss_atom.yaml
debril_rss_atom:
private: true
```### Adding non-standard date formats
Some feeds use date formats which are not compliant with the specifications. You can fix this by adding the format in your configuration
```yml
# config/packages/rss_atom.yaml
debril_rss_atom:
date_formats:
- 'Y/M/d'
```### Using custom Content Type header for feed generation
If you need to customize the Content-Type header of your feed you can specify the value in your configuration
```yml
# config/packages/rss_atom.yaml
debril_rss_atom:
content_type_json: application/json
content_type_xml: application/xhtml+xml
```### Going back to feed-io 3.0
Starting from version 4.1 rss-atom-bundle comes with feed-io 4 if your application depends on PHP 7.1+. If you need to use feed-io 3 instead for some reason, you can do it in `composer.json` :
```yml
"debril/rss-atom-bundle": "^4.1",
"debril/feed-io": "~3.0",
```### Override tip
It could happen that according to the order of the bundles registered in `AppKernel`, this override procedures do not work properly. This happens when a bundle is registered before `rss-atom-bundle`.
In this case, you should use the Symfony `CompilerPass` as reported in the [documentation](http://symfony.com/doc/current/bundles/override.html#services-configuration).`Vendor/Bundle/VendorBundle.php`:
```php
use Vendor\Bundle\DependencyInjection\Compiler\OverrideRssAtomBundleProviderCompilerPass;
use Symfony\Component\DependencyInjection\ContainerBuilder;
use Symfony\Component\HttpKernel\Bundle\Bundle;class VendorBundle extends Bundle
{
public function build(ContainerBuilder $container)
{
parent::build($container);
$container->addCompilerPass(new OverrideRssAtomBundleProviderCompilerPass());
}
}
```and `Vendor/Bundle/DependencyInjection/Compiler/OverrideRssAtomBundleProviderCompilerPass.php`:
```php
use Vendor\Bundle\Provider\FeedProvider;
use Symfony\Component\DependencyInjection\Compiler\CompilerPassInterface;
use Symfony\Component\DependencyInjection\ContainerBuilder;
use Symfony\Component\DependencyInjection\Reference;class OverrideRssAtomBundleProviderCompilerPass implements CompilerPassInterface
{
public function process(ContainerBuilder $container)
{
$definition = $container->getDefinition('debril.rss_atom.provider');
$definition->setClass(FeedProvider::class);
$definition->addArgument(new Reference('my.service1'));
$definition->addArgument(new Reference('my.service2'));
}
}
```You can follow either `services.xml` or `CompilerPass` but with services, you have to pay attention to bundles registration order.
## Fetching the repository
Do this if you want to contribute (and you're welcome to do so):
git clone https://github.com/alexdebril/rss-atom-bundle.git
composer.phar install --dev
## Unit Testing
You can run the unit test suites using the following command in the Bundle's source director:
bin/phpunit