def get322Contents(article, orderedListName, internal=True):
    """
        Return all the images that are linked in an article.

        article is a 3.x.x article
        orderedListName is the name of the attributes which contain the ordered
        list of contents.
             It can be either '__ordered_attachment_refs__', '__ordered_image_refs__'
             or '__ordered_link_refs__'.
        if internal is True, return Images detected as internal, else
        return images given in reference.
    """

    LOG.debug("migration.get322Contents parameters:\n %s %s %s" %
              (article.absolute_url(), orderedListName, repr(internal)))
    if not safe_hasattr(article, "at_references"):
        raise ValueError("Article has no at_references attribute.")

    result = []
    if internal:
        # During migration from old Plone and Zope versions some references
        # are inconsistant.
        # To be sure to migrate all inner content we **guess** that only one inner
        # type contains word in portal_type or in meta_type to filter out other
        # inner types.
        word = ''
        if orderedListName == '__ordered_attachment_refs__':
            word = 'file'
        elif orderedListName == '__ordered_image_refs__':
            word = 'image'
        elif orderedListName == '__ordered_link_refs__':
            word = 'link'
        else:
            # XXX Ouch, it's some unknown orderedListName: try and pray.
            word = 'file'

        result.extend([
            obj for obj in article.objectValues() if
            word in obj.portal_type.lower() or word in obj.meta_type.lower()
        ])
        LOG.debug("inner content for word %s:\n %s" % (word, repr(result)))

    try:
        oList = getattr(article, orderedListName)
    except AttributeError, e:
        # There's something bad there. As we don't want the migration fail here
        # we put a log in 'error' level.
        LOG.error(
            "migration.get322Contents:\n%s attribute does'nt exist for %s" %
            (orderedListName, article.absolute_url()))
        return result
