Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

(dev/core#217) PrevNext - Migrate selection methods #12556

Merged
merged 5 commits into from
Jul 26, 2018

Conversation

totten
Copy link
Member

@totten totten commented Jul 25, 2018

Overview

Migrate methods for managing the selected contacts from CRM_Core_BAO_PrevNextCache to CRM_Core_PrevNextCache_{Interface,Sql}.

This is a cherry-pick from #12377. See also: dev/core#217.

Before

  • markSelection() is a function in CRM_Core_BAO_PrevNextCache.
  • getSelection() is a function in CRM_Core_BAO_PrevNextCache.
  • getSelectedContacts() is a function in CRM_Core_BAO_PrevNextCache. It selects contact ID's based on FROM civicrm_prevnext_cache WHERE cacheKey LIKE {$key}% AND cacheKey NOT LIKE {$key}_alphabet% and returns their names.

After

  • markSelection() is a function in CRM_Core_PrevNextCache_{Interface,Sql}. The unused parameter $entity_table is no longer passed.
  • getSelection() is a function in CRM_Core_PrevNextCache_{Interface,Sql}. The unused parameter $entity_table is no longer passed.
  • getSelectedContactNames() is a function in CRM_Contact_Form_Task. It selects contact ID's based on getSelection() (aka FROM civicrm_prevnext_cache WHERE cacheKey LIKE {$key}%) and returns their names. (See commit notes for more critical evaluation of this change.)

Technical Details

  • markSelection() is only called by CRM_Contact_Page_AJAX::selectUnselectContacts (aka civicrm/ajax/markSelection).
    • I spot-checked the "Find Contacts", "Find Contributions", "Find Participants", and "Find Memberships" with Firefox Dev Console. Although all of these have similar checkbox UI's, only the contact search seemed to hit the AJAX end-point civicrm/ajax/markSelection.
  • getSelection() is called by:
    • CRM_Contact_Page_AJAX::selectUnselectContacts (aka civicrm/ajax/markSelection).
    • CRM_Campaign_Form_Task, CRM_Contact_Form_Search, and CRM_Contact_Form_Task
    • (Ill-advisedly) by duplicated code in com.imba.sendgrid. To smoot this transition, we leave the old BAO function as a stub.
  • getSelectedContacts() is only called by CRM_Contact_Form_Task.
  • As near as I can tell, these callers are all involved with search UIs for contacts/campaign-respondents/custom-searches. None appear to involve dedupe/merge.

The contract feels quirky -- e.g.

* Who would guess that `markSelection()` defaults to `$action == 'unselect'`?
* What's the point of accepting `$entity_table` if it's never used?

Fortunately, this function is only called from `CRM_Contact_Page_AJAX::selectUnselectContacts`,
so it's fairly easy to audit and see that:

* The `$action` is always passed in -- it never relies on the default value.
* The `$entity_table` is never specified explicitly -- it always relies on the default value.
1. Improve docblock formatting
2. The `$entity_table` is never passed in. You can see this by grepping universe for `getSelection`.
This function is used one time -- when you run a search, select some
contacts, and perform a task (like "Delete contacts"), the
`CRM/Contact/Form/Task.php` displays a table with the names of the selected
contacts.

This patch makes the logic portable -- so that it can work regardless of
whether selections are stored in MySQL or Redis.

Before
------

* The contacts are selected `FROM civicrm_prevnext_cache WHERE cacheKey LIKE {$key}% AND cacheKey NOT LIKE {$key}_alphabet%`.
* The contact names come from `civicrm_prevnext_cache.data`, which has been
  pre-filled with either `civicrm_contact.sort_name` (for most contact
  searches) or `civicrm_contact.display_name` (for campaign respondent
  searches).

After
-----

* The selections are chosen with `FROM civicrm_prevnext_cache WHERE cacheKey LIKE {$key}%`.
* The contact names are loaded directly from `civicrm_contact.sort_name`.

Comments
--------

* The use of wildcards with `cacheKey` seems like a code-smell suggest a
  somewhat deeper problem in how `cacheKey` is understood.  However, for our
  purposes, it shouldn't matter.
* The before and after queries are very similar in how they use
  `cacheKey`...  and slightly different.  (Ugh.) Is the new one better or
  worse?  Well, look at how `CRM_Contact_Form_Task` uses `getSelection()`
  (for finding contact IDs, which feed into the task logic) and
  `getSelectedContacts()` (for finding contact names, which are displayed to
  user).  If the subtle difference in `cacheKey` filtering matters, then our
  UX is buggy because we're showing the user one contact-list (based on old
  `getSelectedContacts()`) and we're executing on a different contact-list
  (based on the old `getSelection()`).
* Is the old technique for getting names (querying
  `civicrm_prevnext_cache.data`) better than the new technique (querying
  civicrm_contact.sort_name)?  I haven't benchmarked, but I'm skepitcal.
  Both techniques transfer the full `O(n)` list from mysql to php.
  In typical usage, the size of `n` is limited by what an admin is
  willing to click through in the UI (which is probably a few hundred
  IDs). The contact tables is indexed by ID. Maybe... if you manually
  check several thousand records, it might make a small difference. But
  if you're clicking that many, then other things are also getting more
  expensive (like the actual task). In this case, it feels like an
  unnecessary optimization.
@civibot
Copy link

civibot bot commented Jul 25, 2018

(Standard links)

* A list of contact IDs to (un)select.
* To unselect all contact IDs, use NULL.
*/
public function markSelection($cacheKey, $action, $cIds = NULL) {
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

$cIds is updated to the (better) $ids in the Interface & is inconsistent

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Agree $ids is nicer. I've added a revision to my big branch to use $ids. There are some other cleanups which touch that file, so it'll show up towards the end of the queue.

@eileenmcnaughton
Copy link
Contributor

I noted one little thing which can be a follow up tidy up but this looks good to me. Merging

@eileenmcnaughton eileenmcnaughton merged commit 113f8ef into civicrm:master Jul 26, 2018
@totten totten deleted the master-prevnext-selection branch July 26, 2018 18:35
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
Projects
None yet
Development

Successfully merging this pull request may close these issues.

3 participants