source: enpraxis.educommons/trunk/enpraxis/educommons/browser/__init__.py @ 384

Revision 384, 21.7 KB checked in by david, 4 years ago (diff)

updating licensing information

Line 
1##################################################################################
2#    Copyright (c) 2004-2009 Utah State University, All rights reserved.
3#    Portions copyright 2009 Massachusetts Institute of Technology, All rights reserved.
4#                                                                                 
5#    This program 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#    This program 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 this program; if not, write to the Free Software                 
17#    Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA   
18#                                                                                 
19##################################################################################
20
21__author__  = '''Brent Lambert, David Ray, Jon Thomas'''
22__version__   = '$ Revision 0.0 $'[11:-2]
23from zope.publisher.browser import BrowserView
24from zope.component import getUtility
25from zope.annotation.interfaces import IAnnotations
26from collective.contentlicensing.browser import RSSView as DefaultRSSView
27from collective.contentlicensing.browser import CopyrightBylineView as DefaultCopyrightBylineView
28from Products.CMFPlone.utils import getToolByName
29from enpraxis.educommons.utilities.interfaces import IECUtility
30from collective.contentlicensing.utilities.interfaces import IContentLicensingUtility
31from Products.Five.formlib.formbase import EditForm
32from urlparse import urlsplit
33from xml.dom import minidom
34from string import split, find
35import urllib
36from Acquisition import aq_base, aq_inner, aq_parent
37
38
39class ClearCopyrightField(BrowserView):
40    """ Render the additional cleared copyright field in the edit form  """
41    def __init__(self, context, request):
42        self.context = context
43        self.request = request
44
45    def getClearedCopyright(self):
46        """ Get the clear copyright value from the object  """
47        annotations = IAnnotations(self.context)
48        if annotations.has_key('eduCommons.clearcopyright'):
49            return annotations['eduCommons.clearcopyright']
50        else:
51            return
52
53class ChangeCopyrightForm(BrowserView):
54    """ Test  """
55    def __init__(self, context, request):
56        self.context = context
57        self.request = request
58
59class AccessibilityCompliantField(BrowserView):
60    """ Render the additional accessibility compliant field in the edit form  """
61    def __init__(self, context, request):
62        self.context = context
63        self.request = request
64
65    def getAccessibilityCompliant(self):
66        """ Get the Accessibility Compliant value from the object  """
67        annotations = IAnnotations(self.context)
68        if annotations.has_key('eduCommons.accessible'):
69            return annotations['eduCommons.accessible']
70        else:
71            return
72
73class ChangeAccessibleCompliantForm(BrowserView):
74    """ Test  """
75    def __init__(self, context, request):
76        self.context = context
77        self.request = request
78
79
80class SkinlessView(BrowserView):
81    """ Render a view without the CMS chrome  """
82
83    def getSkinlessView(self):
84        """ Set Titles based on type and get body  """
85       
86        if self.context.Type() in ['Page', 'Division']:
87            title = self.context.Title()
88            content = self.context.getText()
89        else:
90            #Get Full Course Title
91            portal_catalog = self.context.portal_catalog
92            brain = portal_catalog(Title=self.context.Title())[0]
93            self.ecutil = getUtility(IECUtility)
94            title = self.ecutil.getFullCourseTitle(brain)
95            content = self.context.getText()
96
97        return title, content
98
99class SortedCourseListingView(BrowserView):
100    """ Return Courses in the Dept sorted by full course name  """
101
102    def getSortedCourses(self):
103        """ Get Sorted Courses  """
104   
105        self.ecutil = getUtility(IECUtility)
106        portal_catalog = self.context.portal_catalog
107        brains = portal_catalog(path= {'query':'/'.join(self.context.getPhysicalPath())+'/', 'depth':2}, portal_type='Course')
108
109        brains = list(brains)
110        brains.sort(lambda x, y : cmp(self.ecutil.getFullCourseTitle(x),self.ecutil.getFullCourseTitle(y)))
111
112        return brains
113
114class SortedCrossCourseListingView(BrowserView):
115    """ Return Cross listed Courses in the Dept sorted by full course name  """
116
117    def getSortedCrossCourses(self):
118        """ Get Sorted Cross Listed Courses  """
119   
120        self.ecutil = getUtility(IECUtility)
121        portal_catalog = self.context.portal_catalog
122        portal = self.context.portal_url.getPortalObject()
123        brains = portal_catalog(path= {'query':'/'.join(portal.getPhysicalPath())+'/'}, portal_type='Course')
124
125        crosslisted_courses = []
126        for brain in brains:
127            obj = brain.getObject()
128            if self.context.id in obj.crosslisting:
129                crosslisted_courses += [brain]
130        crosslisted_courses = list(crosslisted_courses)
131        crosslisted_courses.sort(lambda x, y : cmp(self.ecutil.getFullCourseTitle(x),self.ecutil.getFullCourseTitle(y)))
132
133        return crosslisted_courses
134
135class SortedResourceListingView(BrowserView):
136    """ Return Non-Course objects in the Dept sorted by name  """
137
138    def getSortedResources(self):
139        """ Get Sorted Resources  """
140        resources = []
141        brains = self.context.getFolderContents()
142        for brain in brains:
143            if 'Course' != brain.portal_type and brain.getObject().getExcludeFromNav() == False:
144                resources += [brain]
145           
146        resources = list(resources)
147
148        resources.sort(lambda x, y : cmp(x.id, y.id))
149
150        return resources
151
152
153class PositionView(BrowserView):
154
155    def __call__(self):
156        context = self.context
157        position = self.request['position']
158        id = self.request['id']
159        url = self.request['url']
160       
161        if position == 'up':
162            self.moveUp(context, position, id, url)
163        elif position == 'down':
164            self.moveDown(context, position, id, url)
165        else:
166            return
167
168
169    def moveUp(self, context, position, id, path):
170        objs = self.getNavObjects(context)
171
172        if len(objs) <= 1:
173            return
174
175        if objs[0].getPath() == path:
176            return
177
178        prev_obj = objs[0]
179
180        for obj in objs[1:]:
181            if path == obj.getPath():
182                self.swapPosition(obj.getObject(), prev_obj.getObject())
183                break
184
185            prev_obj = obj
186
187        context.request.response.redirect('order_courseobjs')
188               
189
190    def moveDown(self, context, position, id,path):
191        objs = self.getNavObjects(context)
192       
193        if len(objs) <= 1:
194            return
195
196        prev_obj = None
197        index = 0
198        for obj in objs:
199
200            if len(objs) == index:
201                return
202
203            if prev_obj:
204                self.swapPosition(obj.getObject(), prev_obj.getObject())
205                break
206            if path == obj.getPath():
207                prev_obj = obj
208
209            index += 1
210
211        context.request.response.redirect('order_courseobjs')
212
213    def swapPosition(self, cur_obj, swp_obj):
214        tmp_pos = IAnnotations(cur_obj)['eduCommons.objPositionInCourse']
215        IAnnotations(cur_obj)['eduCommons.objPositionInCourse'] = IAnnotations(swp_obj)['eduCommons.objPositionInCourse']
216        IAnnotations(swp_obj)['eduCommons.objPositionInCourse'] = tmp_pos
217        cur_obj.reindexObject()
218        swp_obj.reindexObject()
219       
220    def getNavObjects(self, context):
221        contentFilter={'path':{'query':'/'.join(context.getPhysicalPath())+'/'},'sort_on':'getObjPositionInCourse'}
222        brains = context.portal_catalog.searchResults(contentFilter)
223        return [brain for brain in brains if not getattr(brain.aq_explicit, 'exclude_from_nav', True)]
224
225class RSSView(DefaultRSSView):
226    """ Implements eduCommons RSS view """
227
228    def getRSSObjects(self):
229        """ Get RSS objects. """
230        if self.context.Type() in ['Division', 'Course']:
231            syn = self.context.portal_syndication
232            objs = list(syn.getSyndicatableContent(self.context))
233            objs.reverse()
234
235        else:
236            objs = self.context.portal_catalog.searchResults(portal_type='Course',
237                                                             sort_on='modified',
238                                                             sort_order='reverse')
239        return objs
240       
241    def isPartOf(self, obj):
242        """ Gets the parent object of course materials via FindECParent or returns parent object """
243               
244        self.ecutil = getUtility(IECUtility)
245        parent = self.ecutil.FindECParent(obj)
246        parentType = parent.Type()
247        if parentType == 'Course' and obj.Type() != 'Course':
248            return parent.Type(), parent.absolute_url()
249        elif parentType == 'Course' and obj.Type() == 'Course':
250            return parent.Type(), obj.aq_parent.absolute_url()           
251        elif obj.Type() != 'Plone Site':
252            return obj.aq_parent.Type(), obj.aq_parent.absolute_url()
253        else:
254            return ['','']
255       
256
257
258def unicode_sanitize(text):
259    """
260    Intended to be used to correct the inconsistency of plone when you call
261    methods such as Title or Publisher which should ALLWAYS return a unicode
262    object if the output is text.
263    """
264    if isinstance(text,list):
265        sanit_list = []
266        for item in text:
267            if isinstance(item, str):
268                sanit_list += item.decode('utf-8')
269            else:
270                sanit_list += item
271        text = sanit_list         
272    elif isinstance(text, str):
273        text = text.decode('utf-8')
274    return text
275
276
277class CopyrightBylineView(BrowserView):
278    """ Implements eduCommons Citation view for customized Creator information """
279
280    def __init__(self, context, request):
281        self.context = context
282        self.request = request
283        self.props = self.context.portal_url.portal_properties.content_licensing_properties
284        self.clutil = getUtility(IContentLicensingUtility)
285        self.ecutil = getUtility(IECUtility)
286
287    def getLicenseByline(self):
288        """ Get the license byline fields for an object. """
289
290        copyright = self.context.Rights()
291        if not copyright:
292            copyright = self.props.DefaultSiteCopyright
293        holder, license = self.clutil.getLicenseAndHolderFromObject(self.context)
294        if '(site default)' == holder:
295            holder = self.props.DefaultSiteCopyrightHolder
296        if 'Site Default' == license[0]:
297            license = self.props.DefaultSiteLicense
298        license_name = license[1]
299        if not license_name or 'None' == license_name:
300            license_name = ''
301        if 'Creative Commons License' == license[0]:
302            license_name = license[0]
303        license_url = license[2]
304        if not license_url or 'None' == license_url:
305            license_url = ''
306        license_button = license[3]
307        if not license_button or 'None' == license_button:
308            license_button = ''
309        return copyright, holder, license_name, license_url, license_button
310
311
312
313    def getCitationInfo(self):
314        """ Gets the citation information """
315
316        # Title
317        title = self.context.title
318        title = title.replace('--', '-')
319
320        # Creators
321        creator = ''
322        index = 1
323
324        parent = self.ecutil.FindECParent(self.context)
325        parentType = parent.Type()
326        names = []
327        if '(course_default)' in self.context.Creators() and parentType == 'Course':
328            if parent.instructorAsCreator == True:
329                instr_name = parent.instructorName
330                names = [instr_name.strip()]
331                names += [name.strip() for name in parent.Creators()]
332                if len(self.context.Creators()) > 1:
333                    names += [name.strip() for name in self.context.Creators()[1:]]
334        elif self.context.Type() == 'Course':
335            if self.context.instructorAsCreator == True:
336                instr_name = self.context.instructorName
337                names = [instr_name.strip()]
338            names += [name.strip() for name in self.context.Creators()]
339        else:
340            names += [name.strip() for name in self.context.Creators()]
341           
342        for cr in names:
343            inits = ''
344            crs = []
345
346            crs = cr.split(' ')
347           
348
349            for part in crs[:-1]:
350                inits += ' ' + part[0] + '.'   
351       
352            creator += crs[-1]
353            if inits:
354                creator += "," + inits
355            creator += ', '
356            index += 1
357           
358        if creator:
359            creator = creator[:-2]
360            if creator:
361                if creator[-1] != '.':
362                    creator += '.'
363         
364        id = self.context.getId()
365       
366        portal_url = getToolByName(self.context, 'portal_url')
367        portal_name = portal_url.getPortalObject().title
368       
369        create_date = self.context.creation_date.strftime('%Y, %B %d')
370       
371         
372        url = self.context.absolute_url()
373
374        import datetime
375        date = datetime.date.today().strftime('%B %d, %Y')
376 
377       
378        if creator:
379            prompt_text = "%s (%s). %s. Retrieved %s, from %s Web site: %s." %(unicode_sanitize(creator),create_date,unicode_sanitize(title),date,unicode_sanitize(portal_name),url)
380        else:
381            prompt_text = "%s. (%s). Retrieved %s, from %s Web site: %s." %(unicode_sanitize(title),create_date,date,unicode_sanitize(portal_name),url)
382
383        return prompt_text.replace('\'','\\\'').replace('\"','\\\'')
384 
385
386
387
388class RDFMetadataView(BrowserView):
389    """ Express Dublin Core As Rdf  """
390
391    def __init__(self, context, request):
392        self.context = context
393        self.request = request
394        self.document = minidom.Document()
395        self.clutil = getUtility(IContentLicensingUtility)
396        self.ecutil = getUtility(IECUtility)
397        self.props = self.context.portal_url.portal_properties.content_licensing_properties
398        self.holder, self.license = self.clutil.getLicenseAndHolderFromObject(context)
399
400    def __call__(self):
401        self.request.response.setHeader('Content-Type', 'application/rdf+xml')
402        return self.writeRDF()
403
404    def writeRDF(self):
405        """ Write RDF metadata """
406        parent = self.ecutil.FindECParent(self.context)
407        if 'Creative Commons License' == self.license[0] or ('Creative Commons License' == self.props.DefaultSiteLicense[0] and 'Site Default' == self.license[0]):
408            if self.license[0] == 'Site Default':
409                self.license = self.props.DefaultSiteLicense
410            data = self.getCCLicenseRDF(parent)
411        else:
412            data = self.getRDFMetadata(parent)
413        # Remove the XML header
414        index = find(data, '\n')
415        if (index > -1):
416            data = data[index + 1:]
417        return data
418
419    def getRDFMetadata(self, parent):
420        """ Write metadata fields as RDF. """
421        rdf_node = self._createNode(self.document, 'rdf:RDF',
422                       attrs=[('xmlns:rdf', 'http://www.w3.org/1999/02/22-rdf-syntax-ns#'),
423                              ('xmlns:dc', 'http://purl.org/dc/elements/1.1/'),
424                              ('xmlns:dcterms', 'http://purl.org/dc/terms')])
425        desc_node = self._createNode(rdf_node, 'rdf:Description',
426                        attrs=[('rdf:about', self.context.renderBase())])
427        self._writeDCMetadata(desc_node, parent)
428        return self.document.toprettyxml()       
429                               
430
431    def getCCLicenseRDF(self, parent):
432        """ Write into RDF CC License elements. """
433        holder, license = self.clutil.getLicenseAndHolderFromObject(self.context)
434        licenseId = ''
435        if len(self.license) >= 3:
436            lid = urlsplit(self.license[2])
437            if len(lid) >= 3:
438                lid = lid[2].split('/')
439                if len(lid) >= 3:
440                    licenseId = lid[2]
441
442        if licenseId and self.clutil.hasCCLicenseInfo(licenseId):
443
444            cc_rdf = self.clutil.getCCLicenseInfo(licenseId)
445       
446            rdf_node = self._createNode(self.document, 'rdf:RDF',
447                           attrs=[('xmlns', 'http://web.resource.org/cc/'),
448                                  ('xmlns:dc', 'http://purl.org/dc/elements/1.1/'),
449                                  ('xmlns:rdf', 'http://www.w3.org/1999/02/22-rdf-syntax-ns#'),
450                                  ('xmlns:ec', 'http://educommons.com/xsd/coursemetadata1.0.rdf#')])
451            work_node = self._createNode(rdf_node, 'Work', attrs=[('rdf:about',
452                                                                   self.context.renderBase())])
453            self._writeDCMetadata(work_node, parent)
454           
455            parent = self.ecutil.FindECParent(self.context)
456            parentType = parent.Type()
457            if parentType == 'Course':
458                self._writeCourseMetadata(work_node, parent)
459                self._createNode(work_node, 'license', attrs=[('rdf:resource', self.license[2])])
460            return self.document.toprettyxml()
461        else:
462            return ''
463
464    def _writeCourseMetadata(self, node, parent):
465        """ Write the Course metadata in RDF. """
466
467        # Course ID
468        if parent.getCourseId() != '':
469            self._createNode(node, 'ec:course_id', parent.getCourseId())
470
471        # Course Term
472        if parent.getTerm() != '':
473            self._createNode(node, 'ec:term', parent.getTerm())
474
475        # Course Structure
476        if parent.getStructure() != '':
477            self._createNode(node, 'ec:structure', parent.getStructure())
478
479        # Course Level
480        if parent.getLevel() != '':
481            self._createNode(node, 'ec:level', parent.getLevel())
482
483
484    def _writeDCMetadata(self, node, parent):
485        """ Write the dublin core metadata in RDF. """
486
487        # Identifier
488        self._createNode(node, 'dc:identifier', self.context.renderBase())
489
490        # Title
491        self._createNode(node, 'dc:title', self.context.Title())
492
493        # Language
494        lang = self.context.Language()
495        if not lang:
496            po = self.context.portal_url.getPortalObject()
497            lang = po.portal_properties.site_properties.getProperty('default_language')
498        self._createNode(node, 'dc:language', lang)
499
500        # Description
501        desc = self.context.Description()
502        if desc:
503            self._createNode(node, 'dc:description', self.context.Description())
504
505        # Subject
506        self._renderList(node, 'dc:subject', self.context.Subject())
507
508        # Type
509        self._createNode(node, 'dc:type', self.context.Type())
510
511        #Creators
512        parent = self.ecutil.FindECParent(self.context)
513        parentType = parent.Type()
514        course_creators = '',
515
516
517        if '(course_default)' in self.context.Creators() and parentType == 'Course':
518            if parent.instructorAsCreator == True:
519                cres = parent.instructorName
520                course_creators = cres,
521            for creator in parent.Creators():
522                course_creators += creator,
523            if len(self.context.Creators()) > 1:
524                course_creators += self.context.Creators()[1:]
525            self._renderList(node, 'dc:creator', course_creators)
526        elif self.context.Type() == 'Course':
527            if self.context.instructorAsCreator == True:
528                cres = self.context.instructorName
529                course_creators = cres,
530            for creator in self.context.Creators():
531                course_creators += creator,
532            self._renderList(node, 'dc:creator', course_creators)
533        else:
534            for creator in self.context.Creators():
535                course_creators += creator,
536            self._renderList(node, 'dc:creator', course_creators)
537
538
539        # Contributors
540        self._renderList(node, 'dc:contributor', self.context.Contributors())
541
542        # Publisher
543        self._createNode(node, 'dc:publisher', self.context.portal_url.getPortalObject().Publisher())
544
545        # Format
546        self._createNode(node, 'dc:format', self.context.Format())
547
548        # Rights
549        rights = self.context.Rights()
550        if not rights:
551            rights = self.props.DefaultSiteCopyright
552        self._createNode(node, 'dc:rights', rights)
553
554    def _renderList(self, node, element, value):
555        """ Render a list of items in RDF. """
556        if value:
557            if len(value) > 1:
558                value_node = self._createNode(node, element)
559                bag_node = self._createNode(value_node, 'rdf:Bag')
560                for x in value:
561                    self._createNode(bag_node, 'rdf:li', x)
562            else:
563                self._createNode(node, element, value[0])
564       
565
566    def _createNode(self, parent, ename, value=None, attrs=None):
567        """ Create a node in the document. """
568        newNode = self.document.createElement(ename)
569        parent.appendChild(newNode)
570        if value:
571            value = value.replace('--','-')
572            newNode.appendChild(self.document.createTextNode(unicode_sanitize(value)))
573        if attrs:
574            for x in attrs:
575                newNode.setAttribute(x[0], unicode_sanitize(x[1]))
576        return newNode
577
578
579
580
581       
Note: See TracBrowser for help on using the repository browser.