Custom Membership Term plugins
You can add project-specific membership term logic by implementing a new plugin that implements MembershipTermInterface and is discovered by the Membership Term manager.
Steps
1. Create a plugin class
- Place the class in your module under
src/Plugin/MembershipTerm/(e.g.src/Plugin/MembershipTerm/CustomTerm.php). - Extend
Drupal\crm_membership\Plugin\MembershipTermBase. - Add the
#[MembershipTerm]PHP attribute so the plugin is discovered.
Attribute parameters (from Drupal\crm_membership\Attribute\MembershipTerm):
| Parameter | Type | Description |
|---|---|---|
id |
string | Plugin ID (machine name). Required. |
label |
TranslatableMarkup | null | Human-readable label shown in the Membership Type form. |
allowOverrideStartDate |
bool | Whether the start date can be overridden when activating/renewing. Default false. |
allowOverrideEndDate |
bool | Whether the end date can be overridden. Default false. |
durationConfigKey |
string | null | Config key for duration (e.g. for duration_field). Optional. |
timeGapKey |
string | null | Config key for time gap between renewals. Optional. |
2. Example (minimal)
<?php
declare(strict_types=1);
namespace Drupal\my_module\Plugin\MembershipTerm;
use Drupal\Core\StringTranslation\TranslatableMarkup;
use Drupal\crm\Entity\Contact;
use Drupal\crm_membership\Attribute\MembershipTerm;
use Drupal\crm_membership\Plugin\MembershipTermBase;
#[MembershipTerm(
id: "my_custom_term",
label: new TranslatableMarkup("My custom term"),
allowOverrideStartDate: true,
allowOverrideEndDate: true,
)]
final class CustomTerm extends MembershipTermBase {
public function isActiveFor(Contact $contact): bool {
// Your logic.
return TRUE;
}
public function isExpiredFor(Contact $contact): bool {
return FALSE;
}
public function activate(?array $contacts = NULL): void {
// Create initial period(s) using $this->addMembershipPeriod().
}
public function renew(?array $contacts = NULL): void {
// Add new period(s).
}
public function expire(): void {
// Mark membership expired, clear current_periods as needed.
}
public function cancel(): void {
// Cancel logic.
}
public function allowRenewal(): bool {
return TRUE;
}
public function allowOverrideStartDate(): bool {
return TRUE;
}
public function allowOverrideEndDate(): bool {
return TRUE;
}
}
The base class already implements setMembership/getMembership, getSettings, setStartDate/setEndDate, and stores startDate/endDate; you only need to implement the lifecycle and status methods (and optionally buildConfigurationForm for type configuration).
3. Reference implementation
The built-in Fixed duration plugin is a good reference: it supports configurable duration, start/end time, and time gap, and implements activation, renewal, expiration, and date overrides.
- Class:
Drupal\crm_membership\Plugin\MembershipTerm\FixedDuration - File:
src/Plugin/MembershipTerm/FixedDuration.php - Attribute:
src/Attribute/MembershipTerm.php
4. Configuration form (optional)
To expose settings on the Membership Type form, override buildConfigurationForm(array $current_config, FormStateInterface $form_state): array in your plugin and return a Form API array. The submitted values are stored in the type’s membership_term_config and passed to the plugin as configuration.
5. Use your plugin
- Clear caches so the new plugin is discovered.
- Edit a Membership Type (or create one) at Administration → Structure → CRM → Membership Types.
- Select your plugin in the “Membership term” dropdown and save. Any configuration form you added will appear there.
- New memberships of that type will use your plugin for activation, renewal, expiration, and status checks.