--- /dev/null
+<?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 |
+ +--------------------------------------------------------------------+
+ */
+
+/**
+ *
+ * @package CRM
+ * @copyright CiviCRM LLC https://civicrm.org/licensing
+ */
+class CRM_Afform_Utils {
+
+ public static function getEntityWeights($formEntities, $entityValues) {
+ $entityWeights = $entityMapping = $entitiesToBeProcessed = [];
+ foreach ($formEntities as $entityName => $entity) {
+ $entityWeights[$entityName] = 1;
+ $entityMapping[$entityName] = $entity['type'];
+ foreach ($entityValues[$entity['type']][$entityName] as $index => $vals) {
+ foreach ($vals as $field => $value) {
+ if (array_key_exists($value, $entityWeights)) {
+ $entityWeights[$entityName] = max((int) $entityWeights[$entityName], (int) ($entityWeights[$value] + 1));
+ }
+ else {
+ if (!array_key_exists($value, $entitiesToBeProcessed)) {
+ $entitiesToBeProcessed[$value] = [$entityName];
+ }
+ else {
+ $entitiesToBeProcessed[$value][] = $entityName;
+ }
+ }
+ }
+ }
+ // If any other entities have been processed that relied on this entity lets now alter their weights based on this entity's weight.
+ if (array_key_exists($entityName, $entitiesToBeProcessed)) {
+ foreach ($entitiesToBeProcessed[$entityName] as $dependentEntity) {
+ $entityWeights[$dependentEntity] = max((int) $entityWeights[$dependentEntity], (int) ($entityWeights[$entityName] + 1));
+ }
+ }
+ }
+ // Numerically sort the weights now that we have them set
+ asort($entityWeights);
+ return $entityWeights;
+ }
+
+}
/**
* @var array
- * List of definitions of the entities.
- * $entityDefns['spouse'] = ['type' => 'Individual'];
+ * Values to be saved for this entity
+ *
*/
- public $entityDefns;
+ public $values;
/**
- * @var array
- * List of submitted entities to save.
- * $entityValues['Contact']['spouse'] = ['first_name' => 'Optimus Prime'];
+ * @var string
+ * entityType
+ */
+ public $entityType;
+
+ /**
+ * @var string
+ * entityName e.g. Individual1, Activity1,
*/
- public $entityValues;
+ public $entityName;
/**
* @var array
*/
public $entityIds;
- public $entityWeights;
-
- public $entityMapping;
-
/**
* AfformSubmitEvent constructor.
*
* @param array $afform
* @param \Civi\Afform\FormDataModel $formDataModel
* @param \Civi\Api4\Action\Afform\Submit $apiRequest
- * @param array $entityDefns
- * @param array $entityValues
+ * @param array $values
+ * @param string $entityType
+ * @param string $entityName
* @param array $entityIds
- * @param array $entityWeights
- * @param array $entityMapping
*/
- public function __construct(array $afform, FormDataModel $formDataModel, Submit $apiRequest, $entityDefns, array $entityValues, array $entityIds, array $entityWeights, array $entityMapping) {
+ public function __construct(array $afform, FormDataModel $formDataModel, Submit $apiRequest, $values, string $entityType, string $entityName, array $entityIds) {
parent::__construct($afform, $formDataModel, $apiRequest);
- $this->entityDefns = $entityDefns;
- $this->entityValues = $entityValues;
+ $this->values = $values;
+ $this->entityType = $entityType;
+ $this->entityName = $entityName;
$this->entityIds = $entityIds;
- $this->entityWeights = $entityWeights;
- $this->entityMapping = $entityMapping;
- }
-
- /**
- * List of entity types which need processing.
- *
- * @return array
- * Ex: ['Contact', 'Activity']
- */
- public function getTypes() {
- return array_keys($this->entityValues);
}
}
protected $values;
protected function processForm() {
- $entityValues = $entityIds = $entityWeights = $entityMapping = [];
+ $entityValues = $entityIds = [];
foreach ($this->_formDataModel->getEntities() as $entityName => $entity) {
$entityIds[$entityName] = NULL;
- $entityWeights[$entityName] = 1;
- $entityMapping[$entityName] = $entity['type'];
foreach ($this->values[$entityName] ?? [] as $values) {
$entityValues[$entity['type']][$entityName][] = $values + ['fields' => []];
// Predetermined values override submitted values
}
}
}
- foreach ($entityValues[$entity['type']][$entityName] as $index => $vals) {
- foreach ($vals as $field => $value) {
- if (in_array($value, array_keys($entityWeights))) {
- $entityWeights[$entityName] = max((int) $entityWeights[$entityName], (int) ($entityWeights[$value] + 1));
- }
- }
- }
}
- // Numerically sort the weights smallest to largest.
- asort($entityWeights);
- $event = new AfformSubmitEvent($this->_afform, $this->_formDataModel, $this, $this->_formDataModel->getEntities(), $entityValues, $entityIds, $entityWeights, $entityMapping);
- \Civi::dispatcher()->dispatch(self::EVENT_NAME, $event);
+ $entityWeights = \CRM_Afform_Utils::getEntityWeights($this->_formDataModel->getEntities(), $entityValues);
+ foreach ($entityWeights as $entity => $weight) {
+ $values = $entityValues[$entityMapping[$entity]][$entity];
+ $event = new AfformSubmitEvent($this->_afform, $this->_formDataModel, $this, $values, $entityMapping[$entity], $entity, $entityIds);
+ \Civi::dispatcher()->dispatch(self::EVENT_NAME, $event);
+ }
foreach ($event->entityValues as $entityType => $entities) {
if (!empty($entities)) {
throw new \API_Exception(sprintf("Failed to process entities (type=%s; name=%s)", $entityType, implode(',', array_keys($entities))));
* @see afform_civicrm_config
*/
public static function processContacts(AfformSubmitEvent $event) {
- foreach ($event->entityValues['Contact'] ?? [] as $entityName => $contacts) {
- $api4 = $event->formDataModel->getSecureApi4($entityName);
- foreach ($contacts as $contact) {
- $saved = $api4('Contact', 'save', ['records' => [$contact['fields']]])->first();
- $event->entityIds[$entityName] = $saved['id'];
- self::saveJoins('Contact', $saved['id'], $contact['joins'] ?? []);
- }
+ if ($event->entityType !== 'Contact') {
+ return;
}
- unset($event->entityValues['Contact']);
+ $entityName = $event->entityName;
+ $api4 = $event->formDataModel->getSecureApi4($entityName);
+ $saved = $api4('Contact', 'save', ['records' => [$event->values['fields']]])->first();
+ $event->entityIds[$entityName] = $saved['id'];
+ self::saveJoins('Contact', $saved['id'], $event->values['joins'] ?? []);
}
/**
* @see afform_civicrm_config
*/
public static function processGenericEntity(AfformSubmitEvent $event) {
- foreach ($event->entityWeights as $entityName => $weight) {
- $records = $event->entityValues[$event->entityMapping[$entityName]][$entityName];
- $api4 = $event->formDataModel->getSecureApi4($entityName);
- // Replace Entity reference fields that reference other form based entities with their created ids.
- foreach ($records as $record) {
- foreach ($record['fields'] as $field => $value) {
- if (in_array($value, array_keys($event->entityIds)) && !empty($event->entityIds[$value])) {
- $record['fields'][$field] = $event->entityIds[$value];
- }
- }
- $saved = $api4($entityType, 'save', ['records' => [$record['fields']]])->first();
- $event->entityIds[$entityName] = $saved['id'];
- self::saveJoins($entityType, $saved['id'], $record['joins'] ?? []);
+ if ($event->entityType === 'Contact') {
+ return;
+ }
+ $entityName = $event->entityName;
+ $api4 = $event->formDataModel->getSecureApi4($event->entityName);
+ // Replace Entity reference fields that reference other form based entities with their created ids.
+ foreach ($record['fields'] as $field => $value) {
+ if (array_key_exists($value, $event->entityIds) && !empty($event->entityIds[$value])) {
+ $record['fields'][$field] = $event->entityIds[$value];
}
}
- unset($event->entityValues[$entityType]);
+ $saved = $api4($entityType, 'save', ['records' => [$event->values['fields']]])->first();
+ $event->entityIds[$entityName] = $saved['id'];
+ self::saveJoins($entityType, $saved['id'], $event->values['joins'] ?? []);
}
protected static function saveJoins($mainEntityName, $entityId, $joins) {
$this->assertEquals($expected, $actual);
}
+
+ public function formEntityWeightExampls() {
+ $exs = [];
+ $exs[] = [
+ [
+ 'Individual1' => ['type' => 'Contact', ['fields' => ['first_name', 'last_name']]],
+ 'Activity1' => ['type' => 'Activity', ['fields' => ['source_contact_id']]],
+ ],
+ [
+ 'Contact' => ['Individual1' => ['fields' => ['first_name' => 'Test', 'last_name' => 'Contact']]],
+ 'Activity' => ['Activity1' => ['fields' => ['source_contact_id' => 'Individual1']]],
+ ],
+ [
+ 'Individual1' => 1,
+ 'Activity1' => 2,
+ ],
+ ];
+ $exs[] = [
+ [
+ 'Individual1' => ['type' => 'Contact', ['fields' => ['first_name', 'last_name']]],
+ 'Event1' => ['type' => 'Event', ['fields' => ['created_id']]],
+ 'LocBlock1' => ['type' => 'LocBlock', ['fields' => ['event_id']]],
+ ],
+ [
+ 'Contact' => ['Individual1' => ['fields' => ['first_name' => 'Test', 'last_name' => 'Contact']]],
+ 'Event' => ['Event1' => ['fields' => ['created_id' => 'Individual1']]],
+ 'LocBlock' => ['LocBlock1' => ['fields' => ['event_id' => 'Event1']]],
+ ],
+ [
+ 'Individual1' => 1,
+ 'Event1' => 2,
+ 'LocBlock1' => 3,
+ ],
+ ];
+ $exs[] = [
+ [
+ 'Individual1' => ['type' => 'Contact', ['fields' => ['first_name', 'last_name']]],
+ 'LocBlock1' => ['type' => 'LocBlock', ['fields' => ['event_id']]],
+ 'Event1' => ['type' => 'Event', ['fields' => ['created_id']]],
+ ],
+ [
+ 'Contact' => ['Individual1' => ['fields' => ['first_name' => 'Test', 'last_name' => 'Contact']]],
+ 'LocBlock' => ['LocBlock1' => ['fields' => ['event_id' => 'Event1']]],
+ 'Event' => ['Event1' => ['fields' => ['created_id' => 'Individual1']]],
+ ],
+ [
+ 'Individual1' => 1,
+ 'Event1' => 2,
+ 'LocBlock1' => 3,
+ ],
+ ];
+ return $exs;
+ }
+
+ /**
+ * @dataProvider formEntityWeightExampls
+ */
+ public function testEntityWeights($formEntities, $entityValues, $expectedWeights) {
+ $this->assertEquals($expectedWeights, CRM_Afform_Utils::getEntityWeights($formEntities, $entityValues));
+ }
+
}