[1] | 1 | from Products.Archetypes.public import BaseFolderSchema, Schema |
---|
| 2 | from Products.Archetypes.public import StringField, LinesField, IntegerField, BooleanField |
---|
| 3 | from Products.Archetypes.public import SelectionWidget, LinesWidget, TextAreaWidget, MultiSelectionWidget, IntegerWidget, RichWidget, IdWidget, StringWidget, BooleanWidget |
---|
| 4 | from Products.Archetypes.public import BaseFolder, registerType |
---|
| 5 | from Products.Archetypes.public import DisplayList |
---|
| 6 | |
---|
| 7 | from Products.CMFCore import CMFCorePermissions |
---|
| 8 | from DateTime import DateTime |
---|
| 9 | from Products.SimpleBlog.config import DISPLAY_MODE, ENABLE_ADSENSE |
---|
| 10 | import Products.SimpleBlog.Permissions |
---|
| 11 | from Products.CMFCore.utils import getToolByName |
---|
| 12 | |
---|
| 13 | from Products.SimpleBlog import MetaWeblogAPI |
---|
| 14 | from Products.SimpleBlog import BloggerAPI |
---|
| 15 | from Products.SimpleBlog import MovableTypeAPI |
---|
| 16 | from Products.Archetypes.utils import unique |
---|
| 17 | |
---|
| 18 | from Products.ATContentTypes.content.base import ATCTBTreeFolder, ATCTFolder |
---|
| 19 | from Products.ATContentTypes.lib.constraintypes import ConstrainTypesMixinSchema |
---|
| 20 | |
---|
| 21 | schema = ConstrainTypesMixinSchema.copy() + ATCTFolder.schema.copy() + Schema(( |
---|
| 22 | StringField('description', |
---|
| 23 | isMetadata=1, |
---|
| 24 | accessor='Description', |
---|
| 25 | searchable=1, |
---|
| 26 | widget=TextAreaWidget(label='Description', |
---|
| 27 | label_msgid="label_blog_description", |
---|
| 28 | description_msgid="help_blog_description", |
---|
| 29 | i18n_domain="SimpleBlog", |
---|
| 30 | description='Give a description for this SimpleBlog.')), |
---|
| 31 | # this field is deprecated, here for compatibility |
---|
| 32 | StringField('displayMode', |
---|
| 33 | vocabulary=DISPLAY_MODE, |
---|
| 34 | widget=SelectionWidget(label='Display Mode', |
---|
| 35 | label_msgid="label_display_mode", |
---|
| 36 | description_msgid="help_display_mode", |
---|
| 37 | i18n_domain="SimpleBlog", |
---|
| 38 | description='Choose the display mode.', |
---|
| 39 | visible={'view' : 'invisible', 'edit':'invisible'}), |
---|
| 40 | default='descriptionOnly'), |
---|
| 41 | IntegerField('displayItems', |
---|
| 42 | widget=IntegerWidget(label='BlogEntries to display', |
---|
| 43 | label_msgid="label_display_items", |
---|
| 44 | description_msgid="help_display_items", |
---|
| 45 | i18n_domain="SimpleBlog", |
---|
| 46 | description='Set the maximum number of BlogEntries to display.'), |
---|
| 47 | default=20), |
---|
| 48 | LinesField('categories', |
---|
| 49 | widget=LinesWidget(label='Possible Categories', |
---|
| 50 | label_msgid="label_categories", |
---|
| 51 | description_msgid="help_categories", |
---|
| 52 | i18n_domain="SimpleBlog", |
---|
| 53 | description='Supply the list of possible categories that can be used in SimpleBlog Entries.')), |
---|
| 54 | BooleanField('allowCrossPosting', |
---|
| 55 | default=0, |
---|
| 56 | widget=BooleanWidget(condition="python:0", # hide the field |
---|
| 57 | label='Allow cross-posting', |
---|
| 58 | i18n_domain="SimpleBlog", |
---|
| 59 | label_msgid="label_allowCrossPosting", |
---|
| 60 | description_msgid="help_allowCrossPosting", |
---|
| 61 | description='When checked, this blog will include cross-post entries from other blogs.')), |
---|
| 62 | LinesField('tags', |
---|
| 63 | mutator = 'setTags', |
---|
| 64 | widget=LinesWidget(label="Tags", |
---|
| 65 | description='List of tags.'), |
---|
| 66 | ), |
---|
| 67 | BooleanField('warnForUnpublishedEntries', |
---|
| 68 | default=1, |
---|
| 69 | schemata = 'interface', |
---|
| 70 | widget=BooleanWidget(label='Show unpublished entries warning', |
---|
| 71 | i18n_domain="SimpleBlog", |
---|
| 72 | label_msgid="label_warnForUnpublishedEntries", |
---|
| 73 | description_msgid="help_warnForUnpublishedEntries", |
---|
| 74 | description='When checked, a warning will be displayed on the blog\'s frontpage if there are entries that are not yet published.')), |
---|
| 75 | BooleanField('showByline', |
---|
| 76 | default = 1, |
---|
| 77 | schemata = 'interface', |
---|
| 78 | widget=BooleanWidget(label="Show Byline footer", |
---|
| 79 | label_msgid="label_show_buttons", |
---|
| 80 | description_msgid="help_show_buttons",), |
---|
| 81 | ), |
---|
| 82 | BooleanField('showIcons', |
---|
| 83 | default = 1, |
---|
| 84 | schemata = 'interface', |
---|
| 85 | widget=BooleanWidget(label="Show Icons", |
---|
| 86 | label_msgid="label_show_icons", |
---|
| 87 | description_msgid="help_show_icons",), |
---|
| 88 | ), |
---|
| 89 | BooleanField('tagsEnabled', |
---|
| 90 | accessor = 'isTagsEnabled', |
---|
| 91 | default = 1, |
---|
| 92 | schemata = 'interface', |
---|
| 93 | widget = BooleanWidget(label='Enable technorati tags', |
---|
| 94 | label_msgid="label_enable_tags", |
---|
| 95 | description_msgid="help_enable_tags",), |
---|
| 96 | ), |
---|
| 97 | BooleanField('allowTrackback', |
---|
| 98 | default = 1, |
---|
| 99 | schemata = 'interface', |
---|
| 100 | widget=BooleanWidget(label="Allow Trackback", |
---|
| 101 | label_msgid="label_allow_trackback", |
---|
| 102 | description_msgid="help_allow_trackback",), |
---|
| 103 | ), |
---|
| 104 | # used to be new trackbaks notification email address |
---|
| 105 | StringField('adminEmail', |
---|
| 106 | accessor = 'getAdminEmail', |
---|
| 107 | mutator = 'setAdminEmail', |
---|
| 108 | schemata = 'interface', |
---|
| 109 | default = '', |
---|
| 110 | widget=StringWidget(label="Administrator's email", |
---|
| 111 | label_msgid="label_adminEmail", |
---|
| 112 | description_msgid="help_adminEmail", |
---|
| 113 | i18n_domain="SimpleBlog", |
---|
| 114 | condition="python:0", # this line have to be removed in order to be visible/editable |
---|
| 115 | description="Enter administrator's email for receiving notification about blog's activity"), |
---|
| 116 | ), |
---|
| 117 | BooleanField('allowDelicious', |
---|
| 118 | default = 1, |
---|
| 119 | accessor = 'isDeliciousEnabled', |
---|
| 120 | schemata = 'interface', |
---|
| 121 | widget=BooleanWidget(label="Turn Delicious bookmarklet", |
---|
| 122 | label_msgid="label_allow_delicious", |
---|
| 123 | description_msgid="help_allow_delicious"), |
---|
| 124 | ), |
---|
| 125 | BooleanField('allowDigg', |
---|
| 126 | default = 1, |
---|
| 127 | accessor = 'isDiggEnabled', |
---|
| 128 | schemata = 'interface', |
---|
| 129 | widget=BooleanWidget(label="Turn Digg bookmarklet", |
---|
| 130 | label_msgid="label_allow_digg", |
---|
| 131 | description_msgid="help_allow_digg"), |
---|
| 132 | ), |
---|
| 133 | BooleanField('allowYahoo', |
---|
| 134 | default = 1, |
---|
| 135 | accessor = 'isYahooEnabled', |
---|
| 136 | schemata = 'interface', |
---|
| 137 | widget=BooleanWidget(label="Turn Yahoo bookmarklet", |
---|
| 138 | label_msgid="label_allow_yahoo", |
---|
| 139 | description_msgid="help_allow_yahoo"), |
---|
| 140 | ), |
---|
| 141 | BooleanField('allowGoogle', |
---|
| 142 | default = 1, |
---|
| 143 | accessor = 'isGoogleEnabled', |
---|
| 144 | schemata = 'interface', |
---|
| 145 | widget=BooleanWidget(label="Turn Google bookmarklet", |
---|
| 146 | label_msgid="label_allow_google", |
---|
| 147 | description_msgid="help_allow_google"), |
---|
| 148 | ), |
---|
| 149 | BooleanField('allowSpurl', |
---|
| 150 | default = 1, |
---|
| 151 | accessor = 'isSpurlEnabled', |
---|
| 152 | schemata = 'interface', |
---|
| 153 | widget=BooleanWidget(label="Turn Spurl bookmarklet", |
---|
| 154 | label_msgid="label_allow_spurl", |
---|
| 155 | description_msgid="help_allow_spurl"), |
---|
| 156 | ), |
---|
| 157 | BooleanField('enableTopAdsence', |
---|
| 158 | schemata = 'interface', |
---|
| 159 | default=0, |
---|
| 160 | accessor = 'isTopAdsenceEnabled', |
---|
| 161 | widget = BooleanWidget(format = 'select', |
---|
| 162 | label = 'Turn top Adsence block', |
---|
| 163 | label_msgid = "label_enable_top_adsence", |
---|
| 164 | description_msgid = "help_enable_top_adsence", |
---|
| 165 | i18n_domain = "SimpleBlog", |
---|
| 166 | description = None, |
---|
| 167 | condition="python:%s" % ENABLE_ADSENSE)), |
---|
| 168 | StringField('topAdsence', |
---|
| 169 | schemata = 'interface', |
---|
| 170 | vocabulary = 'listAdsenseTemplates', |
---|
| 171 | widget = SelectionWidget(format = 'select', |
---|
| 172 | label = 'Select top adsence template', |
---|
| 173 | label_msgid = "label_top_adsence", |
---|
| 174 | description_msgid = "help_top_adsence", |
---|
| 175 | i18n_domain = "SimpleBlog", |
---|
| 176 | description = None, |
---|
| 177 | condition="python:%s" % ENABLE_ADSENSE)), |
---|
| 178 | BooleanField('enableBottomAdsence', |
---|
| 179 | schemata = 'interface', |
---|
| 180 | default=0, |
---|
| 181 | accessor = 'isBottomAdsenceEnabled', |
---|
| 182 | widget = BooleanWidget(format = 'select', |
---|
| 183 | label = 'Turn bottom adsence block', |
---|
| 184 | label_msgid = "label_enable_bottom_adsence", |
---|
| 185 | description_msgid = "help_enable_bottom_adsence", |
---|
| 186 | i18n_domain = "SimpleBlog", |
---|
| 187 | description = None, |
---|
| 188 | condition="python:%s" % ENABLE_ADSENSE)), |
---|
| 189 | StringField('bottomAdsence', |
---|
| 190 | schemata = 'interface', |
---|
| 191 | vocabulary = 'listAdsenseTemplates', |
---|
| 192 | widget = SelectionWidget(format = 'select', |
---|
| 193 | label = 'Select bottom adsence', |
---|
| 194 | label_msgid = "label_bottom_adsence", |
---|
| 195 | description_msgid = "help_bottom_adsence", |
---|
| 196 | i18n_domain = "SimpleBlog", |
---|
| 197 | description = None, |
---|
| 198 | condition="python:%s" % ENABLE_ADSENSE)), |
---|
| 199 | )) |
---|
| 200 | schema['relatedItems'].widget.visible={'view' : 'invisible', 'edit':'invisible'} |
---|
| 201 | |
---|
| 202 | class Blog(ATCTBTreeFolder,ATCTFolder): |
---|
| 203 | """Blog""" |
---|
| 204 | |
---|
| 205 | portal_type = meta_type = 'Blog' |
---|
| 206 | archetype_name = 'Blog' |
---|
| 207 | content_icon='simpleblog_icon.gif' |
---|
| 208 | schema = schema |
---|
| 209 | global_allow=1 |
---|
| 210 | |
---|
| 211 | default_view = 'simpleblog_view_title_description' |
---|
| 212 | immediate_view = 'simpleblog_view_title_description' |
---|
| 213 | suppl_views = ('simpleblog_view_title_description', 'simpleblog_view_title', 'simpleblog_view_title_description_body') |
---|
| 214 | |
---|
| 215 | filter_content_types=1 |
---|
| 216 | allowed_content_types=('BlogEntry', 'BlogFolder', 'Link', 'Image', 'File', 'Portlet') |
---|
| 217 | |
---|
| 218 | blogger = None |
---|
| 219 | metaWeblog = None |
---|
| 220 | |
---|
| 221 | def initializeArchetype(self, **kwargs): |
---|
| 222 | BaseFolder.initializeArchetype(self, **kwargs) |
---|
| 223 | RPCAuth = self.simpleblog_tool.findRPCAuth(self) |
---|
| 224 | |
---|
| 225 | self.metaWeblog = MetaWeblogAPI.MetaWeblogAPI().__of__(self) |
---|
| 226 | self.metaWeblog.setupRPCAuth(RPCAuth) |
---|
| 227 | self.blogger = BloggerAPI.BloggerAPI().__of__(self) |
---|
| 228 | self.blogger.setupRPCAuth(RPCAuth) |
---|
| 229 | self.mt = MovableTypeAPI.MovableTypeAPI().__of__(self) |
---|
| 230 | self.mt.setupRPCAuth(RPCAuth) |
---|
| 231 | |
---|
| 232 | def canSetDefaultPage(self): |
---|
| 233 | return False |
---|
| 234 | |
---|
| 235 | def manage_afterAdd(self, item, container): |
---|
| 236 | BaseFolder.manage_afterAdd(self, item, container) |
---|
| 237 | if self.simpleblog_tool.getCreatePortletOnBlogCreation(): |
---|
| 238 | if not hasattr(item.aq_base, 'right_slots'): |
---|
| 239 | item._setProperty('right_slots', ['here/portlet_simpleblog/macros/portlet'], 'lines') |
---|
| 240 | |
---|
| 241 | def synContentValues(self): |
---|
| 242 | syn_tool = getToolByName(self, 'portal_syndication') |
---|
| 243 | limit = int(syn_tool.getMaxItems(self)) |
---|
| 244 | entries = self.getEntries(maxResults=limit)[1] |
---|
| 245 | objs = [e.getObject() for e in entries] |
---|
| 246 | return objs |
---|
| 247 | |
---|
| 248 | def listCategories(self): |
---|
| 249 | cats=self.getCategories() |
---|
| 250 | |
---|
| 251 | for c in self.simpleblog_tool.getGlobalCategories(): |
---|
| 252 | if not c in cats: |
---|
| 253 | cats.append(c) |
---|
| 254 | cats = list(cats) |
---|
| 255 | cats.sort() |
---|
| 256 | return tuple(cats) |
---|
| 257 | |
---|
| 258 | def getForeignEntries(self): |
---|
| 259 | """ Returns all entries from other blogs that are published into this blog using the remoteBlogs value """ |
---|
| 260 | return [f for f in self.getBRefs('AppearsIn') if self.portal_membership.checkPermission('View', f)] |
---|
| 261 | |
---|
| 262 | def buildBatch(self, b_start, query, notlimited_len): |
---|
| 263 | """Return batch for navigation""" |
---|
| 264 | #if 'getAlwaysOnTop' in query.keys(): |
---|
| 265 | #query['getAlwaysOnTop']=1 |
---|
| 266 | #len1 = len(self.portal_catalog(**query)) |
---|
| 267 | #query['getAlwaysOnTop']=0 |
---|
| 268 | if 'sort_limit' in query.keys(): |
---|
| 269 | del query['sort_limit'] |
---|
| 270 | total_len = len(self.portal_catalog(**query)) |
---|
| 271 | else: |
---|
| 272 | total_len = notlimited_len |
---|
| 273 | ditems = self.getDisplayItems() |
---|
| 274 | |
---|
| 275 | batch = [] |
---|
| 276 | if total_len > ditems: |
---|
| 277 | max_pages = total_len/ditems + (total_len%ditems and 1 or 0) |
---|
| 278 | vis_middle = 3 # max number of pages in one of the side around current |
---|
| 279 | curr_num = b_start/ditems >= max_pages and max_pages or b_start/ditems+1 |
---|
| 280 | # first page (when current page far from 1st page) |
---|
| 281 | first = [] |
---|
| 282 | if curr_num-vis_middle > 2: |
---|
| 283 | first = [1,"b_start=0"] |
---|
| 284 | batch.append(first) |
---|
| 285 | # last page (when current page far from terminal page) |
---|
| 286 | last = [] |
---|
| 287 | if max_pages-curr_num > vis_middle+1: |
---|
| 288 | last = [max_pages,"b_start=%d" % ((max_pages-1)*ditems)] |
---|
| 289 | batch.append(last) |
---|
| 290 | # form batch around current page |
---|
| 291 | lft_bound = curr_num-vis_middle > 2 and curr_num-vis_middle or 1 |
---|
| 292 | rght_bound = max_pages-curr_num > vis_middle+1 and curr_num+vis_middle or max_pages |
---|
| 293 | lst = [] |
---|
| 294 | for p in range(lft_bound, rght_bound+1): |
---|
| 295 | q = p!=curr_num and "b_start=%d" % ((p-1)*ditems) or "" |
---|
| 296 | lst.append([p,q]) |
---|
| 297 | batch.append(lst) |
---|
| 298 | return batch |
---|
| 299 | |
---|
| 300 | def getStart(self): |
---|
| 301 | """ Validate b_start from request and return right value.""" |
---|
| 302 | request = self.REQUEST |
---|
| 303 | try: |
---|
| 304 | b_start = int(request.get('b_start', 0)) or 0 |
---|
| 305 | except: |
---|
| 306 | b_start = 0 |
---|
| 307 | if b_start < 0: |
---|
| 308 | b_start = 0 |
---|
| 309 | return b_start |
---|
| 310 | |
---|
| 311 | def getEntries(self, category=None, maxResults=None, b_start=0, filterState=1, join=0, skipOnTop=0, mode="", **kwargs): |
---|
| 312 | """ Return all the contained published entries, real objects, not the brains """ |
---|
| 313 | query=kwargs |
---|
| 314 | publishedState = self.simpleblog_tool.getPublishedState() |
---|
| 315 | if category!=None: |
---|
| 316 | query['EntryCategory']=category |
---|
| 317 | if filterState: |
---|
| 318 | query['review_state']=publishedState |
---|
| 319 | if maxResults: |
---|
| 320 | query['sort_limit'] = maxResults + 1 # need to if the last page riched |
---|
| 321 | if not query.has_key('path'): |
---|
| 322 | query['path'] = {'query':self.simpleblog_tool.getObjectPath(self),'level':0} |
---|
| 323 | query['sort_order'] = 'reverse' |
---|
| 324 | query['sort_on'] = 'effective' |
---|
| 325 | query['meta_type'] = 'BlogEntry' |
---|
| 326 | onTop = [] |
---|
| 327 | if not skipOnTop and b_start==0: |
---|
| 328 | query['getAlwaysOnTop']=1 |
---|
| 329 | onTop = list(self.portal_catalog.searchResults(query)) |
---|
| 330 | query['getAlwaysOnTop']=0 |
---|
| 331 | |
---|
| 332 | onBottom = list(self.portal_catalog.searchResults(query)) |
---|
| 333 | #### cut the b_start when it is tooo large |
---|
| 334 | itemsPerPage = self.getDisplayItems() |
---|
| 335 | last = 0 |
---|
| 336 | if len(onBottom) < maxResults + 1: #last page |
---|
| 337 | last = 1 |
---|
| 338 | elif len(onBottom) == maxResults + 1: #not last page yet |
---|
| 339 | onBottom = onBottom[:-1] |
---|
| 340 | if len(onBottom) < b_start: # too large b_start given |
---|
| 341 | b_start = (len(onBottom)/itemsPerPage)*itemsPerPage |
---|
| 342 | if join: |
---|
| 343 | results = onTop+onBottom |
---|
| 344 | batch = 'navigation' in query.keys() and self.buildBatch(b_start, query, len(results)) or [] |
---|
| 345 | if b_start > 0: |
---|
| 346 | if len(onBottom) == b_start: |
---|
| 347 | b_start = b_start-(maxResults-b_start) |
---|
| 348 | last = 1 |
---|
| 349 | results = results[b_start:] |
---|
| 350 | return (results,last,batch) |
---|
| 351 | else: |
---|
| 352 | batch = 'navigation' in query.keys() and self.buildBatch(b_start, query, len(onBottom)) or [] |
---|
| 353 | return (onTop, onBottom, batch) |
---|
| 354 | |
---|
| 355 | def getAdminEmail(self): |
---|
| 356 | """ return blog admin email or root email """ |
---|
| 357 | val = self.getField('adminEmail').get(self) |
---|
| 358 | if not val: |
---|
| 359 | purl = getToolByName(self, 'portal_url') |
---|
| 360 | val = purl.getPortalObject().getProperty("trackback_notification_email", "") |
---|
| 361 | return val |
---|
| 362 | |
---|
| 363 | def setTags(self, value, **kwargs): |
---|
| 364 | """ Save tags in lower case """ |
---|
| 365 | value = unique(value) |
---|
| 366 | value.sort(lambda x, y: cmp(x,y)) |
---|
| 367 | self.getField('tags').set(self, value, **kwargs) |
---|
| 368 | |
---|
| 369 | def listAdsenseTemplates(self): |
---|
| 370 | """ Return DisplayList of available adsence blocks """ |
---|
| 371 | try: |
---|
| 372 | from Products.adsenseproduct.util import getAdsenseMap |
---|
| 373 | except: |
---|
| 374 | return () |
---|
| 375 | templates = [(key, value['title']) for key, value in getAdsenseMap().items()] |
---|
| 376 | return DisplayList(templates) |
---|
| 377 | |
---|
| 378 | registerType(Blog) |
---|
| 379 | |
---|