Skip to content

Commit

Permalink
override scaling view to keep crops on metadata change
Browse files Browse the repository at this point in the history
  • Loading branch information
tomgross committed Feb 26, 2014
1 parent 24c8e3a commit ab47688
Show file tree
Hide file tree
Showing 9 changed files with 62 additions and 10 deletions.
3 changes: 3 additions & 0 deletions buildout.cfg
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,9 @@ test-eggs +=

versions = versions

[versions]
Pillow = 2.3.0

[omelette]
recipe = collective.recipe.omelette
eggs = ${instance:eggs} ${buildout:test-eggs}
Expand Down
9 changes: 9 additions & 0 deletions src/plone/app/imagecropping/browser/configure.zcml
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@
xmlns="http://namespaces.zope.org/zope"
xmlns:browser="http://namespaces.zope.org/browser"
xmlns:i18n="http://xml.zope.org/namespaces/i18n"
xmlns:zcml="http://namespaces.zope.org/zcml"
i18n_domain="plone">

<include package="Products.CMFCore" file="permissions.zcml" />
Expand Down Expand Up @@ -43,4 +44,12 @@
permission="cmf.ModifyPortalContent"
/>

<browser:page
zcml:condition="installed Products.ATContentTypes"
for="Products.ATContentTypes.interfaces.IATImage"
name="images"
class=".scaling.ImageScaling"
allowed_interface="plone.app.imaging.interfaces.IImageScaling"
permission="zope2.View" />

</configure>
3 changes: 1 addition & 2 deletions src/plone/app/imagecropping/browser/crop.py
Original file line number Diff line number Diff line change
Expand Up @@ -25,7 +25,6 @@ def _crop(self, fieldname, scale, box, interface=None):
"""switch between dexterity and Archetypes
"""
croputils = IImageCroppingUtils(self.context)
field = croputils.get_image_field(fieldname)
data = croputils.get_image_data(fieldname)

original_file = StringIO(data)
Expand All @@ -38,7 +37,7 @@ def _crop(self, fieldname, scale, box, interface=None):
cropped_image_file.seek(0)

croputils.save_cropped(
fieldname, field, scale, cropped_image_file, interface)
fieldname, scale, cropped_image_file, interface)

# store crop information in annotations
self._store(fieldname, scale, box)
Expand Down
4 changes: 0 additions & 4 deletions src/plone/app/imagecropping/browser/editor.py
Original file line number Diff line number Diff line change
Expand Up @@ -154,10 +154,6 @@ def _crop(self):
scale=scale_name,
box=(x1, y1, x2, y2),
interface=self.interface)
# Avoid browser cache
# an empty call of setModificationDate uses current timestamp
self.context.setModificationDate()
self.context.reindexObject()

def __call__(self):
form = self.request.form
Expand Down
17 changes: 17 additions & 0 deletions src/plone/app/imagecropping/browser/scaling.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
from zope.annotation.interfaces import IAnnotations

from plone.app.imagecropping import PAI_STORAGE_KEY
from plone.app.imaging.scaling import ImageScaling as BaseImageScaling


class ImageScaling(BaseImageScaling):

def modified(self):
cropped = IAnnotations(self.context).get(PAI_STORAGE_KEY)
if not cropped:
return super(ImageScaling, self).modified()
else:
return 1

This comment has been minimized.

Copy link
@do3cc

do3cc Mar 17, 2016

Member

This clever hack breaks Plone sites that decide to go away from plone.app.imagecropping but cannot totally remove imagecropping code because some marker interfaces get persistet.

This comment has been minimized.

Copy link
@frisi

frisi Mar 17, 2016

Member

i never was a big fan of this solution

  • it's hard to understand - at least i could never really figure out why how this works ;-)
  • under some circumstances cropped scales get lost on my pages when editing the articles (archetypes) with image fields that are cropped

anyway - could you please tell where and why plone.app.imagecropping leaves persistent interfaces?



