Skip to content

Commit

Permalink
[ADD] New module website_blog_mgmt
Browse files Browse the repository at this point in the history
* This module lets you specify a date for the post at which it will be published (in the backend).
* Posts on the website are ordered by publication date.
* The order of posts is preserved when navigating between posts
* Since it's HARD/not possible to extend controller without rewriting completly
the overrided functions, the module also fixes odoo/odoo#3097
(loop issue when pressing the next button on a blog page)
  • Loading branch information
lmignon committed Jan 19, 2015
1 parent 2de71f5 commit e7b583b
Show file tree
Hide file tree
Showing 11 changed files with 635 additions and 0 deletions.
23 changes: 23 additions & 0 deletions website_blog_mgmt/__init__.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
# -*- coding: utf-8 -*-
##############################################################################
#
# Authors: Laurent Mignon
# Copyright (c) 2015 Acsone SA/NV (http://www.acsone.eu)
#
# This program is free software: you can redistribute it and/or modify
# it under the terms of the GNU Affero General Public License as published
# by the Free Software Foundation, either version 3 of the License, or
# (at your option) any later version.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU Affero General Public License for more details.
#
# You should have received a copy of the GNU Affero General Public License
# along with this program. If not, see <http://www.gnu.org/licenses/>.
#
##############################################################################
from . import models
from . import controllers
from .post_init import post_init
50 changes: 50 additions & 0 deletions website_blog_mgmt/__openerp__.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,50 @@
# -*- coding: utf-8 -*-
##############################################################################
#
# Authors: Laurent Mignon
# Copyright (c) 2015 Acsone SA/NV (http://www.acsone.eu)
#
# This program is free software: you can redistribute it and/or modify
# it under the terms of the GNU Affero General Public License as published
# by the Free Software Foundation, either version 3 of the License, or
# (at your option) any later version.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU Affero General Public License for more details.
#
# You should have received a copy of the GNU Affero General Public License
# along with this program. If not, see <http://www.gnu.org/licenses/>.
#
##############################################################################
{
'name': 'Website blog Management',
'version': '1.0',
'author': 'ACSONE SA/NV',
'maintainer': 'ACSONE SA/NV',
'website': 'http://www.acsone.eu',
'category': 'Website',
'depends': [
'website_blog',
],
'description': """
Website blog management
=======================
The module adds a new field to 'blog.post': website_publication_date.
The publication date is used to preserve the order in which posts are listed in
the web site when clicking on the menu 'News'. The same order is used in
the navigation between posts.
The publication date is filled when a post is published. It's also possible to
specify a specific value in the back-end. If the specified date is in the past,
the post is set to published, if the date is in the future the post will be
automatically published at the given date by a scheduled task.
""",
'data': [
'data/website_blog_mgmt_data.xml',
'views/website_blog_views.xml'
],
'installable': True,
'auto_install': False,
'post_init_hook': 'post_init',
}
21 changes: 21 additions & 0 deletions website_blog_mgmt/controllers/__init__.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
# -*- coding: utf-8 -*-
##############################################################################
#
# Authors: Laurent Mignon
# Copyright (c) 2015 Acsone SA/NV (http://www.acsone.eu)
#
# This program is free software: you can redistribute it and/or modify
# it under the terms of the GNU Affero General Public License as published
# by the Free Software Foundation, either version 3 of the License, or
# (at your option) any later version.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU Affero General Public License for more details.
#
# You should have received a copy of the GNU Affero General Public License
# along with this program. If not, see <http://www.gnu.org/licenses/>.
#
#############################################################################
from . import main
217 changes: 217 additions & 0 deletions website_blog_mgmt/controllers/main.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,217 @@
# -*- coding: utf-8 -*-
# include bug fix from rgo-odoo https://github.com/odoo/odoo/pull/3097
# + remove specified order when calling blog_post.search

from openerp.addons.web import http
from openerp.addons.web.http import request
from openerp.addons.website_blog.controllers.main import WebsiteBlog
from openerp.addons.website_blog.controllers.main import QueryURL
from openerp.addons.website.models.website import slug
from openerp import SUPERUSER_ID


class WebsiteBlog(WebsiteBlog):
_blog_post_per_page = 20
_post_comment_per_page = 10

