Exemplo n.º 1
0
    def reply(self):
        # Disable CSRF protection
        if "IDisableCSRFProtection" in dir(plone.protect.interfaces):
            alsoProvides(self.request,
                         plone.protect.interfaces.IDisableCSRFProtection)

        data = json_body(self.request)
        id_ = data.get("id", None)
        if id_ is None:
            self.request.response.setStatus(400)
            return dict(error=dict(type="BadRequest",
                                   message="Missing content id to link to"))

        target = self.get_object(id_)
        if target is None:
            self.request.response.setStatus(400)
            return dict(error=dict(type="BadRequest",
                                   message="Content does not exist"))

        target_language = ILanguage(target).get_language()
        manager = ITranslationManager(self.context)
        current_translation = manager.get_translation(target_language)
        if current_translation is not None:
            self.request.response.setStatus(400)
            return dict(error=dict(
                type="BadRequest",
                message="Already translated into language {}".format(
                    target_language),
            ))

        manager.register_translation(target_language, target)
        self.request.response.setStatus(201)
        self.request.response.setHeader("Location",
                                        self.context.absolute_url())
        return {}
Exemplo n.º 2
0
    def __call__(self):
        pc = getToolByName(self.context, 'portal_catalog')
        pl = getToolByName(self.context, 'portal_languages')
        self.results = []
        for language_supported in pl.getSupportedLanguages():
            translated_objects = pc.searchResults(
                object_provides=LP_TRANSLATABLE,
                Language=language_supported)
            for brain in translated_objects:
                obj = brain.getObject()
                if obj.isCanonical():
                    translations = obj.getTranslations(include_canonical=False)
                    manager = ITranslationManager(obj)
                    if translations:
                        for language in translations.keys():
                            try:
                                manager.register_translation(
                                    language, translations[language][0])
                            except KeyError:
                                logger.info(
                                    '%s already translated to %s: %s' %
                                    (obj.id, language,
                                        str(manager.get_translations())))

                        self.results.append(str(manager.get_translations()))

        logger.info('Finished with transferring catalog information')
        return self.template()
Exemplo n.º 3
0
    def __call__(self):
        pc = getToolByName(self.context, 'portal_catalog')
        pl = getToolByName(self.context, 'portal_languages')
        self.results = []
        for language_supported in pl.getSupportedLanguages():
            translated_objects = pc.searchResults(
                object_provides=LP_TRANSLATABLE,
                Language=language_supported)
            for brain in translated_objects:
                obj = brain.getObject()
                if obj.isCanonical():
                    translations = obj.getTranslations(include_canonical=False)
                    manager = ITranslationManager(obj)
                    if translations:
                        for language in translations.keys():
                            try:
                                manager.register_translation(
                                    language, translations[language][0])
                            except KeyError:
                                logger.info(
                                    '%s already translated to %s: %s' %
                                    (obj.id, language,
                                        str(manager.get_translations())))

                        self.results.append(str(manager.get_translations()))

        logger.info('Finished with transferring catalog information')
        return self.template()
    def set_translation(self, original_path, translation_path,
                        target_language):
        """ Set position of container object given by `id` and `position` """

        from plone.protect.interfaces import IDisableCSRFProtection
        from zope.interface import alsoProvides
        from plone.app.multilingual.interfaces import ITranslationManager

        alsoProvides(self.request, IDisableCSRFProtection)

        source_obj = self.context.restrictedTraverse(original_path, None)
        if source_obj is None:
            raise ValueError("No object found at {}".format(original_path))

        translated_obj = self.context.restrictedTraverse(
            translation_path, None)
        if translated_obj is None:
            raise ValueError("No object found at {}".format(translation_path))

        translated_obj.language = target_language
        translated_obj.reindexObject()

        manager = ITranslationManager(source_obj)
        manager.register_translation(translated_obj.language, translated_obj)

        self.request.response.setStatus(200)
    def set_translation_map(self):
        """ Set position of container object given by `id` and `position` """

        from plone.protect.interfaces import IDisableCSRFProtection
        from zope.interface import alsoProvides
        from plone.app.multilingual.interfaces import ITranslationManager

        alsoProvides(self.request, IDisableCSRFProtection)

        translation_map = json.loads(self.request.BODY)

        for translations in translation_map:
            if "en" not in translations or "de" not in translations:
                continue
            source_obj = self.context.restrictedTraverse(
                str(translations["de"]["path"]), None)
            translated_obj = self.context.restrictedTraverse(
                str(translations["en"]["path"]), None)

            if source_obj is not None and translated_obj is not None:
                print(translations)
                manager = ITranslationManager(source_obj)
                try:
                    manager.register_translation(translated_obj.language,
                                                 translated_obj)
                except KeyError as e:
                    print(e)

        self.request.response.setStatus(200)
