The 'basic' feature is to allow administrators to select a specific group of contacts to be available for a given contact reference custom field when the field is created or edited (i.e. contact search / list widget would expose only contacts in the selected group). An 'Advanced' filter allows administrators to specify more complex filters using available parameters to API v3 Contact Get api.
In order to support including contact reference fields in front-end forms (Profiles, and profiles w/in online contribution pages and event registration pages) - access to this type of field will require EITHER 'access CiviCRM' permission (useful for back-office forms) OR 'access contact reference field' permissions (this permission should be enabled for anonymous users if contact reference fields are to be embedded in front-end forms not requiring login.
A new Search Preference will be added to control the contact data included in the widget's search results dropdown. This setting is configurable from Administer > Customize > Search Preferences. It is separate from the existing Autocomplete Contact Search setting (which controls data included in Quick Search widget results).
The widget will support two contact API actions:
'get' - the existing API action, with any currently available parameters
'lookup' - a new contact API action which is a wrapper for the existing CRM_Contact_Page_AJAX::getContactList method with support for group filtering and appropriate permissioning for front-end usage (details below)
BASIC EXAMPLE: For a basic 'group filter' (e.g. only expose contacts in group_id 3), user would select from a muli-select listing of groups. If they select "Board of Directors" (group_id = 3), we would store: 'action=lookup&group=3' in the filter column. The PHP function invoked by the widget will call the contact get API with that filter parameter: entity=Contact&action=lookup&group=3. Multiple group selection is supported (&group=3,5).
ADVANCED EXAMPLE: Administrator wants to pass additional / alternative filters (as supported by Contact Get API). To expose all 'Students' in group 3, user will click 'Advanced' link which replaces group dropdown with a text input field. They would enter the following value: "action=get&group=3&contact_sub_type=student". The PHP function invoked by the widget will invoke the contact get api with that filter parameter: entity=Contact&action=get&group=3&contact_sub_type=student
NOTE: The api entity (contact) will be hard-coded in the PHP class to simplify error checking and debugging. The widget and enclosing forms do not support other objects (e.g. Activity). A formRule will be used to verify that only valid actions are saved to the filter ('get' or 'lookup'). Other operations (e.g. create) are not supported. The form's preprocess can also easily distinguish between BASIC and ADVANCED mode field display by splitting DB value on & delimiter and checking for values other than / in addition to "action=lookup&group=$listOfINTs".
Add column to the custom field table to store the contact reference list 'filter'. For upgrades:
- ALTER TABLE `civicrm_custom_field` ADD `filter` VARCHAR 255 NULL COMMENT `Stores Contact Get API params contact reference custom fields. May be used for other filters in the future.`
Filter column will store & delimited params to CONTACT GET api.
1. Add Custom Field
1.1 When Data Type = Contact Reference is selected, show a new field for the filter.
Label = 'Limit List to Group(s)'
Field Type = Multi-select with all groups. Preferable use the crmasmSelect widget (as used in Advanced Search). Else the TagsAndGroups style table of checkboxes. Include all groups (regardless of group type) in alpha order by group title.
NOTE: For checkbox / item values - could use just group_id's OR use the corresponding filter strings ("group_id=3") which is what we will be storing in the DB.
1.2 Include link to right of dropdown. Link text = 'Advanced Filter'. When link is clicked, replace the row with the label and dropdown (above) with:
Label = 'Advanced Filter'
Text input field (class=huge)
<span class="description">Filter contact listing using Contact Get API parameters. EXAMPLE: To list only Organizations in group 3: "action=lookup&group=3&contact_type=Organization"
Include link to right of input field. Link text = 'Filter by Group'. Clicking this link hides the advanced filter label / field and shows the basic 'Limit List to Group' filter. If the advanced filter field contains only a group=N filter, we can select (check) that group when we switch back. Otherwise, no group is checked.
- Limit List to Group my be empty (in this case all contacts in the DB are exposed unless a hook is called)
- Advanced Filter field - Check for 'entity=' and for action != 'lookup' AND action !='get'. "Please do not include entity parameter (entity is always 'contact')." "Only 'get' and 'lookup' actions are supported."
Save field value to filter column.
2. Edit Custom Field Preprocess needs to determine if this contact reference field is using 'basic' or 'advanced' mode and display the appropriate field. If the filter field value is anything other than empty OR 'action=lookup&group=' . $listOfINTs, then display advanced filter.
3. Implement 'lookup' action for contact API:
- Wrapper for CRM_Contact_Page_AJAX::getContactList (continue to return contact_autocomplete_options as as configured)
- Adds filter by group(s) when group_id parameter is passed
- Permissioning: lookup action requires 'profile listings' OR 'profile listings and forms' OR 'view all contacts' (or any higher permission that implies view all contacts - not sure about this ??).
4. Modify contact reference implementation of autocomplete widget to invoke the appropriate API (lookup or get) and pass parameters if provided when context=customfield. If no filter, then all contacts should be returned (current behavior) if user has applicable permissions.
NOTE: If we get invalid filter parameters in advanced mode (i.e. the API is returning an error) would be great if we could pass some error string back to the widget in a way that it displays to the user - rather than just spinning or ...
5. Contact reference widget should be rendered by a separate .tpl file (ContactReference.tpl) that is included for custom contact reference field editing (contact form and profiles) - similar to how we've isolated Tag and Group editing (CRM/Contact/Form/Edit/TagsAndGroups.tpl).