@http.route([
'/blog/<model("blog.blog"):blog>',
'/blog/<model("blog.blog"):blog>/page/<int:page>',
'/blog/<model("blog.blog"):blog>/tag/<model("blog.tag"):tag>',
'/blog/<model("blog.blog"):blog>/tag/<model("blog.tag")' +
':tag>/page/<int:page>',
], type='http', auth="public", website=True)
def blog(self, blog=None, tag=None, page=1, **opt):
""" Prepare all values to display the blog.
:return dict values: values for the templates, containing
- 'blog': current blog
- 'blogs': all blogs for navigation
- 'pager': pager of posts
- 'tag': current tag
- 'tags': all tags, for navigation
- 'nav_list': a dict [year][month] for archives navigation
- 'date': date_begin optional parameter, used in archives navigation
- 'blog_url': help object to create URLs
"""
date_begin, date_end = opt.get('date_begin'), opt.get('date_end')

cr, uid, context = request.cr, request.uid, request.context
blog_post_obj = request.registry['blog.post']

blog_obj = request.registry['blog.blog']
blog_ids = blog_obj.search(
cr, uid, [], order="create_date asc", context=context)
blogs = blog_obj.browse(cr, uid, blog_ids, context=context)

domain = []
if blog:
domain += [('blog_id', '=', blog.id)]
if tag:
domain += [('tag_ids', 'in', tag.id)]
if date_begin and date_end:
domain += [("website_publication_date", ">=", date_begin),
("website_publication_date", "<=", date_end)]

blog_url = QueryURL(
'', ['blog', 'tag'], blog=blog, tag=tag,
date_begin=date_begin, date_end=date_end)
post_url = QueryURL(
'', ['blogpost'], tag_id=tag and tag.id or None,
date_begin=date_begin, date_end=date_end)

blog_post_ids = blog_post_obj.search(
cr, uid, domain, context=context)
blog_posts = blog_post_obj.browse(
cr, uid, blog_post_ids, context=context)

pager = request.website.pager(
url=blog_url(),
total=len(blog_posts),
page=page,
step=self._blog_post_per_page,
)
pager_begin = (page - 1) * self._blog_post_per_page
pager_end = page * self._blog_post_per_page
blog_posts = blog_posts[pager_begin:pager_end]

tags = blog.all_tags()[blog.id]

values = {
'blog': blog,
'blogs': blogs,
'tags': tags,
'tag': tag,
'blog_posts': blog_posts,
'pager': pager,
'nav_list': self.nav_list(),
'blog_url': blog_url,
'post_url': post_url,
'date': date_begin,
}
response = request.website.render(
"website_blog.blog_post_short", values)
return response

@http.route([
'''/blog/<model("blog.blog"):blog>/post/<model("blog.post",''' +
''' "[('blog_id','=',blog[0])]"):blog_post>''',
], type='http', auth="public", website=True)
def blog_post(self, blog, blog_post, tag_id=None, page=1,
enable_editor=None, **post):
""" Prepare all values to display the blog.
:return dict values: values for the templates, containing
- 'blog_post': browse of the current post
- 'blog': browse of the current blog
- 'blogs': list of browse records of blogs
- 'tag': current tag, if tag_id in parameters
- 'tags': all tags, for tag-based navigation
- 'pager': a pager on the comments
- 'nav_list': a dict [year][month] for archives navigation
- 'next_post': next blog post, to direct the user towards the next
post
"""
cr, uid, context = request.cr, request.uid, request.context
tag_obj = request.registry['blog.tag']
blog_post_obj = request.registry['blog.post']
date_begin, date_end = post.get('date_begin'), post.get('date_end')

pager_url = "/blogpost/%s" % blog_post.id

pager = request.website.pager(
url=pager_url,
total=len(blog_post.website_message_ids),
page=page,
step=self._post_comment_per_page,
scope=7
)
pager_begin = (page - 1) * self._post_comment_per_page
pager_end = page * self._post_comment_per_page
comments = blog_post.website_message_ids[pager_begin:pager_end]

def get_next_post_id(blog_post_ids, current_blog_post_id):
if not blog_post_ids or not current_blog_post_id:
return False
cur_blog_idx = blog_post_ids.index(current_blog_post_id)
return blog_post_ids[0 if cur_blog_idx == len(blog_post_ids) - 1
else cur_blog_idx + 1]

