Changeset 1039

Show
Ignore:
Timestamp:
02/05/08 08:43:01
Author:
mylan
Message:

Merged revisions 815-1037 via svnmerge from
http://svn/products/SimpleBlog/branches/optimizations

........

r815 | chervol | 2007-03-02 10:39:16 +0200 (Fri, 02 Mar 2007) | 1 line


SimpleBlog? optimizations
........
r816 | chervol | 2007-03-02 11:03:07 +0200 (Fri, 02 Mar 2007) | 1 line


getEntries optimized, added new navigation macros, shortened recent portlet code
........
r817 | chervol | 2007-03-02 11:04:58 +0200 (Fri, 02 Mar 2007) | 1 line


fixed navigation macro name in blog view
........
r823 | chervol | 2007-03-09 19:22:50 +0200 (Fri, 09 Mar 2007) | 1 line


getObject calls reducing
........
r838 | mylan | 2007-04-06 16:42:57 +0300 (Fri, 06 Apr 2007) | 1 line


Move Blog and BlogFolder? to ATCTBtreeFolder. Correct minor issues.
........
r839 | mylan | 2007-04-10 15:45:16 +0300 (Tue, 10 Apr 2007) | 1 line


Add migration to BTree folder module.
........
r840 | mylan | 2007-04-11 12:27:22 +0300 (Wed, 11 Apr 2007) | 1 line


Finish with migration.
........
r841 | mylan | 2007-04-11 13:20:09 +0300 (Wed, 11 Apr 2007) | 1 line


Clean-up code code.
........
r842 | mylan | 2007-04-11 15:53:11 +0300 (Wed, 11 Apr 2007) | 1 line


Remove needless collectEntries method from SimpleblogTool? and simpleblog_standalone template.
........
r843 | mylan | 2007-04-13 19:46:36 +0300 (Fri, 13 Apr 2007) | 1 line


Speed up getAvailableCategory function in SimpleBlog? tool.
........
r844 | mylan | 2007-04-17 18:27:50 +0300 (Tue, 17 Apr 2007) | 1 line


add batch navigation for simple blog view template
........
r845 | mylan | 2007-04-17 18:35:18 +0300 (Tue, 17 Apr 2007) | 1 line


Add squared brackets around current page in navigation.
........
r867 | piv | 2007-05-11 11:47:26 +0300 (Fri, 11 May 2007) | 1 line


Fix blog's type syndication content, update migration external method.
........
r869 | mylan | 2007-05-22 16:42:30 +0300 (Tue, 22 May 2007) | 1 line


Fix batching bugs
........
r870 | mylan | 2007-05-22 16:46:05 +0300 (Tue, 22 May 2007) | 1 line


Fix batching bugs..forget template update
........
r888 | fenix | 2007-06-19 12:25:46 +0300 (Tue, 19 Jun 2007) | 1 line


Remove navigation for only one page of blog content.
........
r896 | chervol | 2007-06-25 15:36:07 +0300 (Mon, 25 Jun 2007) | 1 line


fixed the recent portlet markup, added extra css class for the 'more...' link
........

Files:

Legend:

