[FIX] website_blog: who wrote such stupid domains ?
[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 import datetime
23 import werkzeug
24
25 from openerp import tools
26 from openerp.addons.web import http
27 from openerp.addons.web.http import request
28 from openerp.addons.website.models.website import slug
29 from openerp.osv.orm import browse_record
30 from openerp.tools.translate import _
31 from openerp import SUPERUSER_ID
32
33
34 class QueryURL(object):
35     def __init__(self, path='', path_args=None, **args):
36         self.path = path
37         self.args = args
38         self.path_args = set(path_args or [])
39
40     def __call__(self, path=None, path_args=None, **kw):
41         path = path or self.path
42         for k, v in self.args.items():
43             kw.setdefault(k, v)
44         path_args = set(path_args or []).union(self.path_args)
45         paths, fragments = [], []
46         for key, value in kw.items():
47             if value and key in path_args:
48                 if isinstance(value, browse_record):
49                     paths.append((key, slug(value)))
50                 else:
51                     paths.append((key, value))
52             elif value:
53                 if isinstance(value, list) or isinstance(value, set):
54                     fragments.append(werkzeug.url_encode([(key, item) for item in value]))
55                 else:
56                     fragments.append(werkzeug.url_encode([(key, value)]))
57         for key, value in paths:
58             path += '/' + key + '/%s' % value
59         if fragments:
60             path += '?' + '&'.join(fragments)
61         return path
62
63
64 class WebsiteBlog(http.Controller):
65     _blog_post_per_page = 6
66     _post_comment_per_page = 6
67
68     def nav_list(self):
69         blog_post_obj = request.registry['blog.post']
70         groups = blog_post_obj.read_group(request.cr, request.uid, [], ['name', 'create_date'],
71             groupby="create_date", orderby="create_date asc", context=request.context)
72         for group in groups:
73             begin_date = datetime.datetime.strptime(group['__domain'][0][2], tools.DEFAULT_SERVER_DATETIME_FORMAT).date()
74             end_date = datetime.datetime.strptime(group['__domain'][1][2], tools.DEFAULT_SERVER_DATETIME_FORMAT).date()
75             group['date_begin'] = '%s' % datetime.date.strftime(begin_date, tools.DEFAULT_SERVER_DATE_FORMAT)
76             group['date_end'] = '%s' % datetime.date.strftime(end_date, tools.DEFAULT_SERVER_DATE_FORMAT)
77         return groups
78
79     @http.route([
80         '/blog',
81         '/blog/page/<int:page>',
82     ], type='http', auth="public", website=True, multilang=True)
83     def blogs(self, page=1, **post):
84         cr, uid, context = request.cr, request.uid, request.context
85         blog_obj = request.registry['blog.post']
86         total = blog_obj.search(cr, uid, [], count=True, context=context)
87         pager = request.website.pager(
88             url='/blog',
89             total=total,
90             page=page,
91             step=self._blog_post_per_page,
92         )
93         post_ids = blog_obj.search(cr, uid, [], offset=(page-1)*self._blog_post_per_page, limit=self._blog_post_per_page, context=context)
94         posts = blog_obj.browse(cr, uid, post_ids, context=context)
95         blog_url = QueryURL('', ['blog', 'tag'])
96         return request.website.render("website_blog.latest_blogs", {
97             'posts': posts,
98             'pager': pager,
99             'blog_url': blog_url,
100         })
101
102     @http.route([
103         '/blog/<model("blog.blog"):blog>',
104         '/blog/<model("blog.blog"):blog>/page/<int:page>',
105         '/blog/<model("blog.blog"):blog>/tag/<model("blog.tag"):tag>',
106         '/blog/<model("blog.blog"):blog>/tag/<model("blog.tag"):tag>/page/<int:page>',
107     ], type='http', auth="public", website=True, multilang=True)
108     def blog(self, blog=None, tag=None, page=1, **opt):
109         """ Prepare all values to display the blog.
110
111         :param blog: blog currently browsed.
112         :param tag: tag that is currently used to filter blog posts
113         :param integer page: current page of the pager. Can be the blog or
114                             post pager.
115         :param date: date currently used to filter blog posts (dateBegin_dateEnd)
116
117         :return dict values: values for the templates, containing
118
119          - 'blog_posts': list of browse records that are the posts to display
120                          in a given blog, if not blog_post_id
121          - 'blog': browse of the current blog, if blog_id
122          - 'blogs': list of browse records of blogs
123          - 'pager': the pager to display posts pager in a blog
124          - 'tag': current tag, if tag_id
125          - 'nav_list': a dict [year][month] for archives navigation
126         """
127         date_begin, date_end = opt.get('date_begin'), opt.get('date_end')
128
129         cr, uid, context = request.cr, request.uid, request.context
130         blog_post_obj = request.registry['blog.post']
131
132         blog_posts = None
133
134         blog_obj = request.registry['blog.blog']
135         blog_ids = blog_obj.search(cr, uid, [], order="create_date asc", context=context)
136         blogs = blog_obj.browse(cr, uid, blog_ids, context=context)
137
138         domain = []
139
140         if blog:
141             domain += [('blog_id', '=', blog.id)]
142         if tag:
143             domain += [('tag_ids', 'in', tag.id)]
144         if date_begin and date_end:
145             domain += [("create_date", ">=", date_begin), ("create_date", "<=", date_end)]
146
147         blog_url = QueryURL('', ['blog', 'tag'], blog=blog, tag=tag, date_begin=date_begin, date_end=date_end)
148         post_url = QueryURL('', ['blogpost'], tag_id=tag and tag.id or None, date_begin=date_begin, date_end=date_end)
149
150         blog_post_ids = blog_post_obj.search(cr, uid, domain, order="create_date asc", context=context)
151         blog_posts = blog_post_obj.browse(cr, uid, blog_post_ids, context=context)
152
153         pager = request.website.pager(
154             url=blog_url(),
155             total=len(blog_posts),
156             page=page,
157             step=self._blog_post_per_page,
158         )
159         pager_begin = (page - 1) * self._blog_post_per_page
160         pager_end = page * self._blog_post_per_page
161         blog_posts = blog_posts[pager_begin:pager_end]
162
163         tag_obj = request.registry['blog.tag']
164         tag_ids = tag_obj.search(cr, uid, [], context=context)
165         tags = tag_obj.browse(cr, uid, tag_ids, context=context)
166
167         values = {
168             'blog': blog,
169             'blogs': blogs,
170             'tags': tags,
171             'tag': tag,
172             'blog_posts': blog_posts,
173             'pager': pager,
174             'nav_list': self.nav_list(),
175             'blog_url': blog_url,
176             'post_url': post_url,
177             'date': date_begin,
178         }
179         return request.website.render("website_blog.blog_post_short", values)
180
181     @http.route([
182         '/blogpost/<model("blog.post"):blog_post>',
183     ], type='http', auth="public", website=True, multilang=True)
184     def blog_post(self, blog_post, tag_id=None, page=1, enable_editor=None, **post):
185         """ Prepare all values to display the blog.
186
187         :param blog_post: blog post currently browsed. If not set, the user is
188                           browsing the blog and a post pager is calculated.
189                           If set the user is reading the blog post and a
190                           comments pager is calculated.
191         :param blog: blog currently browsed.
192         :param tag: tag that is currently used to filter blog posts
193         :param integer page: current page of the pager. Can be the blog or
194                             post pager.
195         :param date: date currently used to filter blog posts (dateBegin_dateEnd)
196
197          - 'enable_editor': editor control
198
199         :return dict values: values for the templates, containing
200
201          - 'blog_post': browse of the current post, if blog_post_id
202          - 'blog': browse of the current blog, if blog_id
203          - 'blogs': list of browse records of blogs
204          - 'pager': the pager to display comments pager in a blog post
205          - 'tag': current tag, if tag_id
206          - 'nav_list': a dict [year][month] for archives navigation
207         """
208         date_begin, date_end = post.get('date_begin'), post.get('date_end')
209
210         pager_url = "/blogpost/%s" % blog_post.id
211
212         pager = request.website.pager(
213             url=pager_url,
214             total=len(blog_post.website_message_ids),
215             page=page,
216             step=self._post_comment_per_page,
217             scope=7
218         )
219         pager_begin = (page - 1) * self._post_comment_per_page
220         pager_end = page * self._post_comment_per_page
221         blog_post.website_message_ids = blog_post.website_message_ids[pager_begin:pager_end]
222
223         tag = None
224         if tag_id:
225             tag = request.registry['blog.tag'].browse(request.cr, request.uid, int(tag_id), context=request.context)
226         post_url = QueryURL('', ['blogpost'], blogpost=blog_post, tag_id=tag_id, date_begin=date_begin, date_end=date_end)
227         blog_url = QueryURL('', ['blog', 'tag'], blog=blog_post.blog_id, tag=tag, date_begin=date_begin, date_end=date_end)
228
229         cr, uid, context = request.cr, request.uid, request.context
230         blog_obj = request.registry['blog.blog']
231         blog_ids = blog_obj.search(cr, uid, [], context=context)
232         blogs = blog_obj.browse(cr, uid, blog_ids, context=context)
233
234         tag_obj = request.registry['blog.tag']
235         tag_ids = tag_obj.search(cr, uid, [], context=context)
236         tags = tag_obj.browse(cr, uid, tag_ids, context=context)
237
238         values = {
239             'blog': blog_post.blog_id,
240             'blogs': blogs,
241             'tags': tags,
242             'tag': tag,
243             'blog_post': blog_post,
244             'main_object': blog_post,
245             'pager': pager,
246             'nav_list': self.nav_list(),
247             'enable_editor': enable_editor,
248             'date': date_begin,
249             'post_url': post_url,
250             'blog_url': blog_url,
251         }
252         return request.website.render("website_blog.blog_post_complete", values)
253
254     @http.route(['/blogpost/comment'], type='http', auth="public", methods=['POST'], website=True)
255     def blog_post_comment(self, blog_post_id=0, **post):
256         cr, uid, context = request.cr, request.uid, request.context
257         if post.get('comment'):
258             user = request.registry['res.users'].browse(cr, SUPERUSER_ID, uid, context=context)
259             group_ids = user.groups_id
260             group_id = request.registry["ir.model.data"].get_object_reference(cr, uid, 'website_mail', 'group_comment')[1]
261             if group_id in [group.id for group in group_ids]:
262                 blog_post = request.registry['blog.post']
263                 blog_post.check_access_rights(cr, uid, 'read')
264                 blog_post.message_post(
265                     cr, SUPERUSER_ID, int(blog_post_id),
266                     body=post.get('comment'),
267                     type='comment',
268                     subtype='mt_comment',
269                     author_id=user.partner_id.id,
270                     context=dict(context, mail_create_nosubcribe=True))
271         return werkzeug.utils.redirect(request.httprequest.referrer + "#comments")
272
273     @http.route('/blogpost/new', type='http', auth="public", website=True, multilang=True)
274     def blog_post_create(self, blog_id, **post):
275         cr, uid, context = request.cr, request.uid, request.context
276         create_context = dict(context, mail_create_nosubscribe=True)
277         new_blog_post_id = request.registry['blog.post'].create(
278             request.cr, request.uid, {
279                 'blog_id': blog_id,
280                 'name': _("Blog Post Title"),
281                 'content': '',
282                 'website_published': False,
283             }, context=create_context)
284         return werkzeug.utils.redirect("/blogpost/%s?enable_editor=1" % new_blog_post_id)
285
286     @http.route('/blogpost/duplicate', type='http', auth="public", website=True)
287     def blog_post_copy(self, blog_post_id, **post):
288         """ Duplicate a blog.
289
290         :param blog_post_id: id of the blog post currently browsed.
291
292         :return redirect to the new blog created
293         """
294         cr, uid, context = request.cr, request.uid, request.context
295         create_context = dict(context, mail_create_nosubscribe=True)
296         new_blog_post_id = request.registry['blog.post'].copy(cr, uid, blog_post_id, {}, context=create_context)
297         return werkzeug.utils.redirect("/blogpost/%s?enable_editor=1" % new_blog_post_id)