Exemplo n.º 6
0
    def reply(self):
        # Disable CSRF protection
        if "IDisableCSRFProtection" in dir(plone.protect.interfaces):
            alsoProvides(self.request,
                         plone.protect.interfaces.IDisableCSRFProtection)

        data = json_body(self.request)
        id_ = data.get("id", None)
        if id_ is None:
            self.request.response.setStatus(400)
            return dict(error=dict(type="BadRequest",
                                   message="Missing content id to link to"))

        target = self.get_object(id_)
        if target is None:
            self.request.response.setStatus(400)
            return dict(error=dict(type="BadRequest",
                                   message="Content does not exist"))
        elif target.portal_type == "LRF":
            self.request.response.setStatus(400)
            return dict(error=dict(
                type="BadRequest",
                message=
                "Language Root Folders can only be linked between each other",
            ))

        target_language = ILanguage(target).get_language()
        manager = ITranslationManager(self.context)
        current_translation = manager.get_translation(target_language)
        target_manager = ITranslationManager(target)
        target_translation = target_manager.get_translation(
            self.context.language)
        if current_translation is not None:
            self.request.response.setStatus(400)
            return dict(error=dict(
                type="BadRequest",
                message="Source already translated into language {}".format(
                    target_language),
            ))
        if target_translation is not None:
            self.request.response.setStatus(400)
            return dict(error=dict(
                type="BadRequest",
                message="Target already translated into language {}".format(
                    target_language),
            ))

        manager.register_translation(target_language, target)
        # We want to leave a log in the transaction that the link has been executed
        ts = transaction.get()
        ts.note(
            f'Linked translation {"/".join(self.context.getPhysicalPath())} ({self.context.language}) -> {"/".join(target.getPhysicalPath())} ({target_language})'
        )

        self.request.response.setStatus(201)
        self.request.response.setHeader("Location",
                                        self.context.absolute_url())
        return {}
Exemplo n.º 7
0
def link_translations(items):
    """
        Links the translations with the declared items with the form:
        [(obj1, lang1), (obj2, lang2), ...] assuming that the first element
        is the 'canonical' (in PAM there is no such thing).
    """
    # Grab the first item object and get its canonical handler
    canonical = ITranslationManager(items[0][0])

    for obj, language in items:
        if not canonical.has_translation(language):
            canonical.register_translation(language, obj)
Exemplo n.º 8
0
def link_translations(items):
    """
        Links the translations with the declared items with the form:
        [(obj1, lang1), (obj2, lang2), ...] assuming that the first element
        is the 'canonical' (in PAM there is no such thing).
    """
    # Grab the first item object and get its canonical handler
    canonical = ITranslationManager(items[0][0])

    for obj, language in items:
        if not canonical.has_translation(language):
            canonical.register_translation(language, obj)
Exemplo n.º 9
0
 def handle_add(self, action):
     data, errors = self.extractData()
     if not errors:
         content = data['content']
         language = data['language']
         ILanguage(content).set_language(language)
         itm = ITranslationManager(self.context)
         # the 'register_translation'-method takes content OR
         # UUID as second parameter. We need to use the UUID
         # here because otherwise the catalog can't be acquired
         # and the translation index is not updated
         itm.register_translation(language, IUUID(content))
     return self.request.response.redirect(self.context.absolute_url() +
                                           '/modify_translations')
