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):
41 path = path or self.path
42 for k, v in self.args.items():
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)))
51 paths.append((key, value))
53 if isinstance(value, list) or isinstance(value, set):
54 fragments.append(werkzeug.url_encode([(key, item) for item in value]))
56 fragments.append(werkzeug.url_encode([(key, value)]))
57 for key, value in paths:
58 path += '/' + key + '/%s' % value
60 path += '?' + '&'.join(fragments)
64 class WebsiteBlog(http.Controller):
65 _blog_post_per_page = 6
66 _post_comment_per_page = 6
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)
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)
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(
91 step=self._blog_post_per_page,
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", {
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.
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
115 :param date: date currently used to filter blog posts (dateBegin_dateEnd)
117 :return dict values: values for the templates, containing
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
127 date_begin, date_end = opt.get('date_begin'), opt.get('date_end')
129 cr, uid, context = request.cr, request.uid, request.context
130 blog_post_obj = request.registry['blog.post']
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)
141 domain += [("id", "in", [post.id for post in blog.blog_post_ids])]
143 domain += [("id", "in", [post.id for post in tag.blog_post_ids])]
144 if date_begin and date_end:
145 domain += [("create_date", ">=", date_begin), ("create_date", "<=", date_end)]
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)
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)
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 'blog_url': blog_url,
176 'post_url': post_url,
179 return request.website.render("website_blog.blog_post_short", values)
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.
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
195 :param date: date currently used to filter blog posts (dateBegin_dateEnd)
197 - 'enable_editor': editor control
199 :return dict values: values for the templates, containing
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
208 date_begin, date_end = post.get('date_begin'), post.get('date_end')
210 pager_url = "/blogpost/%s" % blog_post.id
212 pager = request.website.pager(
214 total=len(blog_post.website_message_ids),
216 step=self._post_comment_per_page,
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]
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)
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)
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)
239 'blog': blog_post.blog_id,
243 'blog_post': blog_post,
244 'main_object': blog_post,
246 'nav_list': self.nav_list(),
247 'enable_editor': enable_editor,
249 'post_url': post_url,
250 'blog_url': blog_url,
252 return request.website.render("website_blog.blog_post_complete", values)
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'),
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")
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, {
280 'name': _("Blog Post Title"),
282 'website_published': False,
283 }, context=create_context)
284 return werkzeug.utils.redirect("/blogpost/%s?enable_editor=1" % new_blog_post_id)
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.
290 :param blog_post_id: id of the blog post currently browsed.
292 :return redirect to the new blog created
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)