Commit | Line | Data |
---|---|---|
fc54326f TO |
1 | <?php |
2 | ||
3 | namespace Civi\Afform; | |
4 | ||
0fd2d6af | 5 | use Civi\API\Exception\UnauthorizedException; |
344e8290 CW |
6 | use Civi\Api4\Afform; |
7 | ||
fc54326f TO |
8 | /** |
9 | * Class FormDataModel | |
10 | * @package Civi\Afform | |
11 | * | |
344e8290 | 12 | * Examines a form and determines the entities, fields & joins in use. |
fc54326f TO |
13 | */ |
14 | class FormDataModel { | |
15 | ||
16 | /** | |
17 | * @var array | |
18 | * Ex: $entities['spouse']['type'] = 'Contact'; | |
19 | */ | |
20 | protected $entities; | |
21 | ||
22 | /** | |
344e8290 | 23 | * @var array |
fc54326f | 24 | */ |
344e8290 CW |
25 | protected $blocks = []; |
26 | ||
0fd2d6af TO |
27 | /** |
28 | * @var array | |
29 | * Ex: $secureApi4s['spouse'] = function($entity, $action, $params){...}; | |
30 | */ | |
31 | protected $secureApi4s = []; | |
32 | ||
344e8290 | 33 | public function __construct($layout) { |
fb96a2d7 | 34 | $root = AHQ::makeRoot($layout); |
344e8290 | 35 | $this->entities = array_column(AHQ::getTags($root, 'af-entity'), NULL, 'name'); |
344e8290 CW |
36 | foreach (array_keys($this->entities) as $entity) { |
37 | $this->entities[$entity]['fields'] = $this->entities[$entity]['joins'] = []; | |
38 | } | |
e38db494 CW |
39 | // Pre-load full list of afforms in case this layout embeds other afform directives |
40 | $this->blocks = (array) Afform::get()->setCheckPermissions(FALSE)->setSelect(['name', 'directive_name'])->execute()->indexBy('directive_name'); | |
344e8290 | 41 | $this->parseFields($layout); |
fc54326f TO |
42 | } |
43 | ||
0fd2d6af TO |
44 | /** |
45 | * Prepare to access APIv4 on behalf of a particular entity. This will enforce | |
46 | * any security options associated with that entity. | |
47 | * | |
48 | * $formDataModel->getSecureApi4('me')('Contact', 'get', ['where'=>[...]]); | |
49 | * $formDataModel->getSecureApi4('me')('Email', 'create', [...]); | |
50 | * | |
51 | * @param string $entityName | |
52 | * Ex: 'Individual1', 'Individual2', 'me', 'spouse', 'children', 'theMeeting' | |
53 | * | |
54 | * @return callable | |
55 | * API4-style | |
56 | */ | |
57 | public function getSecureApi4($entityName) { | |
58 | if (!isset($this->secureApi4s[$entityName])) { | |
59 | if (!isset($this->entities[$entityName])) { | |
60 | throw new UnauthorizedException("Cannot delegate APIv4 calls on behalf of unrecognized entity ($entityName)"); | |
61 | } | |
62 | $this->secureApi4s[$entityName] = function(string $entity, string $action, $params = [], $index = NULL) use ($entityName) { | |
63 | // FIXME Pick real value of checkPermissions. Possibly limit by ID. | |
64 | // \Civi::log()->info("secureApi4($entityName): call($entity, $action)"); | |
65 | // $params['checkPermissions'] = FALSE; | |
66 | $params['checkPermissions'] = TRUE; | |
67 | return civicrm_api4($entity, $action, $params, $index); | |
68 | }; | |
69 | } | |
70 | return $this->secureApi4s[$entityName]; | |
71 | } | |
72 | ||
fc54326f | 73 | /** |
e1aca853 | 74 | * @param array $nodes |
e1aca853 | 75 | * @param string $entity |
344e8290 | 76 | * @param string $join |
fc54326f | 77 | */ |
344e8290 | 78 | protected function parseFields($nodes, $entity = NULL, $join = NULL) { |
e1aca853 CW |
79 | foreach ($nodes as $node) { |
80 | if (!is_array($node) || !isset($node['#tag'])) { | |
344e8290 | 81 | continue; |
fa5d6183 | 82 | } |
344e8290 CW |
83 | elseif (!empty($node['af-fieldset']) && !empty($node['#children'])) { |
84 | $this->parseFields($node['#children'], $node['af-fieldset'], $join); | |
e1aca853 CW |
85 | } |
86 | elseif ($entity && $node['#tag'] === 'af-field') { | |
344e8290 CW |
87 | if ($join) { |
88 | $this->entities[$entity]['joins'][$join]['fields'][$node['name']] = AHQ::getProps($node); | |
89 | } | |
90 | else { | |
91 | $this->entities[$entity]['fields'][$node['name']] = AHQ::getProps($node); | |
92 | } | |
e1aca853 | 93 | } |
344e8290 CW |
94 | elseif ($entity && !empty($node['af-join'])) { |
95 | $this->entities[$entity]['joins'][$node['af-join']] = AHQ::getProps($node); | |
96 | $this->parseFields($node['#children'] ?? [], $entity, $node['af-join']); | |
fc54326f | 97 | } |
e1aca853 | 98 | elseif (!empty($node['#children'])) { |
344e8290 CW |
99 | $this->parseFields($node['#children'], $entity, $join); |
100 | } | |
101 | // Recurse into embedded blocks | |
102 | if (isset($this->blocks[$node['#tag']])) { | |
103 | if (!isset($this->blocks[$node['#tag']]['layout'])) { | |
104 | $this->blocks[$node['#tag']] = Afform::get()->setCheckPermissions(FALSE)->setSelect(['name', 'layout'])->addWhere('name', '=', $this->blocks[$node['#tag']]['name'])->execute()->first(); | |
105 | } | |
106 | if (!empty($this->blocks[$node['#tag']]['layout'])) { | |
107 | $this->parseFields($this->blocks[$node['#tag']]['layout'], $entity, $join); | |
108 | } | |
fc54326f TO |
109 | } |
110 | } | |
111 | } | |
112 | ||
113 | /** | |
114 | * @return array | |
115 | * Ex: $entities['spouse']['type'] = 'Contact'; | |
116 | */ | |
117 | public function getEntities() { | |
118 | return $this->entities; | |
119 | } | |
120 | ||
121 | } |