source: trunk/BlogPost.py @ 1919

Revision 1919, 8.8 KB checked in by jukka, 12 years ago (diff)

Refactored groups to not use portal_groups. Things should be faster and users from weird sources shouldn't cause so much problems. Not much tested yet, but archetype update and quickinstaller reinstall works fine.

Line 
1# Copyright 2006 by the LeMill Team (see AUTHORS)
2#
3# This file is part of LeMill.
4#
5# LeMill is free software; you can redistribute it and/or modify
6# it under the terms of the GNU General Public License as published by
7# the Free Software Foundation; either version 2 of the License, or
8# (at your option) any later version.
9#
10# LeMill is distributed in the hope that it will be useful,
11# but WITHOUT ANY WARRANTY; without even the implied warranty of
12# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
13# GNU General Public License for more details.
14#
15# You should have received a copy of the GNU General Public License
16# along with LeMill; if not, write to the Free Software
17# Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
18
19from Products.Archetypes.public import *
20from Products.ATReferenceBrowserWidget.ATReferenceBrowserWidget import ReferenceBrowserWidget
21from Products.CMFCore.permissions import ModifyPortalContent
22from Products.Archetypes.public import BaseSchema, BaseContent, registerType
23from Products.Archetypes.atapi import DisplayList
24from Globals import InitializeClass
25from Products.CMFCore.utils import getToolByName
26from AccessControl import ClassSecurityInfo, Unauthorized
27from config import PROJECTNAME, MODIFY_CONTENT, VIEW
28from Resources import CommonMixIn
29from SharedMetadata import bodytext, bodytext_simple, tags, coverImage, latest_edit_schema, score
30from Products.Archetypes.atapi import DisplayList
31from FieldsWidgets import TagsField, TagsWidget, LeStringWidget
32from permissions import ModerateContent, MODIFY_CONTENT
33from DateTime import DateTime
34
35# Same thing as with MemberFolder but easier: MemberBlogs contain the values of groups itself in indexable storage.
36
37schema = BaseSchema + bodytext_simple + coverImage + latest_edit_schema + score + Schema((
38    StringField(
39        name='title',
40        required=1,
41        searchable=1,
42        default='',
43        accessor='Title',
44        widget=LeStringWidget(
45            label='Topic',
46            label_msgid='label_topic',
47            visible={'view' : 'invisible'},
48            i18n_domain='lemill',
49        ),
50    ),
51    BooleanField(
52        name="is_discussion",
53        default=False,
54        widget=ComputedWidget(
55            visible={'edit':'invisible', 'view':'invisible'}
56            ),
57        ),
58))
59schema = schema.copy()
60schema['bodyText'].required = True
61schema['bodyText'].widget.rows = 10
62
63class BlogPost(BaseContent,CommonMixIn):
64    """Blog post"""
65
66    meta_type = "BlogPost"
67    archetype_name = "BlogPost"
68    allow_discussion = True
69    _at_rename_after_creation = True
70
71    security = ClassSecurityInfo()
72    default_view = ('blogpost_view')
73    security.declareObjectPublic()
74    schema = schema
75
76    security.declarePrivate('manage_afterAdd')
77    def manage_afterAdd(self, item, container):
78        """1) Replaces the left side portlets with the content type's own action portlet. 2) add obj id to list of recent entries in parent GroupBlog. """
79        BaseContent.manage_afterAdd(self, item, container)
80        if not hasattr(item.aq_base, 'left_slots'):
81            self._setProperty('left_slots', ['here/portlet_groupblog_actions/macros/portlet',], 'lines')
82        if hasattr(container, 'recent_posts'):
83            container.addRecent_post(self.getId())
84        mtool = getToolByName(self, 'portal_membership')
85        memberfolder=mtool.getHomeFolder()
86        if memberfolder!=None:
87            memberfolder.note_action(self.UID(), item.portal_type, 'afterAdd')
88        syn_tool = getToolByName(self, 'portal_syndication', None)
89        if syn_tool is not None:
90            try:
91                syn_tool.enableSyndication(self)
92            except: # might get 'Syndication Information Exists'
93                pass
94        BaseContent.manage_afterAdd(self, item, container)
95
96
97
98    security.declarePrivate('at_post_edit_script')
99    def at_post_edit_script(self):
100        """ Rename id to resemble title, add to list of collaboration proposals of community if such, and add to recent posts of blog. """
101        old=self.getId()
102        uid=self.UID()
103        self._renameAfterCreation()
104        new=self.getId()
105
106        if old != new: # new id is updated to recent posts list
107            try: # if for some reason posts are not inside blogs
108                blog=self.getBlog()
109                blog.replaceRecent_post(old, new)
110            except:
111                pass
112        mtool = getToolByName(self, 'portal_membership')
113        memberfolder=mtool.getHomeFolder()
114        if memberfolder!=None:
115            memberfolder.note_action(uid, self.portal_type, 'post_edit')
116
117               
118    def getAuthors(self):
119        """Emulate the method that Resource has"""
120        return [self.Creator(),]
121
122    def getCoverImageURL(self):
123        """BlogPosts shouldn't have their own cover images -- returns authors portrait."""
124        return getattr(self.community,self.Creator).getPortraitURL()
125       
126    def NiceName(self):
127        """ I don't think this will get called but just to make sure. """
128        return self.getTitle()
129
130    def isPost(self):
131        return True
132
133    security.declareProtected(ModerateContent, 'delete_post')
134    def delete_post(self):
135        """ Hide, remove from recent posts and remove from Collaboration proposals """
136        container=self.getBlog()
137        uid=self.UID()
138        self.content_status_modify(workflow_action='delete')
139        self.reindexObject()
140        if hasattr(container, 'recent_posts'):
141            container.removeRecent_post(self.getId())
142
143    security.declareProtected(ModerateContent, 'undelete_post')
144    def undelete_post(self):
145        """ Bring back post but currently doesn't add to collaboration proposals or recent posts """
146        container=self.getBlog()
147        uid=self.UID()
148        self.content_status_modify(workflow_action='publish')
149        self.reindexObject()
150        if hasattr(container, 'recent_posts'):
151            container.addRecent_post(self.getId())
152   
153#    def setProperties(self, newprops=None, **kw):
154#        """ just a helper method """
155#        if newprops is None:
156#            newprops = kw
157#        for (key, value) in newprops.items():
158#            accessor='get'+str(key.capitalize())
159#            mutator='set'+str(key.capitalize())
160#
161#            if hasattr(self, accessor):
162#                if eval('self.'+accessor+'()') != value:
163#                    eval('self.'+mutator+'(value)')
164
165    security.declareProtected(MODIFY_CONTENT, 'setCoverImage')
166    def setCoverImage(self, value, **kwargs):
167        """ This modification for a mutator flags object to have a coverImage """
168        cover=self.getField('coverImage')
169        cover.set(self,value,**kwargs)
170        has_cover=self.getField('hasCoverImage')
171        has_cover.set(self,True)
172
173
174    def getComments(self, n=False):
175        """ Get discussion comments or their number """
176        pd=getToolByName(self, 'portal_discussion')
177        rp=pd.getDiscussionFor(self).getReplies()               
178        if n:
179            return len(rp)
180        rp=self.sort_modified_ascending(rp)
181        return rp
182
183    def getLatestComment(self):
184        """ Return time to latest comment in dictionary of days, hours, minutes """
185        pd=getToolByName(self, 'portal_discussion')
186        letool=getToolByName(self,'lemill_tool')
187        rp=pd.getDiscussionFor(self).getReplies()               
188        if not rp:
189            return None
190        #rp=self.sort_modified_ascending(rp)
191        latest=rp[-1]       
192        return letool.getTimeDifference(latest.CreationDate())
193       
194
195    def Description(self):
196        """ Redirect to full body text """
197        return self.getBodyText()
198   
199    def getDefaultIcon(self, meta_type='', obj=None):
200        """ blogposts don't currently have icons """
201        # in my opinion this should return creator's portrait
202        # but I currently don't have time to find methods for getting them
203        return 'images/default_member.png'
204
205    def getLatestEditDate(self):
206        """ Returns creation date as blog posts do not have History """
207        return DateTime(self.CreationDate())
208
209    def getLastEditor(self):
210        """ Returns id of the Creator """
211        return self.Creator()
212   
213    def getShortenBlog(self):
214        """ Creates shorten link names """
215        lt = getToolByName(self, 'lemill_tool')
216        return lt.split_at_p_or_br(self.getBlog(),min_len=50, max_len=200);
217
218    def getDiscussedResource(self):
219        """ if this is related to some resource, get the resource """
220        reftool= getToolByName(self, 'reference_catalog')
221        obj_uid = self.UID()
222        found = []
223        ref_query = { 'sourceUID': obj_uid, 'type': 'is_discussion_about' }
224        refresults = reftool(ref_query)
225        for q in refresults:
226            refobject = reftool.lookupObject(q.UID)
227            target = refobject.getTargetObject()
228            if target:
229                return target
230        return None
231
232
233registerType(BlogPost, PROJECTNAME)
Note: See TracBrowser for help on using the repository browser.