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 / Services / Permissions / AccessRulesFormScopeExtender.php

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

151 lines 4.2 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\Services\Permissions;
8
9 // phpcs:disable PSR1.Files.SideEffects
10 if (!defined('ABSPATH')) {
11 exit;
12 }
13
14 use IvyForms\Repository\Permissions\AccessRulesRepository;
15 use WP_User;
16
17 /**
18 * When a delegated user creates a form while limited to specific forms, append the new form id
19 * to their scoped access rules so they can continue editing it.
20 */
21 final class AccessRulesFormScopeExtender
22 {
23 private AccessRulesRepository $accessRulesRepository;
24
25 private PermissionResolver $permissionResolver;
26
27 public function __construct(
28 AccessRulesRepository $accessRulesRepository,
29 PermissionResolver $permissionResolver
30 ) {
31 $this->accessRulesRepository = $accessRulesRepository;
32 $this->permissionResolver = $permissionResolver;
33 }
34
35 public function appendCreatedFormToCurrentUserScope(int $formId): void
36 {
37 $user = $this->resolveCurrentUserForScopeAppend($formId);
38 if ($user === null) {
39 return;
40 }
41
42 $payload = $this->accessRulesRepository->getPayload();
43 $rules = $payload['rules'];
44 if (!$this->appendFormIdToUserScopedRules($rules, $formId, $user)) {
45 return;
46 }
47
48 $this->persistUpdatedRules($rules);
49 }
50
51 private function resolveCurrentUserForScopeAppend(int $formId): ?WP_User
52 {
53 if ($formId <= 0 || IvyFormsAccess::hasImplicitElevatedAccess()) {
54 return null;
55 }
56
57 $user = wp_get_current_user();
58 if (!$user instanceof WP_User || (int) $user->ID <= 0) {
59 return null;
60 }
61
62 if (user_can($user, IvyFormsAccess::CAP_MANAGE_ALL)) {
63 return null;
64 }
65
66 if ($this->permissionResolver->userCan('add_edit_forms', $user, $formId)) {
67 return null;
68 }
69
70 return $user;
71 }
72
73 /**
74 * @param list<array<string,mixed>> $rules
75 */
76 private function appendFormIdToUserScopedRules(array &$rules, int $formId, WP_User $user): bool
77 {
78 $changed = false;
79 $now = time();
80
81 foreach ($rules as $index => $rule) {
82 if (!is_array($rule) || !$this->ruleGrantsAddEditForUser($rule, $user)) {
83 continue;
84 }
85
86 if ($this->appendFormIdToRule($rules, $index, $formId, $now)) {
87 $changed = true;
88 }
89 }
90
91 return $changed;
92 }
93
94 /**
95 * @param list<array<string,mixed>> $rules
96 */
97 private function appendFormIdToRule(array &$rules, int $index, int $formId, int $updatedAt): bool
98 {
99 $formIds = $rules[$index]['form_ids'] ?? null;
100 if (!is_array($formIds) || $formIds === []) {
101 return false;
102 }
103
104 $normalizedIds = array_values(array_unique(array_map('intval', $formIds)));
105 if (in_array($formId, $normalizedIds, true)) {
106 return false;
107 }
108
109 $normalizedIds[] = $formId;
110 $rules[$index]['form_ids'] = $normalizedIds;
111 $rules[$index]['updated_at'] = $updatedAt;
112
113 return true;
114 }
115
116 /**
117 * @param list<array<string,mixed>> $rules
118 */
119 private function persistUpdatedRules(array $rules): void
120 {
121 $previousUserIds = AccessRulesRoleCapabilitySynchronizer::extractUserIdsFromUserRules($rules);
122 $this->accessRulesRepository->saveRules($rules);
123 AccessRulesRoleCapabilitySynchronizer::syncFromRules($rules, $previousUserIds);
124 $this->permissionResolver->invalidateCache();
125 }
126
127 /**
128 * @param array<string,mixed> $rule
129 */
130 private function ruleGrantsAddEditForUser(array $rule, WP_User $user): bool
131 {
132 $permissions = isset($rule['permissions']) && is_array($rule['permissions'])
133 ? PermissionCatalog::sanitize($rule['permissions'])
134 : [];
135
136 if (!in_array('add_edit_forms', $permissions, true)) {
137 return false;
138 }
139
140 $ruleType = (string) ($rule['type'] ?? '');
141 if ($ruleType === 'user') {
142 return AccessRuleMatcher::matchesUser($rule, $user);
143 }
144 if ($ruleType === 'role') {
145 return AccessRuleMatcher::matchesRole($rule, $user);
146 }
147
148 return false;
149 }
150 }
151