def get322Contents(article, orderedListName, internal=True):
    """
        Return all the images that are linked in an article.

        article is a 3.x.x article
        orderedListName is the name of the attributes which contain the ordered
        list of contents.
             It can be either '__ordered_attachment_refs__', '__ordered_image_refs__'
             or '__ordered_link_refs__'.
        if internal is True, return Images detected as internal, else
        return images given in reference.
    """

    LOG.debug("migration.get322Contents parameters:\n %s %s %s" % (article.absolute_url(), orderedListName, repr(internal)))
    if not safe_hasattr(article, "at_references"):
        raise ValueError("Article has no at_references attribute.")

    result = []
    if internal:
        # During migration from old Plone and Zope versions some references
        # are inconsistant.
        # To be sure to migrate all inner content we **guess** that only one inner
        # type contains word in portal_type or in meta_type to filter out other
        # inner types.
        word = ''
        if orderedListName == '__ordered_attachment_refs__':
            word = 'file'
        elif orderedListName == '__ordered_image_refs__':
            word = 'image'
        elif orderedListName == '__ordered_link_refs__':
            word = 'link'
        else:
            # XXX Ouch, it's some unknown orderedListName: try and pray.
            word = 'file'

        result.extend([obj for obj in article.objectValues()
                       if word in obj.portal_type.lower() or word in obj.meta_type.lower()])
        LOG.debug("inner content for word %s:\n %s" % (word, repr(result)))

    try:
        oList = getattr(article, orderedListName)
    except AttributeError, e:
        # There's something bad there. As we don't want the migration fail here
        # we put a log in 'error' level.
        LOG.error("migration.get322Contents:\n%s attribute does'nt exist for %s" % (orderedListName, article.absolute_url()))
        return result
    def upgrade(self, REQUEST=None, dry_run=None, swallow_errors=True,
                force_instance_version=None):

        result_log = []
        instance_version = force_instance_version or self.getVersion()[1]

        if dry_run:
            result_log.append(("Dry run selected.", logging.INFO))

        # either get the forced upgrade instance or the current instance
        newv = getattr(REQUEST, "force_instance_version", instance_version)

        result_log.append(("Starting the migration from "
                    "version: %s" % newv, logging.INFO))

        while newv is not None:
            result_log.append(
                ("Attempting to upgrade from: %s" % newv, logging.INFO))
            try:
                newv, msgs = self._upgrade(newv)
                if msgs:
                    for msg in msgs:
                        # if string make list
                        if isinstance(msg, basestring):
                            msg = [msg,]
                        # if no status, add one
                        if len(msg) == 1:
                            msg.append(logging.INFO)
                        result_log.append(msg)
                if newv is not None:
                    result_log.append(("Upgrade to: %s, completed" % newv, logging.INFO))
                    self.setInstanceVersion(newv)

            except ConflictError:
                raise
            except:
                exc_type, exc_value, exc_tb = sys.exc_info()
                result_log.append(("Upgrade aborted", logging.ERROR))
                result_log.append(("Error type: %s" % exc_type, logging.ERROR))
                result_log.append(("Error value: %s" % exc_value, logging.ERROR))
                for line in traceback.format_tb(exc_tb):
                    result_log.append((line, logging.ERROR))

                # set newv to None
                # to break the loop
                newv = None
                if not swallow_errors:
                    for msg, sev in result_log: LOG.log(sev, msg)
                    raise
                else:
                    # abort transaction to safe the zodb
                    transaction.abort()

        result_log.append(("End of upgrade path, migration has finished", logging.INFO))

        if self.needsVersionMigration():
            result_log.append((("The upgrade path did NOT reach "
                        "current version"), logging.ERROR))
            result_log.append(("Migration has failed", logging.ERROR))
        else:
            result_log.append((
                "Your PloneArticle instance is now up-to-date.", logging.INFO))

        if dry_run:
            result_log.append(("Dry run selected, transaction aborted",
                               logging.INFO))
            transaction.abort()

        # log all this
        for msg, sev in result_log:
            LOG.log(sev, msg)

        return result_log
    def upgrade(self,
                REQUEST=None,
                dry_run=None,
                swallow_errors=True,
                force_instance_version=None):

        result_log = []
        instance_version = force_instance_version or self.getVersion()[1]

        if dry_run:
            result_log.append(("Dry run selected.", logging.INFO))

        # either get the forced upgrade instance or the current instance
        newv = getattr(REQUEST, "force_instance_version", instance_version)

        result_log.append(("Starting the migration from "
                           "version: %s" % newv, logging.INFO))

        while newv is not None:
            result_log.append(
                ("Attempting to upgrade from: %s" % newv, logging.INFO))
            try:
                newv, msgs = self._upgrade(newv)
                if msgs:
                    for msg in msgs:
                        # if string make list
                        if isinstance(msg, basestring):
                            msg = [
                                msg,
                            ]
                        # if no status, add one
                        if len(msg) == 1:
                            msg.append(logging.INFO)
                        result_log.append(msg)
                if newv is not None:
                    result_log.append(
                        ("Upgrade to: %s, completed" % newv, logging.INFO))
                    self.setInstanceVersion(newv)

            except ConflictError:
                raise
            except Exception:
                exc_type, exc_value, exc_tb = sys.exc_info()
                result_log.append(("Upgrade aborted", logging.ERROR))
                result_log.append(("Error type: %s" % exc_type, logging.ERROR))
                result_log.append(
                    ("Error value: %s" % exc_value, logging.ERROR))
                for line in traceback.format_tb(exc_tb):
                    result_log.append((line, logging.ERROR))

                # set newv to None
                # to break the loop
                newv = None
                if not swallow_errors:
                    for msg, sev in result_log:
                        LOG.log(sev, msg)
                    raise
                else:
                    # abort transaction to safe the zodb
                    transaction.abort()

        result_log.append(
            ("End of upgrade path, migration has finished", logging.INFO))

        if self.needsVersionMigration():
            result_log.append((("The upgrade path did NOT reach "
                                "current version"), logging.ERROR))
            result_log.append(("Migration has failed", logging.ERROR))
        else:
            result_log.append(("Your PloneArticle instance is now up-to-date.",
                               logging.INFO))

        if dry_run:
            result_log.append(
                ("Dry run selected, transaction aborted", logging.INFO))
            transaction.abort()

        # log all this
        for msg, sev in result_log:
            LOG.log(sev, msg)

        return result_log
    try:
        oList = getattr(article, orderedListName)
    except AttributeError, e:
        # There's something bad there. As we don't want the migration fail here
        # we put a log in 'error' level.
        LOG.error("migration.get322Contents:\n%s attribute does'nt exist for %s" % (orderedListName, article.absolute_url()))
        return result

    for refUid in oList.getItems():
        ref = getattr(article.at_references, refUid)
        ## don't use hasattr (it uses aquisition) use safe_hasattr
        try:
            obj = ref.getTargetObject()
        except AttributeError, e: ## in some case, there is some ghost references...
            LOG.debug("Atributerror during migration on %s" % e)
            continue ## just ignore it...
        if safe_hasattr(article, obj.id) and internal:
            if obj not in result:
                result.append()
        elif not safe_hasattr(article, ref.getTargetObject().id) and not internal:
            result.append(ref.getTargetObject())

    return result


def migrateImages322to400(article, out):
    ## looking for old images
    intImages = get322Contents(article, "__ordered_image_refs__", internal=True)
    extImages = get322Contents(article, "__ordered_image_refs__", internal=False)
        oList = getattr(article, orderedListName)
    except AttributeError, e:
        # There's something bad there. As we don't want the migration fail here
        # we put a log in 'error' level.
        LOG.error(
            "migration.get322Contents:\n%s attribute does'nt exist for %s" %
            (orderedListName, article.absolute_url()))
        return result

    for refUid in oList.getItems():
        ref = getattr(article.at_references, refUid)
        ## don't use hasattr (it uses aquisition) use safe_hasattr
        try:
            obj = ref.getTargetObject()
        except AttributeError, e:  ## in some case, there is some ghost references...
            LOG.debug("Atributerror during migration on %s" % e)
            continue  ## just ignore it...
        if safe_hasattr(article, obj.id) and internal:
            if obj not in result:
                result.append()
        elif not safe_hasattr(article,
                              ref.getTargetObject().id) and not internal:
            result.append(ref.getTargetObject())

    return result


def migrateImages322to400(article, out):
    ## looking for old images
    intImages = get322Contents(article,
                               "__ordered_image_refs__",