1 # -*- coding: utf-8 -*-
2 ##############################################################################
4 # OpenERP, Open Source Management Solution
5 # Copyright (C) 2013-Today OpenERP SA (<http://www.openerp.com>).
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.
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.
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/>.
20 ##############################################################################
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
34 class QueryURL(object):
35 def __init__(self, path='', path_args=None, **args):
38 self.path_args = set(path_args or [])
40 def __call__(self, path=None, path_args=None, **kw):
43 for k, v in self.args.items():
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)))
52 paths.append((key, value))
54 if isinstance(value, list) or isinstance(value, set):
55 fragments.append(werkzeug.url_encode([(key, item) for item in value]))
57 fragments.append(werkzeug.url_encode([(key, value)]))
59 for key, value in paths:
60 path += '/' + key + '/%s' % value
62 path += '?' + '&'.join(fragments)
66 class WebsiteBlog(http.Controller):
67 _blog_post_per_page = 6
68 _post_comment_per_page = 6
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)
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)
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(
93 step=self._blog_post_per_page,
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", {
101 'current_url': current_url,
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.
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
117 :param date: date currently used to filter blog posts (dateBegin_dateEnd)
119 :return dict values: values for the templates, containing
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
129 date_begin, date_end = opt.get('date_begin'), opt.get('date_end')
131 cr, uid, context = request.cr, request.uid, request.context
132 blog_post_obj = request.registry['blog.post']
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)
143 domain += [("id", "in", [post.id for post in blog.blog_post_ids])]
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)
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)
153 pager = request.website.pager(
155 total=len(blog_posts),
157 step=self._blog_post_per_page,
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]
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)
172 'blog_posts': blog_posts,
174 'nav_list': self.nav_list(),
175 'current_url': current_url,
178 return request.website.render("website_blog.blog_post_short", values)
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.
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
194 :param date: date currently used to filter blog posts (dateBegin_dateEnd)
196 - 'enable_editor': editor control
198 :return dict values: values for the templates, containing
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
207 date_begin, date_end = post.get('date_begin'), post.get('date_end')
209 pager_url = "/blogpost/%s" % blog_post.id
211 pager = request.website.pager(
213 total=len(blog_post.website_message_ids),
215 step=self._post_comment_per_page,
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]
224 tag = request.registry['blog.tag'].browse(request.cr, request.uid, tag_id, context=request.context)
226 current_url = QueryURL('', ['blogpost'], blogpost=blog_post, tag_id=tag_id, date_begin=date_begin, date_end=date_end)
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)
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)
238 'blog': blog_post.blog_id,
242 'blog_post': blog_post,
243 'main_object': blog_post,
245 'nav_list': self.nav_list(),
246 'enable_editor': enable_editor,
248 'current_url': current_url
250 return request.website.render("website_blog.blog_post_complete", values)
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'),
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")
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, {
278 'name': _("Blog Post Title"),
280 'website_published': False,
281 }, context=create_context)
282 return werkzeug.utils.redirect("/blogpost/%s?enable_editor=1" % new_blog_post_id)
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.
288 :param blog_post_id: id of the blog post currently browsed.
290 :return redirect to the new blog created
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)