Merge pull request #18324 from mattwire/payproc_configoptional
[civicrm-core.git] / ext / afform / core / Civi / Afform / FormDataModel.php
1 <?php
2
3 namespace Civi\Afform;
4
5 use Civi\Api4\Afform;
6
7 /**
8 * Class FormDataModel
9 * @package Civi\Afform
10 *
11 * Examines a form and determines the entities, fields & joins in use.
12 */
13 class FormDataModel {
14
15 /**
16 * @var array
17 * Ex: $entities['spouse']['type'] = 'Contact';
18 */
19 protected $entities;
20
21 /**
22 * @var array
23 */
24 protected $blocks = [];
25
26 public function __construct($layout) {
27 $root = AHQ::makeRoot($layout);
28 $this->entities = array_column(AHQ::getTags($root, 'af-entity'), NULL, 'name');
29 foreach (array_keys($this->entities) as $entity) {
30 $this->entities[$entity]['fields'] = $this->entities[$entity]['joins'] = [];
31 }
32 // Pre-load full list of afforms in case this layout embeds other afform directives
33 $this->blocks = (array) Afform::get()->setCheckPermissions(FALSE)->setSelect(['name', 'directive_name'])->execute()->indexBy('directive_name');
34 $this->parseFields($layout);
35 }
36
37 /**
38 * @param array $nodes
39 * @param string $entity
40 * @param string $join
41 */
42 protected function parseFields($nodes, $entity = NULL, $join = NULL) {
43 foreach ($nodes as $node) {
44 if (!is_array($node) || !isset($node['#tag'])) {
45 continue;
46 }
47 elseif (!empty($node['af-fieldset']) && !empty($node['#children'])) {
48 $this->parseFields($node['#children'], $node['af-fieldset'], $join);
49 }
50 elseif ($entity && $node['#tag'] === 'af-field') {
51 if ($join) {
52 $this->entities[$entity]['joins'][$join]['fields'][$node['name']] = AHQ::getProps($node);
53 }
54 else {
55 $this->entities[$entity]['fields'][$node['name']] = AHQ::getProps($node);
56 }
57 }
58 elseif ($entity && !empty($node['af-join'])) {
59 $this->entities[$entity]['joins'][$node['af-join']] = AHQ::getProps($node);
60 $this->parseFields($node['#children'] ?? [], $entity, $node['af-join']);
61 }
62 elseif (!empty($node['#children'])) {
63 $this->parseFields($node['#children'], $entity, $join);
64 }
65 // Recurse into embedded blocks
66 if (isset($this->blocks[$node['#tag']])) {
67 if (!isset($this->blocks[$node['#tag']]['layout'])) {
68 $this->blocks[$node['#tag']] = Afform::get()->setCheckPermissions(FALSE)->setSelect(['name', 'layout'])->addWhere('name', '=', $this->blocks[$node['#tag']]['name'])->execute()->first();
69 }
70 if (!empty($this->blocks[$node['#tag']]['layout'])) {
71 $this->parseFields($this->blocks[$node['#tag']]['layout'], $entity, $join);
72 }
73 }
74 }
75 }
76
77 /**
78 * @return array
79 * Ex: $entities['spouse']['type'] = 'Contact';
80 */
81 public function getEntities() {
82 return $this->entities;
83 }
84
85 }