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