source: trunk/LargeSectionFolder.py @ 1915

Revision 1915, 42.0 KB checked in by pjotr, 12 years ago (diff)

Corrected subject area stuff for group browsing

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 config import *
20from Products.Archetypes.public import *
21from Products.ATContentTypes.content.folder import ATFolder, ATBTreeFolderSchema, ATBTreeFolder
22from Products.Archetypes.public import registerType
23from Products.CMFCore.utils import getToolByName
24from Products.CMFPlone.utils import transaction_note
25from ZPublisher.HTTPRequest import FileUpload
26from DocumentTemplate import sequence
27from random import sample
28from DateTime import DateTime
29import re, datetime, urllib
30from AccessControl import ClassSecurityInfo
31from permissions import MODIFY_CONTENT, ADD_CONTENT_PERMISSION
32from Products.LeMill import LeMillMessageFactory as _
33
34communityschema= ATBTreeFolderSchema + Schema((
35    LinesField('collaboration_proposals',
36        default= [],
37        widget = LinesWidget(
38            visible = {'view':'invisible', 'edit':'invisible'},
39            )
40        )
41
42))
43
44
45
46class LargeSectionFolder(ATBTreeFolder):
47    """Section Folder"""
48       
49    archetype_name = "Large Section Folder"
50    meta_type = "Large Section Folder"
51    security = ClassSecurityInfo()
52    isAnObjectManager = 1
53    global_allow= 1
54
55    def getAllContentTypes(self):
56        """ returns a list of all content types """
57        return ALL_CONTENT_TYPES
58
59    def getMaterialTypes(self):
60        """ returns a list of material types """
61        return MATERIAL_TYPES
62
63    def getContentTypes(self):
64        """ returns a list of material types """
65        return CONTENT_TYPES
66
67    def getActivityTypes(self):
68        """ returns a list of activity types """
69        return ACTIVITY_TYPES
70
71    def getToolsTypes(self):
72        """ returns a list of activity types """
73        return TOOLS_TYPES
74
75    def getFeaturedTypes(self):
76        """ returns a list of featured types """
77        return MATERIAL_TYPES + ACTIVITY_TYPES + TOOLS_TYPES
78
79
80    def getMimetypeWhitelist(self):
81        """ returns a list of allowed filetypes """
82        return MIMETYPE_WHITELIST
83
84    def canDeleteOnCancel(self):
85        """ Should be called on resource contexts, so NO """
86        return False
87
88    # Override initializeArchetype to turn on syndication by default
89    security.declarePrivate('initializeArchetype')
90    def initializeArchetype(self, **kwargs):
91        ret_val = ATBTreeFolder.initializeArchetype(self, **kwargs)
92        # Enable topic syndication by default
93        syn_tool = getToolByName(self, 'portal_syndication', None)
94        if syn_tool is not None:
95            if syn_tool.isSiteSyndicationAllowed():
96                try:
97                    syn_tool.enableSyndication(self)
98                except: # might get 'Syndication Information Exists'
99                    pass
100        return ret_val
101
102    security.declareProtected(ADD_CONTENT_PERMISSION,'createPiece')
103    def createPiece(self, container, id=None, file=None):
104        new=self._lemill_invokeFactory(container, 'Piece', id, do_create=True)
105        new.edit(file=file.read(), language='')
106        return new
107
108    # private
109    def _lemill_invokeFactory(self, container, meta_type, id=None, do_create=False):
110        """ add new object, edit it's title and invoke _renameAfterCreation """
111        ft=getToolByName(self, 'portal_factory')
112        if id is None:
113            id = self.generateUniqueId(meta_type)
114        if ft.getFactoryTypes().has_key(meta_type):
115            o = container.restrictedTraverse('portal_factory/' + meta_type + '/' + id)
116            message = None
117            transaction_note('Initiated creation of %s with id %s in %s' % (o.getTypeInfo().getId(), id, container.absolute_url()))
118        else:
119            new_id = container.invokeFactory(id=id, type_name=meta_type)
120            if new_id is None or new_id == '':
121               new_id = id
122            o=getattr(container, new_id, None)
123            tname = o.getTypeInfo().Title()
124            message = _(u'${tname} has been created.', mapping={u'tname' : tname})
125            transaction_note('Created %s with id %s in %s' % (o.getTypeInfo().getId(), new_id, container.absolute_url()))
126        if do_create: # finalizes object
127            o=ft.doCreate(o)
128        return o
129
130
131
132    security.declareProtected(ADD_CONTENT_PERMISSION,'start_translation')
133    def start_translation(self, objId=None):
134        """
135        Start a new translation of an object. This is done by creating new object and
136        then, on second stage copying data from object to new object.
137        Second stage is done by Resources/prefill_translation because of redirect_to -activities
138        lose the data if it is given here.
139        """
140        if objId is None:
141            raise 'object id is None (create_translation)'
142        base_obj = self.restrictedTraverse(objId)
143        meta_type = base_obj.meta_type
144        new = self._lemill_invokeFactory(self, meta_type, id=meta_type.lower()+str(id(base_obj)), do_create=True)
145        # I give up, cannot handle all required references and files while keeping the object in portal_factory, do_create=True
146        return new
147
148
149    def prettyMethodNameDictionary(self):
150        """ Helper method for finding displayable names for search fields """
151        # better to do this in config..
152        return FIELD_METHODS_DISPLAY_STRINGS                     
153
154
155    def getNameOfResourceType(self,restype):
156        """Get human-readable name of resource - first try TYPE_NAMES, then TEMPLATES"""
157        if restype in TYPE_NAMES.keys():
158            return TYPE_NAMES[restype][0].lower()
159        else:
160            for t in TEMPLATES.values():
161                if t['meta_type'] == restype:
162                    if t['title'].isupper():
163                        return t['title']
164                    else:
165                        return t['title'].lower()
166        return ""
167
168    def getSectionFolder(self):
169        """ return this """
170        return self
171
172    def checkTitle(self, obj=None ,title='', objtype=''):
173        """ check if title is not used anywhere in not(deleted, redirector) object, return false if it is """
174        lt=getToolByName(self, 'lemill_tool')
175        return lt.checkTitle(self,obj=obj, title=title, objtype=objtype)
176       
177    def getMetadataFieldsToShowInEditor(self, object):
178        """ gets fields which are shown in metadata edit area """
179        type = object.meta_type
180        shownFieldsList = SHOW_METADATA_FIELDS[type]
181        shownFields = []
182        fields = object.Schemata()['metadata'].fields()
183        # At this point, the method can return a list of all metadata
184        if 'all' in shownFieldsList:
185            return fields
186        else:
187            for field in fields:
188                if field.getName() in shownFieldsList:
189                    shownFields.append(field)
190            return shownFields
191
192    def amIManager(self):
193        """Check whether I'm a manager."""
194        return 'Manager' in self.portal_membership.getAuthenticatedMember().getRoles()
195
196    def canIModerate(self):
197        roles = self.portal_membership.getAuthenticatedMember().getRolesInContext(self)
198        return 'Manager' in roles or 'Reviewer' in roles
199
200    def whoami(self):
201        return self.portal_membership.getAuthenticatedMember().getId()       
202
203    def getMember(self,uname=None):
204        if not uname:
205            uname=self.whoami()
206        try:
207            return self.lemill_usertool.getLeMillMemberFolder(uname)
208        except AttributeError:
209            return None
210
211    def getSamples(self, search_results, language_dependant=True):
212        """ Pick three random objects from search results that have non-default images to display in folders front pages. Gives language-dependant results. """
213        ltool = getToolByName(self, 'portal_languages')
214        favlang = ltool.getLanguageCookie()
215        if favlang == None:
216            favlang = 'en'
217
218        #TODO: This is work-around for a Plone bug. Investigate
219        elif favlang == 'cz':
220            favlang = 'cs'
221
222        hf=getToolByName(self, 'portal_membership').getHomeFolder()
223        if hf:
224            ulanguages=list(hf.getLanguage_skills())
225        else:
226            ulanguages=[]
227        if favlang not in ulanguages:
228            ulanguages.append(favlang)
229        good_results = [x for x in search_results if x.meta_type in FEATURED_TYPES and x.getHasCoverImage and x.review_state=='public' and x.Title]
230
231        def scoreSorter(a, b):
232            if language_dependant:
233                if a.Language in ulanguages and b.Language not in ulanguages:
234                    return -1
235                if a.Language not in ulanguages and b.Language in ulanguages:
236                    return 1
237                if a.Language == 'en' and b.Language != 'en':
238                    return -1
239                if a.Language != 'en' and b.Language == 'en':
240                    return 1
241            return cmp(a.getScore, b.getScore)
242
243        #Sorting the good_results list by language and scores
244        good_results.sort(scoreSorter)
245
246        n = len(good_results)
247        n = min(n, max(3, n / 10))
248        best_favlang_results = []
249        best_en_results = []
250        best_notfavlang_results = []
251
252        #Sort the good_results list into groups
253        if language_dependant:
254            for i in range(n):
255                if good_results[i].Language in ulanguages:
256                    best_favlang_results.append(good_results[i])
257                elif good_results[i].Language == 'en':
258                    best_en_results.append(good_results[i])
259                else:
260                    best_notfavlang_results.append(good_results[i])
261        else:
262            best_favlang_results = good_results[:n]
263           
264        n = min(3, len(best_favlang_results))
265        m = 0
266        k = 0
267        best_results = []
268        #Creating the final list
269        if n > 0:    #If there are some materials which language matches the user's language we will add them to the list
270            best_results.extend(sample(best_favlang_results, n))
271        if n < 3:    #If there were less than 3 materials which language matches the user's language
272            m = min(3 - n, len(best_en_results))
273            if m > 0:    #If there are some English materials we will them to the list
274                best_results.extend(sample(best_en_results, m))
275            z = n + m
276            if z < 3:   #If we still need more materials to reach 3 we will add some materials with other languages
277                k = min(3 - z, len(best_notfavlang_results))
278                if k > 0:   #If there are some materials with other languages we will add them to the list
279                    best_results.extend(sample(best_notfavlang_results, k))
280
281        #Randomizing the final list
282        if m > 0 or k > 0:
283            best_results = sample(best_results, n + m + k)
284
285        return best_results
286       
287    def getTopResults(self, search_results, index_type):
288        """ Should return top three populated subgroups of search results in given index  """
289        pc = getToolByName(self, 'portal_catalog')
290        if index_type in pc.indexes() and index_type in pc.schema():
291            uniques = pc.uniqueValuesFor(index_type)
292            if uniques == ():
293                return []
294            hits={}
295            for a in uniques:
296                hits[a]=0
297            for counter in search_results:
298                if counter.review_state!='deleted':   
299                    values=getattr(counter, index_type)
300                    if isinstance(values,str):
301                         hits[values]=hits[values]+1
302                    else:
303                        try:
304                            for a in values:
305                                hits[a]=hits[a]+1
306                        except TypeError, KeyError:
307                            pass # something wrong with data - let's continue without it
308            topthree= [(x[1],x[0]) for x in hits.items() if x[1]>0 and x[0]!='']
309            topthree.sort()
310            topthree.reverse()
311            topthree= topthree[:min(3,len(topthree))]
312            topthree=[x[1] for x in topthree]
313           
314            return topthree
315        else:
316            return []
317
318    def url_quote(self,word):
319        return urllib.quote(word)
320
321    def getTitleCloud(self, search_results, browse_type):
322        """ Build a cloud based on popularity score for that resource """
323        # uniquetuplelist contains result metadata reordered: (sort_title, count, url, indexvalue, title)
324        from math import log
325        if not search_results:
326            return []
327
328        def adjust(i):
329            # helper method to adjust hit count of this tag to relative size (1,...,8)
330            (a,b,c,d,e)=i
331            b=int((8*log(b,2))/log(maxscore,2))
332            if b==0:
333                b=1
334            i=(a,b,c,d,e)
335            return i       
336        def isDefaultTitle(x):
337            """ some heuristic to recognize default titles """
338            return re.match(r'.*\.(...)$', x) or re.match(r'.*\.(....)$', x)
339                   
340        popularity =[(x.getScore, x.sortable_title, x) for x in search_results]
341        popularity.sort(cmp=lambda t2,t1: cmp(t1[0],t2[0]))
342        popularity=popularity[:100]
343        if browse_type=='members_titles':
344            titlecloud=[(x.getSortable_nicename,pop,x.getURL(),s_title, x.getNicename) for (pop, s_title, x) in popularity]       
345        elif browse_type=='resources_titles':
346            titlecloud=[(s_title,pop,'%s/view' % x.getURL(),s_title, x.Title) for (pop, s_title, x) in popularity if x.Title!='']
347        elif browse_type=='pieces_titles':
348            titlecloud=[(s_title,pop,x.getURL(),s_title, x.Title) for (pop, s_title, x) in popularity if x.Title!='' and not isDefaultTitle(x.Title)]
349        else:
350            titlecloud=[(s_title,pop,x.getURL(),s_title, x.Title) for (pop, s_title, x) in popularity if x.Title]
351       
352        if not titlecloud:
353            return []
354        titlecloud.sort()
355        maxscore=max([x[1] for x in titlecloud])
356        if maxscore>1:
357            titlecloud=map(adjust, titlecloud)
358        return titlecloud
359
360    def getTagCloud(self, search_results, index_type):
361        """ Build a cloud based on how many occurences of this item are in results """
362        if not search_results:
363            return []
364        lemill_tool = getToolByName(self, 'lemill_tool')
365        pc = getToolByName(self, 'portal_catalog')
366        from math import log
367        resultlist=[]
368        maxcount=0
369        uniquevalues=[]
370
371        def adjust(i):
372            # helper method to adjust hit count of this tag to relative size (1,...,8)
373            (a,b,c,d,e)=i
374            b=int((8*log(b,2))/log(maxcount,2))
375            if b==0:
376                b=1
377            i=(a,b,c,d,e)
378            return i
379
380        # -- Step 1 -- : Make list of unique values for this index
381        uniques = pc.uniqueValuesFor(index_type)           
382        if uniques == []:
383            return []
384        hits={}
385        # -- Step 2 -- : Use that list to make a dictionary. Values of list are keys.
386        for a in uniques:
387            hits[a]=0
388        # -- Step 3 -- : Go through the search_results and every time a certain key is found from selected index, add a hit to counter under that key.
389        spent_urls=[]
390        for c_obj in search_results:
391            values=getattr(c_obj, index_type)
392            if values!=None:
393                if type(values)==str or type(values)==int:
394                    hits[values]=hits[values]+1
395                elif type(values)==list or type(values)==tuple:
396                    for a in list(values):
397                        hits[a]=hits[a]+1               
398
399        # -- Step 4 -- : Build a list from previous dictionary.
400        if hits.has_key(''):
401            del hits['']
402        resultlist=[(x[1],x[0]) for x in hits.items() if x[1]>0]
403        if not resultlist:
404            return []
405        resultlist.sort()
406        resultlist.reverse()
407        maxcount=resultlist[0][0]
408        # if the first cut score for tag is x, we want to cut off all of the tags with score x.
409        if len(resultlist)>100:
410            #cutpoint = [x[0] for x in resultlist].index(resultlist[100]) can't figure this now, fix later
411            cutpoint = 100
412            resultlist = resultlist[:cutpoint]
413        resultlist=[(x[1], x[0], '',x[1],x[1]) for x in resultlist]
414
415        # adjust to 1-8. We don't have to worry about score 0, they're already removed.
416        if maxcount>1:
417            resultlist=map(adjust, resultlist)
418        # prettify language names
419        if index_type=='Language' or index_type=='getLanguage_skills':
420            resultlist=[(x[0],x[1],x[2],x[3],lemill_tool.getPrettyLanguage(x[4])) for x in resultlist]           
421        if index_type=='getTarget_group':
422            def compfunc(t2,t1):
423                if t2[0] in TARGET_GROUP and t1[0] in TARGET_GROUP:
424                    return  TARGET_GROUP.index(t2[0]) - TARGET_GROUP.index(t1[0])
425                else:
426                    return -1
427            resultlist.sort(cmp=compfunc)
428        else:   
429            resultlist.sort()
430        return resultlist
431
432    def js_queryForPieces(self, keyword, audio=False):
433        """ javascript is querying for pieces that are images """
434        # when this method is called by javascript, all arguments are packed to string 'keyword'
435        # typical value for keyword: 'foobar,audio=False'
436        keywords=keyword.split(', ')
437        keyword=keywords[0]
438        audio='no'
439        for a in keywords[1:]:
440            if a=='audio=True':
441                audio='only'
442            elif a=='audio=accept':
443                audio='accept'
444
445        result = []
446        stool = getToolByName(self, 'lemill_search')
447        q = {'SearchableText': keyword,
448             'portal_type': ['Piece', ]
449        }
450        q_results = stool.local_search(q)
451        lt=getToolByName(self, 'lemill_tool')           
452        q_results=lt.prioritizeResults(q_results)
453        for r in q_results:
454            if r.review_state == 'deleted':
455                continue
456            if audio=='only':
457                if not r.getObject().isAudio(): continue
458            elif audio=='no':
459                if not r.getObject().isImage(): continue
460            if r.getObject().isAudio():
461                type = 1
462            elif r.getObject().isFLVVideo():
463                type = 2               
464            else:
465                type = 0       
466            tmp = [r.getObject().UID(), r.getId, to_unicode(r.Title).encode('iso-8859-15'), int(type), int(r.getHasCoverImage)]
467            result.append(tmp)
468        return str(result)
469
470    def getDefaultIcon(self, meta_type, obj=None):
471        """ general method for getting proper icon for object, used when only catalog-metadata is available """       
472        address=DEFAULT_ICONS[meta_type]
473        if address!='piece':
474            return address
475        else:
476            try:
477                obj=obj.getObject()
478                return obj.getDefaultIcon()
479            except (AttributeError, KeyError):
480                return DEFAULT_ICONS['Piece']
481
482    def getTitleOfACLGroup(self, group):
483        """ gfjreih5eh """
484        return getToolByName(self, 'portal_groups').getGroupareaFolder(group.getId()).title_or_id()
485
486
487    security.declareProtected(MANAGE_PORTAL, 'recalculate_all_scores')
488    def recalculate_all_scores(self, REQUEST=None):
489        """run private recalc script"""
490        for o in self.objectValues(SEARCHABLE_TYPES):
491            o.recalculateScore()
492            print '%s : %s' % (o.id, o.score)
493        if REQUEST:
494            return REQUEST.RESPONSE.redirect(self.absolute_url())
495
496
497
498    #################################
499    ### Resource conversion stuff ###
500    #################################
501
502
503    security.declareProtected(MANAGE_PORTAL, 'convertResource')
504    def convertResource(self, REQUEST):
505        """ Copy values of some fields to new object and redirect old references """
506        allowed_types={'LeMillReference':'content','Tool':'tools','Activity':'methods','MultimediaMaterial':'content'}
507        plone_utils=getToolByName(self, 'plone_utils')
508
509        # Check if we have everything we need and raise error if not
510        from_obj_id=REQUEST.get('from_obj_id', '')
511        to_obj_type=REQUEST.get('to_obj_type', '')
512        trial_run=REQUEST.get('trial_run', True)
513
514        if trial_run:
515            if trial_run=='False' or trial_run=='0':
516                trial_run=False
517
518        from_obj=getattr(self, from_obj_id)
519        if not from_obj:
520            raise "base object for resource conversion doesn't exist"
521
522        from_obj_type=from_obj.portal_type
523        if from_obj_type not in allowed_types.keys():
524            raise "cannot convert from type %s" % from_obj_type
525        if to_obj_type not in allowed_types.keys():
526            raise "cannot transfer to type %s" % to_obj_type
527
528        # Create to_obj
529        to_folder = getattr(self.aq_parent, allowed_types[to_obj_type])
530        to_obj = self._lemill_invokeFactory(to_folder, to_obj_type, do_create=True)
531
532        from_schema=from_obj.schema
533        to_schema=to_obj.schema
534         
535        import copy
536        ignored_fields=['translation', 'translation_of','id','groups']
537
538        # trial run, report fields that have content but cannot be converted
539        if trial_run:
540            problems=False
541            for k in from_schema.keys():
542                from_accessor = from_schema[k].getEditAccessor(from_obj)
543                if k not in ignored_fields and  k not in to_schema.keys() and from_accessor and from_accessor():
544                    #stupid exceptions
545                    if k=='address' and from_accessor()=='http://':
546                        continue
547                    if k=='address' and 'location' in to_schema.keys():
548                        continue
549                    if k=='location' and 'address' in to_schema.keys():
550                        continue
551                    if k=='video' and len(from_accessor())<5:
552                        continue
553                    problems=True
554                    plone_utils.addPortalMessage(_(u'Cannot convert %s.' % k))
555            to_folder._delObject(to_obj.id)
556            if not problems:
557                plone_utils.addPortalMessage(_(u"Checked conversion and it will be fine. Click 'Convert resource' to do the conversion."))
558            if problems:
559                plone_utils.addPortalMessage(_(u"Indicated fields have text that cannot be copied to other resource type. Click 'Convert resource' if you want to do the conversion anyway."))
560            return REQUEST.RESPONSE.redirect('%s/manage_convert?trial_run=False&from_obj_id=%s&to_obj_type=%s' % (from_obj.absolute_url(), from_obj.id, to_obj_type))
561
562
563        # Helper method for copying fields
564        def copyvalue(from_accessor, to_mutator):
565            if not from_accessor:
566                return
567            val = from_accessor()
568            if k=='bodyText' and from_obj_type=='MultimediaMaterial':
569                val=from_obj.getOnlyText()
570            copied_val = None
571            try:
572                copied_val = copy.copy(val)
573            except TypeError:
574                copied_val = copy.copy(val.aq_base)
575            to_mutator(copied_val)
576
577        # Copy fields with same name
578        for k in from_schema.keys():
579            # list all fields here that shouldn't be copyied to new object
580            if k not in to_schema.keys() or k in ignored_fields:
581                continue
582            from_accessor = from_schema[k].getEditAccessor(from_obj)
583            to_mutator = to_schema[k].getMutator(to_obj)
584            copyvalue(from_accessor, to_mutator)
585
586        # Check convertable pairs of exceptions:
587        for (k,l) in [('address','location')]:
588            if k in from_schema.keys() and l in to_schema.keys():
589                from_accessor = from_schema[k].getEditAccessor(from_obj)
590                to_mutator = to_schema[l].getMutator(to_obj)
591                copyvalue(from_accessor, to_mutator)
592            elif l in from_schema.keys() and k in to_schema.keys():
593                from_accessor = from_schema[l].getEditAccessor(from_obj)
594                to_mutator = to_schema[k].getMutator(to_obj)
595                copyvalue(from_accessor, to_mutator)
596
597        # LeMillReferences use descriptions instead of bodytexts while they still have bodytexts:
598        if to_obj_type=='LeMillReference':
599            from_accessor=from_schema['bodyText'].getEditAccessor(from_obj)
600            to_mutator = to_schema['description'].getMutator(to_obj)
601            copyvalue(from_accessor, to_mutator)
602        if from_obj_type=='LeMillReference':
603            from_accessor=from_schema['description'].getEditAccessor(from_obj)
604            to_mutator = to_schema['bodyText'].getMutator(to_obj)
605            copyvalue(from_accessor, to_mutator)
606
607
608        # Look for references to this object
609        rc=getToolByName(self, 'reference_catalog')
610        uc=getToolByName(self, 'uid_catalog')
611        results=rc({'targetUID':from_obj.UID()})
612
613        # Get object with certain reference and fix it
614        for refobj in results:
615            res=uc({'UID':refobj.sourceUID})
616            if res:
617                obj=res[0].getObject()
618                if refobj.relationship=='relatesToContent':
619                    obj.delContent(from_obj_id)
620                elif refobj.relationship=='relatesToMethods':
621                    obj.delMethods(from_obj_id)
622                elif refobj.relationship=='relatesToTools':
623                    obj.delTools(from_obj_id)
624                if obj.portal_type=='Collection':
625                    obj.addRefsToResources(to_obj.UID())
626
627        # Copy history
628        from_history=from_obj.getHistory()
629        to_obj.setHistory(copy.copy(from_history))
630
631        # Run post_edits
632        to_obj.post_edit_rename()
633        to_obj.recalculateAuthors()
634        to_obj.recalculateScore()
635        to_obj.reindexObject()
636
637        # Delete old object
638        self._delObject(from_obj_id)
639
640        # Return new object
641        plone_utils.addPortalMessage(_(u'Resource converted succesfully.'))       
642        if to_obj.portal_type in MATERIAL_TYPES:
643            return REQUEST.RESPONSE.redirect('%s/view' % to_obj.absolute_url())           
644        else:
645            return REQUEST.RESPONSE.redirect(to_obj.absolute_url())           
646
647
648
649
650
651class LargeContentFolder(LargeSectionFolder):
652
653    archetype_name = "Large Content Folder"
654    meta_type = "Large Content Folder"
655
656    allowed_content_types = CONTENT_TYPES +('Topic','Redirector')
657    default_view = ('lemill_content_view')
658    filter_content_types = True
659    security = ClassSecurityInfo()
660
661
662    security.declareProtected(MANAGE_PORTAL, 'recalculate_all_authors')
663    def recalculate_all_authors(self, REQUEST=None):
664        """run private recalc script"""
665        for o in  self.objectValues(CONTENT_TYPES):
666            o.recalculateAuthors()
667        if REQUEST:
668            return REQUEST.RESPONSE.redirect(self.absolute_url())
669
670
671    def getSelectables(self, results):
672        """Try to find which of languages and target groups are selectable"""
673        lang_dict = getToolByName(self, 'lemill_tool').language_dict
674        langs={}
675        targs={}
676        types={}
677        subjs={}
678        tags={}
679        # Create dictionaries
680        for r in results:
681            types[r.portal_type]=types.get(r.portal_type,0)+1
682            rL=r.Language
683            if rL:
684                langs[rL]=langs.get(rL,0)+1
685            if r.getTarget_group:
686                for s in r.getTarget_group:
687                    targs[s]=targs.get(s,0)+1
688            if r.getSubject_area:
689                for s in r.getSubject_area:
690                    subjs[s]=subjs.get(s,0)+1
691            if r.getTags:
692                for s in r.getTags:
693                    tags[s]=tags.get(s,0)+1
694
695        # Convert them to tuples where (value, display value)
696        langlist=[(lang_dict[x], x, y) for (x,y) in langs.items()]
697        targlist=[(x,x,y) for (x,y) in targs.items()]
698        typelist=[(TYPE_NAMES[x][0],x, y) for (x,y) in types.items()]
699        subjslist=[(x,x,y) for (x,y) in subjs.items()]
700        tagslist=[(x,x,y) for (x,y) in tags.items()]
701        langlist.sort()
702        targlist.sort()
703        typelist.sort()
704        subjslist.sort()
705        tagslist.sort()
706        return {'language':langlist, 'target_group':targlist, 'type':typelist, 'subject_area':subjslist, 'tags':tagslist}
707       
708    def getBrowseArguments(self, request):
709        """ Gets browsing state from arguments and give mapping between visible names and catalog variables """
710        argdict={}
711        has_args=False
712        source=request.form       
713        goodargs={'Language':'language',
714            'getTarget_group':'target_group',
715            'getTags':'tags',
716            'portal_type':'type',
717            'getSubject_area':'subject_area'}
718        for key in source.keys():
719            if key in goodargs.keys() and source[key]:
720                has_args=True
721                argdict[goodargs[key]]=source[key]
722        return {'has_args':has_args,'argdict':argdict, 'tags':'getTags','target_group':'getTarget_group','language':'Language','type':'portal_type', 'subject_area':'getSubject_area',
723        'resources_tags':'Resource', 'pieces_tags':'Piece','references_tags':'Reference'} 
724
725    def getTemplates(self, aslist=False):
726        if not aslist:
727            return TEMPLATES
728        else:           
729            # as list = ordered list of dictionaries, original key is under key 'keyname'
730            rl=[(value['order'], key, value) for (key,value) in TEMPLATES.items()]
731            rl.sort()
732            resl=[]
733            for (order, key, value) in rl:
734                value['keyname']=key
735                resl.append(value)
736            return resl
737
738
739    def getTemplate(self, template_id):
740        return TEMPLATES.get(template_id, None)
741
742
743    security.declareProtected(ADD_CONTENT_PERMISSION,'lemidlet_post')
744    def lemidlet_post(self, REQUEST):
745        """ LeMidlet will post image here...."""
746        #print REQUEST.file.read()
747        file = REQUEST.get('file')
748        if file==None:
749            return 'file not found'       
750        description = REQUEST.get('description')
751        type = 'Piece'
752        new = self._lemill_invokeFactory(self, type, id=type+str(id(self)), do_create=True)
753        new.edit(description=description, file=file.read(),language='',title=REQUEST.get('title'),tags=REQUEST.get('tags'))
754        return 0
755
756       
757class LargeActivityFolder(LargeSectionFolder):
758
759    archetype_name = "Large Activity Folder"
760    meta_type = "Large Activity Folder"
761
762    allowed_content_types = ('Activity','KB', 'Topic','Redirector')
763    default_view = ('lemill_activities_view')
764    filter_content_types = True
765
766    def getBrowseArguments(self, request):
767        """ Gets browsing state from arguments and give mapping between visible names and catalog variables """
768        argdict={}
769        has_args=False
770        source=request.form       
771        goodargs={'Language':'language',
772            'getTags':'tags'}
773        for key in source.keys():
774            if key in goodargs.keys() and source[key]:
775                has_args=True
776                argdict[goodargs[key]]=source[key]
777        return {'has_args':has_args, 'argdict':argdict, 'tags':'getTags', 'language':'Language'} 
778
779    def getSelectables(self, results):
780        """Try to find which of languages and tags are found in results"""
781        lang_dict = getToolByName(self, 'lemill_tool').language_dict
782        langs={}
783        tags={}
784        # Create dictionaries
785        for r in results:
786            rL=r.Language
787            if rL:
788                langs[rL]=langs.get(rL,0)+1
789            if r.getTags:
790                for s in r.getTags:
791                    tags[s]=tags.get(s,0)+1
792
793        # Convert them to tuples where (value, display value)
794        langlist=[(lang_dict[x], x, y) for (x,y) in langs.items()]
795        tagslist=[(x,x,y) for (x,y) in tags.items()]
796        langlist.sort()
797        tagslist.sort()
798        return {'language':langlist,'tags':tagslist}
799   
800class LargeToolFolder(LargeSectionFolder):
801
802    archetype_name = "Large Tool Folder"
803    meta_type = "Large Tool Folder"
804
805    allowed_content_types = ('Tool', 'Topic','Redirector')
806    default_view = ('lemill_tools_view')
807    filter_content_types = True
808
809    def getBrowseArguments(self, request):
810        """ Gets browsing state from arguments and give mapping between visible names and catalog variables """
811        argdict={}
812        has_args=False
813        source=request.form       
814        goodargs={'Language':'language',
815            'getTags':'tags'}
816        for key in source.keys():
817            if key in goodargs.keys() and source[key]:
818                has_args=True
819                argdict[goodargs[key]]=source[key]
820        return {'has_args':has_args, 'argdict':argdict, 'tags':'getTags', 'language':'Language'} 
821
822    def getSelectables(self, results):
823        """Try to find which of languages and tags are found in results"""
824        lang_dict = getToolByName(self, 'lemill_tool').language_dict
825        langs={}
826        tags={}
827        # Create dictionaries
828        for r in results:
829            rL=r.Language
830            if rL:
831                langs[rL]=langs.get(rL,0)+1
832            if r.getTags:
833                for s in r.getTags:
834                    tags[s]=tags.get(s,0)+1
835
836        # Convert them to tuples where (value, display value)
837        langlist=[(lang_dict[x], x, y) for (x,y) in langs.items()]
838        tagslist=[(x,x,y) for (x,y) in tags.items()]
839        langlist.sort()
840        tagslist.sort()
841        return {'language':langlist,'tags':tagslist}
842
843
844class LargeCommunityFolder(LargeSectionFolder):
845
846    archetype_name = "Large Community Folder"
847    meta_type = "Large Community Folder"
848
849    allowed_content_types = ('Topic','Redirector','MemberFolder','GroupBlog','ATBTreeFolder','Large Plone Folder')
850    default_view = ('lemill_community_view')
851    filter_content_types = False
852    security = ClassSecurityInfo()
853
854    schema=communityschema
855
856    ### If MemberFolder for logged in user does not exist, it is created here
857   
858    def my_page(self):
859        """ Checks if user has MemberFolder and creates one if not. Returns the folder url."""
860        mtool = getToolByName(self, "portal_membership")
861        member=mtool.getAuthenticatedMember()
862        if not member: return
863        if member.getHomeFolder()==None:
864            member.createMemberarea()           
865        folder=member.getHomeFolder()
866        if not hasattr(folder.aq_base,'collections'):
867            folder.invokeFactory('CollectionsFolder', id='collections')
868        return folder.absolute_url()   
869
870    def mergeLatestPostsInMyGroups(self):
871        mtool = getToolByName(self, "portal_membership")
872        gtool = getToolByName(self, "portal_groups")
873        member=mtool.getAuthenticatedMember()
874        memberid=member.getId()
875        glist = self.lemill_usertool.getGroupsList(memberid);
876        recents=[]
877        for group in glist:
878            gname= group.getGroupName()
879            garea= gtool.getGroupareaFolder(gname)
880            grecent= garea.getRecent_posts()
881            for postid in grecent:
882                try:
883                    post=garea._getOb(postid)
884                    recents.append((post.CreationDate(),post))
885                except AttributeError:
886                    # do some cleaning:
887                    garea.removeRecent_post(postid)
888        recents.sort()
889        recents = [x[1] for x in recents]
890        recents.reverse()
891        return recents[:20]
892                                   
893    def getCollections(self, obj_uid=None):
894        """ Show collections where object is used."""
895        if not obj_uid:
896            return []
897        res = []
898        q = { 'targetUID': obj_uid }
899        qres = self.reference_catalog(q)
900        for q in qres:
901            v = self.reference_catalog.lookupObject(q.UID)
902            if v:
903                source = v.getSourceObject()
904                if source.meta_type == 'Collection':
905                    res.append(source)
906        return res
907
908    def getSelectablesForMembers(self, results):
909        """Try to find which of languages and target groups are selectable"""
910        lang_dict = getToolByName(self, 'lemill_tool').language_dict
911        langs={}
912        subjs={}
913        locas={}
914        skills={}
915        interests={}
916        # Create dictionaries
917        for r in results:
918            if r.getLanguage_skills:
919                for s in r.getLanguage_skills:
920                    langs[s]=langs.get(s,0)+1
921            if r.getSubject_area:
922                for s in r.getSubject_area:
923                    subjs[s]=subjs.get(s,0)+1
924            rLc=r.getLocation_country
925            if rLc:
926                locas[rLc]=locas.get(rLc,0)+1
927            if r.getSkills:
928                for s in r.getSkills:
929                    skills[s]=skills.get(s,0)+1
930            if r.getInterests:
931                for s in r.getInterests:
932                    interests[s]=interests.get(s,0)+1
933
934                   
935        # Convert them to tuples where (value, display value)
936        langlist=[(lang_dict[x], x, y) for (x,y) in langs.items()]
937        subjslist=[(x,x,y) for (x,y) in subjs.items()]
938        locaslist=[(x,x,y) for (x,y) in locas.items()]
939        skillslist=[(x,x,y) for (x,y) in skills.items()]
940        interestslist=[(x,x,y) for (x,y) in interests.items()]
941        langlist.sort()
942        subjslist.sort()
943        locaslist.sort()
944        skillslist.sort()
945        interestslist.sort()
946        return {'language_skills':langlist, 'subject_area':subjslist, 'location_country':locaslist,'skills':skillslist,'interests':interestslist}
947       
948    def getBrowseArgumentsForMembers(self, request):
949        """ Gets browsing state from arguments and give mapping between visible names and catalog variables """
950        argdict={}
951        has_args=False
952        source=request.form       
953        goodargs={'getLanguage_skills':'language_skills',
954            'getSkills':'skills',
955            'getInterests':'interests',
956            'getLocation_country':'location_country',
957            'getSubject_area':'subject_area'}
958        for key in source.keys():
959            if key in goodargs.keys() and source[key]:
960                has_args=True
961                argdict[goodargs[key]]=source[key]
962        return {'has_args':has_args,'argdict':argdict, 'language_skills':'getLanguage_skills','skills':'getSkills','interests':'getInterests','location_country':'getLocation_country', 'subject_area':'getSubject_area'} 
963
964    def getBrowseArgumentsForGroups(self, request):
965        """ Gets browsing state from arguments and give mapping between visible names and catalog variables """
966        argdict={}
967        has_args=False
968        source=request.form       
969        goodargs={'getLanguage_skills':'language_skills',
970            'getTags':'tags',
971            'getSubject_area':'group_subject_area'}
972        for key in source.keys():
973            if key in goodargs.keys() and source[key]:
974                has_args=True
975                argdict[goodargs[key]]=source[key]
976        return {'has_args':has_args, 'argdict':argdict, 'tags':'getTags', 'language_skills':'getLanguage_skills', 'group_subject_area':'getSubject_area'} 
977
978    def getSelectablesForGroups(self, results):
979        """Try to find which of languages are found in results"""
980        lang_dict = getToolByName(self, 'lemill_tool').language_dict
981        langs={}
982        subjs={}
983        tags={}
984        # Create dictionaries
985        for r in results:
986            if r.getLanguage_skills:
987                for s in r.getLanguage_skills:
988                    langs[s]=langs.get(s,0)+1
989            if r.getSubject_area:
990                for s in r.getSubject_area:
991                    subjs[s]=subjs.get(s,0)+1
992            if r.getTags:
993                for s in r.getTags:
994                    tags[s]=tags.get(s,0)+1
995
996        # Convert them to tuples where (value, display value)
997        langlist=[(lang_dict[x], x, y) for (x,y) in langs.items()]
998        subjslist=[(x,x,y) for (x,y) in subjs.items()]
999        tagslist=[(x,x,y) for (x,y) in tags.items()]
1000        langlist.sort()
1001        subjslist.sort()
1002        tagslist.sort()
1003        return {'language_skills':langlist, 'group_subject_area':subjslist,'tags':tagslist}
1004
1005    def getBrowseArgumentsForPortfolio(self, request):
1006        """ Gets browsing state from arguments and give mapping between visible names and catalog variables """
1007        argdict={}
1008        has_args=False
1009        source=request.form
1010        creatorstring=''       
1011        goodargs={'portal_type':'type',
1012            'getTags':'tags'}
1013        for key in source.keys():
1014            if key in goodargs.keys() and source[key]:
1015                has_args=True
1016                argdict[goodargs[key]]=source[key]
1017            if key=='Creator':
1018                argdict['Creator']=source['Creator']
1019                creatorstring='&Creator=%s' % source['Creator']
1020        return {'has_args':has_args, 'argdict':argdict, 'tags':'getTags', 'type':'portal_type', 'creatorstring':creatorstring} 
1021
1022    def getSelectablesForPortfolio(self, results):
1023        """Try to find which types are found in results and show them as selectables """
1024        types={}
1025        tags={}
1026        # Create dictionaries
1027        for r in results:
1028            types[r.portal_type]=types.get(r.portal_type,0)+1
1029            if r.getTags:
1030                for s in r.getTags:
1031                    tags[s]=tags.get(s,0)+1
1032        # Convert them to tuples where (value, display value)
1033        types=[(x, x, y) for (x,y) in types.items()]
1034        tagslist=[(x,x,y) for (x,y) in tags.items()]
1035        tagslist.sort()
1036        return {'type':types,'tags':tagslist}
1037
1038
1039
1040class LargeTrashFolder(LargeSectionFolder):
1041
1042    archetype_name = "Large Trash Folder"
1043    meta_type = "Large Trash Folder"
1044
1045    allowed_content_types = ALL_CONTENT_TYPES
1046    filter_content_types = False
1047    default_view = ('lemill_trash_view')
1048    security = ClassSecurityInfo()
1049
1050       
1051registerType(LargeContentFolder, PROJECTNAME)
1052registerType(LargeActivityFolder, PROJECTNAME)
1053registerType(LargeToolFolder, PROJECTNAME)
1054registerType(LargeCommunityFolder, PROJECTNAME)
1055registerType(LargeTrashFolder, PROJECTNAME)
Note: See TracBrowser for help on using the repository browser.