def recursively_bind_translation(source, target, language,
                                 keep_workflow_states):

    if ITranslatable.providedBy(source):
        tm_source = ITranslationManager(source)
        tm_source.register_translation(language=language, content=target)

    if keep_workflow_states:
        try:
            api.content.transition(target,
                                   to_state=api.content.get_state(source))
        except WorkflowException:
            pass

    if IFolderish.providedBy(source) and IFolderish.providedBy(target):
        for source_obj_id, source_obj in source.objectItems():
            target_obj = target[source_obj_id]
            recursively_bind_translation(source_obj, target_obj, language,
                                         keep_workflow_states)
Exemplo n.º 11
0
    def _update_deferred(self):
        for path, canonicalpath, language in self.deferred:
            obj = self._traverse(path)
            if obj is None:
                continue
            canonical = self._traverse(canonicalpath)
            if canonical is None:
                continue

            if (ITranslatable.providedBy(obj) and
                    ITranslatable.providedBy(canonical)):
                try:
                    translation_group = IMutableTG(canonical).get()
                    IMutableTG(obj).set(translation_group)
                    manager = ITranslationManager(obj)
                    manager.register_translation(language, obj)
                except KeyError:
                    # put obj in a separate translation group when registration
                    # fails
                    IMutableTG(obj).set(self.uuid_generator())
Exemplo n.º 12
0
    def _update_deferred(self):
        for path, canonicalpath, language in self.deferred:
            obj = self._traverse(path)
            if obj is None:
                continue
            canonical = self._traverse(canonicalpath)
            if canonical is None:
                continue

            if (ITranslatable.providedBy(obj)
                    and ITranslatable.providedBy(canonical)):
                try:
                    translation_group = IMutableTG(canonical).get()
                    IMutableTG(obj).set(translation_group)
                    manager = ITranslationManager(obj)
                    manager.register_translation(language, obj)
                except KeyError:
                    # put obj in a separate translation group when registration
                    # fails
                    IMutableTG(obj).set(self.uuid_generator())
Exemplo n.º 13
0
    def linkTranslations(self):
        """Links the translations of the default language Folders
        """
        doneSomething = False

        try:
            canonical = ITranslationManager(self.folders[self.defaultLanguage])
        except TypeError as e:
            raise TypeError(str(e) + u' Are your folders ITranslatable?')

        for language in self.languages:
            if language == self.defaultLanguage:
                continue
            if not canonical.has_translation(language):
                language_folder = self.folders[language]
                canonical.register_translation(language, language_folder)
                doneSomething = True

        if doneSomething:
            logger.info(u'Translations linked.')

        return doneSomething
Exemplo n.º 14
0
    def linkTranslations(self):
        """Links the translations of the default language Folders
        """
        doneSomething = False

        try:
            canonical = ITranslationManager(self.folders[self.defaultLanguage])
        except TypeError as e:
            raise TypeError(str(e) + u' Are your folders ITranslatable?')

        for language in self.languages:
            if language == self.defaultLanguage:
                continue
            if not canonical.has_translation(language):
                language_folder = self.folders[language]
                canonical.register_translation(language, language_folder)
                doneSomething = True

        if doneSomething:
            logger.info(u'Translations linked.')

        return doneSomething
Exemplo n.º 15
0
    def __iter__(self):
        for item in self.previous:
            pathkey = self.pathkey(*item.keys())[0]
            if not pathkey:
                yield item
                continue

            path = item[pathkey]
            if isinstance(path, unicode):
                path = path.encode('ascii')

            obj = self._traverse(path)
            if obj is None:
                yield item
                continue

            canonicalkey = self.canonicalkey(*item.keys())[0]
            translationkey = self.translationkey(*item.keys())[0]

            if not canonicalkey:
                yield item
                continue

            canonicalpath = item[translationkey]
            if isinstance(canonicalpath, unicode):
                canonicalpath = canonicalpath.encode('ascii')
            language = item['language']
            if ITranslatable.providedBy(obj):
                ILanguage(obj).set_language(language)
            if item[canonicalkey]:
                IMutableTG(obj).set(self.uuid_generator())
                manager = ITranslationManager(obj)
                manager.register_translation(language, obj)
            else:
                self.deferred.append((path, canonicalpath, language))
            yield item

        self._update_deferred()
