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 ##############################################################################
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
32 class WebsiteBlog(http.Controller):
33 _category_post_per_page = 6
34 _post_comment_per_page = 6
37 blog_post_obj = request.registry['blog.post']
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]
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)
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.
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
65 :return dict values: values for the templates, containing
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
75 cr, uid, context = request.cr, request.uid, request.context
76 blog_post_obj = request.registry['blog.post']
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)
85 pager_url = "/blog/cat/%s/" % category.id
86 blog_posts = category.blog_post_ids
88 pager_url = '/blog/tag/%s/' % tag.id
89 blog_posts = tag.blog_post_ids
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)
95 pager = request.website.pager(
97 total=len(blog_posts),
99 step=self._category_post_per_page,
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]
107 'category': category,
108 'categories': categories,
110 'blog_posts': blog_posts,
112 'nav_list': self.nav_list(),
116 values['main_object'] = tag
118 values['main_object'] = category
120 return request.website.render("website_blog.blog_post_short", values)
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.
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
135 :param dict post: kwargs, may contain
137 - 'enable_editor': editor control
139 :return dict values: values for the templates, containing
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
146 pager = request.website.pager(
147 url="/blog/%s/" % blog_post.id,
148 total=len(blog_post.website_message_ids),
150 step=self._post_comment_per_page,
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]
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)
163 'category': blog_post.category_id,
164 'categories': categories,
165 'blog_post': blog_post,
167 'nav_list': self.nav_list(),
168 'enable_editor': enable_editor,
170 return request.website.render("website_blog.blog_post_complete", values)
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",
186 'website_published': blog_post.website_published,
187 'fragment': request.website.render("website_blog.blog_archive_link", {
188 'blog_post': blog_post
191 for blog_post in request.registry['blog.post'].browse(cr, uid, blog_post_ids, context=context)
193 return simplejson.dumps(blog_post_data)
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'),
202 subtype='mt_comment',
203 context=dict(context, mail_create_nosubcribe=True))
204 return werkzeug.utils.redirect(request.httprequest.referrer + "#comments")
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"),
215 'website_published': False,
216 }, context=create_context)
217 return werkzeug.utils.redirect("/blog/%s/?enable_editor=1" % (new_blog_post_id))
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))