Permalink
Browse files

feature #425 Add a blog posts RSS channel (yceruto, javiereguiluz)

This PR was merged into the master branch.

Discussion
----------

Add a blog posts RSS channel

This try to implement a simple RSS channel accepted in #155 since Aug 2015.

Knowledge that brings:
* Custom XML extension to specify the format of the template (`index.xml.twig`).
* How to render a simple XML file.

Any suggestions would be welcome! ;)

Commits
-------

d7420d5 Moved the RSS link to the sidebar
cc8fe6b Minor tweaks
8a02a15 add rss title to link element
4e2c7db simplify the blog_rss route definition
254632c Minor tweaks in the translation strings
8a51859 add rss channel
  • Loading branch information...
2 parents c700a55 + d7420d5 commit 4d93cdaf4f584e37797077d461c3b3420ca00aa7 @javiereguiluz javiereguiluz committed Jan 12, 2017
@@ -243,6 +243,10 @@
<source>menu.logout</source>
<target>Logout</target>
</trans-unit>
+ <trans-unit id="menu.rss">
+ <source>menu.rss</source>
+ <target>Blog Posts RSS</target>
+ </trans-unit>
<trans-unit id="post.to_publish_a_comment">
<source>post.to_publish_a_comment</source>
@@ -317,6 +321,15 @@
<source>help.more_information</source>
<target><![CDATA[For more information, check out the <a href="http://symfony.com/doc">Symfony doc</a>.]]></target>
</trans-unit>
+
+ <trans-unit id="rss.title">
+ <source>rss.title</source>
+ <target>Symfony Demo blog</target>
+ </trans-unit>
+ <trans-unit id="rss.description">
+ <source>rss.description</source>
+ <target>Most recent posts published on the Symfony Demo blog</target>
+ </trans-unit>
</body>
</file>
</xliff>
@@ -9,6 +9,7 @@
<meta charset="UTF-8" />
<meta name="viewport" content="width=device-width, initial-scale=1"/>
<title>{% block title %}Symfony Demo application{% endblock %}</title>
+ <link rel="alternate" type="application/rss+xml" title="{{ 'rss.title'|trans }}" href="{{ path('blog_rss') }}">
{% block stylesheets %}
<link rel="stylesheet" href="{{ asset('css/bootstrap-flatly-3.3.7.min.css') }}">
<link rel="stylesheet" href="{{ asset('css/font-awesome-4.6.3.min.css') }}">
@@ -0,0 +1,5 @@
+<div class="section rss">
+ <a href="{{ path('blog_rss') }}">
+ <i class="fa fa-rss" aria-hidden="true"></i> {{ 'menu.rss'|trans }}
+ </a>
+</div>
@@ -28,4 +28,5 @@
{{ parent() }}
{{ show_source_code(_self) }}
+ {{ include('blog/_rss.html.twig') }}
{% endblock %}
@@ -0,0 +1,22 @@
+<?xml version="1.0" encoding="UTF-8" ?>
+<rss version="2.0">
+ <channel>
+ <title>{{ 'rss.title'|trans }}</title>
+ <description>{{ 'rss.description'|trans }}</description>
+ <pubDate>{{ 'now'|date('r', timezone='GMT') }}</pubDate>
+ <lastBuildDate>{{ (posts|last).publishedAt|default('now')|date('r', timezone='GMT') }}</lastBuildDate>
+ <link>{{ url('blog_index') }}</link>
+ <language>{{ app.request.locale }}</language>
+
+ {% for post in posts %}
+ <item>
+ <title>{{ post.title }}</title>
+ <description>{{ post.summary }}</description>
+ <link>{{ url('blog_post', {'slug': post.slug}) }}</link>
+ <guid>{{ url('blog_post', {'slug': post.slug}) }}</guid>
+ <pubDate>{{ post.publishedAt|date(format='r', timezone='GMT') }}</pubDate>
+ <author>{{ post.authorEmail }}</author>
+ </item>
+ {% endfor %}
+ </channel>
+</rss>
@@ -63,4 +63,5 @@
{{ parent() }}
{{ show_source_code(_self) }}
+ {{ include('blog/_rss.html.twig') }}
{% endblock %}
@@ -34,16 +34,24 @@
class BlogController extends Controller
{
/**
- * @Route("/", defaults={"page": "1"}, name="blog_index")
- * @Route("/page/{page}", requirements={"page": "[1-9]\d*"}, name="blog_index_paginated")
+ * @Route("/", defaults={"page": "1", "_format"="html"}, name="blog_index")
+ * @Route("/rss.xml", defaults={"page": "1", "_format"="xml"}, name="blog_rss")
+ * @Route("/page/{page}", defaults={"_format"="html"}, requirements={"page": "[1-9]\d*"}, name="blog_index_paginated")
* @Method("GET")
* @Cache(smaxage="10")
+ *
+ * NOTE: For standard formats, Symfony will also automatically choose the best
+ * Content-Type header for the response.
+ * See http://symfony.com/doc/current/quick_tour/the_controller.html#using-formats
*/
- public function indexAction($page)
+ public function indexAction($page, $_format)
{
$posts = $this->getDoctrine()->getRepository(Post::class)->findLatest($page);
- return $this->render('blog/index.html.twig', ['posts' => $posts]);
+ // Every template name also has two extensions that specify the format and
+ // engine for that template.
+ // See https://symfony.com/doc/current/templating.html#template-suffix
+ return $this->render('blog/index.'.$_format.'.twig', ['posts' => $posts]);
}
/**
@@ -37,4 +37,21 @@ public function testIndex()
'The homepage displays the right number of posts.'
);
}
+
+ public function testRss()
+ {
+ $client = static::createClient();
+ $crawler = $client->request('GET', '/en/blog/rss.xml');
+
+ $this->assertSame(
+ 'text/xml; charset=UTF-8',
+ $client->getResponse()->headers->get('Content-Type')
+ );
+
+ $this->assertCount(
+ Post::NUM_ITEMS,
+ $crawler->filter('item'),
+ 'The xml file displays the right number of posts.'
+ );
+ }
}
View
@@ -118,6 +118,13 @@ footer #footer-resources i {
min-width: 75px
}
+/* Misc. elements
+ ------------------------------------------------------------------------- */
+.section.rss a {
+ color: #f39c12;
+ font-size: 21px;
+}
+
/* Forms
------------------------------------------------------------------------- */
.form-group.has-error .form-control {

0 comments on commit 4d93cda

Please sign in to comment.