Exemplo n.º 16
0
    def __iter__(self):
        for item in self.previous:
            pathkey = self.pathkey(*item.keys())[0]
            if not pathkey:
                yield item
                continue

            path = item[pathkey]
            if isinstance(path, unicode):
                path = path.encode('ascii')

            obj = self._traverse(path)
            if obj is None:
                yield item
                continue

            canonicalkey = self.canonicalkey(*item.keys())[0]
            translationkey = self.translationkey(*item.keys())[0]

            if not canonicalkey:
                yield item
                continue

            canonicalpath = item[translationkey]
            if isinstance(canonicalpath, unicode):
                canonicalpath = canonicalpath.encode('ascii')
            language = item['language']
            if ITranslatable.providedBy(obj):
                ILanguage(obj).set_language(language)
            if item[canonicalkey]:
                IMutableTG(obj).set(self.uuid_generator())
                manager = ITranslationManager(obj)
                manager.register_translation(language, obj)
            else:
                self.deferred.append((path, canonicalpath, language))
            yield item

        self._update_deferred()
Exemplo n.º 17
0
    def reply(self):
        data = json_body(self.request)

        type_ = data.get("@type", None)
        id_ = data.get("id", None)
        title = data.get("title", None)
        translation_of = data.get("translation_of", None)
        language = data.get("language", None)
        uid = data.get("UID", None)

        if not type_:
            raise BadRequest("Property '@type' is required")

        # Disable CSRF protection
        if "IDisableCSRFProtection" in dir(plone.protect.interfaces):
            alsoProvides(self.request,
                         plone.protect.interfaces.IDisableCSRFProtection)

        sm = getSecurityManager()
        # ManagePortal is required to set the uid of an object during creation
        if uid and not sm.checkPermission(ManagePortal, self.context):
            self.request.response.setStatus(403)
            msg = "Setting UID of an object requires Manage Portal permission"
            return dict(error=dict(type="Forbidden", message=msg))

        try:
            obj = create(self.context, type_, id_=id_, title=title)
        except Unauthorized as exc:
            self.request.response.setStatus(403)
            return dict(error=dict(type="Forbidden", message=str(exc)))
        except BadRequest as exc:
            self.request.response.setStatus(400)
            return dict(error=dict(type="Bad Request", message=str(exc)))

        # Acquisition wrap temporarily to satisfy things like vocabularies
        # depending on tools
        temporarily_wrapped = False
        if IAcquirer.providedBy(obj) and not safe_hasattr(obj, "aq_base"):
            obj = obj.__of__(self.context)
            temporarily_wrapped = True

        # Update fields
        deserializer = queryMultiAdapter((obj, self.request),
                                         IDeserializeFromJson)
        if deserializer is None:
            self.request.response.setStatus(501)
            return dict(error=dict(
                message=f"Cannot deserialize type {obj.portal_type}"))

        try:
            deserializer(validate_all=True, create=True)
        except DeserializationError as e:
            self.request.response.setStatus(400)
            return dict(
                error=dict(type="DeserializationError", message=str(e)))

        if temporarily_wrapped:
            obj = aq_base(obj)

        if uid:
            setattr(obj, "_plone.uuid", uid)

        if not getattr(deserializer, "notifies_create", False):
            notify(ObjectCreatedEvent(obj))

        obj = add(self.context, obj, rename=not bool(id_))

        # Link translation given the translation_of property
        if (IPloneAppMultilingualInstalled.providedBy(self.request)
                and translation_of and language):
            source = self.get_object(translation_of)
            if source:
                manager = ITranslationManager(source)
                manager.register_translation(language, obj)

        self.request.response.setStatus(201)
        self.request.response.setHeader("Location", obj.absolute_url())

        serializer = queryMultiAdapter((obj, self.request), ISerializeToJson)

        serialized_obj = serializer()

        # HypermediaBatch can't determine the correct canonical URL for
        # objects that have just been created via POST - so we make sure
        # to set it here
        serialized_obj["@id"] = obj.absolute_url()

        return serialized_obj
