[IMP] Blogs better views hierarchies
[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     def nav_list(self):
37         blog_post_obj = request.registry['blog.post']
38         nav = {}
39         for group in blog_post_obj.read_group(request.cr, request.uid, [], ['name', 'create_date'], 
40                 groupby="create_date", orderby="create_date asc", context=request.context):
41             # FIXME: vietnamese month names contain spaces. Set sail for fail.
42             year = group['create_date'].split(" ")[1]
43             if not year in nav:
44                 nav[year] = {'name': year, 'create_date_count': 0, 'months': []}
45             nav[year]['create_date_count'] += group['create_date_count']
46             nav[year]['months'].append(group)
47         return nav
48
49     @website.route([
50         '/blog/',
51         '/blog/page/<int:page>/',
52         '/blog/cat/<model("blog.category"):category>/',
53         '/blog/cat/<model("blog.category"):category>/page/<int:page>/',
54         '/blog/tag/<model("blog.tag"):tag>/',
55         '/blog/tag/<model("blog.tag"):tag>/page/<int:page>/',
56     ], type='http', auth="public", multilang=True)
57     def blog(self, category=None, tag=None, page=1):
58         """ Prepare all values to display the blog.
59
60         :param category: category currently browsed.
61         :param tag: tag that is currently used to filter blog posts
62         :param integer page: current page of the pager. Can be the category or
63                             post pager.
64
65         :return dict values: values for the templates, containing
66
67          - 'blog_posts': list of browse records that are the posts to display
68                          in a given category, if not blog_post_id
69          - 'category': browse of the current category, if category_id
70          - 'categories': list of browse records of categories
71          - 'pager': the pager to display posts pager in a category
72          - 'tag': current tag, if tag_id
73          - 'nav_list': a dict [year][month] for archives navigation
74         """
75         cr, uid, context = request.cr, request.uid, request.context
76         blog_post_obj = request.registry['blog.post']
77
78         blog_posts = None
79
80         category_obj = request.registry['blog.category']
81         category_ids = category_obj.search(cr, uid, [], context=context)
82         categories = category_obj.browse(cr, uid, category_ids, context=context)
83
84         if category:
85             pager_url = "/blog/cat/%s/" % category.id
86             blog_posts = category.blog_post_ids
87         elif tag:
88             pager_url = '/blog/tag/%s/' % tag.id
89             blog_posts = tag.blog_post_ids
90         else:
91             pager_url = '/blog/'
92             blog_post_ids = blog_post_obj.search(cr, uid, [], context=context)
93             blog_posts = blog_post_obj.browse(cr, uid, blog_post_ids, context=context)
94
95         pager = request.website.pager(
96             url=pager_url,
97             total=len(blog_posts),
98             page=page,
99             step=self._category_post_per_page,
100             scope=7
101         )
102         pager_begin = (page - 1) * self._category_post_per_page
103         pager_end = page * self._category_post_per_page
104         blog_posts = blog_posts[pager_begin:pager_end]
105
106         values = {
107             'category': category,
108             'categories': categories,
109             'tag': tag,
110             'blog_posts': blog_posts,
111             'pager': pager,
112             'nav_list': self.nav_list(),
113         }
114
115         if tag:
116             values['main_object'] = tag
117         elif category:
118             values['main_object'] = category
119
120         return request.website.render("website_blog.blog_post_short", values)
121
122     @website.route([
123         '/blog/<model("blog.post"):blog_post>/',
124         '/blog/<model("blog.post"):blog_post>/page/<int:page>/'
125     ], type='http', auth="public", multilang=True)
126     def blog_post(self, blog_post=None, page=1, enable_editor=None):
127         """ Prepare all values to display the blog.
128
129         :param blog_post: blog post currently browsed. If not set, the user is
130                           browsing the category and a post pager is calculated.
131                           If set the user is reading the blog post and a
132                           comments pager is calculated.
133         :param integer page: current page of the pager. Can be the category or
134                             post pager.
135         :param dict post: kwargs, may contain
136
137          - 'enable_editor': editor control
138
139         :return dict values: values for the templates, containing
140
141          - 'blog_post': browse of the current post, if blog_post_id
142          - 'category': browse of the current category, if category_id
143          - 'pager': the pager to display comments pager in a blog post
144          - 'nav_list': a dict [year][month] for archives navigation
145         """
146         pager = request.website.pager(
147             url="/blog/%s/" % blog_post.id,
148             total=len(blog_post.website_message_ids),
149             page=page,
150             step=self._post_comment_per_page,
151             scope=7
152         )
153         pager_begin = (page - 1) * self._post_comment_per_page
154         pager_end = page * self._post_comment_per_page
155         blog_post.website_message_ids = blog_post.website_message_ids[pager_begin:pager_end]
156
157         cr, uid, context = request.cr, request.uid, request.context
158         category_obj = request.registry['blog.category']
159         category_ids = category_obj.search(cr, uid, [], context=context)
160         categories = category_obj.browse(cr, uid, category_ids, context=context)
161
162         values = {
163             'category': blog_post.category_id,
164             'categories': categories,
165             'blog_post': blog_post,
166             'pager': pager,
167             'nav_list': self.nav_list(),
168             'enable_editor': enable_editor,
169         }
170         return request.website.render("website_blog.blog_post_complete", values)
171
172     # TODO: Refactor (used in website_blog.js for archive links)
173     # => the archive links should be generated server side
174     @website.route(['/blog/nav'], type='http', auth="public", multilang=True)
175     def nav(self, **post):
176         cr, uid, context = request.cr, request.uid, request.context
177         blog_post_ids = request.registry['blog.post'].search(
178             cr, uid, safe_eval(post.get('domain')),
179             order="create_date asc",
180             limit=None,
181             context=context
182         )
183         blog_post_data = [
184             {
185                 'id': blog_post.id,
186                 'website_published': blog_post.website_published,
187                 'fragment': request.website.render("website_blog.blog_archive_link", {
188                     'blog_post': blog_post
189                 }),
190             }
191             for blog_post in request.registry['blog.post'].browse(cr, uid, blog_post_ids, context=context)
192         ]
193         return simplejson.dumps(blog_post_data)
194
195     @website.route(['/blog/<int:blog_post_id>/comment'], type='http', auth="public")
196     def blog_post_comment(self, blog_post_id=None, **post):
197         cr, uid, context = request.cr, request.uid, request.context
198         request.registry['blog.post'].message_post(
199             cr, uid, blog_post_id,
200             body=post.get('comment'),
201             type='comment',
202             subtype='mt_comment',
203             context=dict(context, mail_create_nosubcribe=True))
204         return werkzeug.utils.redirect(request.httprequest.referrer + "#comments")
205
206     @website.route(['/blog/<int:category_id>/new'], type='http', auth="public", multilang=True)
207     def blog_post_create(self, category_id=None, **post):
208         cr, uid, context = request.cr, request.uid, request.context
209         create_context = dict(context, mail_create_nosubscribe=True)
210         new_blog_post_id = request.registry['blog.post'].create(
211             request.cr, request.uid, {
212                 'category_id': category_id,
213                 'name': _("Blog title"),
214                 'content': '',
215                 'website_published': False,
216             }, context=create_context)
217         return werkzeug.utils.redirect("/blog/%s/?enable_editor=1" % (new_blog_post_id))
218
219     @website.route(['/blog/<int:blog_post_id>/duplicate'], type='http', auth="public")
220     def blog_post_copy(self, blog_post_id=None, **post):
221         cr, uid, context = request.cr, request.uid, request.context
222         create_context = dict(context, mail_create_nosubscribe=True)
223         new_blog_post_id = request.registry['blog.post'].copy(cr, uid, blog_post_id, {}, context=create_context)
224         return werkzeug.utils.redirect("/blog/%s/?enable_editor=1" % (new_blog_post_id))