A client has a couple of activity types with custom data. The client would like to see some of this data pulled through to the summary shown in the Activities tab.
Also, my client finds that seeing all the Bulk Email activities clouds the more useful, meaningful activities and wanted that out of the way.
What didn't work
Having been on 2 days' of CiviCRM developer training, I thought I ought to be able to do this with my eyes shut. Or at least know where to start. I looked in the HTML comments to see which template files were being invoked. I looked for the corresponding PHP classes. I bashed away at the API Explorer. I implemented hooks. I considered a .extra.tpl. No joy.
Some findings, in case it saves you from same assumptions:
- The API cannot (yet?) filter activities for both a
activity_type_id.Separately these work, but together I get all records for the
- The API cannot (yet?) filter activities for an array of activity types; i.e. it can't do
- The API is not used by the AJAX calls used by the Activities tab.
- hook_civicrm_searchColumns is not called by the Activities tab list.
What did work
The Activitiy Tab's "Selector" is populated by
So I took a copy of this file (
CRM/Activity/BAO/Activity.php) into my customisations folder and hacked it.
getActivities() is a huge operation that draws on another method to build SQL. From what I could figure: a temporary table is created (in memory(!)) to hold a copy of the results. This table is fed first by a three UNION'ed queries, including some customisations for CiviCase, and then contact names for target, source and assignee are added on at a later stage. Then this table's results are fetched and looped to populate an array for the Selector to feed back as JSON.
I didn't want to add in my code inside this loop as it would be inefficient to do lookups in 2 custom data value tables for every row. So instead I fetched all the custom data for the activity Ids encountered in one SQL clause (because of similiarities in the data and formatting I required I was able to use a UNION), then looped that to replace the subject field.
To move the Bulk Emails out of the way, I confess to a hack: where the default ordering is set, I prepended
(tbl.activity_type_id IN (19,3)) where 19 and 3 are the looked-up activity type IDs for (Bulk) Email. This has the effect of moving them to the bottom, which means they're still there if you want them, but the don't get in the way of more important day-to-day information.
How will I maintain this core patch?
It's great that CiviCRM allows you to override pretty much any of its code. But of course if you branch off from the main development line you need to find a way to keep up-to-date.
The way I do this is
- Copy the core file
- Commit it as-is. (I use Git)
- Work on it, commit that.
This way when a new version is released I can easily obtain a patch for my work and reapply this to the new version of the file. It's a bit more awkward than a full git solution, such as a rebase, but this is the trade off for being able to override core files without actually overwriting them. I think if CiviCRM used git I might not use the separate customisation files and run my own branch off of core instead.
If I had a bit more time (always the issue!) I might have been tempted to create a hook after the activities are fetched, much like the search columns hook, which would keep the patch simpler and move my custom code to an implementation of the hook. If I had even more time I would love to write a module to replace the default implementation of tab pages with one that allowed more customisation without needing to override core classes as currently it's very difficult to tweak these things.