| 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] |
|---|
| 23 | from zope.publisher.browser import BrowserView |
|---|
| 24 | from zope.component import getUtility |
|---|
| 25 | from zope.annotation.interfaces import IAnnotations |
|---|
| 26 | from collective.contentlicensing.browser import RSSView as DefaultRSSView |
|---|
| 27 | from collective.contentlicensing.browser import CopyrightBylineView as DefaultCopyrightBylineView |
|---|
| 28 | from Products.CMFPlone.utils import getToolByName |
|---|
| 29 | from enpraxis.educommons.utilities.interfaces import IECUtility |
|---|
| 30 | from collective.contentlicensing.utilities.interfaces import IContentLicensingUtility |
|---|
| 31 | from Products.Five.formlib.formbase import EditForm |
|---|
| 32 | from urlparse import urlsplit |
|---|
| 33 | from xml.dom import minidom |
|---|
| 34 | from string import split, find |
|---|
| 35 | import urllib |
|---|
| 36 | from Acquisition import aq_base, aq_inner, aq_parent |
|---|
| 37 | |
|---|
| 38 | |
|---|
| 39 | class 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 | |
|---|
| 53 | class ChangeCopyrightForm(BrowserView): |
|---|
| 54 | """ Test """ |
|---|
| 55 | def __init__(self, context, request): |
|---|
| 56 | self.context = context |
|---|
| 57 | self.request = request |
|---|
| 58 | |
|---|
| 59 | class 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 | |
|---|
| 73 | class ChangeAccessibleCompliantForm(BrowserView): |
|---|
| 74 | """ Test """ |
|---|
| 75 | def __init__(self, context, request): |
|---|
| 76 | self.context = context |
|---|
| 77 | self.request = request |
|---|
| 78 | |
|---|
| 79 | |
|---|
| 80 | class 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 | |
|---|
| 99 | class 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 | |
|---|
| 114 | class 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 | |
|---|
| 135 | class 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 | |
|---|
| 153 | class 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 | |
|---|
| 225 | class 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 | |
|---|
| 258 | def 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 | |
|---|
| 277 | class 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 | |
|---|
| 388 | class 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 | |
|---|