From 096410eb57a097b9a63c803420422612a587fec4 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Juan=20Pablo=20Gim=C3=A9nez?= Date: Fri, 12 Apr 2013 09:23:06 -0300 Subject: [PATCH 01/12] update changelog and some improvements. --- docs/HISTORY.rst | 7 ++++++- src/collective/cover/tiles/carousel.py | 1 - src/collective/cover/tiles/image.py | 24 ++++++++++++++++++++---- 3 files changed, 26 insertions(+), 6 deletions(-) diff --git a/docs/HISTORY.rst b/docs/HISTORY.rst index af39b9b35..7f37365fa 100644 --- a/docs/HISTORY.rst +++ b/docs/HISTORY.rst @@ -6,11 +6,16 @@ Because you have to know where your towel is. 1.0a3 (unreleased) ^^^^^^^^^^^^^^^^^^ +- Implement issue #156 to copy scales from the original object, this way + we can support products like plone.app.imagecropping. [jpgimenez] + +- Improve the way than images are accesed from the original object, using + the standard images traversal. [jpgimenez] + - Fixed a bug with Plone 4.3 that avoided TinyMCE being displayed for RichText. (closes `#157`_). [ericof] - 1.0a2 (2013-04-09) ^^^^^^^^^^^^^^^^^^ - Move Galleria's stylesheet and JS init to . [davilima6] diff --git a/src/collective/cover/tiles/carousel.py b/src/collective/cover/tiles/carousel.py index 43ba2ac37..812fedd2e 100644 --- a/src/collective/cover/tiles/carousel.py +++ b/src/collective/cover/tiles/carousel.py @@ -1,5 +1,4 @@ # -*- coding: utf-8 -*- - from zope import schema from Products.Five.browser.pagetemplatefile import ViewPageTemplateFile diff --git a/src/collective/cover/tiles/image.py b/src/collective/cover/tiles/image.py index e2b2eae8d..cfed43614 100644 --- a/src/collective/cover/tiles/image.py +++ b/src/collective/cover/tiles/image.py @@ -1,17 +1,21 @@ # -*- coding: utf-8 -*- - +import time +from Acquisition import aq_inner from zope.interface import implements +from zope.component import queryMultiAdapter from Products.Five.browser.pagetemplatefile import ViewPageTemplateFile from plone.namedfile.field import NamedBlobImage as NamedImage -from plone.namedfile.file import NamedBlobImage +from plone.namedfile.file import NamedBlobImage as NamedImageFile from plone.tiles.interfaces import ITileDataManager from collective.cover import _ from collective.cover.tiles.base import IPersistentCoverTile from collective.cover.tiles.base import PersistentCoverTile +from collective.cover.tiles.base import AnnotationStorage +from plone.scale.storage import AnnotationStorage as BaseAnnotationStorage class IImageTile(IPersistentCoverTile): @@ -37,9 +41,21 @@ def populate_with_object(self, obj): # check permissions super(ImageTile, self).populate_with_object(obj) - data_mgr = ITileDataManager(self) + data = {} + obj = aq_inner(obj) + scales = queryMultiAdapter((obj, self.request), name="images") + if scales and scales.scale('image'): + data['image'] = NamedImageFile(str(scales.scale('image').data)) - data_mgr.set({'image': NamedBlobImage(obj.getImage().data)}) + data_mgr = ITileDataManager(self) + data_mgr.set(data) + tile_storage = AnnotationStorage(self) + obj_storage = BaseAnnotationStorage(obj) + for k, v in obj_storage.items(): + tile_storage.storage[k] = v + tile_storage.storage[k]['modified'] = '%f' % time.time() + scale_data = obj_storage.storage[k]['data'].open().read() + tile_storage.storage[k]['data'] = NamedImageFile(str(scale_data)) def accepted_ct(self): """ Return a list of content types accepted by the tile. From 9f5c6fd4692994903de9fb1a7417c4000597baf3 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Juan=20Pablo=20Gim=C3=A9nez?= Date: Fri, 12 Apr 2013 10:23:29 -0300 Subject: [PATCH 02/12] Fix test suite... --- src/collective/cover/testing.py | 2 +- src/collective/cover/tiles/basic.py | 7 ++++--- src/collective/cover/tiles/image.py | 7 ++++--- 3 files changed, 9 insertions(+), 7 deletions(-) diff --git a/src/collective/cover/testing.py b/src/collective/cover/testing.py index b85b415e0..dcae8f1cc 100644 --- a/src/collective/cover/testing.py +++ b/src/collective/cover/testing.py @@ -88,7 +88,7 @@ def setUpPloneSite(self, portal): # Install into Plone site using portal_setup self.applyProfile(portal, 'collective.cover:default') self.applyProfile(portal, 'collective.cover:testfixture') - portal['my-image'].setImage(loadImage('canoneye.jpg')) + portal['my-image'].setImage(generate_jpeg(50, 50)) portal['my-image1'].setImage(generate_jpeg(50, 50)) portal['my-image2'].setImage(generate_jpeg(50, 50)) portal['my-file'].setFile(loadImage('canoneye.jpg')) diff --git a/src/collective/cover/tiles/basic.py b/src/collective/cover/tiles/basic.py index b9faf634d..969c7e7fe 100644 --- a/src/collective/cover/tiles/basic.py +++ b/src/collective/cover/tiles/basic.py @@ -130,10 +130,11 @@ def populate_with_object(self, obj): # plone.app.referenceablebehavior obj = aq_inner(obj) - scales = queryMultiAdapter((obj, self.request), name="images") - if scales and scales.scale('image'): + try: + scales = queryMultiAdapter((obj, self.request), name="images") data['image'] = NamedImageFile(str(scales.scale('image').data)) - + except AttributeError: + pass data_mgr = ITileDataManager(self) data_mgr.set(data) tile_storage = AnnotationStorage(self) diff --git a/src/collective/cover/tiles/image.py b/src/collective/cover/tiles/image.py index cfed43614..50f7061ae 100644 --- a/src/collective/cover/tiles/image.py +++ b/src/collective/cover/tiles/image.py @@ -43,10 +43,11 @@ def populate_with_object(self, obj): data = {} obj = aq_inner(obj) - scales = queryMultiAdapter((obj, self.request), name="images") - if scales and scales.scale('image'): + try: + scales = queryMultiAdapter((obj, self.request), name="images") data['image'] = NamedImageFile(str(scales.scale('image').data)) - + except AttributeError: + pass data_mgr = ITileDataManager(self) data_mgr.set(data) tile_storage = AnnotationStorage(self) From 8e12a8499f53889980c5b25181517a3d0367ed1e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Juan=20Pablo=20Gim=C3=A9nez?= Date: Fri, 12 Apr 2013 17:16:17 -0300 Subject: [PATCH 03/12] Trigger Travis --- docs/HISTORY.rst | 9 +++++---- 1 file changed, 5 insertions(+), 4 deletions(-) diff --git a/docs/HISTORY.rst b/docs/HISTORY.rst index 7f37365fa..e3db09324 100644 --- a/docs/HISTORY.rst +++ b/docs/HISTORY.rst @@ -6,11 +6,12 @@ Because you have to know where your towel is. 1.0a3 (unreleased) ^^^^^^^^^^^^^^^^^^ -- Implement issue #156 to copy scales from the original object, this way - we can support products like plone.app.imagecropping. [jpgimenez] +- Implement issue `#156`_ to copy scales from the original object, + this way we can support products like plone.app.imagecropping. + [jpgimenez] -- Improve the way than images are accesed from the original object, using - the standard images traversal. [jpgimenez] +- Improve the way than images are accesed from the original object, + using the standard images traversal. [jpgimenez] - Fixed a bug with Plone 4.3 that avoided TinyMCE being displayed for RichText. (closes `#157`_). From 96fbf3d183c323418c7cb08def9ccf3fe2cb4953 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Juan=20Pablo=20Gim=C3=A9nez?= Date: Fri, 12 Apr 2013 17:17:37 -0300 Subject: [PATCH 04/12] typo --- docs/HISTORY.rst | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs/HISTORY.rst b/docs/HISTORY.rst index e3db09324..89ada5245 100644 --- a/docs/HISTORY.rst +++ b/docs/HISTORY.rst @@ -6,7 +6,7 @@ Because you have to know where your towel is. 1.0a3 (unreleased) ^^^^^^^^^^^^^^^^^^ -- Implement issue `#156`_ to copy scales from the original object, +- Implement issue `#158`_ to copy scales from the original object, this way we can support products like plone.app.imagecropping. [jpgimenez] From b575ea6811af9b9a483a517818e0ff8316de63f2 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Juan=20Pablo=20Gim=C3=A9nez?= Date: Wed, 17 Apr 2013 00:28:41 -0300 Subject: [PATCH 05/12] Now images are traversed to the original object if there isn't a local image loaded into the tile. --- src/collective/cover/tests/test_basic_tile.py | 45 +++++++++---------- src/collective/cover/tiles/basic.py | 42 ++++++++--------- src/collective/cover/tiles/templates/basic.pt | 9 ++-- 3 files changed, 49 insertions(+), 47 deletions(-) diff --git a/src/collective/cover/tests/test_basic_tile.py b/src/collective/cover/tests/test_basic_tile.py index 345e905ac..deccc3eef 100644 --- a/src/collective/cover/tests/test_basic_tile.py +++ b/src/collective/cover/tests/test_basic_tile.py @@ -4,7 +4,6 @@ from DateTime import DateTime -from ZODB.blob import Blob from zope.interface.verify import verifyClass from zope.interface.verify import verifyObject @@ -16,8 +15,9 @@ from collective.cover.tiles.permissions import ITilesPermissions from zope.annotation.interfaces import IAnnotations from collective.cover.tiles.configuration import ITilesConfigurationScreen -from plone.scale.storage import AnnotationStorage as BaseAnnotationStorage -from collective.cover.tiles.base import AnnotationStorage +from zope.component import queryMultiAdapter +from plone.namedfile.file import NamedBlobImage as NamedImageFile +from plone.tiles.interfaces import ITileDataManager class BasicTileTestCase(unittest.TestCase): @@ -100,8 +100,8 @@ def test_basic_tile_render(self): self.assertIn( "This news item was created for testing purposes", rendered) - # the image must be there - self.assertIn('test-basic-tile/@@images', rendered) + # the image must be there, pointing to original image + self.assertIn('my-news-item/@@images', rendered) # the localized time must be there utils = getMultiAdapter((self.portal, self.request), name=u'plone') @@ -140,7 +140,11 @@ def test_delete_tile_persistent_data(self): def test_image_traverser(self): obj = self.portal['my-image'] - self.tile.populate_with_object(obj) + data = self.tile.data + scales = queryMultiAdapter((obj, self.request), name="images") + self.tile.data['image'] = NamedImageFile(str(scales.scale('image').data)) + data_mgr = ITileDataManager(self.tile) + data_mgr.set(data) scales = self.layer['portal'].restrictedTraverse('@@%s/%s/@@images' % ('collective.cover.basic', 'test-basic-tile',)) @@ -148,21 +152,16 @@ def test_image_traverser(self): self.assertTrue(images_are_equal(str(self.tile.data['image'].data), str(img.index_html().read()))) - def test_modified_scale(self): - obj = self.portal['my-image'] - obj_scales = obj.restrictedTraverse('@@images') - self.assertFalse(BaseAnnotationStorage(obj).items()) - obj_scales.scale('image', width=64, height=64) - obj_storage = BaseAnnotationStorage(obj) - obj_storage[(('fieldname', 'image'), - ('height', 64), - ('width', 64))]['data'] = Blob(generate_jpeg(64, 64)) + def test_basic_tile_image(self): + obj = self.portal['my-news-item'] + obj.setImage(generate_jpeg(128, 128)) + obj.reindexObject() + self.tile.populate_with_object(obj) - tile_storage = AnnotationStorage(self.tile) - self.assertTrue(images_are_equal( - obj_storage[(('fieldname', 'image'), - ('height', 64), - ('width', 64))]['data'].open().read(), - tile_storage[(('fieldname', 'image'), - ('height', 64), - ('width', 64))]['data'].open().read())) + rendered = self.tile() + + # the image must be there, pointing to original image + self.assertIn('my-news-item/@@images', rendered) + + # old code copy the image + self.assertNotIn('test-basic-tile/@@images', rendered) diff --git a/src/collective/cover/tiles/basic.py b/src/collective/cover/tiles/basic.py index 969c7e7fe..c44fe5afd 100644 --- a/src/collective/cover/tiles/basic.py +++ b/src/collective/cover/tiles/basic.py @@ -1,15 +1,11 @@ # -*- coding: utf-8 -*- -import time -from Acquisition import aq_inner from zope import schema from zope.interface import implements from zope.component import getUtility -from zope.component import queryMultiAdapter from plone.memoize import view from plone.memoize.instance import memoizedproperty from plone.namedfile.field import NamedBlobImage as NamedImage -from plone.namedfile.file import NamedBlobImage as NamedImageFile from plone.registry.interfaces import IRegistry from plone.tiles.interfaces import ITileDataManager from plone.uuid.interfaces import IUUID @@ -23,8 +19,7 @@ from collective.cover.tiles.base import PersistentCoverTile from collective.cover.controlpanel import ICoverSettings from collective.cover.tiles.configuration_view import IDefaultConfigureForm -from collective.cover.tiles.base import AnnotationStorage -from plone.scale.storage import AnnotationStorage as BaseAnnotationStorage +from plone.app.uuid.utils import uuidToObject class IBasicTile(IPersistentCoverTile): @@ -109,6 +104,21 @@ def Subject(self): if self.brain is not None: return self.brain.Subject + def img_obj(self): + """ Return the image object, internal or external. + """ + if self.data.get('image') not in (None, True): + return self + elif self.data.get('uuid') is not None: + obj = uuidToObject(self.data.get('uuid')) + try: + # Target obj have an image? + obj.restrictedTraverse('@@images').scale('image') + return obj + except AttributeError: + return None + return None + def populate_with_object(self, obj): super(BasicTile, self).populate_with_object(obj) @@ -128,22 +138,8 @@ def populate_with_object(self, obj): # behaviour enable then it will not work here # we need to figure out how to enforce the use of # plone.app.referenceablebehavior - - obj = aq_inner(obj) - try: - scales = queryMultiAdapter((obj, self.request), name="images") - data['image'] = NamedImageFile(str(scales.scale('image').data)) - except AttributeError: - pass data_mgr = ITileDataManager(self) data_mgr.set(data) - tile_storage = AnnotationStorage(self) - obj_storage = BaseAnnotationStorage(obj) - for k, v in obj_storage.items(): - tile_storage.storage[k] = v - tile_storage.storage[k]['modified'] = '%f' % time.time() - scale_data = obj_storage.storage[k]['data'].open().read() - tile_storage.storage[k]['data'] = NamedImageFile(str(scale_data)) @view.memoize def accepted_ct(self): @@ -158,3 +154,9 @@ def accepted_ct(self): registry = getUtility(IRegistry) settings = registry.forInterface(ICoverSettings) return settings.searchable_content_types + + def get_configured_fields(self): + if self.data['image'] is None and self.data['uuid']: + self.data['image'] = True + fields = super(BasicTile, self).get_configured_fields() + return fields diff --git a/src/collective/cover/tiles/templates/basic.pt b/src/collective/cover/tiles/templates/basic.pt index d815a11a0..8547eb31a 100644 --- a/src/collective/cover/tiles/templates/basic.pt +++ b/src/collective/cover/tiles/templates/basic.pt @@ -40,13 +40,14 @@ - + position python:field.get('position', ''); + img_obj view/img_obj;"> - Date: Fri, 12 Apr 2013 10:23:29 -0300 Subject: [PATCH 07/12] Fix test suite... --- src/collective/cover/testing.py | 2 +- src/collective/cover/tiles/image.py | 7 ++++--- 2 files changed, 5 insertions(+), 4 deletions(-) diff --git a/src/collective/cover/testing.py b/src/collective/cover/testing.py index b6f2d3b9f..7fe120a23 100644 --- a/src/collective/cover/testing.py +++ b/src/collective/cover/testing.py @@ -88,7 +88,7 @@ def setUpPloneSite(self, portal): # Install into Plone site using portal_setup self.applyProfile(portal, 'collective.cover:default') self.applyProfile(portal, 'collective.cover:testfixture') - portal['my-image'].setImage(loadFile('canoneye.jpg')) + portal['my-image'].setImage(generate_jpeg(50, 50)) portal['my-image1'].setImage(generate_jpeg(50, 50)) portal['my-image2'].setImage(generate_jpeg(50, 50)) portal['my-file'].setFile(loadFile('lorem_ipsum.txt')) diff --git a/src/collective/cover/tiles/image.py b/src/collective/cover/tiles/image.py index cfed43614..50f7061ae 100644 --- a/src/collective/cover/tiles/image.py +++ b/src/collective/cover/tiles/image.py @@ -43,10 +43,11 @@ def populate_with_object(self, obj): data = {} obj = aq_inner(obj) - scales = queryMultiAdapter((obj, self.request), name="images") - if scales and scales.scale('image'): + try: + scales = queryMultiAdapter((obj, self.request), name="images") data['image'] = NamedImageFile(str(scales.scale('image').data)) - + except AttributeError: + pass data_mgr = ITileDataManager(self) data_mgr.set(data) tile_storage = AnnotationStorage(self) From dec6477b2b72f0c554a5a22bac3b042320ac16d7 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Juan=20Pablo=20Gim=C3=A9nez?= Date: Fri, 12 Apr 2013 17:16:17 -0300 Subject: [PATCH 08/12] Trigger Travis --- docs/HISTORY.rst | 9 +++++---- 1 file changed, 5 insertions(+), 4 deletions(-) diff --git a/docs/HISTORY.rst b/docs/HISTORY.rst index c54e077bc..56e2555ee 100644 --- a/docs/HISTORY.rst +++ b/docs/HISTORY.rst @@ -8,11 +8,12 @@ Because you have to know where your towel is. - Implements an original size scale to show the original image. [jpgimenez] -- Implement issue #156 to copy scales from the original object, this way - we can support products like plone.app.imagecropping. [jpgimenez] +- Implement issue `#156`_ to copy scales from the original object, + this way we can support products like plone.app.imagecropping. + [jpgimenez] -- Improve the way than images are accesed from the original object, using - the standard images traversal. [jpgimenez] +- Improve the way than images are accesed from the original object, + using the standard images traversal. [jpgimenez] - Fixed a bug with Plone 4.3 that avoided TinyMCE being displayed for RichText. (closes `#157`_). From 027c464def9f8666e2010ac9ccaf3e8e36e51fe7 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Juan=20Pablo=20Gim=C3=A9nez?= Date: Fri, 12 Apr 2013 17:17:37 -0300 Subject: [PATCH 09/12] typo --- docs/HISTORY.rst | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs/HISTORY.rst b/docs/HISTORY.rst index 56e2555ee..bb2ebb050 100644 --- a/docs/HISTORY.rst +++ b/docs/HISTORY.rst @@ -8,7 +8,7 @@ Because you have to know where your towel is. - Implements an original size scale to show the original image. [jpgimenez] -- Implement issue `#156`_ to copy scales from the original object, +- Implement issue `#158`_ to copy scales from the original object, this way we can support products like plone.app.imagecropping. [jpgimenez] From 59ec5ff33391a8be1a3696eb2fbf895188d2f7eb Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Juan=20Pablo=20Gim=C3=A9nez?= Date: Wed, 17 Apr 2013 00:28:41 -0300 Subject: [PATCH 10/12] Now images are traversed to the original object if there isn't a local image loaded into the tile. --- src/collective/cover/tests/test_basic_tile.py | 45 +++++++++---------- src/collective/cover/tiles/basic.py | 42 ++++++++--------- src/collective/cover/tiles/templates/basic.pt | 18 ++++++-- 3 files changed, 58 insertions(+), 47 deletions(-) diff --git a/src/collective/cover/tests/test_basic_tile.py b/src/collective/cover/tests/test_basic_tile.py index 63d18242f..65ba10065 100644 --- a/src/collective/cover/tests/test_basic_tile.py +++ b/src/collective/cover/tests/test_basic_tile.py @@ -4,7 +4,6 @@ from DateTime import DateTime -from ZODB.blob import Blob from zope.interface.verify import verifyClass from zope.interface.verify import verifyObject @@ -16,8 +15,9 @@ from collective.cover.tiles.permissions import ITilesPermissions from zope.annotation.interfaces import IAnnotations from collective.cover.tiles.configuration import ITilesConfigurationScreen -from plone.scale.storage import AnnotationStorage as BaseAnnotationStorage -from collective.cover.tiles.base import AnnotationStorage +from zope.component import queryMultiAdapter +from plone.namedfile.file import NamedBlobImage as NamedImageFile +from plone.tiles.interfaces import ITileDataManager class BasicTileTestCase(unittest.TestCase): @@ -100,8 +100,8 @@ def test_basic_tile_render(self): self.assertIn( "This news item was created for testing purposes", rendered) - # the image must be there - self.assertIn('test-basic-tile/@@images', rendered) + # the image must be there, pointing to original image + self.assertIn('my-news-item/@@images', rendered) # the localized time must be there utils = getMultiAdapter((self.portal, self.request), name=u'plone') @@ -152,7 +152,11 @@ def test_populate_with_file(self): def test_image_traverser(self): obj = self.portal['my-image'] - self.tile.populate_with_object(obj) + data = self.tile.data + scales = queryMultiAdapter((obj, self.request), name="images") + self.tile.data['image'] = NamedImageFile(str(scales.scale('image').data)) + data_mgr = ITileDataManager(self.tile) + data_mgr.set(data) scales = self.layer['portal'].restrictedTraverse('@@%s/%s/@@images' % ('collective.cover.basic', 'test-basic-tile',)) @@ -160,21 +164,16 @@ def test_image_traverser(self): self.assertTrue(images_are_equal(str(self.tile.data['image'].data), str(img.index_html().read()))) - def test_modified_scale(self): - obj = self.portal['my-image'] - obj_scales = obj.restrictedTraverse('@@images') - self.assertFalse(BaseAnnotationStorage(obj).items()) - obj_scales.scale('image', width=64, height=64) - obj_storage = BaseAnnotationStorage(obj) - obj_storage[(('fieldname', 'image'), - ('height', 64), - ('width', 64))]['data'] = Blob(generate_jpeg(64, 64)) + def test_basic_tile_image(self): + obj = self.portal['my-news-item'] + obj.setImage(generate_jpeg(128, 128)) + obj.reindexObject() + self.tile.populate_with_object(obj) - tile_storage = AnnotationStorage(self.tile) - self.assertTrue(images_are_equal( - obj_storage[(('fieldname', 'image'), - ('height', 64), - ('width', 64))]['data'].open().read(), - tile_storage[(('fieldname', 'image'), - ('height', 64), - ('width', 64))]['data'].open().read())) + rendered = self.tile() + + # the image must be there, pointing to original image + self.assertIn('my-news-item/@@images', rendered) + + # old code copy the image + self.assertNotIn('test-basic-tile/@@images', rendered) diff --git a/src/collective/cover/tiles/basic.py b/src/collective/cover/tiles/basic.py index 969c7e7fe..c44fe5afd 100644 --- a/src/collective/cover/tiles/basic.py +++ b/src/collective/cover/tiles/basic.py @@ -1,15 +1,11 @@ # -*- coding: utf-8 -*- -import time -from Acquisition import aq_inner from zope import schema from zope.interface import implements from zope.component import getUtility -from zope.component import queryMultiAdapter from plone.memoize import view from plone.memoize.instance import memoizedproperty from plone.namedfile.field import NamedBlobImage as NamedImage -from plone.namedfile.file import NamedBlobImage as NamedImageFile from plone.registry.interfaces import IRegistry from plone.tiles.interfaces import ITileDataManager from plone.uuid.interfaces import IUUID @@ -23,8 +19,7 @@ from collective.cover.tiles.base import PersistentCoverTile from collective.cover.controlpanel import ICoverSettings from collective.cover.tiles.configuration_view import IDefaultConfigureForm -from collective.cover.tiles.base import AnnotationStorage -from plone.scale.storage import AnnotationStorage as BaseAnnotationStorage +from plone.app.uuid.utils import uuidToObject class IBasicTile(IPersistentCoverTile): @@ -109,6 +104,21 @@ def Subject(self): if self.brain is not None: return self.brain.Subject + def img_obj(self): + """ Return the image object, internal or external. + """ + if self.data.get('image') not in (None, True): + return self + elif self.data.get('uuid') is not None: + obj = uuidToObject(self.data.get('uuid')) + try: + # Target obj have an image? + obj.restrictedTraverse('@@images').scale('image') + return obj + except AttributeError: + return None + return None + def populate_with_object(self, obj): super(BasicTile, self).populate_with_object(obj) @@ -128,22 +138,8 @@ def populate_with_object(self, obj): # behaviour enable then it will not work here # we need to figure out how to enforce the use of # plone.app.referenceablebehavior - - obj = aq_inner(obj) - try: - scales = queryMultiAdapter((obj, self.request), name="images") - data['image'] = NamedImageFile(str(scales.scale('image').data)) - except AttributeError: - pass data_mgr = ITileDataManager(self) data_mgr.set(data) - tile_storage = AnnotationStorage(self) - obj_storage = BaseAnnotationStorage(obj) - for k, v in obj_storage.items(): - tile_storage.storage[k] = v - tile_storage.storage[k]['modified'] = '%f' % time.time() - scale_data = obj_storage.storage[k]['data'].open().read() - tile_storage.storage[k]['data'] = NamedImageFile(str(scale_data)) @view.memoize def accepted_ct(self): @@ -158,3 +154,9 @@ def accepted_ct(self): registry = getUtility(IRegistry) settings = registry.forInterface(ICoverSettings) return settings.searchable_content_types + + def get_configured_fields(self): + if self.data['image'] is None and self.data['uuid']: + self.data['image'] = True + fields = super(BasicTile, self).get_configured_fields() + return fields diff --git a/src/collective/cover/tiles/templates/basic.pt b/src/collective/cover/tiles/templates/basic.pt index 5223395e7..8547eb31a 100644 --- a/src/collective/cover/tiles/templates/basic.pt +++ b/src/collective/cover/tiles/templates/basic.pt @@ -40,10 +40,20 @@ - - + + + + From a16a81fe241d4961a4341a268d15cc17e2f66fb7 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Juan=20Pablo=20Gim=C3=A9nez?= Date: Wed, 17 Apr 2013 13:03:29 -0300 Subject: [PATCH 11/12] Purge cache when changing images. --- setup.py | 1 + src/collective/cover/tiles/data.py | 3 +++ 2 files changed, 4 insertions(+) diff --git a/setup.py b/setup.py index 917bc88c9..11b61cb34 100644 --- a/setup.py +++ b/setup.py @@ -50,6 +50,7 @@ 'collective.js.galleria', 'collective.js.jqueryui', 'Pillow', + 'plone.cachepurging', 'plone.app.blocks', 'plone.app.dexterity[grok,relations]', 'plone.app.jquery>=1.7.2', diff --git a/src/collective/cover/tiles/data.py b/src/collective/cover/tiles/data.py index b64c26c7d..6852ba57b 100644 --- a/src/collective/cover/tiles/data.py +++ b/src/collective/cover/tiles/data.py @@ -9,6 +9,8 @@ from plone.namedfile.interfaces import INamedImage from collective.cover.tiles.base import IPersistentCoverTile +from z3c.caching.purge import Purge +from zope.event import notify class PersistentCoverTileDataManager(PersistentTileDataManager): @@ -41,5 +43,6 @@ def set(self, data): (self.key in self.annotations and data[k] != self.annotations[self.key][k])): # set modification time of the image + notify(Purge(self.tile)) data['%s_mtime' % k] = '%f' % time.time() self.annotations[self.key] = PersistentDict(data) From 2929a34743060f98405e6971660416a6dd6557f5 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Juan=20Pablo=20Gim=C3=A9nez?= Date: Wed, 17 Apr 2013 23:55:53 -0300 Subject: [PATCH 12/12] Implements IPurgePaths for cover tiles, this code should be moved to plone.tiles to implement it for every persitent tile. --- src/collective/cover/tests/test_basic_tile.py | 38 +++++++++++++++++++ src/collective/cover/tiles/base.py | 32 +++++++++++++++- src/collective/cover/tiles/configure.zcml | 2 + 3 files changed, 71 insertions(+), 1 deletion(-) diff --git a/src/collective/cover/tests/test_basic_tile.py b/src/collective/cover/tests/test_basic_tile.py index 65ba10065..0b062ab90 100644 --- a/src/collective/cover/tests/test_basic_tile.py +++ b/src/collective/cover/tests/test_basic_tile.py @@ -18,6 +18,13 @@ from zope.component import queryMultiAdapter from plone.namedfile.file import NamedBlobImage as NamedImageFile from plone.tiles.interfaces import ITileDataManager +from zope.annotation.interfaces import IAttributeAnnotatable +from zope.interface import alsoProvides +from zope.component import provideUtility +from zope.globalrequest import setRequest +from plone.registry.interfaces import IRegistry +from plone.cachepurging.interfaces import ICachePurgingSettings +from zope.component import queryUtility class BasicTileTestCase(unittest.TestCase): @@ -177,3 +184,34 @@ def test_basic_tile_image(self): # old code copy the image self.assertNotIn('test-basic-tile/@@images', rendered) + + def test_basic_tile_purge_cache(self): + request = self.request + alsoProvides(request, IAttributeAnnotatable) + setRequest(request) + + registry = queryUtility(IRegistry) + registry.registerInterface(ICachePurgingSettings) + provideUtility(registry, IRegistry) + + settings = registry.forInterface(ICachePurgingSettings) + settings.enabled = True + settings.cachingProxies = ('http://localhost:1234',) + + obj = self.portal['my-image'] + data = self.tile.data + scales = queryMultiAdapter((obj, self.request), name="images") + self.tile.data['image'] = NamedImageFile(str(scales.scale('image').data)) + data_mgr = ITileDataManager(self.tile) + data_mgr.set(data) + + self.assertEquals(set(['/@@collective.cover.basic/test-basic-tile', + '/@@collective.cover.basic/test-basic-tile/@@images/image', + '/@@collective.cover.basic/test-basic-tile/@@images/icon', + '/@@collective.cover.basic/test-basic-tile/@@images/mini', + '/@@collective.cover.basic/test-basic-tile/@@images/large', + '/@@collective.cover.basic/test-basic-tile/@@images/listing', + '/@@collective.cover.basic/test-basic-tile/@@images/thumb', + '/@@collective.cover.basic/test-basic-tile/@@images/preview', + '/@@collective.cover.basic/test-basic-tile/@@images/tile']), + IAnnotations(request)['plone.cachepurging.urls']) diff --git a/src/collective/cover/tiles/base.py b/src/collective/cover/tiles/base.py index ba2501a80..3272d8bd4 100644 --- a/src/collective/cover/tiles/base.py +++ b/src/collective/cover/tiles/base.py @@ -7,7 +7,7 @@ from logging import exception from AccessControl import Unauthorized -from Acquisition import aq_base +from Acquisition import aq_base, aq_parent from ZODB.POSException import ConflictError from zope.component import getMultiAdapter @@ -51,6 +51,8 @@ from collective.cover.tiles.permissions import ITilesPermissions from collective.cover import _ +from z3c.caching.interfaces import IPurgePaths +from zope.component import adapts logger = logging.getLogger(PROJECTNAME) @@ -389,3 +391,31 @@ def scale(self, fieldname=None, scale=None, info['fieldname'] = fieldname scale_view = ImageScale(self.context, self.request, **info) return scale_view.__of__(self.context) + + +class PersistentCoverTilePurgePaths(object): + """Paths to purge for cover tiles + """ + + implements(IPurgePaths) + adapts(IPersistentCoverTile) + + def __init__(self, context): + self.context = context + + def getRelativePaths(self): + context = self.context.aq_inner + portal_state = getMultiAdapter((context, context.request), + name=u'plone_portal_state') + prefix = context.url.replace(portal_state.portal_url(), '', 1) + + yield prefix + for _, v in context.data.items(): + if INamedImage.providedBy(v): + yield "%s/@@images/image" % prefix + scales = aq_parent(context).restrictedTraverse(prefix + '/@@images') + for size in scales.getAvailableSizes().keys(): + yield "%s/@@images/%s" % (prefix, size,) + + def getAbsolutePaths(self): + return [] diff --git a/src/collective/cover/tiles/configure.zcml b/src/collective/cover/tiles/configure.zcml index 5cd0fa700..01c3fe738 100644 --- a/src/collective/cover/tiles/configure.zcml +++ b/src/collective/cover/tiles/configure.zcml @@ -225,4 +225,6 @@ factory=".list.GenericUIDsProvider" /> + +