Exemplo n.º 18
0
    def do_reply(self):
        """This is the reply method from plone.restapi, overrided
           to manage returning the fullobject after creation or the summary."""

        # imio.restapi, nothing changed until next comment "imio.restapi ..." comment
        data = json_body(self.request)

        type_ = data.get("@type", None)
        id_ = data.get("id", None)
        title = data.get("title", None)
        translation_of = data.get("translation_of", None)
        language = data.get("language", None)

        if not type_:
            raise BadRequest("Property '@type' is required")

        # Disable CSRF protection
        if "IDisableCSRFProtection" in dir(plone.protect.interfaces):
            alsoProvides(self.request, plone.protect.interfaces.IDisableCSRFProtection)

        try:
            obj = create(self.context, type_, id_=id_, title=title)
        except Unauthorized as exc:
            self.request.response.setStatus(403)
            return dict(error=dict(type="Forbidden", message=str(exc)))
        except BadRequest as exc:
            self.request.response.setStatus(400)
            return dict(error=dict(type="Bad Request", message=str(exc)))

        # Acquisition wrap temporarily to satisfy things like vocabularies
        # depending on tools
        temporarily_wrapped = False
        if IAcquirer.providedBy(obj) and not safe_hasattr(obj, "aq_base"):
            obj = obj.__of__(self.context)
            temporarily_wrapped = True

        # Update fields
        deserializer = queryMultiAdapter((obj, self.request), IDeserializeFromJson)
        if deserializer is None:
            self.request.response.setStatus(501)
            return dict(
                error=dict(message="Cannot deserialize type {}".format(obj.portal_type))
            )

        try:
            deserializer(validate_all=True, create=True)
        except DeserializationError as e:
            self.request.response.setStatus(400)
            return dict(error=dict(type="DeserializationError", message=str(e)))

        if temporarily_wrapped:
            obj = aq_base(obj)

        if not getattr(deserializer, "notifies_create", False):
            notify(ObjectCreatedEvent(obj))

        obj = add(self.context, obj, rename=not bool(id_))

        # Link translation given the translation_of property
        if PAM_INSTALLED and PLONE5:
            from plone.app.multilingual.interfaces import (
                IPloneAppMultilingualInstalled,
            )  # noqa
            from plone.app.multilingual.interfaces import ITranslationManager

            if (
                IPloneAppMultilingualInstalled.providedBy(self.request)
                and translation_of
                and language
            ):
                source = self.get_object(translation_of)
                if source:
                    manager = ITranslationManager(source)
                    manager.register_translation(language, obj)

        self.request.response.setStatus(201)
        self.request.response.setHeader("Location", obj.absolute_url())

        # imio.restapi, begin changes, manage returning full object or summary
        return_full_object = data.get(
            "return_fullobject", get_return_fullobject_after_creation_default())
        if return_full_object:
            serializer = queryMultiAdapter((obj, self.request), ISerializeToJson)
        else:
            serializer = queryMultiAdapter((obj, self.request), ISerializeToJsonSummary)

        serialized_obj = serializer()
        # imio.restapi, end changes, manage returning full object or summary

        # HypermediaBatch can't determine the correct canonical URL for
        # objects that have just been created via POST - so we make sure
        # to set it here
        serialized_obj["@id"] = obj.absolute_url()

        return serialized_obj
Exemplo n.º 19
0
    def update(self, obj, data):
        ILanguage(obj).set_language(data['language'])
        IMutableTG(obj).set(data['translation_group_uuid'])

        manager = ITranslationManager(obj)
        manager.register_translation(data['language'], obj)
