source: trunk/LargeSectionFolder.py @ 1930

Revision 1930, 42.0 KB checked in by jukka, 12 years ago (diff)

Fixed tests and other stuff, fixed #1376, closed #1420.

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    security.declareProtected(MANAGE_PORTAL, 'recalculate_all_scores')
483    def recalculate_all_scores(self, REQUEST=None):
484        """run private recalc script"""
485        for o in self.objectValues(SEARCHABLE_TYPES):
486            o.recalculateScore()
487            print '%s : %s' % (o.id, o.score)
488        if REQUEST:
489            return REQUEST.RESPONSE.redirect(self.absolute_url())
490
491
492
493    #################################
494    ### Resource conversion stuff ###
495    #################################
496
497
498    security.declareProtected(MANAGE_PORTAL, 'convertResource')
499    def convertResource(self, REQUEST):
500        """ Copy values of some fields to new object and redirect old references """
501        allowed_types={'LeMillReference':'content','Tool':'tools','Activity':'methods','MultimediaMaterial':'content'}
502        plone_utils=getToolByName(self, 'plone_utils')
503
504        # Check if we have everything we need and raise error if not
505        from_obj_id=REQUEST.get('from_obj_id', '')
506        to_obj_type=REQUEST.get('to_obj_type', '')
507        trial_run=REQUEST.get('trial_run', True)
508
509        if trial_run:
510            if trial_run=='False' or trial_run=='0':
511                trial_run=False
512
513        from_obj=getattr(self, from_obj_id)
514        if not from_obj:
515            raise "base object for resource conversion doesn't exist"
516
517        from_obj_type=from_obj.portal_type
518        if from_obj_type not in allowed_types.keys():
519            raise "cannot convert from type %s" % from_obj_type
520        if to_obj_type not in allowed_types.keys():
521            raise "cannot transfer to type %s" % to_obj_type
522
523        # Create to_obj
524        to_folder = getattr(self.aq_parent, allowed_types[to_obj_type])
525        to_obj = self._lemill_invokeFactory(to_folder, to_obj_type, do_create=True)
526
527        from_schema=from_obj.schema
528        to_schema=to_obj.schema
529         
530        import copy
531        ignored_fields=['translation', 'translation_of','id','groups']
532
533        # trial run, report fields that have content but cannot be converted
534        if trial_run:
535            problems=False
536            for k in from_schema.keys():
537                from_accessor = from_schema[k].getEditAccessor(from_obj)
538                if k not in ignored_fields and  k not in to_schema.keys() and from_accessor and from_accessor():
539                    #stupid exceptions
540                    if k=='address' and from_accessor()=='http://':
541                        continue
542                    if k=='address' and 'location' in to_schema.keys():
543                        continue
544                    if k=='location' and 'address' in to_schema.keys():
545                        continue
546                    if k=='video' and len(from_accessor())<5:
547                        continue
548                    problems=True
549                    plone_utils.addPortalMessage(_(u'Cannot convert %s.' % k))
550            to_folder._delObject(to_obj.id)
551            if not problems:
552                plone_utils.addPortalMessage(_(u"Checked conversion and it will be fine. Click 'Convert resource' to do the conversion."))
553            if problems:
554                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."))
555            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))
556
557
558        # Helper method for copying fields
559        def copyvalue(from_accessor, to_mutator):
560            if not from_accessor:
561                return
562            val = from_accessor()
563            if k=='bodyText' and from_obj_type=='MultimediaMaterial':
564                val=from_obj.getOnlyText()
565            copied_val = None
566            try:
567                copied_val = copy.copy(val)
568            except TypeError:
569                copied_val = copy.copy(val.aq_base)
570            to_mutator(copied_val)
571
572        # Copy fields with same name
573        for k in from_schema.keys():
574            # list all fields here that shouldn't be copyied to new object
575            if k not in to_schema.keys() or k in ignored_fields:
576                continue
577            from_accessor = from_schema[k].getEditAccessor(from_obj)
578            to_mutator = to_schema[k].getMutator(to_obj)
579            copyvalue(from_accessor, to_mutator)
580
581        # Check convertable pairs of exceptions:
582        for (k,l) in [('address','location')]:
583            if k in from_schema.keys() and l in to_schema.keys():
584                from_accessor = from_schema[k].getEditAccessor(from_obj)
585                to_mutator = to_schema[l].getMutator(to_obj)
586                copyvalue(from_accessor, to_mutator)
587            elif l in from_schema.keys() and k in to_schema.keys():
588                from_accessor = from_schema[l].getEditAccessor(from_obj)
589                to_mutator = to_schema[k].getMutator(to_obj)
590                copyvalue(from_accessor, to_mutator)
591
592        # LeMillReferences use descriptions instead of bodytexts while they still have bodytexts:
593        if to_obj_type=='LeMillReference':
594            from_accessor=from_schema['bodyText'].getEditAccessor(from_obj)
595            to_mutator = to_schema['description'].getMutator(to_obj)
596            copyvalue(from_accessor, to_mutator)
597        if from_obj_type=='LeMillReference':
598            from_accessor=from_schema['description'].getEditAccessor(from_obj)
599            to_mutator = to_schema['bodyText'].getMutator(to_obj)
600            copyvalue(from_accessor, to_mutator)
601
602
603        # Look for references to this object
604        rc=getToolByName(self, 'reference_catalog')
605        uc=getToolByName(self, 'uid_catalog')
606        results=rc({'targetUID':from_obj.UID()})
607
608        # Get object with certain reference and fix it
609        for refobj in results:
610            res=uc({'UID':refobj.sourceUID})
611            if res:
612                obj=res[0].getObject()
613                if refobj.relationship=='relatesToContent':
614                    obj.delContent(from_obj_id)
615                elif refobj.relationship=='relatesToMethods':
616                    obj.delMethods(from_obj_id)
617                elif refobj.relationship=='relatesToTools':
618                    obj.delTools(from_obj_id)
619                if obj.portal_type=='Collection':
620                    obj.addRefsToResources(to_obj.UID())
621
622        # Copy history
623        from_history=from_obj.getHistory()
624        to_obj.setHistory(copy.copy(from_history))
625
626        # Run post_edits
627        to_obj.post_edit_rename()
628        to_obj.recalculateAuthors()
629        to_obj.recalculateScore()
630        to_obj.reindexObject()
631
632        # Delete old object
633        self._delObject(from_obj_id)
634
635        # Return new object
636        plone_utils.addPortalMessage(_(u'Resource converted succesfully.'))       
637        if to_obj.portal_type in MATERIAL_TYPES:
638            return REQUEST.RESPONSE.redirect('%s/view' % to_obj.absolute_url())           
639        else:
640            return REQUEST.RESPONSE.redirect(to_obj.absolute_url())           
641
642
643
644
645
646class LargeContentFolder(LargeSectionFolder):
647
648    archetype_name = "Large Content Folder"
649    meta_type = "Large Content Folder"
650
651    allowed_content_types = CONTENT_TYPES +('Topic','Redirector')
652    default_view = ('lemill_content_view')
653    filter_content_types = True
654    security = ClassSecurityInfo()
655
656
657    security.declareProtected(MANAGE_PORTAL, 'recalculate_all_authors')
658    def recalculate_all_authors(self, REQUEST=None):
659        """run private recalc script"""
660        for o in  self.objectValues(CONTENT_TYPES):
661            o.recalculateAuthors()
662        if REQUEST:
663            return REQUEST.RESPONSE.redirect(self.absolute_url())
664
665
666    def getSelectables(self, results):
667        """Try to find which of languages and target groups are selectable"""
668        lang_dict = getToolByName(self, 'lemill_tool').language_dict
669        langs={}
670        targs={}
671        types={}
672        subjs={}
673        tags={}
674        # Create dictionaries
675        for r in results:
676            types[r.portal_type]=types.get(r.portal_type,0)+1
677            rL=r.Language
678            if rL:
679                langs[rL]=langs.get(rL,0)+1
680            if r.getTarget_group:
681                for s in r.getTarget_group:
682                    targs[s]=targs.get(s,0)+1
683            if r.getSubject_area:
684                for s in r.getSubject_area:
685                    subjs[s]=subjs.get(s,0)+1
686            if r.getTags:
687                for s in r.getTags:
688                    tags[s]=tags.get(s,0)+1
689
690        # Convert them to tuples where (value, display value)
691        langlist=[(lang_dict[x], x, y) for (x,y) in langs.items()]
692        targlist=[(x,x,y) for (x,y) in targs.items()]
693        typelist=[(TYPE_NAMES[x][0],x, y) for (x,y) in types.items()]
694        subjslist=[(x,x,y) for (x,y) in subjs.items()]
695        tagslist=[(x,x,y) for (x,y) in tags.items()]
696        langlist.sort()
697        targlist.sort()
698        typelist.sort()
699        subjslist.sort()
700        tagslist.sort()
701        return {'language':langlist, 'target_group':targlist, 'type':typelist, 'subject_area':subjslist, 'tags':tagslist}
702       
703    def getBrowseArguments(self, request):
704        """ Gets browsing state from arguments and give mapping between visible names and catalog variables """
705        argdict={}
706        has_args=False
707        source=request.form       
708        goodargs={'Language':'language',
709            'getTarget_group':'target_group',
710            'getTags':'tags',
711            'portal_type':'type',
712            'getSubject_area':'subject_area'}
713        for key in source.keys():
714            if key in goodargs.keys() and source[key]:
715                has_args=True
716                argdict[goodargs[key]]=source[key]
717        return {'has_args':has_args,'argdict':argdict, 'tags':'getTags','target_group':'getTarget_group','language':'Language','type':'portal_type', 'subject_area':'getSubject_area',
718        'resources_tags':'Resource', 'pieces_tags':'Piece','references_tags':'Reference'} 
719
720    def getTemplates(self, aslist=False):
721        if not aslist:
722            return TEMPLATES
723        else:           
724            # as list = ordered list of dictionaries, original key is under key 'keyname'
725            rl=[(value['order'], key, value) for (key,value) in TEMPLATES.items()]
726            rl.sort()
727            resl=[]
728            for (order, key, value) in rl:
729                value['keyname']=key
730                resl.append(value)
731            return resl
732
733
734    def getTemplate(self, template_id):
735        return TEMPLATES.get(template_id, None)
736
737
738    security.declareProtected(ADD_CONTENT_PERMISSION,'lemidlet_post')
739    def lemidlet_post(self, REQUEST):
740        """ LeMidlet will post image here...."""
741        #print REQUEST.file.read()
742        file = REQUEST.get('file')
743        if file==None:
744            return 'file not found'       
745        description = REQUEST.get('description')
746        type = 'Piece'
747        new = self._lemill_invokeFactory(self, type, id=type+str(id(self)), do_create=True)
748        new.edit(description=description, file=file.read(),language='',title=REQUEST.get('title'),tags=REQUEST.get('tags'))
749        return 0
750
751       
752class LargeActivityFolder(LargeSectionFolder):
753
754    archetype_name = "Large Activity Folder"
755    meta_type = "Large Activity Folder"
756
757    allowed_content_types = ('Activity','KB', 'Topic','Redirector')
758    default_view = ('lemill_activities_view')
759    filter_content_types = True
760
761    def getBrowseArguments(self, request):
762        """ Gets browsing state from arguments and give mapping between visible names and catalog variables """
763        argdict={}
764        has_args=False
765        source=request.form       
766        goodargs={'Language':'language',
767            'getTags':'tags'}
768        for key in source.keys():
769            if key in goodargs.keys() and source[key]:
770                has_args=True
771                argdict[goodargs[key]]=source[key]
772        return {'has_args':has_args, 'argdict':argdict, 'tags':'getTags', 'language':'Language'} 
773
774    def getSelectables(self, results):
775        """Try to find which of languages and tags are found in results"""
776        lang_dict = getToolByName(self, 'lemill_tool').language_dict
777        langs={}
778        tags={}
779        # Create dictionaries
780        for r in results:
781            rL=r.Language
782            if rL:
783                langs[rL]=langs.get(rL,0)+1
784            if r.getTags:
785                for s in r.getTags:
786                    tags[s]=tags.get(s,0)+1
787
788        # Convert them to tuples where (value, display value)
789        langlist=[(lang_dict[x], x, y) for (x,y) in langs.items()]
790        tagslist=[(x,x,y) for (x,y) in tags.items()]
791        langlist.sort()
792        tagslist.sort()
793        return {'language':langlist,'tags':tagslist}
794   
795class LargeToolFolder(LargeSectionFolder):
796
797    archetype_name = "Large Tool Folder"
798    meta_type = "Large Tool Folder"
799
800    allowed_content_types = ('Tool', 'Topic','Redirector')
801    default_view = ('lemill_tools_view')
802    filter_content_types = True
803
804    def getBrowseArguments(self, request):
805        """ Gets browsing state from arguments and give mapping between visible names and catalog variables """
806        argdict={}
807        has_args=False
808        source=request.form       
809        goodargs={'Language':'language',
810            'getTags':'tags'}
811        for key in source.keys():
812            if key in goodargs.keys() and source[key]:
813                has_args=True
814                argdict[goodargs[key]]=source[key]
815        return {'has_args':has_args, 'argdict':argdict, 'tags':'getTags', 'language':'Language'} 
816
817    def getSelectables(self, results):
818        """Try to find which of languages and tags are found in results"""
819        lang_dict = getToolByName(self, 'lemill_tool').language_dict
820        langs={}
821        tags={}
822        # Create dictionaries
823        for r in results:
824            rL=r.Language
825            if rL:
826                langs[rL]=langs.get(rL,0)+1
827            if r.getTags:
828                for s in r.getTags:
829                    tags[s]=tags.get(s,0)+1
830
831        # Convert them to tuples where (value, display value)
832        langlist=[(lang_dict[x], x, y) for (x,y) in langs.items()]
833        tagslist=[(x,x,y) for (x,y) in tags.items()]
834        langlist.sort()
835        tagslist.sort()
836        return {'language':langlist,'tags':tagslist}
837
838
839class LargeCommunityFolder(LargeSectionFolder):
840
841    archetype_name = "Large Community Folder"
842    meta_type = "Large Community Folder"
843
844    allowed_content_types = ('Topic','Redirector','MemberFolder','GroupBlog','ATBTreeFolder','Large Plone Folder')
845    default_view = ('lemill_community_view')
846    filter_content_types = False
847    security = ClassSecurityInfo()
848
849    schema=communityschema
850
851    ### If MemberFolder for logged in user does not exist, it is created here
852   
853    def my_page(self):
854        """ Checks if user has MemberFolder and creates one if not. Returns the folder url."""
855        mtool = getToolByName(self, "portal_membership")
856        member=mtool.getAuthenticatedMember()
857        if not member: return
858        if member.getHomeFolder()==None:
859            member.createMemberarea()           
860        folder=member.getHomeFolder()
861        if not hasattr(folder.aq_base,'collections'):
862            folder.invokeFactory('CollectionsFolder', id='collections')
863        return folder.absolute_url()   
864
865    def getMemberFolderById(self,id):
866        """ sometimes it is easier to just get it directly from btreefolder """
867        return getattr(self, id, None)
868
869    def getGroupById(self,id):
870        """ sometimes it is easier to just get it directly from btreefolder """
871        return getattr(self, id, None)
872
873    def mergeLatestPostsInMyGroups(self):
874        mtool = getToolByName(self, "portal_membership")
875        memberfolder=mtool.getHomeFolder()
876        if not memberfolder:
877            return []
878        glist=memberfolder.getGroups(objects=True)
879        recents=[]
880        for group in glist:
881            grecent= group.getRecent_posts()
882            for postid in grecent:
883                try:
884                    post=group._getOb(postid)
885                    recents.append((post.CreationDate(),post))
886                except AttributeError:
887                    # do some cleaning:
888                    group.removeRecent_post(postid)
889        recents.sort()
890        recents = [x[1] for x in recents]
891        recents.reverse()
892        return recents[:20]
893                                   
894    def getCollections(self, obj_uid=None):
895        """ Show collections where object is used."""
896        if not obj_uid:
897            return []
898        res = []
899        q = { 'targetUID': obj_uid }
900        qres = self.reference_catalog(q)
901        for q in qres:
902            v = self.reference_catalog.lookupObject(q.UID)
903            if v:
904                source = v.getSourceObject()
905                if source.meta_type == 'Collection':
906                    res.append(source)
907        return res
908
909    def getSelectablesForMembers(self, results):
910        """Try to find which of languages and target groups are selectable"""
911        lang_dict = getToolByName(self, 'lemill_tool').language_dict
912        langs={}
913        subjs={}
914        locas={}
915        skills={}
916        interests={}
917        # Create dictionaries
918        for r in results:
919            if r.getLanguage_skills:
920                for s in r.getLanguage_skills:
921                    langs[s]=langs.get(s,0)+1
922            if r.getSubject_area:
923                for s in r.getSubject_area:
924                    subjs[s]=subjs.get(s,0)+1
925            rLc=r.getLocation_country
926            if rLc:
927                locas[rLc]=locas.get(rLc,0)+1
928            if r.getSkills:
929                for s in r.getSkills:
930                    skills[s]=skills.get(s,0)+1
931            if r.getInterests:
932                for s in r.getInterests:
933                    interests[s]=interests.get(s,0)+1
934
935                   
936        # Convert them to tuples where (value, display value)
937        langlist=[(lang_dict[x], x, y) for (x,y) in langs.items()]
938        subjslist=[(x,x,y) for (x,y) in subjs.items()]
939        locaslist=[(x,x,y) for (x,y) in locas.items()]
940        skillslist=[(x,x,y) for (x,y) in skills.items()]
941        interestslist=[(x,x,y) for (x,y) in interests.items()]
942        langlist.sort()
943        subjslist.sort()
944        locaslist.sort()
945        skillslist.sort()
946        interestslist.sort()
947        return {'language_skills':langlist, 'subject_area':subjslist, 'location_country':locaslist,'skills':skillslist,'interests':interestslist}
948       
949    def getBrowseArgumentsForMembers(self, request):
950        """ Gets browsing state from arguments and give mapping between visible names and catalog variables """
951        argdict={}
952        has_args=False
953        source=request.form       
954        goodargs={'getLanguage_skills':'language_skills',
955            'getSkills':'skills',
956            'getInterests':'interests',
957            'getLocation_country':'location_country',
958            'getSubject_area':'subject_area'}
959        for key in source.keys():
960            if key in goodargs.keys() and source[key]:
961                has_args=True
962                argdict[goodargs[key]]=source[key]
963        return {'has_args':has_args,'argdict':argdict, 'language_skills':'getLanguage_skills','skills':'getSkills','interests':'getInterests','location_country':'getLocation_country', 'subject_area':'getSubject_area'} 
964
965    def getBrowseArgumentsForGroups(self, request):
966        """ Gets browsing state from arguments and give mapping between visible names and catalog variables """
967        argdict={}
968        has_args=False
969        source=request.form       
970        goodargs={'getLanguage_skills':'language_skills',
971            'getTags':'tags',
972            'getSubject_area':'group_subject_area'}
973        for key in source.keys():
974            if key in goodargs.keys() and source[key]:
975                has_args=True
976                argdict[goodargs[key]]=source[key]
977        return {'has_args':has_args, 'argdict':argdict, 'tags':'getTags', 'language_skills':'getLanguage_skills', 'group_subject_area':'getSubject_area'} 
978
979    def getSelectablesForGroups(self, results):
980        """Try to find which of languages are found in results"""
981        lang_dict = getToolByName(self, 'lemill_tool').language_dict
982        langs={}
983        subjs={}
984        tags={}
985        # Create dictionaries
986        for r in results:
987            if r.getLanguage_skills:
988                for s in r.getLanguage_skills:
989                    langs[s]=langs.get(s,0)+1
990            if r.getSubject_area:
991                for s in r.getSubject_area:
992                    subjs[s]=subjs.get(s,0)+1
993            if r.getTags:
994                for s in r.getTags:
995                    tags[s]=tags.get(s,0)+1
996
997        # Convert them to tuples where (value, display value)
998        langlist=[(lang_dict[x], x, y) for (x,y) in langs.items()]
999        subjslist=[(x,x,y) for (x,y) in subjs.items()]
1000        tagslist=[(x,x,y) for (x,y) in tags.items()]
1001        langlist.sort()
1002        subjslist.sort()
1003        tagslist.sort()
1004        return {'language_skills':langlist, 'group_subject_area':subjslist,'tags':tagslist}
1005
1006    def getBrowseArgumentsForPortfolio(self, request):
1007        """ Gets browsing state from arguments and give mapping between visible names and catalog variables """
1008        argdict={}
1009        has_args=False
1010        source=request.form
1011        creatorstring=''       
1012        goodargs={'portal_type':'type',
1013            'getTags':'tags'}
1014        for key in source.keys():
1015            if key in goodargs.keys() and source[key]:
1016                has_args=True
1017                argdict[goodargs[key]]=source[key]
1018            if key=='Creator':
1019                argdict['Creator']=source['Creator']
1020                creatorstring='&Creator=%s' % source['Creator']
1021        return {'has_args':has_args, 'argdict':argdict, 'tags':'getTags', 'type':'portal_type', 'creatorstring':creatorstring} 
1022
1023    def getSelectablesForPortfolio(self, results):
1024        """Try to find which types are found in results and show them as selectables """
1025        types={}
1026        tags={}
1027        # Create dictionaries
1028        for r in results:
1029            types[r.portal_type]=types.get(r.portal_type,0)+1
1030            if r.getTags:
1031                for s in r.getTags:
1032                    tags[s]=tags.get(s,0)+1
1033        # Convert them to tuples where (value, display value)
1034        types=[(x, x, y) for (x,y) in types.items()]
1035        tagslist=[(x,x,y) for (x,y) in tags.items()]
1036        tagslist.sort()
1037        return {'type':types,'tags':tagslist}
1038
1039
1040
1041class LargeTrashFolder(LargeSectionFolder):
1042
1043    archetype_name = "Large Trash Folder"
1044    meta_type = "Large Trash Folder"
1045
1046    allowed_content_types = ALL_CONTENT_TYPES
1047    filter_content_types = False
1048    default_view = ('lemill_trash_view')
1049    security = ClassSecurityInfo()
1050
1051       
1052registerType(LargeContentFolder, PROJECTNAME)
1053registerType(LargeActivityFolder, PROJECTNAME)
1054registerType(LargeToolFolder, PROJECTNAME)
1055registerType(LargeCommunityFolder, PROJECTNAME)
1056registerType(LargeTrashFolder, PROJECTNAME)
Note: See TracBrowser for help on using the repository browser.