[hooks] Synchronize user_cardinality of binary data object and its reference
authorSylvain Thénault <sylvain.thenault@logilab.fr>
Wed, 29 Mar 2017 09:54:11 +0200
changeset 2544 d642581ad90b
parent 2543 891c2f852c5c
child 2545 fe959b171205
[hooks] Synchronize user_cardinality of binary data object and its reference when in a simplified profile, because the ui only display bdo's cardinality. Closes #17066567
cubicweb_seda/hooks.py
test/test_hooks.py
--- a/cubicweb_seda/hooks.py	Wed Mar 29 09:52:54 2017 +0200
+++ b/cubicweb_seda/hooks.py	Wed Mar 29 09:54:11 2017 +0200
@@ -233,6 +233,47 @@
             do_ref.cw_set(user_cardinality=u'1')
 
 
+class SimplifiedProfileSyncDORefCardOnCreateHook(hook.Hook):
+    """Hook triggering an operation to keep in sync user_cardinality of data object reference and
+    its associated data object for simplified profiles, on creation of the relation between them.
+    """
+    __regid__ = 'seda.doref.default'
+    __select__ = hook.Hook.__select__ & hook.match_rtype('seda_data_object_reference_id')
+    events = ('after_add_relation',)
+
+    def __call__(self):
+        ref = self._cw.entity_from_eid(self.eidfrom)
+        bdo = self._cw.entity_from_eid(self.eidto)
+        if ref.cw_etype == 'SEDADataObjectReference' and bdo.cw_etype == 'SEDABinaryDataObject':
+            SimplifiedProfileSyncDORefCardOp(self._cw, do_ref=ref, do=bdo)
+
+
+class SimplifiedProfileSyncDORefCardOnUpdateHook(hook.Hook):
+    """Hook triggering an operation to keep in sync user_cardinality of data object reference and
+    its associated data object for simplified profiles, on update of the data object's cardinality.
+    """
+    __regid__ = 'seda.doref.default'
+    __select__ = hook.Hook.__select__ & is_instance('SEDABinaryDataObject')
+    events = ('after_update_entity',)
+
+    def __call__(self):
+        if 'user_cardinality' in self.entity.cw_edited:
+            references = self.entity.reverse_seda_data_object_reference_id
+            if len(references) == 1:  # else it can't be a simplified profile
+                SimplifiedProfileSyncDORefCardOp(self._cw, do_ref=references[0], do=self.entity)
+
+
+class SimplifiedProfileSyncDORefCardOp(hook.Operation):
+    """Keep in sync user_cardinality of data object reference and its associated data object for
+    simplified profiles.
+    """
+
+    def precommit_event(self):
+        container = self.do.seda_binary_data_object[0] if self.do.seda_binary_data_object else None
+        if container and container.simplified_profile:
+            self.do_ref.cw_set(user_cardinality=self.do.user_cardinality)
+
+
 class CheckProfileSEDACompatiblityOp(hook.DataOperationMixIn, hook.LateOperation):
     """Data operation that will check compatibility of a SEDA profile upon modification.
 
--- a/test/test_hooks.py	Wed Mar 29 09:52:54 2017 +0200
+++ b/test/test_hooks.py	Wed Mar 29 09:54:11 2017 +0200
@@ -165,6 +165,28 @@
 
             self.assertEqual(do_ref.user_cardinality, '1')
 
+    def test_simplified_profile_do_ref_sync(self):
+        """When creating a SEDABinaryDataObject in a simplified profile from the ui, one only
+        specifies user_cardinality for it, not for it's associated reference whose cardinality
+        should have the same value.
+        """
+        with self.admin_access.client_cnx() as cnx:
+            transfer = cnx.create_entity('SEDAArchiveTransfer', title=u'test profile',
+                                         simplified_profile=True)
+            unit, unit_alt, unit_alt_seq = testutils.create_archive_unit(transfer)
+            bdo = testutils.create_data_object(unit_alt_seq, user_cardinality=u'1',
+                                               seda_binary_data_object=transfer)
+            cnx.commit()
+            ref = cnx.find('SEDADataObjectReference').one()
+
+            ref.cw_clear_all_caches()
+            self.assertEqual(ref.user_cardinality, '1')
+
+            bdo.cw_set(user_cardinality=u'1..n')
+            cnx.commit()
+            ref.cw_clear_all_caches()
+            self.assertEqual(ref.user_cardinality, '1..n')
+
 
 class CheckProfileTC(CubicWebTC):