[FIX] SEO for blog tags and categories
[odoo/odoo.git] / addons / website_blog / controllers / main.py
1 # -*- coding: utf-8 -*-
2 ##############################################################################
3 #
4 #    OpenERP, Open Source Management Solution
5 #    Copyright (C) 2013-Today OpenERP SA (<http://www.openerp.com>).
6 #
7 #    This program is free software: you can redistribute it and/or modify
8 #    it under the terms of the GNU Affero General Public License as
9 #    published by the Free Software Foundation, either version 3 of the
10 #    License, or (at your option) any later version.
11 #
12 #    This program is distributed in the hope that it will be useful,
13 #    but WITHOUT ANY WARRANTY; without even the implied warranty of
14 #    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
15 #    GNU Affero General Public License for more details.
16 #
17 #    You should have received a copy of the GNU Affero General Public License
18 #    along with this program.  If not, see <http://www.gnu.org/licenses/>.
19 #
20 ##############################################################################
21
22 from openerp.addons.web import http
23 from openerp.addons.web.http import request
24 from openerp.addons.website.models import website
25 from openerp.tools.translate import _
26 from openerp.tools.safe_eval import safe_eval
27
28 import simplejson
29 import werkzeug
30
31
32 class WebsiteBlog(http.Controller):
33     _category_post_per_page = 6
34     _post_comment_per_page = 6
35
36     @website.route([
37         '/blog/',
38         '/blog/<int:blog_post_id>/',
39         '/blog/<int:blog_post_id>/page/<int:page>/',
40         '/blog/cat/<int:category_id>/',
41         '/blog/cat/<int:category_id>/page/<int:page>/',
42         '/blog/tag/',
43         '/blog/tag/<int:tag_id>/',
44     ], type='http', auth="public")
45     def blog(self, category_id=None, blog_post_id=None, tag_id=None, page=1, **post):
46         """ Prepare all values to display the blog.
47
48         :param integer category_id: id of the category currently browsed.
49         :param integer tag_id: id of the tag that is currently used to filter
50                                blog posts
51         :param integer blog_post_id: ID of the blog post currently browsed. If not
52                                      set, the user is browsing the category and
53                                      a post pager is calculated. If set the user
54                                      is reading the blog post and a comments pager
55                                      is calculated.
56         :param integer page: current page of the pager. Can be the category or
57                             post pager.
58         :param dict post: kwargs, may contain
59
60          - 'unable_editor': editor control
61
62         :return dict values: values for the templates, containing
63
64          - 'blog_post': browse of the current post, if blog_post_id
65          - 'blog_posts': list of browse records that are the posts to display
66                          in a given category, if not blog_post_id
67          - 'category': browse of the current category, if category_id
68          - 'categories': list of browse records of categories
69          - 'pager': the pager to display, posts pager in a category or comments
70                     pager in a blog post
71          - 'tag': current tag, if tag_id
72          - 'nav_list': a dict [year][month] for archives navigation
73         """
74         cr, uid, context = request.cr, request.uid, request.context
75         blog_post_obj = request.registry['blog.post']
76         tag_obj = request.registry['blog.tag']
77         category_obj = request.registry['blog.category']
78
79         tag = None
80         category = None
81         blog_post = None
82         blog_posts = None
83         pager = None
84         nav = {}
85
86         category_ids = category_obj.search(cr, uid, [], context=context)
87         categories = category_obj.browse(cr, uid, category_ids, context=context)
88
89         if tag_id:
90             tag = tag_obj.browse(cr, uid, tag_id, context=context)
91         if category_id:
92             category = category_obj.browse(cr, uid, category_id, context=context)
93         elif blog_post_id:
94             blog_post = blog_post_obj.browse(cr, uid, blog_post_id, context=context)
95             blog_message_ids = blog_post.website_message_ids
96             category = blog_post.category_id
97             category_id = category.id
98
99         if not blog_post_id:
100             if category and tag:
101                 blog_posts = [cat_post for cat_post in category.blog_post_ids
102                               if tag_id in [post_tag.id for post_tag in cat_post.tag_ids]]
103             elif category:
104                 blog_posts = category.blog_post_ids
105             elif tag:
106                 blog_posts = tag.blog_post_ids
107             else:
108                 blog_post_ids = blog_post_obj.search(cr, uid, [], context=context)
109                 blog_posts = blog_post_obj.browse(cr, uid, blog_post_ids, context=context)
110
111         if blog_posts:
112             pager = request.website.pager(
113                 url="/blog/cat/%s/" % category_id,
114                 total=len(blog_posts),
115                 page=page,
116                 step=self._category_post_per_page,
117                 scope=7
118             )
119             pager_begin = (page - 1) * self._category_post_per_page
120             pager_end = page * self._category_post_per_page
121             blog_posts = blog_posts[pager_begin:pager_end]
122
123         if blog_post:
124             pager = request.website.pager(
125                 url="/blog/%s/" % blog_post_id,
126                 total=len(blog_message_ids),
127                 page=page,
128                 step=self._post_comment_per_page,
129                 scope=7
130             )
131             pager_begin = (page - 1) * self._post_comment_per_page
132             pager_end = page * self._post_comment_per_page
133             blog_post.website_message_ids = blog_post.website_message_ids[pager_begin:pager_end]
134
135         for group in blog_post_obj.read_group(cr, uid, [], ['name', 'create_date'], groupby="create_date", orderby="create_date asc", context=context):
136             year = group['create_date'].split(" ")[1]
137             if not year in nav:
138                 nav[year] = {'name': year, 'create_date_count': 0, 'months': []}
139             nav[year]['create_date_count'] += group['create_date_count']
140             nav[year]['months'].append(group)
141
142         values = {
143             'category': category,
144             'categories': categories,
145             'tag': tag,
146             'blog_post': blog_post,
147             'blog_posts': blog_posts,
148             'pager': pager,
149             'nav_list': nav,
150             'unable_editor': post.get('unable_editor')
151         }
152
153         if blog_post:
154             values['main_object'] = blog_post
155         elif tag:
156             values['main_object'] = tag
157         elif category:
158             values['main_object'] = category
159
160         return request.website.render("website_blog.index", values)
161
162     @website.route(['/blog/nav'], type='http', auth="public")
163     def nav(self, **post):
164         cr, uid, context = request.cr, request.uid, request.context
165         blog_post_ids = request.registry['blog.post'].search(
166             cr, uid, safe_eval(post.get('domain')),
167             order="create_date asc",
168             limit=None,
169             context=context
170         )
171         blog_post_data = [
172             {
173                 'id': blog_post.id,
174                 'name': blog_post.name,
175                 'website_published': blog_post.website_published,
176                 'category_id': blog_post.category_id and blog_post.category_id.id or False,
177             }
178             for blog_post in request.registry['blog.post'].browse(cr, uid, blog_post_ids, context=context)
179         ]
180         return simplejson.dumps(blog_post_data)
181
182     @website.route(['/blog/<int:blog_post_id>/post'], type='http', auth="public")
183     def blog_post_comment(self, blog_post_id=None, **post):
184         cr, uid, context = request.cr, request.uid, request.context
185         url = request.httprequest.host_url
186         request.session.body = post.get('body')
187         if request.context['is_public_user']:  # purpose of this ?
188             return '%s/web#action=redirect&url=%s/blog/%s/post' % (url, url, blog_post_id)
189
190         if request.session.get('body') and blog_post_id:
191             request.registry['blog.post'].message_post(
192                 cr, uid, blog_post_id,
193                 body=request.session.body,
194                 type='comment',
195                 subtype='mt_comment',
196                 context=dict(context, mail_create_nosubcribe=True))
197             request.session.body = False
198
199         return werkzeug.utils.redirect("/blog/%s/?unable_editor=1" % (blog_post_id))
200
201     @website.route(['/blog/<int:category_id>/new'], type='http', auth="public")
202     def blog_post_create(self, category_id=None, **post):
203         cr, uid, context = request.cr, request.uid, request.context
204         create_context = dict(context, mail_create_nosubscribe=True)
205         new_blog_post_id = request.registry['blog.post'].create(
206             request.cr, request.uid, {
207                 'category_id': category_id,
208                 'name': _("Blog title"),
209                 'content': '',
210                 'website_published': False,
211             }, context=create_context)
212         return werkzeug.utils.redirect("/blog/%s/?unable_editor=1" % (new_blog_post_id))
213
214     @website.route(['/blog/<int:blog_post_id>/duplicate'], type='http', auth="public")
215     def blog_post_copy(self, blog_post_id=None, **post):
216         cr, uid, context = request.cr, request.uid, request.context
217         create_context = dict(context, mail_create_nosubscribe=True)
218         new_blog_post_id = request.registry['blog.post'].copy(cr, uid, blog_post_id, {}, context=create_context)
219         return werkzeug.utils.redirect("/blog/%s/?unable_editor=1" % (new_blog_post_id))