Exemplo n.º 20
0
    def import_item(self, dirpath, *filenames):
        __traceback_info__ = dirpath
        logger.info("Importing item at %s", dirpath)
        all_info = {}
        blobs = {}
        for name in filenames:
            filepath = os.path.join(dirpath, name)
            key, ext = os.path.splitext(name)
            if ext != ".json":
                logger.info("Found non json file, will use as blob, at %s",
                            filepath)
                blobs[key] = filepath
                continue
            logger.info("Reading %s", filepath)
            with open(filepath) as myfile:
                content = json.loads(myfile.read())
            all_info[key] = content

        # Get meta info.  We might also get some of this from default.json.
        # Maybe we need less in meta.
        meta = all_info["meta"]
        # if "front-page" in meta.get("path", ""):
        #     import pdb; pdb.set_trace()
        # See if the object already exists.
        obj = self.get_object(**meta)
        if obj is None:
            # We need to get some parent, either from default["parent"] or meta.
            path = meta["path"]
            parent_path = path.rpartition("/")[0]
            parent_obj = self.get_object(path=parent_path)
            if parent_obj is None:
                logger.warning(
                    "Parent object not found, cannot create content for %s",
                    path)
                return
            default = all_info["default"]
            # Code taken from plone.restapi add.py FolderPost.reply.
            # It would be nice if we could call that method directly, but it does too much.
            # We would need to split it a bit, especially:
            # don't get json from the request body, and don't change the response.
            type_ = default.get("@type", None)
            id_ = default.get("id", None)
            title = default.get("title", None)
            translation_of = default.get("translation_of", None)
            language = default.get("language", None)
            # except Unauthorized / BadRequest
            obj = create(parent_obj, type_, id_=id_, title=title)
            # Acquisition wrap temporarily to satisfy things like vocabularies
            # depending on tools
            temporarily_wrapped = False
            if IAcquirer.providedBy(obj) and not safe_hasattr(obj, "aq_base"):
                obj = obj.__of__(self.context)
                temporarily_wrapped = True
            deserializer = queryMultiAdapter((obj, self.request),
                                             IDeserializeFromJson)
            if deserializer is None:
                logger.error("Cannot deserialize type %s", obj.portal_type)
                return
            if blobs:
                for fieldname, path in blobs.items():
                    if fieldname in default:
                        with open(path, "rb") as myfile:
                            default[fieldname]["data"] = myfile.read()

            # except DeserializationError as e:
            deserializer(validate_all=True, data=default, create=True)
            if temporarily_wrapped:
                obj = aq_base(obj)
            if not getattr(deserializer, "notifies_create", False):
                notify(ObjectCreatedEvent(obj))
            obj = add(parent_obj, obj, rename=not bool(id_))
            obj_path = "/".join(obj.getPhysicalPath())
            logger.info("Created %s at %s", type_, obj_path)

            # Link translation given the translation_of property
            if PAM_INSTALLED:
                # Note: untested.
                from plone.app.multilingual.interfaces import (
                    IPloneAppMultilingualInstalled, )  # noqa
                from plone.app.multilingual.interfaces import ITranslationManager

                if (IPloneAppMultilingualInstalled.providedBy(self.request)
                        and translation_of and language):
                    source = self.get_object(translation_of)
                    if source:
                        manager = ITranslationManager(source)
                        manager.register_translation(language, obj)

            # TODO: call other, named deserializers, but they do not work currently anyway.
        else:
            obj_path = "/".join(obj.getPhysicalPath())
            if is_locked(obj, self.request):
                # TODO: We could throw an error, but we should probably just unlock.
                logger.warning("Content is locked: %s", obj_path)
            logger.info("Updating existing content at %s", obj_path)
            deserializers = getAdapters((obj, self.request),
                                        IDeserializeFromJson)
            if not deserializers:
                logger.error("Cannot deserialize type %s", obj.portal_type)
                return
            for name, deserializer in deserializers:
                if not name:
                    name = "default"
                # XXX This traceback info overrides the previous.
                # When done in a separate method, it should be fine.
                # __traceback_info__ = name
                __traceback_info__ = dirpath, name
                content = all_info[name]
                if name == "local_roles":
                    # TODO Fix this in plone.restapi.
                    logger.info(
                        "Ignoring local_roles deserializer for now, as it does not accept a content parameter."
                    )
                    continue
                if name == "default" and blobs:
                    for fieldname, path in blobs.items():
                        if fieldname in content:
                            with open(path, "rb") as myfile:
                                content[fieldname]["data"] = myfile.read()
                try:
                    deserializer(data=content)
                except TypeError:
                    # Happens for site root.  But I want to fix it there too, if that is acceptable.
                    logger.info(
                        "TypeError, likely because deserializer does not accept data keyword argument: %s",
                        deserializer)
            # TODO: maybe try / except DeserializationError

        # Report back that we made an import.
        return True