Skip to content

Commit

Permalink
Reduce use of undeclared properties, use trait to track entities
Browse files Browse the repository at this point in the history
A lot of the undeclared properties on this form & similar are just tracking
values of various relevant entities. This adds some functionality for that tracking
onto a trait & uses that. This reduces the need
to pass around values whose only importance is that they have
been loaded from the database & would require
another db call to access them from elsewhere.

Note I have swapped out the interaction with _contributorEmail & _contributorDisplayName
in getStatusMessage and send email receipts - these are the last 2 functions
called in the submit routine & the only reason the receipt function needs to set it is
to pass them to getStatusMessage. There are a couple of earlier interactions which are
odd so I ignored them for now.

The loop for sending out receipts is pretty messed up - so the first step is
getting the inputs & outputs for that loop clarified - but this
property is bang in the middle
  • Loading branch information
eileenmcnaughton committed Aug 25, 2023
1 parent 0aa8f20 commit 4d80053
Show file tree
Hide file tree
Showing 2 changed files with 129 additions and 13 deletions.
118 changes: 118 additions & 0 deletions CRM/Core/Form/EntityTrackingTrait.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,118 @@
<?php

/*
+--------------------------------------------------------------------+
| Copyright CiviCRM LLC. All rights reserved. |
| |
| This work is published under the GNU AGPLv3 license with some |
| permitted exceptions and without any warranty. For full license |
| and copyright information, see https://civicrm.org/licensing |
+--------------------------------------------------------------------+
*/

/**
* This trait provides a form of lazy loading for forms.
*
* It is intended to reduce the need for forms to pass values around while avoiding
* constantly reloading them from the database.
*
* @package CRM
* @copyright CiviCRM LLC https://civicrm.org/licensing
*/
trait CRM_Core_Form_EntityTrackingTrait {

/**
* Array of loaded entities.
*
* These are stored with keys that are consistent with apiv4 style parameters.
*
* @var array
*/
private $entities = [];

public function setEntity($entity, $identifier, $values): void {
$this->entities[$entity][$identifier] = $values;
}

/**
* Get the value for a property of an entity, loading from the database if needed.
*
* Permissions are not applied to the api call.
*
* @param string $entity
* @param int $id
* @param string $key
*
* @api supported for use outside of core. Will not change in a point release.
*
* @return mixed
*/
public function getEntityValue(string $entity, int $id, string $key) {
if (!isset($this->entities[$entity][$id]) || !array_key_exists($key, $this->entities[$entity][$id])) {
$this->loadEntity($entity, $id);
}
return $this->entities[$entity][$id][$key];
}

/**
* Get a value from a participant record.
*
* This function requires that the form implements `getParticipantID()`.
*
* @param string $fieldName
* @param int|null $id If not provided getParticipantID() is called.
*
* @api supported for use outside of core. Will not change in a point release.
*
* @return mixed
*/
public function getParticipantValue(string $fieldName, ?int $id = NULL) {
$id = $id ?? $this->getParticipantID();
return $this->getEntityValue('Participant', $id, $fieldName);
}

/**
* Get a value from a contact record.
*
* This function requires that the form implements `getContactID()`.
*
* @param string $fieldName
* @param int|null $id If not provided getContactID() is called.
*
* @api supported for use outside of core. Will not change in a point release.
*
* @return mixed
*/
public function getContactValue(string $fieldName, ?int $id = NULL) {
$id = $id ?? $this->getContactID();
return $this->getEntityValue('Contact', $id, $fieldName);
}

/**
* Load the requested entity.
*
* If we are going to load an entity we generally load all the values for it.
*
* @param string $entity
* @param int $id
*
* @noinspection PhpUnhandledExceptionInspection
* @noinspection PhpDocMissingThrowsInspection
*/
protected function loadEntity(string $entity, int $id): void {
if ($entity === 'Contact') {
// If we are loading a contact we generally also want their email.
$select = ['email_primary.email', 'email_primary.on_hold', '*', 'custom'];
}
else {
$select = ['*'];
}
$this->entities[$entity][$id] = civicrm_api4($entity, 'get', [
'where' => [['id', '=', $id]],
'checkPermissions' => FALSE,
// @todo - load pseudoconstants too...
'select' => $select,
]);
}

}
24 changes: 11 additions & 13 deletions CRM/Event/Form/Participant.php
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,8 @@
*/
class CRM_Event_Form_Participant extends CRM_Contribute_Form_AbstractEditPayment {

use CRM_Core_Form_EntityTrackingTrait;

/**
* Participant ID - use getParticipantID.
*
Expand Down Expand Up @@ -1382,19 +1384,19 @@ public function setCustomDataTypes(): void {
protected function getStatusMsg(array $params, int $numberSent, int $numberNotSent, string $updateStatusMsg): string {
$statusMsg = '';
if (($this->_action & CRM_Core_Action::UPDATE)) {
$statusMsg = ts('Event registration information for %1 has been updated.', [1 => $this->_contributorDisplayName]);
$statusMsg = ts('Event registration information for %1 has been updated.', [1 => $this->getContactValue('display_name')]);
if (!empty($params['send_receipt']) && $numberSent) {
$statusMsg .= ' ' . ts('A confirmation email has been sent to %1', [1 => $this->_contributorEmail]);
$statusMsg .= ' ' . ts('A confirmation email has been sent to %1', [1 => $this->getContactValue('email_primary.email')]);
}

if ($updateStatusMsg) {
$statusMsg = "{$statusMsg} {$updateStatusMsg}";
}
}
elseif ($this->_action & CRM_Core_Action::ADD) {
$statusMsg = ts('Event registration for %1 has been added.', [1 => $this->_contributorDisplayName]);
$statusMsg = ts('Event registration for %1 has been added.', [1 => $this->getContactValue('display_name')]);
if (!empty($params['send_receipt']) && $numberSent) {
$statusMsg .= ' ' . ts('A confirmation email has been sent to %1.', [1 => $this->_contributorEmail]);
$statusMsg .= ' ' . ts('A confirmation email has been sent to %1.', [1 => $this->getContactValue('email_primary.email')]);
}
}
return $statusMsg;
Expand Down Expand Up @@ -1933,18 +1935,14 @@ protected function getEventValue(string $fieldName) {
}

/**
* Get a value from the existing participant record (applies to edits).
* Get the contact id that the form is being submitted for.
*
* @param string $fieldName
* @todo consolidate Contact ID properties....
*
* @return array
* @throws \CRM_Core_Exception
* @return int
*/
protected function getParticipantValue($fieldName) {
if (!$this->participantRecord) {
$this->participantRecord = civicrm_api3('Participant', 'getsingle', ['id' => $this->_id]);
}
return $this->participantRecord[$fieldName] ?? $this->participantRecord['participant_' . $fieldName];
public function getContactID() {
return $this->_contactId;
}

/**
Expand Down

0 comments on commit 4d80053

Please sign in to comment.