--- a/src/pyams_content/component/illustration/__init__.py Mon Sep 11 14:53:15 2017 +0200
+++ b/src/pyams_content/component/illustration/__init__.py Mon Sep 11 14:54:30 2017 +0200
@@ -16,5 +16,125 @@
# import standard library
# import interfaces
+from pyams_content.component.illustration.interfaces import IIllustrationRenderer, IIllustration, IIllustrationTarget, \
+ ILLUSTRATION_KEY
+from pyams_file.interfaces import DELETED_FILE, IResponsiveImage, IFileInfo
+from pyams_i18n.interfaces import INegotiator, II18n
+from zope.annotation.interfaces import IAnnotations
+from zope.lifecycleevent.interfaces import IObjectAddedEvent, IObjectModifiedEvent
+from zope.location.interfaces import ISublocations
+from zope.traversing.interfaces import ITraversable
# import packages
+from persistent import Persistent
+from pyams_i18n.property import I18nFileProperty
+from pyams_utils.adapter import adapter_config, ContextAdapter
+from pyams_utils.registry import query_utility
+from pyams_utils.request import check_request
+from pyams_utils.vocabulary import vocabulary_config
+from pyramid.events import subscriber
+from pyramid.threadlocal import get_current_registry
+from zope.container.contained import Contained
+from zope.interface import implementer, alsoProvides
+from zope.lifecycleevent import ObjectCreatedEvent, ObjectAddedEvent
+from zope.location import locate
+from zope.schema.fieldproperty import FieldProperty
+from zope.schema.vocabulary import SimpleVocabulary, SimpleTerm
+
+
+@implementer(IIllustration)
+class Illustration(Persistent, Contained):
+ """Illustration persistent class"""
+
+ title = FieldProperty(IIllustration['title'])
+ alt_title = FieldProperty(IIllustration['alt_title'])
+ description = FieldProperty(IIllustration['description'])
+ author = FieldProperty(IIllustration['author'])
+ _data = I18nFileProperty(IIllustration['data'])
+ renderer = FieldProperty(IIllustration['renderer'])
+
+ @property
+ def data(self):
+ return self._data
+
+ @data.setter
+ def data(self, value):
+ self._data = value
+ for data in value.values():
+ if (data is not None) and (data is not DELETED_FILE):
+ alsoProvides(data, IResponsiveImage)
+
+
+@adapter_config(context=IIllustrationTarget, provides=IIllustration)
+def illustration_factory(context):
+ """Illustration factory"""
+ annotations = IAnnotations(context)
+ illustration = annotations.get(ILLUSTRATION_KEY)
+ if illustration is None:
+ illustration = annotations[ILLUSTRATION_KEY] = Illustration()
+ registry = get_current_registry()
+ registry.notify(ObjectCreatedEvent(illustration))
+ locate(illustration, context, '++illustration++')
+ registry.notify(ObjectAddedEvent(illustration, context, '++illustration++'))
+ return illustration
+
+
+def update_illustration_properties(illustration):
+ """Update missing file properties"""
+ request = check_request()
+ i18n = query_utility(INegotiator)
+ if i18n is not None:
+ lang = i18n.server_language
+ data = II18n(illustration).get_attribute('data', lang, request)
+ if data:
+ info = IFileInfo(data)
+ info.title = II18n(illustration).get_attribute('title', lang, request)
+ info.description = II18n(illustration).get_attribute('alt_title', lang, request)
+ for lang, data in (illustration.data or {}).items():
+ if data is not None:
+ IFileInfo(data).language = lang
+
+
+@subscriber(IObjectAddedEvent, context_selector=IIllustration)
+def handle_added_illustration(event):
+ """Handle added illustration"""
+ illustration = event.object
+ update_illustration_properties(illustration)
+
+
+@subscriber(IObjectModifiedEvent, context_selector=IIllustration)
+def handle_modified_illustration(event):
+ """Handle modified illustration"""
+ illustration = event.object
+ update_illustration_properties(illustration)
+
+
+@adapter_config(name='illustration', context=IIllustrationTarget, provides=ITraversable)
+class IllustrationNamespace(ContextAdapter):
+ """++illustration++ namespace adapter"""
+
+ def traverse(self, name, furtherpath=None):
+ return IIllustration(self.context)
+
+
+@adapter_config(name='illustration', context=IIllustrationTarget, provides=ISublocations)
+class IllustrationSublocations(ContextAdapter):
+ """Illustration sub-locations adapter"""
+
+ def sublocations(self):
+ return IIllustration(self.context),
+
+
+@vocabulary_config(name='PyAMS illustration renderers')
+class IllustrationRendererVocabulary(SimpleVocabulary):
+ """Illustration renderer utilities vocabulary"""
+
+ def __init__(self, context=None):
+ request = check_request()
+ translate = request.localizer.translate
+ registry = request.registry
+ context = Illustration()
+ terms = [SimpleTerm(name, title=translate(adapter.label))
+ for name, adapter in sorted(registry.getAdapters((context, request), IIllustrationRenderer),
+ key=lambda x: x[1].weight)]
+ super(IllustrationRendererVocabulary, self).__init__(terms)