Skip to content

hook_civicrm_searchKitTasks

Summary

This hook is called to allow you to add to or alter the tasks available in search kit.

Definition

hook_civicrm_searchKitTasks(array &$tasks, bool $checkPermissions, ?int $userID)

Parameters

  • $tasks (array) - the current set of tasks. You can add/remove existing tasks. Each task is an array and has keys like

    • title - title to display - remember to use ts() in core and E::ts() in extensions
    • icon - associated icon (optional)
    • uiDialog - array containing the path to the templateUrl
    • module - name of the angular module to require.
    • apiBatch - (from 5.56) array describing the action if you are not providing a form (if you just want a generic UI). Has the keys:
      • action - Name of API action to call once per row
      • params- Optional array of additional api params
      • confirmMsg - If omitted, the action will run immediately with no confirmation
      • runMsg - Message to display while running
      • successMsg - Message to display on successful completion
      • errorMsg - Message to display if errors

Note: the *Msg messages can include %1 and %2 which will be set to the number of records being processed, and the entity name respectively.

Note: the $tasks array is keyed by the entity that it applies to. Depending on context, the array may or may not already be populated with some data. Your hook implementation should add its tasks regardless of what's already in the array.

  • $checkPermissions (boolean) - Whether permissions ought to be taken into account. If the tasks you are adding shouldn't be available to all users, perform any necessary permission checks only if this value is true.

  • $userID (int|null) - If $checkPermissions is true, will contain the contact ID of the acting user.

Returns

  • null

Example: Add a new task with a generic interface and standard action

Create a task called 'Mark as "Do Not Email"'

    /**
     * Implements hook_civicrm_searchKitTasks().
     *
     * @param array[] $tasks
     * @param bool $checkPermissions
     * @param int|null $userID
     */
    function myext_civicrm_searchKitTasks(array &$tasks, bool $checkPermissions, ?int $userID) {
      $tasks['Contact']['do_not_email'] = [
        'title' => E::ts('Mark as "Do Not Email"'),
        'icon' => 'fa-random',
        'apiBatch' => [
          'action' => 'update',
          'params' => ['values' => ['do_not_email' => TRUE]],   // values specified in code
          'confirmMsg' => E::ts('Are you sure you want to set %1 %2 as "Do Not Email"?'),
          'runMsg' => E::ts('Setting %1 %2 as "Do Not Email"...'),
          'successMsg' => E::ts('Successfully set %1 %2 to "Do Not Email".'),
          'errorMsg' => E::ts('An error occurred while attempting to run myAction on %1 %2.'),
        ],
      ];
    }

Example: Add a new task with a generic interface and standard action with a value set by the user (5.80+)

Create a task called 'Update Contact Source' - prompts user for source value

    /**
     * Implements hook_civicrm_searchKitTasks().
     *
     *
     * @param array[] $tasks
     * @param bool $checkPermissions
     * @param int|null $userID
     */
    function myext_civicrm_searchKitTasks(array &$tasks, bool $checkPermissions, ?int $userID) {
      $tasks['Contact']['update_source'] = [
        'title' => E::ts('Update Contact Source'),
        'icon' => 'fa-random',
        'apiBatch' => [
          'action' => 'update',
          'fields' => [['name' => 'source', 'required' => TRUE]],  // 'required' is optional
          'confirmMsg' => E::ts('Are you sure you want to update the Source field for %1 %2?'),
          'runMsg' => E::ts('Setting source for %1 %2...'),
          'successMsg' => E::ts('Successfully set source for %1 %2.'),
          'errorMsg' => E::ts('An error occurred while attempting to update source on %1 %2.'),
        ],
      ];
    }

Example: Add a new task with a generic interface and custom action

Create a task 'My SearchKit Task' where the behaviour is a custom APIv4 action.

    /**
     * Implements hook_civicrm_searchKitTasks().
     *
     * @param array[] $tasks
     * @param bool $checkPermissions
     * @param int|null $userID
     */
    function myext_civicrm_searchKitTasks(array &$tasks, bool $checkPermissions, ?int $userID) {
      $tasks['Contact']['myAction'] = [
        'title' => E::ts('My SearchKit Task'),
        'icon' => 'fa-random',
        'apiBatch' => [
          'action' => 'myAction',
          'confirmMsg' => E::ts('Are you sure you want to run myAction on %1 %2?'),
          'runMsg' => E::ts('Running myAction on %1 %2...'),
          'successMsg' => E::ts('Successfully ran myAction on %1 %2.'),
          'errorMsg' => E::ts('An error occurred while attempting to run myAction on %1 %2.'),
        ],
      ];
    }

The myAction is assumed to be a custom APIv4 action provided by your extension. For example, create the file Civi/Api4/Action/Contact/MyAction.php with the following code:

<?php

namespace Civi\Api4\Action\Contact;

use Civi;

class MyAction extends \Civi\Api4\Generic\BasicBatchAction {

  protected function doTask($item) {
    foreach ($item as $key => $contact_id) {
      // todo whatever you need to do
    }

    return $item;
  }

}

Make sure to use the correct namespace for your entity (Contact, Activity, etc), and to flush the CiviCRM cache after adding the new code.

Example: Add a new task with a custom interface

Create a task called 'Flip first/last name' with a custom angular template

    /**
     * Implements hook_civicrm_searchKitTasks().
     *
     * @param array[] $tasks
     * @param bool $checkPermissions
     * @param int|null $userID
     */
    function deduper_civicrm_searchKitTasks(array &$tasks, bool $checkPermissions, ?int $userID) {
      $tasks['Contact']['flip'] = [
        'module' => 'dedupeSearchTasks',
        'title' => E::ts('Flip first/last name'),
        'icon' => 'fa-random',
        'uiDialog' => ['templateUrl' => '~/dedupeSearchTasks/dedupeSearchTaskFlip.html'],
      ];
    }

This would have a js & a php file ang/dedupeSearchTasks.js that declares the module. These can be generated using civix - eg. civix generate:angular-module --am=dedupeSearchTasks

    (function(angular, $, _) {
        angular.module('dedupeSearchTasks', CRM.angRequires('dedupeSearchTasks'));
    })(angular, CRM.$, CRM._);

See also

Links and Tasks