def test_relations_are_migrated(self): from plone.app.contenttypes.migration.migration import ( restoreReferences, migrate_documents, ) # IIntIds is not registered in the test env. So register it here sm = getSiteManager(self.portal) addUtility(sm, IIntIds, IntIds, ofs_name='intids', findroot=False) # create ATDocuments self.portal.invokeFactory('Document', 'doc1') at_doc1 = self.portal['doc1'] self.portal.invokeFactory('Document', 'doc2') at_doc2 = self.portal['doc2'] self.portal.invokeFactory('Document', 'doc3') at_doc3 = self.portal['doc3'] self.portal.invokeFactory('News Item', 'newsitem') at_newsitem = self.portal['newsitem'] # relate them at_doc1.setRelatedItems([at_doc2]) at_doc2.setRelatedItems([at_newsitem, at_doc3, at_doc1]) at_doc3.setRelatedItems(at_doc1) # migrate content applyProfile(self.portal, 'plone.app.contenttypes:default') migrate_documents(self.portal) dx_doc1 = self.portal['doc1'] dx_doc2 = self.portal['doc2'] dx_doc3 = self.portal['doc3'] # migrate references restoreReferences(self.portal) # assert single references dx_doc1_related = [x.to_object for x in dx_doc1.relatedItems] self.assertEqual(dx_doc1_related, [dx_doc2]) dx_doc3_related = [x.to_object for x in dx_doc3.relatedItems] self.assertEqual(dx_doc3_related, [dx_doc1]) # assert multi references, order is restored dx_doc2_related = [x.to_object for x in dx_doc2.relatedItems] self.assertEqual(dx_doc2_related, [at_newsitem, dx_doc3, dx_doc1])
def test_relations_are_migrated(self): from Products.ATContentTypes.content.document import ATDocument from plone.app.contenttypes.migration.migration import DocumentMigrator # IIntIds is not registered in the test env. So register it here sm = getSiteManager(self.portal) addUtility(sm, IIntIds, IntIds, ofs_name='intids', findroot=False) # create three ATDocument at_doc1 = self.createATCTobject(ATDocument, 'doc1') at_doc2 = self.createATCTobject(ATDocument, 'doc2') at_doc3 = self.createATCTobject(ATDocument, 'doc3') # relate them at_doc1.setRelatedItems([at_doc2.UID(), ]) at_doc2.setRelatedItems([at_doc1, at_doc3]) at_doc3.setRelatedItems(at_doc1) # migrate migrator = self.get_migrator(at_doc1, DocumentMigrator) migrator.migrate() migrator = self.get_migrator(at_doc2, DocumentMigrator) migrator.migrate() migrator = self.get_migrator(at_doc3, DocumentMigrator) migrator.migrate() restoreReferences(self.portal) # assertions new_doc1 = self.portal['doc1'] new_doc2 = self.portal['doc2'] new_doc3 = self.portal['doc3'] self.assertEqual(len(new_doc1.relatedItems), 1) rel1 = new_doc1.relatedItems[0] self.assertEqual(rel1.to_object, new_doc2) self.assertEqual(len(new_doc2.relatedItems), 2) rel1 = new_doc2.relatedItems[0] rel2 = new_doc2.relatedItems[1] self.assertEqual( set([rel1.to_object, rel2.to_object]), set([new_doc1, new_doc3])) self.assertEqual(len(new_doc3.relatedItems), 1) rel1 = new_doc3.relatedItems[0] self.assertEqual(rel1.to_object, new_doc1)
def migrateAT2DX(context): """ @param context: Products.GenericSetup.context.DirectoryImportContext instance """ # We check from our GenericSetup context whether we are running # add-on installation for your product or any other proudct if context.readDataFile('migrateAT2DX.txt') is None: # Not your add-on return portal = context.getSite() migration.migrate_folders(portal) migration.migrate_documents(portal) migration.migrate_collections(portal) migration.migrate_blobimages(portal) migration.migrate_blobfiles(portal) migration.migrate_blobnewsitems(portal) migration.restoreReferences(portal) migration.restoreReferencesOrder(portal)
def __call__(self, migrate=False, content_types="all", migrate_schemaextended_content=False, migrate_references=True, from_form=False): portal = self.context if not from_form and migrate not in ['1', 'True', 'true', 1]: url1 = '{0}/@@migrate_from_atct?migrate=1'.format( portal.absolute_url()) url2 = '{0}/@@atct_migrator'.format(portal.absolute_url()) msg = u'Warning \n' msg += u'-------\n' msg += u'You are accessing "@@migrate_from_atct" directly. ' msg += u'This will migrate all content to dexterity!\n\n' msg += u'Really migrate all content now: {0}\n\n'.format(url1) msg += u'First select what to migrate: {0}'.format(url2) return msg helpers = getMultiAdapter((portal, self.request), name="atct_migrator_helpers") if helpers.linguaplone_installed(): msg = 'Warning\n' msg += 'Migration aborted since Products.LinguaPlone is ' msg += 'installed. See ' msg += 'http://github.com/plone/plone.app.contenttypes#migration ' msg += 'for more information.' return msg stats_before = self.stats() starttime = datetime.now() catalog = portal.portal_catalog # switch linkintegrity temp off ptool = queryUtility(IPropertiesTool) site_props = getattr(ptool, 'site_properties', None) link_integrity = site_props.getProperty('enable_link_integrity_checks', False) site_props.manage_changeProperties(enable_link_integrity_checks=False) # switch of setModificationDate on changes self.patchNotifyModified() not_migrated = [] migrated_types = {} for (k, v) in ATCT_LIST.items(): if content_types != "all" and k not in content_types: not_migrated.append(k) continue # test if the ct is extended beyond blobimage and blobfile if len(isSchemaExtended(v['iface'])) > len(v['extended_fields']) \ and not migrate_schemaextended_content: not_migrated.append(k) continue query = { 'object_provides': v['iface'].__identifier__, 'meta_type': v['old_meta_type'], } if HAS_MULTILINGUAL and 'Language' in catalog.indexes(): query['Language'] = 'all' amount_to_be_migrated = len(catalog(query)) starttime_for_current = datetime.now() logger.info("Start migrating %s objects from %s to %s" % ( amount_to_be_migrated, v['old_meta_type'], v['type_name'])) installTypeIfNeeded(v['type_name']) # call the migrator v['migrator'](portal) # logging duration_current = datetime.now() - starttime_for_current duration_human = str(timedelta(seconds=duration_current.seconds)) logger.info("Finished migrating %s objects from %s to %s in %s" % ( amount_to_be_migrated, v['old_meta_type'], v['type_name'], duration_human)) # some data for the results-page migrated_types[k] = {} migrated_types[k]['amount_migrated'] = amount_to_be_migrated migrated_types[k]['old_meta_type'] = v['old_meta_type'] migrated_types[k]['type_name'] = v['type_name'] # if there are blobnewsitems we just migrate them silently. migration.migrate_blobnewsitems(portal) if migrate_references: migration.restoreReferences(portal) # switch linkintegrity back to what it was before migrating site_props.manage_changeProperties( enable_link_integrity_checks=link_integrity ) # switch on setModificationDate on changes self.resetNotifyModified() duration = str(timedelta(seconds=(datetime.now() - starttime).seconds)) if not_migrated: msg = ("The following types were not migrated: \n %s" % "\n".join(not_migrated)) else: msg = "Migration successful\n\n" msg += '\n-----------------------------\n' msg += 'Migration finished in: %s' % duration msg += '\n-----------------------------\n' msg += 'Migration statictics:\n' msg += pformat(migrated_types) msg += '\n-----------------------------\n' msg += 'State before:\n' msg += pformat(stats_before) msg += '\n-----------------------------\n' msg += 'Stats after:\n' msg += pformat(self.stats()) msg += '\n-----------------------------\n' if not from_form: logger.info(msg) return msg else: stats = { 'duration': duration, 'before': stats_before, 'after': self.stats(), 'content_types': content_types, 'migrated_types': migrated_types, } return stats
def __call__(self, content_types="all", migrate_schemaextended_content=False, migrate_references=True, from_form=False): stats_before = self.stats() starttime = datetime.now() portal = self.context helpers = getMultiAdapter((portal, self.context), name="atct_migrator_helpers") if helpers.linguaplone_installed(): msg = 'Warning\n' msg += 'Migration aborted since Products.LinguaPlone is ' msg += 'installed. See ' msg += 'http://github.com/plone/plone.app.contenttypes#migration ' msg += 'for more information.' return msg # switch linkintegrity temp off ptool = queryUtility(IPropertiesTool) site_props = getattr(ptool, 'site_properties', None) link_integrity = site_props.getProperty('enable_link_integrity_checks', False) site_props.manage_changeProperties(enable_link_integrity_checks=False) not_migrated = [] for (k, v) in ATCT_LIST.items(): if content_types != "all" and k not in content_types: not_migrated.append(k) continue # test if the ct is extended beyond blobimage and blobfile if len(isSchemaExtended(v['iface'])) > len(v['extended_fields']) \ and not migrate_schemaextended_content: not_migrated.append(k) continue # call the migrator v['migrator'](portal) # if there are blobnewsitems we just migrate them silently. migration.migrate_blobnewsitems(portal) if migrate_references: migration.restoreReferences(portal) migration.restoreReferencesOrder(portal) # switch linkintegrity back to what it was before migrating site_props.manage_changeProperties( enable_link_integrity_checks=link_integrity ) endtime = datetime.now() duration = (endtime - starttime).seconds if not from_form: if not_migrated: msg = ("The following were not migrated as they " "have extended schemas (from " "archetypes.schemaextender): \n %s" % "\n".join(not_migrated)) else: msg = "Default content types successfully migrated\n\n" msg += 'Migration finished in %s seconds' % duration msg += '\n-----------------------------\n' msg += 'State before:\n' msg += pformat(stats_before) msg += '\n-----------------------------\n' msg += 'Stats after:\n' msg += pformat(self.stats()) msg += '\n-----------------------------\n' return msg else: stats = { 'duration': duration, 'before': stats_before, 'after': self.stats() } return stats
def __call__(self, migrate=False, content_types="all", migrate_schemaextended_content=False, migrate_references=True, from_form=False): portal = self.context if content_types == 'all': content_types = DEFAULT_TYPES if not from_form and migrate not in ['1', 'True', 'true', 1]: url1 = '{0}/@@migrate_from_atct?migrate=1'.format( portal.absolute_url()) url2 = '{0}/@@atct_migrator'.format(portal.absolute_url()) msg = u'Warning \n' msg += u'-------\n' msg += u'You are accessing "@@migrate_from_atct" directly. ' msg += u'This will migrate all content to dexterity!\n\n' msg += u'Really migrate all content now: {0}\n\n'.format(url1) msg += u'First select what to migrate: {0}'.format(url2) return msg helpers = getMultiAdapter((portal, self.request), name="atct_migrator_helpers") if helpers.linguaplone_installed(): msg = 'Warning\n' msg += 'Migration aborted since Products.LinguaPlone is ' msg += 'installed. See ' msg += 'http://github.com/plone/plone.app.contenttypes#migration ' msg += 'for more information.' return msg stats_before = self.stats() starttime = datetime.now() catalog = portal.portal_catalog # switch linkintegrity temp off ptool = queryUtility(IPropertiesTool) site_props = getattr(ptool, 'site_properties', None) link_integrity = site_props.getProperty('enable_link_integrity_checks', False) site_props.manage_changeProperties(enable_link_integrity_checks=False) # switch of setModificationDate on changes self.patchNotifyModified() # patch UUIDIndex patch(UUIDIndex, 'insertForwardIndexEntry', patched_insertForwardIndexEntry) not_migrated = [] migrated_types = {} for (k, v) in ATCT_LIST.items(): if k not in content_types: not_migrated.append(k) continue # test if the ct is extended beyond blobimage and blobfile if len(isSchemaExtended(v['iface'])) > len(v['extended_fields']) \ and not migrate_schemaextended_content: not_migrated.append(k) continue query = { 'object_provides': v['iface'].__identifier__, 'meta_type': v['old_meta_type'], } if HAS_MULTILINGUAL and 'Language' in catalog.indexes(): query['Language'] = 'all' amount_to_be_migrated = len(catalog(query)) starttime_for_current = datetime.now() logger.info( "Start migrating %s objects from %s to %s" % (amount_to_be_migrated, v['old_meta_type'], v['type_name'])) installTypeIfNeeded(v['type_name']) # call the migrator v['migrator'](portal) # logging duration_current = datetime.now() - starttime_for_current duration_human = str(timedelta(seconds=duration_current.seconds)) logger.info("Finished migrating %s objects from %s to %s in %s" % (amount_to_be_migrated, v['old_meta_type'], v['type_name'], duration_human)) # some data for the results-page migrated_types[k] = {} migrated_types[k]['amount_migrated'] = amount_to_be_migrated migrated_types[k]['old_meta_type'] = v['old_meta_type'] migrated_types[k]['type_name'] = v['type_name'] # if there are blobnewsitems we just migrate them silently. migration.migrate_blobnewsitems(portal) catalog.clearFindAndRebuild() # rebuild catalog, restore references and cleanup migration.restoreReferences(portal, migrate_references, content_types) # switch linkintegrity back to what it was before migrating site_props.manage_changeProperties( enable_link_integrity_checks=link_integrity) # switch on setModificationDate on changes self.resetNotifyModified() # unpatch UUIDIndex undoPatch(UUIDIndex, 'insertForwardIndexEntry') duration = str(timedelta(seconds=(datetime.now() - starttime).seconds)) if not_migrated: msg = ("The following types were not migrated: \n %s" % "\n".join(not_migrated)) else: msg = "Migration successful\n\n" msg += '\n-----------------------------\n' msg += 'Migration finished in: %s' % duration msg += '\n-----------------------------\n' msg += 'Migration statictics:\n' msg += pformat(migrated_types) msg += '\n-----------------------------\n' msg += 'State before:\n' msg += pformat(stats_before) msg += '\n-----------------------------\n' msg += 'Stats after:\n' msg += pformat(self.stats()) msg += '\n-----------------------------\n' if not from_form: logger.info(msg) return msg else: stats = { 'duration': duration, 'before': stats_before, 'after': self.stats(), 'content_types': content_types, 'migrated_types': migrated_types, } logger.info(msg) return stats