[Products.Silva][Sylvain Viollon] Make possible to use GhostAsse...
[email protected] Mon, 11 Nov 2013 15:01:54 +0100
| Newsgroups | gmane.comp.web.zope.silva.cvs |
|---|---|
| Message-ID | <[email protected]> |
author: Sylvain Viollon
date: Mon Nov 11 15:01:46 2013 +0100
revision: 11878:eb61cd1d2344 in Products.Silva
branch: 2.4
details: https://hg.infrae.com/Products.Silva?cmd=changeset;node=eb61cd1d2344
modified: Products/Silva/Ghost/base.py Products/Silva/GhostAsset/content.py Products/Silva/tests/test_ghost_asset.py
added:
removed:
log: Make possible to use GhostAsset as images in the documents if they
points to an actual image.
diffstat:
Products/Silva/Ghost/base.py | 19 +++++++++-----
Products/Silva/GhostAsset/content.py | 40 +++++++++++++++++++++++++++++++-
Products/Silva/tests/test_ghost_asset.py | 37 +++++++++++++++++++++++++++--
3 files changed, 85 insertions(+), 11 deletions(-)
diffs (190 lines):
diff -r 3068cee1e5c0 -r eb61cd1d2344 Products/Silva/Ghost/base.py
--- a/Products/Silva/Ghost/base.py Fri Nov 08 17:40:33 2013 +0100
+++ b/Products/Silva/Ghost/base.py Mon Nov 11 15:01:46 2013 +0100
@@ -20,7 +20,6 @@
from silva.core.interfaces import IGhostAware, IGhostManager, IPublishable
from silva.core.references.reference import DeleteSourceReferenceValue
from silva.core.references.reference import WeakReferenceValue
-from silva.core.references.reference import get_content_id
from silva.core.references.interfaces import IReferenceService
from silva.translations import translate as _
@@ -176,20 +175,26 @@
return content.get_short_title_editable()
return _(u"Ghost target is broken")
+ def _get_haunted_factories(self, auto_delete=False):
+ # Give the possibilties to override the selection of reference
+ # factories.
+ if auto_delete:
+ return DeleteSourceReferenceValue
+ return WeakReferenceValue
+
security.declareProtected(
SilvaPermissions.ChangeSilvaContent, 'set_haunted')
def set_haunted(self, content, auto_delete=False):
""" Set the content as the haunted object
"""
service = getUtility(IReferenceService)
- factory = WeakReferenceValue
- if auto_delete:
- factory = DeleteSourceReferenceValue
+ factory = self._get_haunted_factories(auto_delete)
reference = service.get_reference(
aq_inner(self), name=u"haunted", add=True, factory=factory)
- if not isinstance(content, int):
- content = get_content_id(content)
- reference.set_target_id(content)
+ if isinstance(content, int):
+ reference.set_target_id(content)
+ else:
+ reference.set_target(content)
security.declareProtected(SilvaPermissions.View, 'get_haunted')
def get_haunted(self):
diff -r 3068cee1e5c0 -r eb61cd1d2344 Products/Silva/GhostAsset/content.py
--- a/Products/Silva/GhostAsset/content.py Fri Nov 08 17:40:33 2013 +0100
+++ b/Products/Silva/GhostAsset/content.py Mon Nov 11 15:01:46 2013 +0100
@@ -2,6 +2,7 @@
# Zope 3
from five import grok
from zeam.component import component
+from zope.interface import noLongerProvides, alsoProvides
# Zope 2
from AccessControl import ClassSecurityInfo
@@ -15,21 +16,58 @@
from silva.core.interfaces import IGhostAsset, IAsset
from silva.core.interfaces import IAssetPayload, IGhostManager
+from silva.core.interfaces import IImage, IImageIncluable
from silva.core.interfaces.errors import AssetInvalidTarget
+from silva.core.references.reference import get_content_from_id, get_content_id
+from silva.core.references.reference import DeleteSourceReferenceValue
+
+
+class ImageDeleteSourceReferenceValue(DeleteSourceReferenceValue):
+
+ def _check_image(self, target):
+ source = self.source
+ if source is not None:
+ is_image = IImage.providedBy(target)
+ have_image = IImageIncluable.providedBy(source)
+ if is_image and not have_image:
+ alsoProvides(source, IImageIncluable)
+ elif not is_image and have_image:
+ noLongerProvides(source, IImageIncluable)
+
+ def set_target_id(self, target_id):
+ self._check_image(get_content_from_id(target_id))
+ super(ImageDeleteSourceReferenceValue, self).set_target_id(target_id)
+
+ def set_target(self, target):
+ self._check_image(target)
+ super(ImageDeleteSourceReferenceValue, self).set_target_id(
+ get_content_id(target))
+
+
+class ImageWeakReferenceValue(ImageDeleteSourceReferenceValue):
+
+ def cleanup(self):
+ pass
+
class GhostAsset(GhostBase, Asset):
grok.implements(IGhostAsset)
security = ClassSecurityInfo()
meta_type = "Silva Ghost Asset"
+ def _get_haunted_factories(self, auto_delete=False):
+ if auto_delete:
+ return ImageDeleteSourceReferenceValue
+ return ImageWeakReferenceValue
+
security.declareProtected(
SilvaPermissions.AccessContentsInformation, 'get_filename')
def get_filename(self):
asset = self.get_haunted()
if asset is not None:
return asset.get_filename()
- return ''
+ return self.getId()
security.declareProtected(
SilvaPermissions.AccessContentsInformation, 'get_file_size')
diff -r 3068cee1e5c0 -r eb61cd1d2344 Products/Silva/tests/test_ghost_asset.py
--- a/Products/Silva/tests/test_ghost_asset.py Fri Nov 08 17:40:33 2013 +0100
+++ b/Products/Silva/tests/test_ghost_asset.py Mon Nov 11 15:01:46 2013 +0100
@@ -11,7 +11,8 @@
from zope.interface.verify import verifyObject
from Products.Silva.testing import FunctionalLayer, Transaction
-from silva.core.interfaces import IGhostAsset
+from silva.core.interfaces import IGhostAsset, IImageIncluable
+from silva.core.interfaces.errors import EmptyInvalidTarget
from silva.core.services.interfaces import IMetadataService
@@ -26,6 +27,8 @@
factory = self.root.manage_addProduct['Silva']
with self.layer.open_fixture('silva.png') as stream:
factory.manage_addImage('logo', 'Silva Logo', stream)
+ with self.layer.open_fixture('dark_energy.txt') as stream:
+ factory.manage_addFile('text', 'Text file', stream)
with Transaction():
metadata = getUtility(IMetadataService).getMetadata(self.root.logo)
@@ -37,8 +40,8 @@
self.root.logo.get_modification_datetime(),
DateTime('2010-04-25T12:00:00Z'))
- def test_create_and_access(self):
- """Create and test a Ghost Asset content type.
+ def test_haunt_image(self):
+ """Create and test a Ghost Asset content type that haunt an image.
"""
with Transaction():
factory = self.root.manage_addProduct['Silva']
@@ -52,6 +55,7 @@
self.assertEqual(ghost.get_haunted(), self.root.logo)
self.assertEqual(ghost.get_filename(), 'logo.png')
self.assertEqual(ghost.get_mime_type(), 'image/png')
+ self.assertTrue(IImageIncluable.providedBy(ghost))
self.assertEqual(
ghost.get_file_size(),
self.root.logo.get_file_size())
@@ -62,6 +66,33 @@
aq_chain(ghost.get_haunted()),
aq_chain(self.root.logo))
+ # Now edit an break the reference.
+ ghost.set_haunted(0)
+ self.assertIsInstance(ghost.get_link_status(), EmptyInvalidTarget)
+ self.assertEqual(ghost.get_haunted(), None)
+ self.assertEqual(ghost.get_filename(), 'ghost')
+ self.assertEqual(ghost.get_file_size(), 0)
+ self.assertEqual(ghost.get_mime_type(), 'application/octet-stream')
+ self.assertFalse(IImageIncluable.providedBy(ghost))
+
+ def test_haunt_file(self):
+ """Create and test a Ghost Asset content type that haunt a
+ file.
+ """
+ with Transaction():
+ factory = self.root.manage_addProduct['Silva']
+ factory.manage_addGhostAsset('ghost', None, haunted=self.root.text)
+
+ self.assertIn('ghost', self.root.objectIds())
+ ghost = self.root._getOb('ghost')
+ self.assertTrue(verifyObject(IGhostAsset, ghost))
+ self.assertIn(ghost, self.root.get_non_publishables())
+ self.assertEqual(ghost.get_link_status(), None)
+ self.assertEqual(ghost.get_haunted(), self.root.text)
+ self.assertEqual(ghost.get_filename(), 'text')
+ self.assertEqual(ghost.get_mime_type(), 'text/plain')
+ self.assertFalse(IImageIncluable.providedBy(ghost))
+
def test_download(self):
"""create and download a Ghost Asset content type.
"""