PluginProbe
The Innovative Form Builder – IvyForms / 1.4.1
The Innovative Form Builder – IvyForms v1.4.1
1.5.1 1.5 1.4.1 1.4 trunk 0.1.2 0.2 0.2.1 0.3 0.3.1 0.4 0.5 0.6 0.6.1 0.6.1-backup 0.6.1.1 0.7 0.8 0.8.1 0.8.2 0.9 0.9.1 1.0 1.1 1.1.1 All 27 releases
ivyforms / backend / src / Controllers / Permissions / GetAccessRulesController.php

GetAccessRulesController.php in The Innovative Form Builder – IvyForms 1.4.1, at backend/src/Controllers/Permissions/GetAccessRulesController.php

262 lines 7.9 KB
No matching file
Up and down to move Enter to open Esc to close
Raw Download Zip
1 <?php
2
3 /**
4 * @copyright © Melograno Venture Studio. All rights reserved.
5 */
6
7 namespace IvyForms\Controllers\Permissions;
8
9 // phpcs:disable PSR1.Files.SideEffects
10 if (!defined('ABSPATH')) {
11 exit;
12 }
13
14 use IvyForms\Common\Exceptions\ForbiddenException;
15 use IvyForms\Common\Sanitizer\Sanitizer;
16 use IvyForms\Controllers\Controller;
17 use IvyForms\Repository\Permissions\AccessRulesRepository;
18 use IvyForms\Repository\Form\FormRepositoryInterface;
19 use IvyForms\Services\Permissions\PermissionCatalog;
20 use IvyForms\Services\Translations\BackendStrings;
21 use WP_REST_Request;
22 use WP_REST_Response;
23
24 class GetAccessRulesController extends Controller
25 {
26 private AccessRulesRepository $accessRulesRepository;
27 private FormRepositoryInterface $formRepository;
28
29 public function __construct(
30 AccessRulesRepository $accessRulesRepository,
31 FormRepositoryInterface $formRepository
32 ) {
33 $this->accessRulesRepository = $accessRulesRepository;
34 $this->formRepository = $formRepository;
35 }
36
37 /**
38 * @throws ForbiddenException
39 */
40 public function handle(WP_REST_Request $data): WP_REST_Response
41 {
42 Sanitizer::verifyNonce($data->get_header('X-WP-Nonce'));
43
44 $payload = $this->accessRulesRepository->getPayload();
45 $rules = $this->stripDeletedFormIdsFromRules($payload['rules']);
46 $roleNames = wp_roles()->role_names;
47 $permissionLabelMap = PermissionCatalog::labelMap();
48 $permissionStrings = BackendStrings::getPermissionsStrings();
49 $allFormsLabel = (string) ($permissionStrings['all_forms'] ?? '');
50 $allEmailsForRole = (string) ($permissionStrings['all_emails_for_role'] ?? '');
51 $formNameMap = $this->loadFormNameMap($rules);
52
53 $rows = [];
54 foreach ($rules as $rule) {
55 $rows[] = $this->hydrateRow(
56 $rule,
57 $roleNames,
58 $permissionLabelMap,
59 $formNameMap,
60 $allFormsLabel,
61 $allEmailsForRole
62 );
63 }
64
65 return new WP_REST_Response(
66 [
67 'message' => BackendStrings::getCommonStrings()['ok'],
68 'rules' => $rows,
69 ],
70 200
71 );
72 }
73
74 /**
75 * Drop form IDs that no longer exist so clients do not re-submit stale scopes.
76 *
77 * @param list<array<string,mixed>> $rules
78 * @return list<array<string,mixed>>
79 */
80 private function stripDeletedFormIdsFromRules(array $rules): array
81 {
82 $allFormIds = $this->collectPositiveFormIdsFromRules($rules);
83 if ($allFormIds === []) {
84 return $rules;
85 }
86
87 $existingSet = array_flip($this->formRepository->filterExistingIds($allFormIds));
88 $sanitized = [];
89 foreach ($rules as $rule) {
90 $sanitized[] = $this->sanitizeRuleFormIds($rule, $existingSet);
91 }
92
93 return $sanitized;
94 }
95
96 /**
97 * @param list<array<string,mixed>> $rules
98 * @return list<int>
99 */
100 private function collectPositiveFormIdsFromRules(array $rules): array
101 {
102 $allFormIds = [];
103 foreach ($rules as $rule) {
104 foreach ($this->positiveFormIdsFromRule($rule) as $formId) {
105 $allFormIds[] = $formId;
106 }
107 }
108
109 return $allFormIds;
110 }
111
112 /**
113 * @param array<string,mixed> $rule
114 * @return list<int>
115 */
116 private function positiveFormIdsFromRule(array $rule): array
117 {
118 $ruleFormIds = $rule['form_ids'] ?? null;
119 if (!is_array($ruleFormIds)) {
120 return [];
121 }
122
123 $ids = [];
124 foreach ($ruleFormIds as $formId) {
125 $normalizedId = (int) $formId;
126 if ($normalizedId > 0) {
127 $ids[] = $normalizedId;
128 }
129 }
130
131 return $ids;
132 }
133
134 /**
135 * @param array<string,mixed> $rule
136 * @param array<int, int> $existingSet
137 * @return array<string,mixed>
138 */
139 private function sanitizeRuleFormIds(array $rule, array $existingSet): array
140 {
141 $ruleFormIds = $rule['form_ids'] ?? null;
142 if (!is_array($ruleFormIds)) {
143 return $rule;
144 }
145
146 $validIds = [];
147 foreach ($ruleFormIds as $formId) {
148 $normalizedId = (int) $formId;
149 if ($normalizedId > 0 && isset($existingSet[ $normalizedId ])) {
150 $validIds[] = $normalizedId;
151 }
152 }
153
154 $rule['form_ids'] = array_values(array_unique($validIds));
155
156 return $rule;
157 }
158
159 /**
160 * @param list<array<string,mixed>> $rules
161 * @return array<int, string>
162 */
163 private function loadFormNameMap(array $rules): array
164 {
165 $formIds = array_values(array_unique($this->collectPositiveFormIdsFromRules($rules)));
166 if ($formIds === []) {
167 return [];
168 }
169
170 return $this->formRepository->getNamesByIds($formIds);
171 }
172
173 /**
174 * @param array<string,mixed> $rule
175 * @param array<string, string> $roleNames
176 * @param array<string, string> $permissionLabelMap
177 * @param array<int, string> $formNameMap
178 * @return array<string, mixed>
179 */
180 private function hydrateRow(
181 array $rule,
182 array $roleNames,
183 array $permissionLabelMap,
184 array $formNameMap,
185 string $allFormsLabel,
186 string $allEmailsForRole
187 ): array {
188 $base = [
189 'id' => $rule['id'] ?? '',
190 'type' => $rule['type'] ?? '',
191 'permissions' => $rule['permissions'] ?? [],
192 'form_ids' => $rule['form_ids'] ?? null,
193 'created_at' => isset($rule['created_at']) ? (int) $rule['created_at'] : 0,
194 'updated_at' => isset($rule['updated_at']) ? (int) $rule['updated_at'] : 0,
195 'user_id' => null,
196 'role_slug' => '',
197 'role_name' => '',
198 'email_display' => '',
199 ];
200
201 $permissions = is_array($rule['permissions'] ?? null) ? $rule['permissions'] : [];
202 $base['forms_display'] = $this->formatFormsDisplay(
203 $rule['form_ids'] ?? null,
204 $formNameMap,
205 $allFormsLabel
206 );
207 $base['permissions_display'] = $this->formatPermissionsDisplay($permissions, $permissionLabelMap);
208
209 if (($rule['type'] ?? '') === 'role') {
210 $slug = (string) ($rule['role_slug'] ?? '');
211 $base['role_slug'] = $slug;
212 $base['role_name'] = $roleNames[ $slug ] ?? $slug;
213 $base['email_display'] = $allEmailsForRole;
214
215 return $base;
216 }
217
218 $uid = isset($rule['user_id']) ? (int) $rule['user_id'] : 0;
219 $base['user_id'] = $uid;
220 $user = get_userdata($uid);
221 $base['email_display'] = $user && $user->user_email ? (string) $user->user_email : '';
222
223 return $base;
224 }
225
226 /**
227 * @param mixed $formIds
228 * @param array<int, string> $formNameMap
229 */
230 private function formatFormsDisplay($formIds, array $formNameMap, string $allFormsLabel): string
231 {
232 if ($formIds === null) {
233 return $allFormsLabel;
234 }
235 if (!is_array($formIds) || $formIds === []) {
236 return '';
237 }
238
239 $titles = [];
240 foreach ($formIds as $formId) {
241 $normalizedId = (int) $formId;
242 $titles[] = $formNameMap[ $normalizedId ] ?? (string) $normalizedId;
243 }
244
245 return implode(', ', $titles);
246 }
247
248 /**
249 * @param mixed[] $permissions
250 * @param array<string, string> $permissionLabelMap
251 */
252 private function formatPermissionsDisplay(array $permissions, array $permissionLabelMap): string
253 {
254 $labels = [];
255 foreach (PermissionCatalog::sanitize($permissions) as $key) {
256 $labels[] = $permissionLabelMap[ $key ] ?? $key;
257 }
258
259 return implode(', ', $labels);
260 }
261 }
262