diff --git a/castle/cms/browser/content/fc.py b/castle/cms/browser/content/fc.py index 78b763946..b622b397f 100644 --- a/castle/cms/browser/content/fc.py +++ b/castle/cms/browser/content/fc.py @@ -32,6 +32,12 @@ from zope.event import notify from zope.interface import implementer from zope.lifecycleevent import ObjectModifiedEvent +from zope.component.hooks import getSite +from plone.app.contenttypes.interfaces import IDocument +from zope.annotation.interfaces import IAnnotations +from persistent.mapping import PersistentMapping +from plone.namedfile.file import NamedBlobImage +from ZODB.POSException import POSKeyError from re import sub from plone.app.content.browser.vocabulary import ( @@ -190,6 +196,50 @@ def __call__(self): except CopyError: return self.copy_error() + # XXX: Experimental code block + # Can be removed in lieu of installing "experimental.gracefulblobmissing" package, + # which ignores missing blob errors + + site = getSite() + for path in paste_data.get('paths'): + print(path) + + try: + obj = site.restrictedTraverse(path.strip('/'), None) + print(obj) + if obj is None: + logger.error("Object not found: '{}'".format(path)) + return + except Exception as e: + logger.error("Error retrieving object: {}".format(e)) + return + + if IDocument.providedBy(obj): + annotations = IAnnotations(obj) + + # The ANNOTATIONS_KEY_PREFIX ignores tiles with images/blobs + for key in annotations.keys(): + data = annotations[key] + + # PersistentMapping tiles contain the blobs we want + if isinstance(data, PersistentMapping): + for item in data.values(): + if isinstance(item, dict) and isinstance(item.get('data'), NamedBlobImage): + blobfile = item.get('data') + blob = blobfile._blob + try: + # Check blob, opening may not be best approach + f = blob.open('r') + f.close() + except POSKeyError: + # Broken blob reference + # XXX: Call save() on blob or reassign to generic fallback blob + path_on_disk = blob._p_blob_committed + pass + + # XXX: end of block + + tasks.paste_items.delay( self.request.form['folder'], paste_data['op'], paste_data['mdatas']) diff --git a/castle/cms/profiles/3017/registry/resources.xml b/castle/cms/profiles/3017/registry/resources.xml new file mode 100644 index 000000000..e3fc35ffa --- /dev/null +++ b/castle/cms/profiles/3017/registry/resources.xml @@ -0,0 +1,15 @@ + + + + + 2024-09-24 00:00:00 + + + + 2024-09-24 00:00:00 + + + diff --git a/castle/cms/profiles/default/metadata.xml b/castle/cms/profiles/default/metadata.xml index 246079d28..6ce391ae7 100644 --- a/castle/cms/profiles/default/metadata.xml +++ b/castle/cms/profiles/default/metadata.xml @@ -1,6 +1,6 @@ - 3016 + 3017 profile-plone.app.querystring:default profile-plone.app.mosaic:default diff --git a/castle/cms/upgrades.zcml b/castle/cms/upgrades.zcml index 435d45676..5813bbfd0 100644 --- a/castle/cms/upgrades.zcml +++ b/castle/cms/upgrades.zcml @@ -261,4 +261,20 @@ profile="castle.cms:default" /> + + + diff --git a/castle/cms/upgrades/__init__.py b/castle/cms/upgrades/__init__.py index 225cbd95a..885924cca 100644 --- a/castle/cms/upgrades/__init__.py +++ b/castle/cms/upgrades/__init__.py @@ -141,3 +141,4 @@ def upgrade_3011(site, logger=CASTLE_LOGGER): upgrade_3014 = default_upgrade_factory('3014') upgrade_3015 = default_upgrade_factory('3015') upgrade_3016 = default_upgrade_factory('3016') +upgrade_3017 = default_upgrade_factory('3017') diff --git a/travis.cfg b/travis.cfg index 51312737e..b36c0f147 100644 --- a/travis.cfg +++ b/travis.cfg @@ -38,6 +38,7 @@ eggs += Pillow Products.PloneKeywordManager plone.app.robotframework + experimental.gracefulblobmissing zcml = castle.cms-overrides diff --git a/versions.cfg b/versions.cfg index 104499b8f..a3ef5d589 100644 --- a/versions.cfg +++ b/versions.cfg @@ -57,6 +57,7 @@ z3c.jbot = 0.7.2 castle.theme = 1.0.6 Products.PloneKeywordManager = 2.2.1 wildcard.hps = 1.4.0 +experimental.gracefulblobmissing = 2.0 # dependency pins