| 32 | | class ObjectMigrator(CMFItemMigrator): |
| 33 | | """Persist annotations to new object""" |
| 34 | | |
| 35 | | def migrate_annotations(self): |
| 36 | | """Persist annotations""" |
| 37 | | if hasattr(self.old, '__annotations__'): |
| 38 | | annotations = self.old.__annotations__ |
| 39 | | self.new.__annotations__ = annotations |
| 40 | | |
| 41 | | def migrate_clearcopyright(self): |
| 42 | | """Migrate clear copyright status to annotation """ |
| 43 | | if hasattr(self.old, 'clearedCopyright'): |
| 44 | | copyright_status = self.old.getClearedCopyright() |
| 45 | | """ Manually append field to default content type """ |
| 46 | | self.new.__annotations__['eduCommons.clearcopyright'] = copyright_status |
| 47 | | |
| 48 | | def migrate_current_workflow(self): |
| 49 | | """Annotate the current workflow state""" |
| 50 | | wft = self.old.portal_url.portal_workflow |
| 51 | | cur_state = wft.getInfoFor(self.old, 'review_state') |
| 52 | | self.new.__annotations__['review_state'] = cur_state |
| 53 | | |
| 82 | | """Place course specific fields in an annotation, to be used post-install of 3.0.1 """ |
| 83 | | if hasattr(self.old, 'Term'): |
| 84 | | self.new.__annotations__['course.term'] = self.old.Term |
| 85 | | if hasattr(self.old, 'CourseId'): |
| 86 | | self.new.__annotations__['course.courseid'] = self.old.CourseId |
| 87 | | if hasattr(self.old, 'InstructorName'): |
| 88 | | self.new.__annotations__['course.instructorname'] = self.old.InstructorName |
| 89 | | if hasattr(self.old, 'instructorAsPrincipalCreator'): |
| 90 | | self.new.__annotations__['course.instructor_principal'] = self.old.instructorAsPrincipalCreator |
| 91 | | if hasattr(self.old, 'InstructorEmail'): |
| 92 | | self.new.__annotations__['course.instructoremail'] = self.old.InstructorEmail |
| 93 | | if hasattr(self.old, 'displayInstructorEmail'): |
| 94 | | self.new.__annotations__['course.displayInstructorEmail'] = self.old.displayInstructorEmail |
| 95 | | |
| | 61 | """Place course specific fields in an annotation, to be used in 3.1.1 to 3.2.1 migration """ |
| | 62 | if hasattr(self.old, 'term'): |
| | 63 | self.new.__annotations__['course.term'] = self.old.term |
| | 64 | if hasattr(self.old, 'courseId'): |
| | 65 | self.new.__annotations__['course.courseid'] = self.old.courseId |
| | 66 | if hasattr(self.old, 'structure'): |
| | 67 | self.new.__annotations__['course.structure'] = self.old.structure |
| | 68 | if hasattr(self.old, 'level'): |
| | 69 | self.new.__annotations__['course.level'] = self.old.level |
| | 70 | if hasattr(self.old, 'instructorName'): |
| | 71 | self.new.__annotations__['course.instructorname'] = self.old.instructorName |
| | 72 | if hasattr(self.old, 'instructorAsCreator'): |
| | 73 | self.new.__annotations__['course.instructor_principal'] = self.old.instructorAsCreator |
| | 74 | if hasattr(self.old, 'instructorEmail'): |
| | 75 | self.new.__annotations__['course.instructoremail'] = self.old.instructorEmail |
| | 76 | if hasattr(self.old, 'displayInstEmail'): |
| | 77 | self.new.__annotations__['course.displayInstructorEmail'] = self.old.displayInstEmail |
| | 78 | if hasattr(self.old, 'crosslisting'): |
| | 79 | self.new.__annotations__['course.crosslisting'] = self.old.crosslisting |
| 124 | | class ECFolderMigrator(eduCommonsFoldersMigrator): |
| 125 | | """Base class to migrate to Folder """ |
| 126 | | |
| 127 | | walkerClass = CatalogWalker |
| 128 | | src_meta_type = 'ECFolder' |
| 129 | | src_portal_type = 'ECFolder' |
| 130 | | dst_meta_type = 'ATFolder' |
| 131 | | dst_portal_type = 'Folder' |
| 132 | | |
| 133 | | map = {'getExcludeFromNav' : 'setExcludeFromNav'} |
| 134 | | |
| 135 | | |
| 136 | | |
| 137 | | # Object migrators |
| 138 | | class GFolderMigrator(CMFFolderMigrator): |
| 139 | | """Base class to migrate to Folder """ |
| 140 | | |
| 141 | | walkerClass = CatalogWalker |
| 142 | | src_meta_type = 'GFolder' |
| 143 | | src_portal_type = 'GFolder' |
| 144 | | dst_meta_type = 'ATFolder' |
| 145 | | dst_portal_type = 'Folder' |
| 146 | | |
| 147 | | def migrate_current_workflow(self): |
| 148 | | """Annotate the current workflow state""" |
| 149 | | wft = self.old.portal_url.portal_workflow |
| 150 | | cur_state = wft.getInfoFor(self.old, 'review_state') |
| 151 | | self.new.__annotations__['review_state'] = cur_state |
| 152 | | |
| 153 | | map = {'getExcludeFromNav' : 'setExcludeFromNav'} |
| 154 | | |
| 155 | | |
| 156 | | class ECDocumentMigrator(ObjectMigrator): |
| 157 | | """Base class to migrate to Document """ |
| 158 | | |
| 159 | | walkerClass = CatalogWalker |
| 160 | | src_meta_type = 'ECDocument' |
| 161 | | src_portal_type = 'ECDocument' |
| 162 | | dst_meta_type = 'ATDocument' |
| 163 | | dst_portal_type = 'Document' |
| 164 | | map = {'getRawText' : 'setText', |
| 165 | | 'getExcludeFromNav' : 'setExcludeFromNav'} |
| 166 | | |
| 167 | | class GDocumentMigrator(ObjectMigrator): |
| 168 | | """Base class to migrate to Document """ |
| 169 | | |
| 170 | | walkerClass = CatalogWalker |
| 171 | | src_meta_type = 'GDocument' |
| 172 | | src_portal_type = 'GDocument' |
| 173 | | dst_meta_type = 'ATDocument' |
| 174 | | dst_portal_type = 'Document' |
| 175 | | map = {'getRawText' : 'setText', |
| 176 | | 'Format' : 'setFormat', |
| 177 | | 'getExcludeFromNav' : 'setExcludeFromNav'} |
| 178 | | |
| 179 | | class ECFileMigrator(ObjectMigrator): |
| 180 | | """Base class to migrate to File """ |
| 181 | | |
| 182 | | walkerClass = CatalogWalker |
| 183 | | src_meta_type = 'ECFile' |
| 184 | | src_portal_type = 'ECFile' |
| 185 | | dst_meta_type = 'ATFile' |
| 186 | | dst_portal_type = 'File' |
| 187 | | map = {'getFile' : 'setFile', |
| 188 | | 'getExcludeFromNav' : 'setExcludeFromNav'} |
| 189 | | |
| 190 | | class GFileMigrator(ObjectMigrator): |
| 191 | | """Base class to migrate to File """ |
| 192 | | |
| 193 | | walkerClass = CatalogWalker |
| 194 | | src_meta_type = 'GFile' |
| 195 | | src_portal_type = 'GFile' |
| 196 | | dst_meta_type = 'ATFile' |
| 197 | | dst_portal_type = 'File' |
| 198 | | map = {'getFile' : 'setFile', |
| 199 | | 'getExcludeFromNav' : 'setExcludeFromNav'} |
| 200 | | |
| 201 | | class ECImageMigrator(ObjectMigrator): |
| 202 | | """Base class to migrate to default Image """ |
| 203 | | |
| 204 | | walkerClass = CatalogWalker |
| 205 | | src_meta_type = 'ECImage' |
| 206 | | src_portal_type = 'ECImage' |
| 207 | | dst_meta_type = 'ATImage' |
| 208 | | dst_portal_type = 'Image' |
| 209 | | map = {'getImage' : 'setImage', |
| 210 | | 'getExcludeFromNav' : 'setExcludeFromNav'} |
| 211 | | |
| 212 | | class GImageMigrator(ObjectMigrator): |
| 213 | | """Base class to migrate to default Image """ |
| 214 | | |
| 215 | | walkerClass = CatalogWalker |
| 216 | | src_meta_type = 'GImage' |
| 217 | | src_portal_type = 'GImage' |
| 218 | | dst_meta_type = 'ATImage' |
| 219 | | dst_portal_type = 'Image' |
| 220 | | map = {'getImage' : 'setImage', |
| 221 | | 'getExcludeFromNav' : 'setExcludeFromNav'} |
| 222 | | |
| 223 | | class ECLinkMigrator(ObjectMigrator): |
| 224 | | """Base class to migrate to default Link""" |
| 225 | | |
| 226 | | walkerClass = CatalogWalker |
| 227 | | src_meta_type = 'ECLink' |
| 228 | | src_portal_type = 'ECLink' |
| 229 | | dst_meta_type = 'ATLink' |
| 230 | | dst_portal_type = 'Link' |
| 231 | | map = {'getRemoteUrl' : 'setRemoteUrl', |
| 232 | | 'getExcludeFromNav' : 'setExcludeFromNav'} |
| 233 | | |
| 234 | | def pre_migrate_2_3_1_to_3_0_4(self): |
| | 112 | def pre_migrate_3_1_1_to_3_2_1(self): |
| 256 | | #create ims_properties to migrate out of tool |
| 257 | | portal.portal_properties.addPropertySheet('ims_properties', 'IMS Transport Properties') |
| 258 | | ims_props = portal.portal_properties.ims_properties |
| 259 | | IMStool = portal.portal_IMSTransportTool |
| 260 | | for prop in IMStool.propertyMap(): |
| 261 | | if prop['id'] != 'title': |
| 262 | | #make an ims_properties entry |
| 263 | | id = prop['id'] |
| 264 | | type = prop['type'] |
| 265 | | value = IMStool.getProperty(id) |
| 266 | | ims_props.manage_addProperty(id=id, type=type, value=value) |
| 267 | | |
| 268 | | #create contentlicensing_properties to capture tool props that need to migrate |
| 269 | | portal.portal_properties.addPropertySheet('contentlicensing_properties', 'Content Licensing Properties') |
| 270 | | cl_props = portal.portal_properties.contentlicensing_properties |
| 271 | | CLtool = portal.portal_contentlicensing |
| 272 | | for prop in CLtool.propertyMap(): |
| 273 | | if prop['id'] != 'title': |
| 274 | | id = prop['id'] |
| 275 | | type = prop['type'] |
| 276 | | value = CLtool.getProperty(id) |
| 277 | | if id == 'Jurisdiction': |
| 278 | | type = 'string' |
| 279 | | cl_props.manage_addProperty(id=id, type=type, value=value) |
| 280 | | |
| 281 | | transaction.commit() |
| 282 | | |
| 283 | | #create annotation for position in course, as one cannot access it properly in the migrators |
| 284 | | brains = portal.portal_catalog.searchResults(portal_type=['ECFolder', |
| 285 | | 'ECImage', |
| 286 | | 'ECDocument', |
| 287 | | 'ECFile', |
| 288 | | 'ECLink'], |
| 289 | | path='/') |
| 290 | | for brain in brains: |
| 291 | | obj = brain.getObject() |
| 292 | | #Only annotate those objects set to show in Navigation |
| 293 | | if obj.getExcludeFromNav() == False: |
| 294 | | if not hasattr(obj, '__annotations__') and obj.portal_type != 'ECLink': |
| 295 | | annotations = IAnnotations(obj) |
| 296 | | annotations['eduCommons.objPositionInCourse'] = '' |
| 297 | | if obj.portal_type in ['ECFolder', 'ECImage', 'ECDocument', 'ECFile']: |
| 298 | | pos = obj.getNavPosition() |
| 299 | | obj.__annotations__['eduCommons.objPositionInCourse'] = pos + 2 |
| 300 | | elif obj.portal_type == 'ECLink': |
| 301 | | #Links are not annotatable by default, allow each Link to be annotatable |
| 302 | | directly = directlyProvidedBy(obj) |
| 303 | | directlyProvides(obj, directly + IAttributeAnnotatable) |
| 304 | | annotations = IAnnotations(obj) |
| 305 | | pos = obj.getNavPosition() |
| 306 | | annotations['eduCommons.objPositionInCourse'] = pos + 2 |
| 307 | | |
| 308 | | transaction.commit() |
| 309 | | |
| 310 | | migrators = ( |
| 311 | | GDocumentMigrator, ECDocumentMigrator, |
| 312 | | GFileMigrator, ECFileMigrator, |
| 313 | | GImageMigrator, ECImageMigrator, |
| 314 | | ECLinkMigrator, ECFolderMigrator, |
| 315 | | ECDepartmentMigrator, ECCourseMigrator, |
| 316 | | GFolderMigrator,) |
| | 130 | migrators = ( DivisionMigrator, CourseMigrator) |
| 327 | | |
| 328 | | #remove display_view from front_page |
| 329 | | fp = getattr(self, 'front-page', None) |
| 330 | | |
| 331 | | if fp: |
| 332 | | fp.manage_delProperties(['layout',]) |
| 333 | | print >> out, "Removed layout from front-page" |
| 334 | | |
| 335 | | |
| 336 | | #remove caching policy |
| 337 | | self.caching_policy_manager.removePolicy('ECImageAndECFilePolicy') |
| 338 | | print >> out, "Removed Image and File Caching Policy" |
| 339 | | |
| 340 | | #uninstall FCKEditor |
| 341 | | if self.portal_quickinstaller.isProductInstalled('FCKeditor'): |
| 342 | | self.portal_quickinstaller.uninstallProducts(products=['FCKeditor']) |
| 343 | | print >> out, "Uninstalled FCKEditor" |
| 344 | | if not self.portal_quickinstaller.isProductInstalled('Kupu'): |
| 345 | | self.portal_quickinstaller.installProducts(products=['Kupu']) |
| 346 | | self.portal_properties.site_properties.available_editors = ('None', 'Kupu') |
| 347 | | print >> out, "Installed Kupu" |
| 348 | | |
| 349 | | #Rename default objects |
| 350 | | #Need to add Folder back to addable for Plone Site first.... |
| 351 | | pt = self.portal_types |
| 352 | | plone_site = pt.getTypeInfo('Plone Site') |
| 353 | | plone_site.allowed_content_types += ('Folder',) |
| 354 | | |
| 355 | | ap = getattr(self, 'About', None) |
| 356 | | if ap: |
| 357 | | ap.setId('about') |
| 358 | | |
| 359 | | hp = getattr(self, 'Help', None) |
| 360 | | if hp: |
| 361 | | hp.setId('help') |
| 362 | | |
| 363 | | fp = getattr(self, 'Feedback', None) |
| 364 | | if fp: |
| 365 | | fp.setId('feedback') |