WIP Entity Reference Submission fields
authorSeamus Lee <seamuslee001@gmail.com>
Thu, 6 May 2021 08:34:03 +0000 (18:34 +1000)
committerSeamus Lee <seamuslee001@gmail.com>
Wed, 19 May 2021 09:26:02 +0000 (19:26 +1000)
ext/afform/core/Civi/Afform/Event/AfformSubmitEvent.php
ext/afform/core/Civi/Api4/Action/Afform/Submit.php

index 88112fd87302cfe917816da443cb5857ed5e2307..f2bdf951aa6de02bc05be7697e20b325b4580676 100644 (file)
@@ -32,6 +32,17 @@ class AfformSubmitEvent extends AfformBaseEvent {
    */
   public $entityValues;
 
+  /**
+   * @var array
+   *   List of Submitted Entities and their matching ids
+   *   $entityIds['Individual1'] = 1;
+   */
+  public $entityIds;
+
+  public $entityWeights;
+
+  public $entityMapping;
+
   /**
    * AfformSubmitEvent constructor.
    *
@@ -40,11 +51,17 @@ class AfformSubmitEvent extends AfformBaseEvent {
    * @param \Civi\Api4\Action\Afform\Submit $apiRequest
    * @param array $entityDefns
    * @param array $entityValues
+   * @param array $entityIds
+   * @param array $entityWeights
+   * @param array $entityMapping
    */
-  public function __construct(array $afform, FormDataModel $formDataModel, Submit $apiRequest, $entityDefns, array $entityValues) {
+  public function __construct(array $afform, FormDataModel $formDataModel, Submit $apiRequest, $entityDefns, array $entityValues, array $entityIds, array $entityWeights, array $entityMapping) {
     parent::__construct($afform, $formDataModel, $apiRequest);
     $this->entityDefns = $entityDefns;
     $this->entityValues = $entityValues;
+    $this->entityIds = $entityIds;
+    $this->entityWeights = $entityWeights;
+    $this->entityMapping = $entityMapping;
   }
 
   /**
index ec505c10c432a74436241fe75613a486bea4e88f..b79b807150b199f0170d786cd4da5d4fc5e429ae 100644 (file)
@@ -20,8 +20,11 @@ class Submit extends AbstractProcessor {
   protected $values;
 
   protected function processForm() {
-    $entityValues = [];
+    $entityValues = $entityIds = $entityWeights = $entityMapping = [];
     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
@@ -31,8 +34,17 @@ class Submit extends AbstractProcessor {
           }
         }
       }
+      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));
+          }
+        }
+      }
     }
-    $event = new AfformSubmitEvent($this->_afform, $this->_formDataModel, $this, $this->_formDataModel->getEntities(), $entityValues);
+    // 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);
     foreach ($event->entityValues as $entityType => $entities) {
       if (!empty($entities)) {
@@ -54,6 +66,7 @@ class Submit extends AbstractProcessor {
       $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'] ?? []);
       }
     }
@@ -66,17 +79,22 @@ class Submit extends AbstractProcessor {
    * @see afform_civicrm_config
    */
   public static function processGenericEntity(AfformSubmitEvent $event) {
-    foreach ($event->entityValues as $entityType => $entities) {
-      // Each record is an array of one or more items (can be > 1 if af-repeat is used)
-      foreach ($entities as $entityName => $records) {
-        $api4 = $event->formDataModel->getSecureApi4($entityName);
-        foreach ($records as $record) {
-          $saved = $api4($entityType, 'save', ['records' => [$record['fields']]])->first();
-          self::saveJoins($entityType, $saved['id'], $record['joins'] ?? []);
+    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'] ?? []);
       }
-      unset($event->entityValues[$entityType]);
     }
+    unset($event->entityValues[$entityType]);
   }
 
   protected static function saveJoins($mainEntityName, $entityId, $joins) {