def check_blog_post_status(blog_post_id, visited_ids):
# recursive check to see if the blog posts which client earlier
# visited(stored in 'visited_blogs' cookies) are been 'unpublished'
# or deleted.
if not blog_post_id:
return False
if blog_post_obj.search(
cr, uid, [('id', '=', blog_post_id)], context=context):
return blog_post_id
next_blog_post_id = get_next_post_id(visited_ids, blog_post_id)
visited_ids.remove(blog_post_id)
return check_blog_post_status(next_blog_post_id, visited_ids)

tag = None
if tag_id:
tag = request.registry['blog.tag'].browse(
request.cr, request.uid, int(tag_id), context=request.context)
post_url = QueryURL(
'', ['blogpost'], blogpost=blog_post, tag_id=tag_id,
date_begin=date_begin, date_end=date_end)
blog_url = QueryURL(
'', ['blog', 'tag'], blog=blog_post.blog_id, tag=tag,
date_begin=date_begin, date_end=date_end)

if not blog_post.blog_id.id == blog.id:
return request.redirect(
"/blog/%s/post/%s" % (slug(blog_post.blog_id),
slug(blog_post)))

tags = tag_obj.browse(
cr, uid, tag_obj.search(
cr, uid, [], context=context), context=context)

# Find next Post
visited_blogs = request.httprequest.cookies.get('visited_blogs') or ''
visited_ids = filter(None, visited_blogs.split(','))
visited_ids = map(lambda x: int(x), visited_ids)
if blog_post.id not in visited_ids:
visited_ids.append(blog_post.id)
next_post_id = blog_post_obj.search(cr, uid, [
('id', 'not in', visited_ids),
], order='website_publication_date desc', limit=1, context=context)
if not next_post_id:
next_post_id = get_next_post_id(visited_ids, blog_post.id)
next_post_id = check_blog_post_status(next_post_id, visited_ids)
next_post = next_post_id and blog_post_obj.browse(
cr, uid, next_post_id, context=context) or False

values = {
'tags': tags,
'tag': tag,
'blog': blog,
'blog_post': blog_post,
'main_object': blog_post,
'nav_list': self.nav_list(),
'enable_editor': enable_editor,
'next_post': next_post,
'date': date_begin,
'post_url': post_url,
'blog_url': blog_url,
'pager': pager,
'comments': comments,
}
response = request.website.render(
'website_blog.blog_post_complete', values)
response.set_cookie('visited_blogs', ','.join(map(str, visited_ids)))

request.session[request.session_id] = request.session.get(
request.session_id, [])
if not (blog_post.id in request.session[request.session_id]):
request.session[request.session_id].append(blog_post.id)
# Increase counter
blog_post_obj.write(cr, SUPERUSER_ID, [blog_post.id], {
'visits': blog_post.visits+1,
}, context=context)
return response
16 changes: 16 additions & 0 deletions website_blog_mgmt/data/website_blog_mgmt_data.xml
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
<?xml version="1.0" encoding="UTF-8"?>
<openerp>
<data noupdate="1">
<record forcecreate="True" id="ir_cron_publish_blog"
model="ir.cron">
<field name="name">Publish blog post</field>
<field name="interval_number">1</field>
<field name="interval_type">minutes</field>
<field name="numbercall">-1</field>
<field eval="False" name="doall" />
<field name="model">blog.post</field>
<field name="function">cron_publish_posts</field>
<field name="args">()</field>
</record>
</data>
</openerp>
21 changes: 21 additions & 0 deletions website_blog_mgmt/models/__init__.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
# -*- coding: utf-8 -*-
##############################################################################
#
# Authors: Laurent Mignon
# Copyright (c) 2015 Acsone SA/NV (http://www.acsone.eu)
#
# This program is free software: you can redistribute it and/or modify
# it under the terms of the GNU Affero General Public License as published
# by the Free Software Foundation, either version 3 of the License, or
# (at your option) any later version.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU Affero General Public License for more details.
#
# You should have received a copy of the GNU Affero General Public License
# along with this program. If not, see <http://www.gnu.org/licenses/>.
#
#############################################################################
from . import website_blog
Loading

0 comments on commit e7b583b

Please sign in to comment.