Commit | Line | Data |
---|---|---|
11e724f0 TO |
1 | <?php |
2 | ||
3 | namespace Civi\Api4\Action\Afform; | |
4 | ||
9c84a124 CW |
5 | use Civi\Api4\CustomField; |
6 | use Civi\Api4\CustomGroup; | |
67d666c6 | 7 | use CRM_Afform_ExtensionUtil as E; |
9c84a124 | 8 | |
11e724f0 | 9 | /** |
28b4ace4 | 10 | * @inheritDoc |
11e724f0 TO |
11 | * @package Civi\Api4\Action\Afform |
12 | */ | |
28b4ace4 | 13 | class Get extends \Civi\Api4\Generic\BasicGetAction { |
11e724f0 | 14 | |
28b4ace4 | 15 | use \Civi\Api4\Utils\AfformFormatTrait; |
11e724f0 TO |
16 | |
17 | public function getRecords() { | |
18 | /** @var \CRM_Afform_AfformScanner $scanner */ | |
19 | $scanner = \Civi::service('afform_scanner'); | |
60a62215 | 20 | $getComputed = $this->_isFieldSelected('has_local', 'has_base'); |
9c84a124 | 21 | $getLayout = $this->_isFieldSelected('layout'); |
b076c308 | 22 | $getSearchDisplays = $this->_isFieldSelected('search_displays'); |
2ca6eeda | 23 | $values = []; |
9c84a124 | 24 | |
edf837b4 | 25 | // This helps optimize lookups by file/module/directive name |
2ca6eeda | 26 | $getNames = array_filter([ |
edf837b4 CW |
27 | 'name' => $this->_itemsToGet('name'), |
28 | 'module_name' => $this->_itemsToGet('module_name'), | |
29 | 'directive_name' => $this->_itemsToGet('directive_name'), | |
30 | ]); | |
2ca6eeda | 31 | $getTypes = $this->_itemsToGet('type'); |
11e724f0 | 32 | |
2ca6eeda | 33 | $names = $getNames['name'] ?? array_keys($scanner->findFilePaths()); |
25f2b36b | 34 | |
2ca6eeda CW |
35 | // Get autogenerated blocks if type block is not excluded |
36 | if (!$getTypes || in_array('block', $getTypes, TRUE)) { | |
37 | $values = $this->getAutoGenerated($names, $getNames, $getLayout); | |
38 | } | |
11e724f0 | 39 | |
48be26b0 CW |
40 | if ($this->checkPermissions) { |
41 | $names = array_filter($names, [$this, 'checkPermission']); | |
42 | } | |
43 | ||
11e724f0 | 44 | foreach ($names as $name) { |
25f2b36b | 45 | $info = [ |
edf837b4 | 46 | 'name' => $name, |
25f2b36b CW |
47 | 'module_name' => _afform_angular_module_name($name, 'camel'), |
48 | 'directive_name' => _afform_angular_module_name($name, 'dash'), | |
49 | ]; | |
2ca6eeda CW |
50 | // Skip if afform does not match requested name |
51 | foreach ($getNames as $key => $names) { | |
52 | if (!in_array($info[$key], $names)) { | |
fa8dc3f2 | 53 | continue 2; |
edf837b4 | 54 | } |
25f2b36b | 55 | } |
11e724f0 | 56 | $record = $scanner->getMeta($name); |
2ca6eeda CW |
57 | // Skip if afform does not exist or is not of requested type(s) |
58 | if ( | |
59 | (!$record && !isset($values[$name])) || | |
a003d5f7 | 60 | ($getTypes && isset($record['type']) && !in_array($record['type'], $getTypes, TRUE)) |
2ca6eeda | 61 | ) { |
9c84a124 CW |
62 | continue; |
63 | } | |
25f2b36b | 64 | $values[$name] = array_merge($values[$name] ?? [], $record ?? [], $info); |
9c84a124 CW |
65 | if ($getComputed) { |
66 | $scanner->addComputedFields($values[$name]); | |
1aebf5b0 | 67 | } |
b076c308 | 68 | if ($getLayout || $getSearchDisplays) { |
236719c6 | 69 | // Autogenerated layouts will already be in values but can be overridden; scanner takes priority |
9c84a124 | 70 | $values[$name]['layout'] = $scanner->getLayout($name) ?? $values[$name]['layout'] ?? ''; |
11e724f0 | 71 | } |
b076c308 CW |
72 | if ($getSearchDisplays) { |
73 | $values[$name]['search_displays'] = $this->getSearchDisplays($values[$name]['layout']); | |
74 | } | |
11e724f0 TO |
75 | } |
76 | ||
9c84a124 CW |
77 | if ($getLayout && $this->layoutFormat !== 'html') { |
78 | foreach ($values as $name => $record) { | |
79 | $values[$name]['layout'] = $this->convertHtmlToOutput($record['layout']); | |
80 | } | |
81 | } | |
82 | ||
83 | return $values; | |
84 | } | |
85 | ||
48be26b0 CW |
86 | /** |
87 | * Assert that a form is authorized. | |
88 | * | |
89 | * @return bool | |
90 | */ | |
91 | protected function checkPermission($name) { | |
92 | return \CRM_Core_Permission::check("@afform:$name"); | |
93 | } | |
94 | ||
9c84a124 CW |
95 | /** |
96 | * Generates afform blocks from custom field sets. | |
97 | * | |
2ca6eeda CW |
98 | * @param array $names |
99 | * @param array $getNames | |
100 | * @param bool $getLayout | |
9c84a124 CW |
101 | * @return array |
102 | * @throws \API_Exception | |
103 | */ | |
2ca6eeda | 104 | protected function getAutoGenerated(&$names, $getNames, $getLayout) { |
9c84a124 | 105 | $values = $groupNames = []; |
2ca6eeda | 106 | foreach ($getNames['name'] ?? [] as $name) { |
fa8dc3f2 CW |
107 | if (strpos($name, 'afblockCustom_') === 0 && strlen($name) > 13) { |
108 | $groupNames[] = substr($name, 14); | |
9c84a124 CW |
109 | } |
110 | } | |
c3273f01 | 111 | // Early return if this api call is fetching afforms by name and those names are not custom-related |
2ca6eeda CW |
112 | if ((!empty($getNames['name']) && !$groupNames) |
113 | || (!empty($getNames['module_name']) && !strstr(implode(' ', $getNames['module_name']), 'afblockCustom')) | |
114 | || (!empty($getNames['directive_name']) && !strstr(implode(' ', $getNames['directive_name']), 'afblock-custom')) | |
edf837b4 | 115 | ) { |
9c84a124 CW |
116 | return $values; |
117 | } | |
2ca6eeda | 118 | $customApi = CustomGroup::get(FALSE) |
83412ba5 | 119 | ->addSelect('name', 'title', 'help_pre', 'help_post', 'extends', 'max_multiple') |
9c84a124 CW |
120 | ->addWhere('is_multiple', '=', 1) |
121 | ->addWhere('is_active', '=', 1); | |
122 | if ($groupNames) { | |
123 | $customApi->addWhere('name', 'IN', $groupNames); | |
124 | } | |
125 | if ($getLayout) { | |
83412ba5 CW |
126 | $customApi->addSelect('help_pre', 'help_post'); |
127 | $customApi->addChain('fields', CustomField::get(FALSE) | |
9c84a124 CW |
128 | ->addSelect('name') |
129 | ->addWhere('custom_group_id', '=', '$id') | |
130 | ->addWhere('is_active', '=', 1) | |
131 | ->addOrderBy('weight', 'ASC') | |
132 | ); | |
133 | } | |
134 | foreach ($customApi->execute() as $custom) { | |
fa8dc3f2 | 135 | $name = 'afblockCustom_' . $custom['name']; |
9c84a124 CW |
136 | if (!in_array($name, $names)) { |
137 | $names[] = $name; | |
138 | } | |
139 | $item = [ | |
140 | 'name' => $name, | |
b1335297 | 141 | 'type' => 'block', |
9c84a124 | 142 | 'requires' => [], |
fa8dc3f2 | 143 | 'title' => E::ts('%1 block', [1 => $custom['title']]), |
9c84a124 | 144 | 'description' => '', |
1887d8bd | 145 | 'is_dashlet' => FALSE, |
9c84a124 | 146 | 'is_public' => FALSE, |
053ab2a5 | 147 | 'is_token' => FALSE, |
9c84a124 | 148 | 'permission' => 'access CiviCRM', |
fa8dc3f2 CW |
149 | 'join_entity' => 'Custom_' . $custom['name'], |
150 | 'entity_type' => $custom['extends'], | |
9c84a124 CW |
151 | 'has_base' => TRUE, |
152 | ]; | |
153 | if ($getLayout) { | |
154 | $item['layout'] = ($custom['help_pre'] ? '<div class="af-markup">' . $custom['help_pre'] . "</div>\n" : ''); | |
155 | foreach ($custom['fields'] as $field) { | |
156 | $item['layout'] .= "<af-field name=\"{$field['name']}\" />\n"; | |
157 | } | |
158 | $item['layout'] .= ($custom['help_post'] ? '<div class="af-markup">' . $custom['help_post'] . "</div>\n" : ''); | |
159 | } | |
160 | $values[$name] = $item; | |
161 | } | |
11e724f0 TO |
162 | return $values; |
163 | } | |
164 | ||
b076c308 CW |
165 | /** |
166 | * Find search display tags in afform markup | |
167 | * | |
168 | * @param string $html | |
169 | * @return string[] | |
170 | */ | |
171 | private function getSearchDisplays(string $html) { | |
172 | $tags = $searchDisplays = []; | |
173 | preg_match_all('/<\\s*crm-search-display[^>]+>/', $html, $tags); | |
174 | foreach ($tags[0] ?? [] as $tag) { | |
175 | $searchName = $displayName = []; | |
176 | preg_match('/search-name\\s*=\\s*[\'"]([^\'"]+)[\'"]/', $tag, $searchName); | |
5c952e51 | 177 | // Note: display name will be blank when using the default (autogenerated) display |
b076c308 | 178 | preg_match('/display-name\\s*=\\s*[\'"]([^\'"]+)[\'"]/', $tag, $displayName); |
5c952e51 CW |
179 | if (!empty($searchName[1])) { |
180 | $searchDisplays[] = $searchName[1] . (empty($displayName[1]) ? '' : '.' . $displayName[1]); | |
b076c308 CW |
181 | } |
182 | } | |
183 | return $searchDisplays; | |
184 | } | |
185 | ||
11e724f0 | 186 | } |