From 5d88374789b1a67dd9050367535f16479152e93a Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Laur=C3=A9line=20Gu=C3=A9rin?= <zebuline@entrouvert.com>
Date: Thu, 7 Oct 2021 16:45:35 +0200
Subject: [PATCH] formdata: form_role variables & user-function (#57506)

---
 tests/test_formdata.py | 30 ++++++++++++++++++++++++++++++
 wcs/formdata.py        | 37 ++++++++++++++++++++++++++-----------
 wcs/variables.py       | 15 ++-------------
 3 files changed, 58 insertions(+), 24 deletions(-)

diff --git a/tests/test_formdata.py b/tests/test_formdata.py
index 3fd5aa3e..605e8dbc 100644
--- a/tests/test_formdata.py
+++ b/tests/test_formdata.py
@@ -2000,6 +2000,36 @@ def test_roles_templatefilter(pub, variable_test_data):
     assert condition.evaluate() is False
 
 
+def test_function_users(pub):
+    user1 = pub.user_class(name='userA')
+    user1.store()
+    user2 = pub.user_class(name='userB')
+    user2.store()
+
+    formdef = FormDef()
+    formdef.name = 'foobar'
+    formdef.url_name = 'foobar'
+    formdef.fields = []
+    formdef.store()
+
+    formdata = formdef.data_class()()
+    formdata.workflow_roles = {'_receiver': '_user:%s' % user1.id}
+    formdata.store()
+    pub.substitutions.feed(formdata)
+    condition = Condition({'type': 'django', 'value': 'form_role_receiver_name == "userA"'})
+    assert condition.evaluate() is True
+    static_vars = formdata.get_static_substitution_variables()
+    assert static_vars['form_role_receiver_name'] == 'userA'
+
+    formdata.workflow_roles = {'_receiver': ['_user:%s' % user1.id, '_user:%s' % user2.id]}
+    formdata.store()
+    pub.substitutions.feed(formdata)
+    condition = Condition({'type': 'django', 'value': 'form_role_receiver_name == "userA, userB"'})
+    assert condition.evaluate() is True
+    static_vars = formdata.get_static_substitution_variables()
+    assert static_vars['form_role_receiver_name'] == 'userA, userB'
+
+
 def test_lazy_now_and_today(pub, variable_test_data):
     for condition_value in (
         'now > "1970-01-01"',
diff --git a/wcs/formdata.py b/wcs/formdata.py
index 43ace962..31601287 100644
--- a/wcs/formdata.py
+++ b/wcs/formdata.py
@@ -104,6 +104,31 @@ def flatten_dict(d):
             del d[k]
 
 
+def get_workflow_roles_substitution_variables(workflow_roles, prefix=''):
+    d = {}
+    for role_type, role_ids in workflow_roles.items():
+        if not role_ids:
+            continue
+
+        _prefix = '%s%s_' % (prefix, role_type.replace('-', '_').strip('_'))
+        if not isinstance(role_ids, list):
+            role_ids = [role_ids]
+        if str(role_ids[0]).startswith('_user:'):
+            try:
+                users = [get_publisher().user_class.get(role_id.split(':')[1]) for role_id in role_ids]
+            except KeyError:
+                continue
+            d['%sname' % _prefix] = ', '.join([u.name for u in users])
+            continue
+
+        role_id = role_ids[0]
+        try:
+            d.update(get_publisher().role_class.get(role_id).get_substitution_variables(_prefix))
+        except KeyError:
+            pass
+    return d
+
+
 class Evolution:
     who = None
     status = None
@@ -887,17 +912,7 @@ class FormData(StorableObject):
         if self.workflow_roles:
             workflow_roles.update(self.workflow_roles)
 
-        for role_type, role_id in workflow_roles.items():
-            if not role_id:
-                continue
-            if isinstance(role_id, list):
-                # only return first role
-                role_id = role_id[0]
-            prefix = 'form_role_%s_' % role_type.replace('-', '_').strip('_')
-            try:
-                d.update(get_publisher().role_class.get(role_id).get_substitution_variables(prefix))
-            except KeyError:
-                pass
+        d.update(get_workflow_roles_substitution_variables(workflow_roles, prefix='form_role_'))
 
         if self.evolution and self.evolution[-1].comment:
             d['form_comment'] = self.evolution[-1].comment
diff --git a/wcs/variables.py b/wcs/variables.py
index 33dd8965..9eaae087 100644
--- a/wcs/variables.py
+++ b/wcs/variables.py
@@ -22,6 +22,7 @@ from pyproj import Geod
 from quixote import get_publisher, get_request
 
 from .carddef import CardDef
+from .formdata import get_workflow_roles_substitution_variables
 from .formdef import FormDef
 from .qommon import _, force_str, misc
 from .qommon.evalutils import make_datetime
@@ -512,19 +513,7 @@ class LazyFormData(LazyFormDef):
         if self._formdata.workflow_roles:
             workflow_roles.update(self._formdata.workflow_roles)
 
-        d = {}
-        for role_type, role_id in workflow_roles.items():
-            if not role_id:
-                continue
-            prefix = '%s_' % role_type.replace('-', '_').strip('_')
-            if isinstance(role_id, list):
-                # only return first role
-                role_id = role_id[0]
-            try:
-                d.update(get_publisher().role_class.get(role_id).get_substitution_variables(prefix))
-            except KeyError:
-                pass
-        return d
+        return get_workflow_roles_substitution_variables(workflow_roles)
 
     @property
     def comment(self):
-- 
2.33.0

