3 namespace Civi\Api4\Action\Afform
;
5 use Civi\Afform\Event\AfformSubmitEvent
;
9 * @package Civi\Api4\Action\Afform
11 class Submit
extends AbstractProcessor
{
13 const EVENT_NAME
= 'civi.afform.submit';
22 protected function processForm() {
24 foreach ($this->_formDataModel
->getEntities() as $entityName => $entity) {
25 foreach ($this->values
[$entityName] ??
[] as $values) {
26 $entityValues[$entity['type']][$entityName][] = $values +
['fields' => []];
27 // Predetermined values override submitted values
28 if (!empty($entity['data'])) {
29 foreach ($entityValues[$entity['type']][$entityName] as $index => $vals) {
30 $entityValues[$entity['type']][$entityName][$index]['fields'] = $entity['data'] +
$vals['fields'];
35 $event = new AfformSubmitEvent($this->_afform
, $this->_formDataModel
, $this, $this->_formDataModel
->getEntities(), $entityValues);
36 \Civi
::dispatcher()->dispatch(self
::EVENT_NAME
, $event);
37 foreach ($event->entityValues
as $entityType => $entities) {
38 if (!empty($entities)) {
39 throw new \
API_Exception(sprintf("Failed to process entities (type=%s; name=%s)", $entityType, implode(',', array_keys($entities))));
43 // What should I return?
48 * @param \Civi\Afform\Event\AfformSubmitEvent $event
49 * @throws \API_Exception
50 * @see afform_civicrm_config
52 public static function processContacts(AfformSubmitEvent
$event) {
53 foreach ($event->entityValues
['Contact'] ??
[] as $entityName => $contacts) {
54 $api4 = $event->formDataModel
->getSecureApi4($entityName);
55 foreach ($contacts as $contact) {
56 $saved = $api4('Contact', 'save', ['records' => [$contact['fields']]])->first();
57 self
::saveJoins($api4, 'Contact', $saved['id'], $contact['joins'] ??
[]);
60 unset($event->entityValues
['Contact']);
64 * @param \Civi\Afform\Event\AfformSubmitEvent $event
65 * @throws \API_Exception
66 * @see afform_civicrm_config
68 public static function processGenericEntity(AfformSubmitEvent
$event) {
69 foreach ($event->entityValues
as $entityType => $entities) {
70 // Each record is an array of one or more items (can be > 1 if af-repeat is used)
71 foreach ($entities as $entityName => $records) {
72 $api4 = $event->formDataModel
->getSecureApi4($entityName);
73 foreach ($records as $record) {
74 $saved = $api4($entityType, 'save', ['records' => [$record['fields']]])->first();
75 self
::saveJoins($api4, $entityType, $saved['id'], $record['joins'] ??
[]);
78 unset($event->entityValues
[$entityType]);
82 protected static function saveJoins($api4, $mainEntityName, $entityId, $joins) {
83 foreach ($joins as $joinEntityName => $join) {
84 $values = self
::filterEmptyJoins($joinEntityName, $join);
85 // FIXME: Replace/delete should only be done to known contacts
87 $api4($joinEntityName, 'replace', [
88 'where' => self
::getJoinWhereClause($mainEntityName, $joinEntityName, $entityId),
94 $api4($joinEntityName, 'delete', [
95 'where' => self
::getJoinWhereClause($mainEntityName, $joinEntityName, $entityId),
98 catch (\API_Exception
$e) {
99 // No records to delete
106 * Filter out joins that have been left blank on the form
112 private static function filterEmptyJoins($entity, $join) {
113 return array_filter($join, function($item) use($entity) {
116 return !empty($item['email']);
119 return !empty($item['phone']);
122 return !empty($item['name']);
125 return !empty($item['url']);
128 \CRM_Utils_Array
::remove($item, 'id', 'is_primary', 'location_type_id', 'entity_id', 'contact_id', 'entity_table');
129 return (bool) array_filter($item);