# XXX need this for plone.namedfile and NEWSItem too
2 changes: 1 addition & 1 deletion src/plone/app/imagecropping/interfaces.py
Original file line number Diff line number Diff line change
Expand Up @@ -30,7 +30,7 @@ def get_image_size(fieldname, interface):
(100, 200)
"""

def save_cropped(fieldname, field, scale, image_file, interface=None):
def save_cropped(fieldname, scale, image_file, interface=None):
""" Save the cropped iamge under the name of the selected scale in
plone.scale.storage.AnnotationStorage, so that it is available
in plone.app.imaging @@images view
Expand Down
21 changes: 21 additions & 0 deletions src/plone/app/imagecropping/tests/test_cropping.py
Original file line number Diff line number Diff line change
Expand Up @@ -117,3 +117,24 @@ def test_image_formats(self):
# XXX: fixme
# self.assertEqual(open(croppedData).format, 'JPEG',
# "cropped scale does not have same format as the original")

def test_modify_context(self):
""" See https://github.com/collective/plone.app.imagecropping/issues/21
"""

view = self.img.restrictedTraverse('@@crop-image')
traverse = self.portal.REQUEST.traverseName
scales = traverse(self.img, '@@images')
unscaled_thumb = scales.scale('image', 'thumb')

# store cropped version for thumb and check if the result
# is a square now
view._crop(fieldname='image', scale='thumb', box=(14, 14, 218, 218))
thumb = scales.scale('image', 'thumb')
self.failIfEqual(thumb.data, unscaled_thumb.data)

self.img.setTitle('A new title')
self.img.reindexObject()

thumb2 = scales.scale('image', 'thumb')
self.assertEqual(thumb.data, thumb2.data)
3 changes: 2 additions & 1 deletion src/plone/app/imagecropping/tests/test_editor.py
Original file line number Diff line number Diff line change
Expand Up @@ -58,7 +58,8 @@ def test_singleimage_editorview(self):

def test_editview_crop(self):
request = self.layer['request']
request.form.update({'x1': 1.0, 'y1': 2.7, 'x2': 10.6, 'y2': 8.4})
request.form.update({'x1': 1.0, 'y1': 2.7, 'x2': 10.6, 'y2': 8.4,
'scalename': 'mini'})
cropview = self.img.restrictedTraverse('@@croppingeditor')
cropview._crop()

Expand Down
10 changes: 8 additions & 2 deletions src/plone/app/imagecropping/utils.py
Original file line number Diff line number Diff line change
Expand Up @@ -82,9 +82,10 @@ def get_image_size(self, fieldname, interface=None):
return image_size

def save_cropped(
self, fieldname, field, scale, image_file, interface=None):
self, fieldname, scale, image_file, interface=None):
""" see interface
"""
field = self.get_image_field(fieldname)
handler = IImageScaleHandler(field)
sizes = field.getAvailableSizes(self.context)
w, h = sizes[scale]
Expand All @@ -104,6 +105,10 @@ def crop_factory(fieldname, direction='keep', **parameters):
result.close()
return blob, image_format, dimensions

# Avoid browser cache
# calling reindexObject updates the modified metadate too
self.context.reindexObject()

# call storage with actual time in milliseconds
# this always invalidates old scales
storage = AnnotationStorage(self.context, self.now_millis)
Expand Down Expand Up @@ -162,7 +167,7 @@ def get_image_size(self, fieldname, interface=None):
return image_size

def save_cropped(
self, fieldname, field, scale, image_file, interface=None):
self, fieldname, scale, image_file, interface=None):
""" see interface
"""
sizes = getAllowedSizes()
Expand All @@ -173,6 +178,7 @@ def crop_factory(fieldname, **parameters):
if result is not None:
data, format, dimensions = result
mimetype = 'image/%s' % format.lower()
field = self.get_image_field(fieldname)
value = field.__class__(
data,
contentType=mimetype,
Expand Down

0 comments on commit ab47688

Please sign in to comment.