Skip to content

Add a custom entity to scheduled reminders

The aim of this step-by-step guide

The aim of this step-by-step guide is to add a newly created entity to Scheduled Reminders. So that a site administrator can setup scheduled reminders.

In our case we do this for the User entity so that a site administrator can send a reminder about changing your password after a given period.

The User entity is defined in the standaloneusers extension in CiviCRM standalone.

Create an ActionMapping class

To add an entity to scheduled reminder one should extend the Civi\ActionSchedule\MappingBase class.

In you extension add a file called Civi/StandalonePasswordExpire/ActionSchedule/ActionMapping.php and start with the following content:

<?php

namespace Civi\StandalonePasswordExpire\ActionSchedule;

use Civi\ActionSchedule\MappingBase;
use CRM_Standaloneautologout_ExtensionUtil as E;

class ActionMapping extends MappingBase {

  /**
   * Unique name of this mapping type.
   *
   * Should return a "machine_name" style string (should be the same as `getId()`).
   * @return string
   */
  public function getName(): string {
    return 'User';
  }

  public function getLabel(): string {
    return E::ts('User');
  }

  public function modifyApiSpec(\Civi\Api4\Service\Spec\RequestSpec $spec) {
  }

}

The code above creates the class and makes sure it has a unique name and a translatable label.

Let schedule reminders know which entity it is reacting on

Let schedule reminders know it reacts on the User entity. Add the funtions getEntityName, getStatusLabels and getValueLabels to the class. The function getValueLabels returns an array of all subtypes of the entity. We do not have subtypes. With the function getStatusLabels one can also let the site admin set a scheduled reminder for certain statuses. We do not have any status.

class ActionMapping extends MappingBase {

  //...

  /**
   * Main entity name e.g. `Activity`
   * @return string
   */
  public function getEntityName(): string {
    return 'User';
  }

  /**
   * Get option list for the `entity_value` field.
   */
  public function getValueLabels(): array {
    return [];
  }

  /**
   * Get option list for the `entity_status` field.
   *
   * @param array|null $entityValue
   *   Selected value(s) of the `entity_value` field.
   */
  public function getStatusLabels(?array $entityValue): array {
    return [];
  }

}

Let the administrator select the date field

Add the function getDateFields so that the site administrator can select the date field of the entity. We will add the fields when_created, when_updated, when_last_accessed.

class ActionMapping extends MappingBase {

  //...

  public function getDateFields(?array $entityValue = NULL): array {
    return [
      'when_created' => E::ts('When Created'),
      'when_updated' => E::ts('When Updated'),
      'when_last_accessed' => E::ts('When Last Accessed'),
    ];
  }
}

Add the query for selecting entities when sending a scheduled reminder

Now we create a query to select the users which fit the schedule reminder. Add the function createQuery to your class:

class ActionMapping extends MappingBase {

  //...

  /**
   * Generate a query to locate recipients who match the given
   * schedule.
   *
   * @param \CRM_Core_DAO_ActionSchedule $schedule
   *   The schedule as configured by the administrator.
   * @param string $phase
   *   See, e.g., RecipientBuilder::PHASE_RELATION_FIRST.
   * @param array $defaultParams
   *
   * @return \CRM_Utils_SQL_Select
   * @throws \CRM_Core_Exception
   * @see RecipientBuilder
   */
  public function createQuery($schedule, $phase, $defaultParams): \CRM_Utils_SQL_Select {
    $query = \CRM_Utils_SQL_Select::from('civicrm_uf_match e')->param($defaultParams);
    $query->param([
      'casAddlCheckFrom' => 'civicrm_uf_match e',
      'casContactIdField' => 'e.contact_id',
      'casEntityIdField' => 'e.id',
    ]);
    $query->where('e.is_active = 1');
    $query['casDateField'] = $schedule->start_action_date;
    return $query;
  }
}

The createQuery function return a CRM_Utils_SQL_Select and we create this by defining three params:

  • casAddlCheckFrom which is the database table to query whch needs the alias e
  • casContactIdField the name of the field in the table which holds the contact ID
  • casEntityIdField the name of the field which holds the entity ID. Usually e.id.

When then add a where statement to only query active users. And last we add casDateField and we set it to the selected start date of the scheduled reminder.

Last bits: check the mixins in your extension

Make sure your extension has the scan-classes mixin.

civix mixin --enable=scan-classes@1

That is it. Now you can create a scheduled reminder for a Standalone User.