Skip to content

Commit

Permalink
Fire notifications when UID references are created/destroyed (senaite…
Browse files Browse the repository at this point in the history
…#2061)

* Fire notifications when references are created/destroyed

* Changelog updated

* Docstring added
  • Loading branch information
ramonski committed Jul 18, 2022
1 parent 5d9b1d1 commit 5adaf31
Show file tree
Hide file tree
Showing 4 changed files with 80 additions and 8 deletions.
1 change: 1 addition & 0 deletions CHANGES.rst
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@ Changelog
2.3.0 (unreleased)
------------------

- #2061 Fire notifications when UID references are created/destroyed
- #2058 Filter 'Interpretation templates' in sample view by template and type
- #2048 Fix catalog logging counter duplicates
- #2047 Make resultsinterpretation.pt to retrieve departments from viewlet
Expand Down
52 changes: 52 additions & 0 deletions src/senaite/core/events/uidreference.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,52 @@
# -*- coding: utf-8 -*-

from zope.interface import implementer
from zope.interface.interfaces import IObjectEvent


class IUIDReferenceCreatedEvent(IObjectEvent):
"""An event fired after a reference between two objects was cretated
"""


class IUIDReferenceDestroyedEvent(IObjectEvent):
"""An event fired after a reference between two objects was destroyed
"""


@implementer(IUIDReferenceCreatedEvent)
class UIDReferenceCreated(object):

def __init__(self, field, source, target):
"""Reference Created Event
:param field: The field on the source object
:param source: The context object holding the UID reference field
:param target: The context object being referenced
"""
self.field = field
self.source = source
self.target = target

# See IObjectEvent
# -> Allow to define an event subscriber for a custom type
self.object = source


@implementer(IUIDReferenceDestroyedEvent)
class UIDReferenceDestroyed(object):

def __init__(self, field, source, target):
"""Reference Destroyed Event
:param field: The field on the source object
:param source: The context object holding the UID reference field
:param target: The context object being referenced
"""
self.field = field
self.source = source
self.target = target

# See IObjectEvent
# -> Allow to define an event subscriber for a custom type
self.object = source
5 changes: 4 additions & 1 deletion src/senaite/core/schema/configure.zcml
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,9 @@
i18n_domain="senaite.core">

<!-- Event subscribers -->
<subscriber handler=".uidreferencefield.on_object_created" />
<subscriber
for="senaite.core.interfaces.IHaveUIDReferences
zope.lifecycleevent.interfaces.IObjectCreatedEvent"
handler=".uidreferencefield.on_object_created" />

</configure>
30 changes: 23 additions & 7 deletions src/senaite/core/schema/uidreferencefield.py
Original file line number Diff line number Diff line change
Expand Up @@ -9,21 +9,33 @@
from plone.behavior.interfaces import IBehavior
from plone.uuid.interfaces import ATTRIBUTE_NAME
from senaite.core import logger
from senaite.core.events.uidreference import UIDReferenceCreated
from senaite.core.events.uidreference import UIDReferenceDestroyed
from senaite.core.interfaces import IHaveUIDReferences
from senaite.core.schema.fields import BaseField
from senaite.core.schema.interfaces import IUIDReferenceField
from zope.annotation.interfaces import IAnnotations
from zope.component import adapter
from zope.event import notify
from zope.interface import alsoProvides
from zope.interface import implementer
from zope.lifecycleevent.interfaces import IObjectCreatedEvent
from zope.schema import ASCIILine
from zope.schema import List

BACKREFS_STORAGE = "senaite.core.schema.uidreferencefield.backreferences"


@adapter(IHaveUIDReferences, IObjectCreatedEvent)
def notify_reference_created(field, source, target):
"""Notify that a reference between two objects was created
"""
notify(UIDReferenceCreated(field, source, target))


def notify_reference_destroyed(field, source, target):
"""Notify that a reference between two objects was destroyed
"""
notify(UIDReferenceDestroyed(field, source, target))


def on_object_created(object, event):
"""Link backreferences after the object was created
Expand All @@ -41,17 +53,19 @@ def on_object_created(object, event):
value = field.get(object)
# handle single valued reference fields
if api.is_object(value):
field.link_backref(value, object)
logger.info(
"Adding back reference from %s -> %s" % (
value, object))
if field.link_backref(value, object):
notify_reference_created(field, object, value)
# handle multi valued reference fields
elif isinstance(value, list):
for ref in value:
logger.info(
"Adding back reference from %s -> %s" % (
ref, object))
field.link_backref(ref, object)
if field.link_backref(ref, object):
notify_reference_created(field, object, ref)


def get_backrefs(context, relationship, as_objects=False):
Expand Down Expand Up @@ -208,11 +222,13 @@ def set(self, object, value):

# link backreferences of new uids
for added_obj in added_objs:
self.link_backref(added_obj, object)
if self.link_backref(added_obj, object):
notify_reference_created(self, object, added_obj)

# unlink backreferences of removed UIDs
for removed_obj in removed_objs:
self.unlink_backref(removed_obj, object)
if self.unlink_backref(removed_obj, object):
notify_reference_destroyed(self, object, removed_obj)

super(UIDReferenceField, self).set(object, uids)

Expand Down

0 comments on commit 5adaf31

Please sign in to comment.