def test_migrate_xx_functions(self):
        from Products.ATContentTypes.content.image import ATImage
        from Products.ATContentTypes.content.file import ATFile
        from plone.app.contenttypes.migration.migration import (
            migrate_documents,
            migrate_collections,
            migrate_images,
            migrate_blobimages,
            migrate_files,
            migrate_blobfiles,
            migrate_links,
            migrate_newsitems,
            migrate_blobnewsitems,
            migrate_folders,
            migrate_events,
        )

        # create all content types
        self.portal.invokeFactory('Document', 'document')
        self.portal.invokeFactory('Image', 'image')
        self.createATCTobject(ATImage, 'blobimage')
        self.portal.invokeFactory('File', 'blobfile')
        self.createATCTobject(ATFile, 'file')
        self.portal.invokeFactory('Collection', 'collection')
        self.portal.invokeFactory('Link', 'link')
        self.portal.invokeFactory('News Item', 'newsitem')
        self.createATCTBlobNewsItem('blobnewsitem')
        self.portal.invokeFactory('Folder', 'folder')
        self.portal.invokeFactory('Event', 'event')

        # migrate all
        applyProfile(self.portal, 'plone.app.contenttypes:default')
        migrate_documents(self.portal)
        migrate_collections(self.portal)
        migrate_images(self.portal)
        migrate_blobimages(self.portal)
        migrate_files(self.portal)
        migrate_blobfiles(self.portal)
        migrate_links(self.portal)
        migrate_newsitems(self.portal)
        migrate_blobnewsitems(self.portal)
        migrate_folders(self.portal)
        migrate_events(self.portal)

        # assertions
        cat = self.catalog
        at_contents = cat(object_provides='Products.ATContentTypes'
                          '.interfaces.IATContentType')
        dx_contents = cat(object_provides='plone.dexterity'
                          '.interfaces.IDexterityContent')
        self.assertEqual(len(at_contents), 0)
        self.assertEqual(len(dx_contents), 11)
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,
        migrate=False,
        content_types='all',
        migrate_schemaextended_content=False,
        migrate_references=True,
        from_form=False,
        reindex_catalog=True,
        patch_searchabletext=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()

        self.request['plone.app.contenttypes_migration_running'] = True

        msg = 'Starting Migration\n\n'
        msg += '\n-----------------------------\n'
        msg += 'Content statictics:\n'
        msg += pformat(stats_before)
        msg += '\n-----------------------------\n'
        msg += 'Types to be migrated:\n'
        msg += pformat(content_types)
        msg += '\n-----------------------------\n'
        logger.info(msg)

        # store references on the portal
        if migrate_references:
            store_references(portal)
        catalog = portal.portal_catalog

        # Patch various things that make migration harder
        (link_integrity, queue_indexing,
         patch_searchabletext) = patch_before_migration(patch_searchabletext)

        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'],
            }
            amount_to_be_migrated = len(catalog(query))
            starttime_for_current = datetime.now()
            logger.info('Start migrating {0} objects from {1} to {2}'.format(
                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 {0} objects from {1} to {2} in {3}'.format(
                    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)

        # make sure the view-methods on the plone site are updated
        use_new_view_names(portal, types_to_fix=['Plone Site'])

        if reindex_catalog:
            catalog.clearFindAndRebuild()

        # restore references
        if migrate_references:
            restore_references(portal)

        # Revert to the original state
        undo_patch_after_migration(link_integrity, queue_indexing,
                                   patch_searchabletext)

        duration = str(timedelta(seconds=(datetime.now() - starttime).seconds))
        if not_migrated:
            msg = ('The following types were not migrated: \n {0}'.format(
                '\n'.join(not_migrated)))
        else:
            msg = 'Migration successful\n\n'
        msg += '\n-----------------------------\n'
        msg += 'Migration finished in: {0}'.format(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
    def __call__(self,
                 migrate=False,
                 content_types='all',
                 migrate_schemaextended_content=False,
                 migrate_references=True,
                 from_form=False,
                 reindex_catalog=True,
                 patch_searchabletext=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()

        self.request['plone.app.contenttypes_migration_running'] = True

        msg = 'Starting Migration\n\n'
        msg += '\n-----------------------------\n'
        msg += 'Content statictics:\n'
        msg += pformat(stats_before)
        msg += '\n-----------------------------\n'
        msg += 'Types to be migrated:\n'
        msg += pformat(content_types)
        msg += '\n-----------------------------\n'
        logger.info(msg)

        # store references on the portal
        if migrate_references:
            store_references(portal)
        catalog = portal.portal_catalog

        # Patch various things that make migration harder
        (link_integrity,
         queue_indexing,
         patch_searchabletext) = patch_before_migration(patch_searchabletext)

        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'],
            }
            amount_to_be_migrated = len(catalog(query))
            starttime_for_current = datetime.now()
            logger.info(
                'Start migrating {0} objects from {1} to {2}'.format(
                    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 {0} objects from {1} to {2} in {3}'.format(
                    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)

        # make sure the view-methods on the plone site are updated
        use_new_view_names(portal, types_to_fix=['Plone Site'])

        if reindex_catalog:
            catalog.clearFindAndRebuild()

        # restore references
        if migrate_references:
            restore_references(portal)

        # Revert to the original state
        undo_patch_after_migration(
            link_integrity, queue_indexing, patch_searchabletext)

        duration = str(timedelta(seconds=(datetime.now() - starttime).seconds))
        if not_migrated:
            msg = (
                'The following types were not migrated: \n {0}'.format(
                    '\n'.join(not_migrated)
                )
            )
        else:
            msg = 'Migration successful\n\n'
        msg += '\n-----------------------------\n'
        msg += 'Migration finished in: {0}'.format(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
    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()

        # store references on the portal
        if migrate_references:
            store_references(portal)
        catalog = portal.portal_catalog

        # switch linkintegrity temp off
        ptool = queryUtility(IPropertiesTool)
        site_props = getattr(ptool, 'site_properties', None)
        link_integrity_in_props = False
        if site_props and site_props.hasProperty(
                'enable_link_integrity_checks'):
            link_integrity_in_props = True
            link_integrity = site_props.getProperty(
                'enable_link_integrity_checks', False)
            site_props.manage_changeProperties(
                enable_link_integrity_checks=False)
        else:
            # Plone 5
            registry = getUtility(IRegistry)
            editing_settings = registry.forInterface(IEditingSchema,
                                                     prefix='plone')
            link_integrity = editing_settings.enable_link_integrity_checks
            editing_settings.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 {0} objects from {1} to {2}'.format(
                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 {0} objects from {1} to {2} in {3}'.format(
                    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)

        # make sure the view-methods on the plone site are updated
        use_new_view_names(portal, types_to_fix=['Plone Site'])

        catalog.clearFindAndRebuild()

        # restore references
        if migrate_references:
            restore_references(portal)

        # switch linkintegrity back to what it was before migrating
        if link_integrity_in_props:
            site_props.manage_changeProperties(
                enable_link_integrity_checks=link_integrity)
        else:
            editing_settings.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 {0}'.format(
                '\n'.join(not_migrated)))
        else:
            msg = 'Migration successful\n\n'
        msg += '\n-----------------------------\n'
        msg += 'Migration finished in: {0}'.format(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
    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
Exemple #8
0
    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()

        # store references on the portal
        if migrate_references:
            store_references(portal)
        catalog = portal.portal_catalog

        # switch linkintegrity temp off
        ptool = queryUtility(IPropertiesTool)
        site_props = getattr(ptool, 'site_properties', None)
        link_integrity_in_props = False
        if site_props and site_props.hasProperty(
                'enable_link_integrity_checks'):
            link_integrity_in_props = True
            link_integrity = site_props.getProperty(
                'enable_link_integrity_checks', False)
            site_props.manage_changeProperties(
                enable_link_integrity_checks=False)
        else:
            # Plone 5
            registry = getUtility(IRegistry)
            editing_settings = registry.forInterface(
                IEditingSchema, prefix='plone')
            link_integrity = editing_settings.enable_link_integrity_checks
            editing_settings.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 {0} objects from {1} to {2}'.format(
                    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 {0} objects from {1} to {2} in {3}'.format(
                    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)

        # make sure the view-methods on the plone site are updated
        use_new_view_names(portal, types_to_fix=['Plone Site'])

        catalog.clearFindAndRebuild()

        # restore references
        if migrate_references:
            restore_references(portal)

        # switch linkintegrity back to what it was before migrating
        if link_integrity_in_props:
            site_props.manage_changeProperties(
                enable_link_integrity_checks=link_integrity
            )
        else:
            editing_settings.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 {0}'.format(
                    '\n'.join(not_migrated)
                )
            )
        else:
            msg = 'Migration successful\n\n'
        msg += '\n-----------------------------\n'
        msg += 'Migration finished in: {0}'.format(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