Unmodified
Added
Removed
Modified
Copied
Moved
  • SimpleBlog/trunk

    • Property svnmerge-integrated changed from /SimpleBlog/branches/optimizations:1-814 to /SimpleBlog/branches/optimizations:1-1037
  • SimpleBlog/trunk/SimpleBlogTool.py

    r694 r1039  
    1818    meta_type= 'SimpleBlog manager'  
    1919    plone_tool = 1 
    20          
     20 
    2121    manage_options=PropertyManager.manage_options 
    22      
     22 
    2323    security = ClassSecurityInfo() 
    2424    calendar_types=['BlogEntry'] 
    2525    use_session="" 
    26      
     26 
    2727    def __init__(self): 
    2828        self.manage_addProperty('publishedState', 'published', 'string') 
     
    7676        except: 
    7777            return [] 
    78          
     78 
    7979    def _getCreatePortletOnBlogCreation(self): 
    8080        try: 
     
    100100 
    101101        self.globalCategories=value 
    102      
     102 
    103103    security.declarePublic('getPublishedState') 
    104104    def getPublishedState(self): 
    105105        return self._getState() 
    106      
    107      
     106 
    108107    security.declarePublic('getMaxItemsInPortlet') 
    109108    def getMaxItemsInPortlet(self): 
    110109        return self._getMaxItemsInPortlet() 
    111      
     110 
    112111    security.declarePublic('getFrontPage') 
    113112    def getFrontPage(self, context): 
     
    127126                    break 
    128127                parent=parent.aq_parent 
    129              
     128 
    130129            if found==1: 
    131130                return parent 
     
    142141        """ 
    143142        plone_utils = getToolByName(context, 'plone_utils') 
    144          
     143 
    145144        startpoint = self.getFrontPage(context) 
    146145        if not startpoint: 
     
    152151        else: 
    153152            return startpoint 
    154       
     153 
    155154    security.declarePublic('getAvailableCategories') 
    156155    def getAvailableCategories(self, context, startpoint=None): 
     
    162161        # if we are higher in the tree than any Blog then we will end up in the portalobject itself 
    163162        # in that case we just search for categories starting in context. 
    164  
    165163        if not startpoint: 
    166164            startpoint = self.getStartpoint(context, fromHere=0) 
    167  
    168         # now we have the starting point for our search 
    169          
    170         result = startpoint.portal_catalog.searchResults(meta_type=['BlogFolder', 'Blog'], path={'query':self.getObjectPath(startpoint),'level':0}) 
    171          
    172         # now fetch all the available categories 
    173         categories=[] 
    174         for o in result: 
    175             obj=o.getObject() 
    176             cats = obj.getCategories() 
    177             for c in cats: 
    178                 if not c in categories: 
    179                     categories.append(c) 
    180          
    181         # add the global categories 
    182         for c in self.getGlobalCategories(): 
    183             if not c in categories: 
    184                 categories.append(c) 
    185          
     165        categories = context.portal_catalog.uniqueValuesFor('EntryCategory') 
     166        path = self.getObjectPath(startpoint) 
     167 
    186168        # now we have a list of unique categories available from startpoint and deeper in tree 
    187169        # next step is to count the number of entries for each category 
    188170        rescats={} 
    189         for c in categories: 
    190             result = startpoint.portal_catalog.searchResults(review_state=self._getState(), meta_type='BlogEntry', EntryCategory=c,  path={'query':self.getObjectPath(startpoint),'level':0}) 
    191             rescats[c]=len(result) 
     171        [rescats.update({c:0}) for c in categories] 
     172        result = startpoint.portal_catalog.searchResults(review_state=self._getState(), meta_type='BlogEntry', path={'query':path,'level':0}) 
     173 
     174        for r in result: 
     175            for c in r.EntryCategory: rescats[c] = rescats[c]+1 
     176        for c,n in rescats.items(): 
     177            if n==0: del rescats[c] 
    192178        return rescats 
    193      
     179 
    194180    security.declarePublic('getSortedKeys') 
    195181    def getSortedKeys(self, dict): 
     
    197183        keys.sort() 
    198184        return keys 
    199      
     185 
    200186    security.declarePublic('getGlobalCategories') 
    201187    def getGlobalCategories(self): 
    202188        return self._getGlobalCategories() 
    203      
     189 
    204190    security.declarePublic('getStartpoint') 
    205191    def getStartpoint(self, context, fromHere=0): 
     
    216202                    break 
    217203                parent=parent.aq_parent 
    218              
     204 
    219205            if found==1: 
    220206                startpoint=parent 
     
    228214 
    229215        return startpoint 
    230      
     216 
    231217    security.declarePublic('searchForEntries') 
    232218    def searchForEntries(self, context, category=None, maxResults=None, fromHere=0, filterState=1, **kwargs): 
     
    234220        # leave it to None to get the max from the properties 
    235221        # set fromHere=1 to search from the current location. Is used for BlogFolders 
    236          
     222 
    237223        # first, get the context right 
    238224        # when inside a Blog: search for the frontpage 
    239225        # when outside a Blog: use context (or its container) 
    240          
     226 
    241227        #filterState controls whether you want to return only published entries 
    242              
     228 
    243229        startpoint = self.getStartpoint(context, fromHere) 
    244         # now we have the starting point for our search 
    245          
    246230        query=kwargs 
    247  
    248231        publishedState = self._getState() 
    249          
    250232        if category!=None: 
    251233            query['EntryCategory']=category 
    252234 
    253         query['getAlwaysOnTop']=1 
    254          
    255235        if filterState: 
    256236            query['review_state']=publishedState             
    257237 
    258              
    259         resultsTop = startpoint.portal_catalog.searchResults(query, meta_type='BlogEntry', path={'query':self.getObjectPath(startpoint),'level':0}, sort_order='reverse', sort_on='effective') 
    260          
    261         query['getAlwaysOnTop']=0 
    262         resultsNoTop = startpoint.portal_catalog.searchResults(query, meta_type='BlogEntry', path={'query':self.getObjectPath(startpoint),'level':0}, sort_order='reverse', sort_on='effective') 
    263          
    264         results = resultsTop + resultsNoTop 
    265  
    266         if maxResults==0: 
     238        results = startpoint.portal_catalog.searchResults(query, meta_type='BlogEntry',  
     239                  path={'query':self.getObjectPath(startpoint),'level':0}, sort_order='reverse',  
     240                  sort_on='effective', sort_limit=maxResults and maxResults or None) 
     241 
     242        if  maxResults==0: 
    267243            return results 
    268244        elif maxResults==None: 
     
    271247            return results[:maxResults]     
    272248 
    273  
    274     security.declarePublic('searchForEntries') 
    275     def collectEntries(self, context, category=None, maxResults=None,  filterState=1, allBlogs=0, **kwargs): 
    276         # first get all the blogs 
    277         if allBlogs: 
    278             query = {'meta_type':'Blog', 
    279                         'path':{'query':self.getObjectPath(context),'level':0} 
    280                         } # used meta_type because for some reason, syndication objects also show up. 
    281             blogs = [b.getObject() for b in self.portal_catalog.searchResults(query)] 
    282             onTop=[] 
    283             atBottom=[] 
    284             # now collect all the entries 
    285             for blog in blogs: 
    286                 tmpTop, tmpBottom = blog.getEntries(category=category, maxResults=maxResults, filterState = filterState, sort=0, **kwargs) 
    287                 onTop = onTop+tmpTop 
    288                 atBottom = atBottom+tmpBottom 
    289             #sort 
    290             onTop.sort((lambda x,y:cmp(y.effective(), x.effective()))) 
    291             atBottom.sort((lambda x,y:cmp(y.effective(), x.effective()))) 
    292      
    293             results = onTop+atBottom 
    294         else: 
    295             results = context.getEntries(category=category, maxResults=maxResults, filterState = filterState, sort=0, join=1, skipOnTop=1, **kwargs) 
    296              
    297  
    298         if maxResults==0: 
    299             return results 
    300         elif maxResults==None: 
    301             return results[:self._getMaxItemsInPortlet()] 
    302         else: 
    303             return results[:maxResults] 
    304249 
    305250    security.declarePublic('searchForDay') 
     
    371316                    lst.append(states[s].id) 
    372317        return lst 
    373      
     318 
    374319    security.declareProtected(CMFCorePermissions.ManagePortal,'getEntryWorkflowStates') 
    375320    def getEntryWorkflowStates(self, context): 
     
    381326                if not states[s].id in lst: 
    382327                    lst.append(states[s].id) 
    383          
     328 
    384329        return lst 
    385330 
     
    387332    def getObjectPath(self, object): 
    388333        return os.path.join(*object.getPhysicalPath()).replace('\\', '/') 
    389          
     334 
    390335    # ====================================================== 
    391336    # calendar stuff, copied from CMFCalender 
     
    406351        """ Returns a list of days with the correct start day first """         
    407352        return calendar.weekheader(2).split() 
    408          
     353 
    409354    security.declarePublic('getWeeksList') 
    410355    def getWeeksList(self, month='1', year='2002'): 
     
    419364        #  [28, 29, 30, 31, 0, 0, 0]] 
    420365        daysByWeek=calendar.monthcalendar(year, month) 
    421      
     366 
    422367        return daysByWeek 
    423368 
     
    437382        daysByWeek=calendar.monthcalendar(year, month) 
    438383        weeks=[] 
    439          
     384 
    440385        events=self.catalog_getevents(context, year, month) 
    441      
     386 
    442387        for week in daysByWeek: 
    443388            days=[] 
     
    447392                else: 
    448393                    days.append({'day': day, 'event': 0, 'eventslist':[]}) 
    449                  
     394 
    450395            weeks.append(days) 
    451              
     396 
    452397        return weeks 
    453      
     398 
    454399    security.declarePublic('catalog_getevents') 
    455400    def catalog_getevents(self, context, year, month): 
     
    461406        ## last_date=DateTime(str(month)+'/'+str(last_day)+'/'+str(year)) 
    462407        last_date=first_date + last_day     
    463          
     408 
    464409        # get the starting point for our search. This is where we depart from the standard catalog_tool: 
    465410        startpoint = self.getStartpoint(context, fromHere=0) 
    466          
     411 
    467412        query=self.portal_catalog(portal_type=self.calendar_types, 
    468413                              review_state=self._getState(), 
     
    473418                              path={'query':self.getObjectPath(startpoint),'level':0}, 
    474419                              sort_on='start') 
    475          
     420 
    476421        # compile a list of the days that have events 
    477422        eventDays={} 
     
    523468        # end calendar stuff 
    524469        # ================== 
    525      
    526      
    527      
     470 
    528471InitializeClass(SimpleBlogManager) 
  • SimpleBlog/trunk/content/blog.py

    r694 r1039  
    1616from Products.Archetypes.utils import  unique 
    1717 
    18 from Products.ATContentTypes.content.base import ATCTFolder 
    19  
    20 schema = ATCTFolder.schema.copy() +  Schema(( 
     18from Products.ATContentTypes.content.base import  ATCTBTreeFolder, ATCTFolder 
     19from Products.ATContentTypes.lib.constraintypes import  ConstrainTypesMixinSchema 
     20 
     21schema = ConstrainTypesMixinSchema.copy() + ATCTFolder.schema.copy() +  Schema(( 
    2122    StringField('description', 
    2223                isMetadata=1, 
     
    3839                                       visible={'view' : 'invisible', 'edit':'invisible'}), 
    3940                default='descriptionOnly'), 
    40     IntegerField('displayItems',  
     41    IntegerField('displayItems', 
    4142                widget=IntegerWidget(label='BlogEntries to display',  
    4243                                      label_msgid="label_display_items", 
     
    197198                           condition="python:%s" % ENABLE_ADSENSE)), 
    198199        )) 
    199  
    200 # hide relatedItems 
    201200schema['relatedItems'].widget.visible={'view' : 'invisible', 'edit':'invisible'} 
    202201 
    203 class Blog(ATCTFolder): 
     202class Blog(ATCTBTreeFolder,ATCTFolder): 
    204203    """Blog""" 
    205204 
     
    224223        RPCAuth = self.simpleblog_tool.findRPCAuth(self) 
    225224 
    226         # Setup the MetaWeblog API 
    227225        self.metaWeblog = MetaWeblogAPI.MetaWeblogAPI().__of__(self) 
    228226        self.metaWeblog.setupRPCAuth(RPCAuth) 
    229  
    230         # Setup the Blogger API 
    231227        self.blogger = BloggerAPI.BloggerAPI().__of__(self) 
    232228        self.blogger.setupRPCAuth(RPCAuth) 
    233  
    234         # Setup the MovableTypeAPI API 
    235229        self.mt = MovableTypeAPI.MovableTypeAPI().__of__(self) 
    236230        self.mt.setupRPCAuth(RPCAuth)     
     
    246240 
    247241    def synContentValues(self): 
    248         # get brains for items that are published within the context of this blog. 
    249         entries = self.simpleblog_tool.searchForEntries(self, maxResults=0) 
    250  
    251         # convert to objects 
     242        syn_tool = getToolByName(self, 'portal_syndication') 
     243        limit = int(syn_tool.getMaxItems(self)) 
     244        entries = self.getEntries(maxResults=limit)[1] 
    252245        objs = [e.getObject() for e in entries] 
    253246        return objs 
     
    256249        cats=self.getCategories() 
    257250 
    258         # add the global categories 
    259251        for c in self.simpleblog_tool.getGlobalCategories(): 
    260252            if not c in cats: 
     
    268260        return [f for f in self.getBRefs('AppearsIn') if self.portal_membership.checkPermission('View', f)] 
    269261 
    270     def getEntries(self, category=None, maxResults=None, fromHere=0, filterState=1, sort=1, join=0, addCrossPostInfo=0, skipOnTop=0, **kwargs): 
     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): 
    271312        """ Return all the contained published entries, real objects, not the brains """ 
    272         # see simpleblog_tool.searchForEntries for API description 
    273313        query=kwargs 
    274314        publishedState = self.simpleblog_tool.getPublishedState() 
     
    278318            query['review_state']=publishedState 
    279319        if maxResults: 
    280             query['sort_limit'] = maxResults 
    281         query['path'] = {'query':self.simpleblog_tool.getObjectPath(self),'level':0} 
     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} 
    282323        query['sort_order'] = 'reverse' 
    283324        query['sort_on'] = 'effective' 
    284325        query['meta_type'] = 'BlogEntry' 
    285         if not skipOnTop: 
     326        onTop = [] 
     327        if not skipOnTop and b_start==0: 
    286328            query['getAlwaysOnTop']=1 
    287             # first the items that need to be listed on top 
    288             localOnTop = self.portal_catalog.searchResults(query) 
    289             localOnTop = [r.getObject() for r in localOnTop ] 
    290             # then the other items 
     329            onTop = list(self.portal_catalog.searchResults(query)) 
    291330            query['getAlwaysOnTop']=0 
    292         else: 
    293             localOnTop = [] 
    294         localNoTop = self.portal_catalog.searchResults(query) 
    295         localNoTop= [r.getObject() for r in localNoTop] 
    296  
    297         onTop = localOnTop 
    298         onBottom = localNoTop 
     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 
    299342        if join: 
    300343            results = onTop+onBottom 
    301             if maxResults==0: 
    302                 return results 
    303             elif maxResults==None: 
    304                 return results[:self.simpleblog_tool.getMaxItemsInPortlet()] 
    305             else: 
    306                 return results[:maxResults] 
     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) 
    307351        else: 
    308             return (onTop, onBottom) 
     352            batch = 'navigation' in query.keys() and self.buildBatch(b_start, query, len(onBottom)) or [] 
     353            return (onTop, onBottom, batch) 
    309354 
    310355    def getAdminEmail(self): 
  • SimpleBlog/trunk/content/blogentry.py

    r695 r1039  
    7878                    accessor='EntryCategory',  
    7979                    edit_accessor='EntryCategory',  
    80                     index='KeywordIndex',  
     80                    index='KeywordIndex:schema',  
    8181                    vocabulary='listCategories', 
    8282                    widget=MultiSelectionWidget(format='select',  
     
    124124     )) 
    125125 
    126 # Finalise the schema according to ATContentTypes standards. This basically 
    127 # moves the Related items and Allow discussion fields to the bottom of the 
    128 # form. See ATContentTypes.content.schemata for details. 
    129126finalizeATCTSchema(schema) 
    130  
    131127 
    132128class BlogEntry(parentClass): 
     
    134130    A BlogEntry can exist inside a SimpleBlog Folder or an EntryFolder 
    135131    """ 
    136     # Standard content type setup 
    137132    portal_type = meta_type = 'BlogEntry' 
    138133    archetype_name = 'Blog Entry' 
     
    145140    immediate_view = 'blogentry_view' 
    146141 
    147     # Make sure we get title-to-id generation when an object is created 
    148142    _at_rename_after_creation = True 
    149143 
    150144    if ENTRY_IS_FOLDERISH: 
    151145        filter_content_types=1 
    152         allowed_content_types=('TrackBack') #('Link', 'Image', 'File', 'TrackBack') 
    153  
     146        allowed_content_types=('TrackBack') 
    154147 
    155148    def canSetDefaultPage(self): 
    156149        return False 
    157  
    158150 
    159151    def getAlwaysOnTop(self): 
     
    165157        else: 
    166158            return 0 
    167              
     159 
    168160    def getIcon(self, relative_to_portal=0): 
    169161        try: 
     
    174166        except: 
    175167            return 'entry_icon.gif' 
    176          
     168 
    177169    def listCategories(self): 
    178         # traverse upwards in the tree to collect all the available categories 
    179         # stop collecting when a SimpleBlog object is reached 
    180          
     170        """ Traverse upwards in the tree to collect all the available categories.""" 
    181171        cats=[] 
    182172        parent=self.aq_parent 
    183173        portal=self.portal_url.getPortalObject() 
    184          
     174 
    185175        while parent!=portal: 
    186176           if parent.portal_type=='Blog' or parent.portal_type=='BlogFolder': 
    187                # add cats 
    188177               pcats=parent.getCategories() 
    189178               for c in pcats: 
     
    193182                   break 
    194183           parent=parent.aq_parent 
    195             
    196         # add the global categories 
     184 
    197185        for c in self.simpleblog_tool.getGlobalCategories(): 
    198186            if not c in cats: 
    199                 cats.append(c)            
     187                cats.append(c) 
    200188        cats.sort() 
    201189        return tuple(cats) 
     
    203191    def start(self): 
    204192        return self.getEffectiveDate() 
    205          
     193 
    206194    def end(self): 
    207         """  
    208         return the same data as start() since an entry is not an event but an item that is published on a specific 
    209         date. We want the entries in the calendar to appear on only one day. 
     195        """ Return the same data as start() since an entry is not an event but an item that is 
     196            published on a specific date. We want the entries in the calendar to appear on only one day. 
    210197        """ 
    211198        return self.getEffectiveDate() 
    212199 
    213  
    214  
    215  
    216 # ============================= 
    217  
    218     #function for sending ping 
    219200    def sendTrackBack(self): 
    220201        message = "TrackBack sent" 
     
    241222 
    242223    def getTrackbacks(self): 
    243         """ """ 
    244224        return self.listFolderContents(spec="TrackBack") 
    245225 
     
    276256 
    277257    def getBody(self): 
    278        return self.getField('body').get(self) 
     258        return self.getField('body').get(self) 
    279259 
    280260registerType(BlogEntry) 
  • SimpleBlog/trunk/content/blogfolder.py

    r694 r1039  
    55from Products.CMFCore import CMFCorePermissions 
    66 
    7 from Products.ATContentTypes.content.base import ATCTFolder 
     7from Products.ATContentTypes.content.base import  ATCTBTreeFolder, ATCTFolder 
     8from Products.ATContentTypes.lib.constraintypes import  ConstrainTypesMixinSchema 
    89 
    910import Products.SimpleBlog.Permissions 
    1011 
    1112 
    12 schema = ATCTFolder.schema.copy() +  Schema(( 
     13schema = ConstrainTypesMixinSchema.copy() + ATCTFolder.schema.copy() +  Schema(( 
    1314    StringField('description', 
    1415                isMetadata=1, 
     
    3435 
    3536 
    36 class BlogFolder(ATCTFolder): 
     37class BlogFolder(ATCTBTreeFolder, ATCTFolder): 
    3738    """ 
    3839    A folder object to store BlogEntries in 
     
    5758     
    5859    def getInheritedCategories(self): 
    59             # traverse upwards in the tree to collect all the available categories 
    60             # stop collecting when a SimpleBlog object is reached 
    61              
    62             cats=[] 
    63             parent=self.aq_parent 
    64             portal=self.portal_url.getPortalObject() 
    65             categories='<ul>' 
    66             while parent!=portal: 
    67                if parent.portal_type=='Blog' or parent.portal_type=='BlogFolder': 
    68                    # add cats 
    69                    pcats=parent.getCategories() 
    70                    for c in pcats: 
    71                        if c not in cats: 
    72                            categories=categories + '<li>' + c + '</li>' 
    73                            cats.append(c) 
    74                    if parent.portal_type=='Blog': 
    75                        break 
    76                parent=parent.aq_parent 
    77             categories = categories + '</li>' 
    78             if len(cats)==0: 
    79                 return '-' 
    80             else: 
    81                 return categories 
     60        """ Traverse upwards in the tree to collect all the available categories.""" 
     61        cats=[] 
     62        parent=self.aq_parent 
     63        portal=self.portal_url.getPortalObject() 
     64        categories='<ul>' 
     65        while parent!=portal: 
     66            if parent.portal_type=='Blog' or parent.portal_type=='BlogFolder': 
     67                # add cats 
     68                pcats=parent.getCategories() 
     69                for c in pcats: 
     70                    if c not in cats: 
     71                        categories=categories + '<li>' + c + '</li>' 
     72                        cats.append(c) 
     73                if parent.portal_type=='Blog': 
     74                    break 
     75            parent=parent.aq_parent 
     76        categories = categories + '</li>' 
     77        if len(cats)==0: 
     78            return '-' 
     79        else: 
     80            return categories 
    8281 
    8382    def getEntries(self, maxResults=None, **kwargs): 
    8483        """ Return all the contained published entries, real objects, not the brains """ 
    85         # see simpleblog_tool.searchForEntries for API description 
     84        blog = self.simpleblog_tool.getFrontPage(self) 
     85        kwargs.update({'path':{'query':'/'+'/'.join(self.getPhysicalPath()),'level':0}}) 
     86        return blog.getEntries(maxResults=maxResults, **kwargs) 
    8687 
    87         query=kwargs 
    8888 
    89         publishedState = self.simpleblog_tool.getPublishedState() 
    90          
    91         query['getAlwaysOnTop']=1 
    92          
    93         # first the items that need to be listed on top 
    94         localOnTop = self.portal_catalog.searchResults(query, meta_type='BlogEntry', path={'query':self.simpleblog_tool.getObjectPath(self),'level':0}, sort_order='reverse', sort_on='effective') 
    95         localOnTop = [r.getObject() for r in localOnTop ] 
    96          
    97         # then the other items 
    98         query['getAlwaysOnTop']=0 
    99         localNoTop = self.portal_catalog.searchResults(query, meta_type='BlogEntry', path={'query':self.simpleblog_tool.getObjectPath(self),'level':0}, sort_order='reverse', sort_on='effective') 
    100         localNoTop= [r.getObject() for r in localNoTop]         
    101          
    102         results = localOnTop+localNoTop 
    103          
    104         if maxResults==0: 
    105             return results 
    106         elif maxResults==None: 
    107             return results[:self.simpleblog_tool.getMaxItemsInPortlet()] 
    108         else: 
    109             return results[:maxResults]                
    110      
    11189    def synContentValues(self): 
    112         # get brains for items that are published within the context of this blog. 
    11390        entries = self.simpleblog_tool.searchForEntries(self, fromHere=1, maxResults=0) 
    114          
    115         # convert to objects 
    11691        objs = [e.getObject() for e in entries] 
    117         return objs         
    118                  
     92        return objs 
     93 
    11994registerType(BlogFolder) 
  • SimpleBlog/trunk/docs/readme.txt

    r694 r1039  
    115115will be sufficient. 
    116116 
    117 Using SimpleBlog as your homepage in Plone 
    118  
    119     Inside the skin folder there is a template called **simpleblog_standalone**. First get rid of the current index_html 
    120 in your portal root by deleting it or renaming it. Then create a new Page template in the root and call it index_html. 
    121 Then copy/paste the code from simpleblog_standalone in there and adjust it at will. All this is done in ZMI. 
    122  
    123117Well, that's all you have to know to set up SimpleBlog. Enjoy it. 
    124118 
  • SimpleBlog/trunk/skins/SimpleBlog/SimpleBlog_macros.pt

    r694 r1039  
    2828        <span tal:define="item_type obj/portal_type; 
    2929                    item_type_class python:'contenttype-' + normalizeString(item_type);" 
    30               tal:attributes="class string:simpleBlogIcons ${item_type_class}" tal:content="obj/title"/></a> 
     30              tal:attributes="class string:simpleBlogIcons ${item_type_class}" tal:content="obj/Title"/></a> 
    3131    </h2> 
    3232    <h2 class="noMargin" tal:condition="not:showIcons"> 
     
    3535    </h2> 
    3636    <p class="simpleBlogDescription" 
    37        tal:content="structure python:obj.Description()
     37       tal:content="structure obj/Description
    3838       tal:condition="obj/Description">Description</p> 
    39     <div tal:replace="structure python:obj.getBody()" class="simpleBlogBody"/> 
     39    <div tal:replace="structure obj/getBody" class="simpleBlogBody"/> 
    4040    <tal:tags metal:use-macro="obj/simpleblog_byline/macros/technoratiTags"/> 
    4141    <tal:byline tal:condition="showByline"> 
     
    5757    </h2> 
    5858    <p class="simpleBlogDescription" 
    59        tal:content="structure python:obj.Description()
     59       tal:content="structure obj/Description
    6060       tal:condition="obj/Description">Description</p> 
    6161    <tal:tags metal:use-macro="obj/simpleblog_byline/macros/technoratiTags"/> 
  • SimpleBlog/trunk/skins/SimpleBlog/simpleblog_portlet_macros.pt

    r694 r1039  
    2424 
    2525<!-- macro used by the portlets to compile a list of recent additions --> 
    26 <div metal:define-macro="portletRecent"> 
    27      <tal:x tal:condition="maxItems|nothing"><tal:x tal:define="global maxResults maxItems"/> 
    28      </tal:x><tal:x tal:condition="not: maxItems|nothing"><tal:x tal:define="global maxResults python:0"/> 
    29      </tal:x><tal:block tal:define="maxResults python:test(maxResults==0,here.simpleblog_tool.getMaxItemsInPortlet(),maxResults);  
    30                                     recent python:startpoint.getEntries(maxResults=maxResults,skipOnTop=1, join=1); 
    31                                     global showIcons startpoint/getShowIcons;" 
    32      tal:omit-tag=""><tal:toggle tal:define="global toggle python:1"/> 
     26<div metal:define-macro="portletRecent" tal:omit-tag=""><tal:block  
     27           tal:define="maxResults here/simpleblog_tool/getMaxItemsInPortlet; 
     28                       recent python:startpoint.getEntries(maxResults=maxResults,skipOnTop=1, join=1)[0]; 
     29                       global showIcons startpoint/getShowIcons;"><tal:toggle  
     30           tal:define="global toggle python:1"/> 
    3331    <tal:entries tal:repeat="entry recent"> 
    3432        <tal:start tal:condition="python:inBlog and not solo"> 
     
    3634                     tal:condition="repeat/entry/start"  
    3735                     tal:attributes="class python:test(toggle, 'portletItem odd','portletItem even')"> 
    38             <tal:frontpage> 
    39                 <strong i18n:translate="recent_additions">Recent entries:</strong> 
    40             </tal:frontpage> 
     36        <strong i18n:translate="recent_additions">Recent entries:</strong> 
    4137        </dd></tal:start> 
    4238        <dd class="" 
    4339            tal:define="oddrow repeat/entry/odd; 
    44                         item_type entry/portal_type; 
     40                        obj entry; 
     41                        item_type obj/portal_type; 
    4542                        item_type_class python:'contenttype-' + normalizeString(item_type);"  
    4643            tal:attributes="class python:test(toggle, 'portletItem even','portletItem odd')"> 
    4744            <a href="#"  
    48                tal:attributes="href entry/absolute_url;"  
     45               tal:attributes="href obj/getURL;"  
    4946                               title="entry"> 
    50                <span tal:attributes="class python:showIcons and 'simpleBlogPortletIcons '+item_type_class or ''" tal:content="entry/title_or_id"/> 
     47               <span tal:attributes="class python:showIcons and 'simpleBlogPortletIcons '+item_type_class or ''" tal:content="obj/Title"/> 
    5148            </a><tal:toggle tal:define="global toggle python:test(toggle==1,0,1)"/> 
    5249        </dd> 
     
    5653                        className python:test(solo,'portletFooter', 'portletItem')"  
    5754            tal:condition="repeat/entry/end"  
    58             tal:attributes="class python:test(toggle, className + ' even', className + ' odd')"> 
    59             <a href="#" tal:attributes="href string:${startpoint/absolute_url}/SimpleBlogFullSearch"  
     55            tal:attributes="class python:test(toggle, className + ' even details', className + ' odd details')"> 
     56            <a href="#" tal:attributes="href string:${startpoint/absolute_url}"  
    6057                           title="more..." 
    6158                           i18n:attributes="title box_morelink" 
  • SimpleBlog/trunk/skins/SimpleBlog/simpleblog_view.pt

    r694 r1039  
    66<div metal:fill-slot="main"> 
    77    <tal:main-macro metal:define-macro="main" 
    8       tal:define="displayItems python:here.getDisplayItems(); 
    9                   displayMode displayMode | python:here.getDisplayMode(); 
    10                   results python:here.getEntries(maxResults=0, sort=1, join=1, addCrossPostInfo=1); 
     8      tal:define="displayMode displayMode | python:here.getDisplayMode(); 
     9                  displayItems python:here.getDisplayItems(); 
    1110                  b_size python:displayItems; 
    12                   b_start python:0
    13                   b_start request/b_start | b_start
    14                   Batch python:modules['Products.CMFPlone'].Batch;"> 
     11                  b_start here/getStart
     12                  results python:here.getEntries(maxResults=b_start+displayItems, sort=1, join=1, b_start=b_start,mode=displayMode,navigation=1)
     13                  last python:results[1];"> 
    1514        <tal:block metal:use-macro="here/SimpleBlog_macros/macros/blogGlobals"/> 
    1615        <div metal:use-macro="here/document_actions/macros/document_actions">