PluginProbe
Search Atlas SEO – OTTO AI SEO Automation for WordPress / 2.6.13
Search Atlas SEO – OTTO AI SEO Automation for WordPress v2.6.13
2.6.26 2.6.25 2.6.24 2.6.23 2.6.22 2.6.21 2.6.20 2.6.19 2.6.18 2.6.17 2.6.16 2.6.15 2.6.14 2.6.13 2.6.12 2.6.11 2.6.10 2.6.9 2.6.8 2.6.7 2.6.6 2.6.5 2.6.4 2.6.3 2.5.23 All 138 releases
metasync / includes / class-metasync-access-control-ui.php

class-metasync-access-control-ui.php in Search Atlas SEO – OTTO AI SEO Automation for WordPress 2.6.13, at includes/class-metasync-access-control-ui.php

427 lines 16.0 KB
No matching file
Up and down to move Enter to open Esc to close
Raw Download Zip
1 <?php
2 // If this file is called directly, abort.
3 if (!defined('ABSPATH')) {
4 exit;
5 }
6
7 /**
8 * Access Control UI Renderer
9 *
10 * Handles rendering of access control UI components in the whitelabel settings.
11 * Provides a clean, user-friendly interface for managing feature access.
12 *
13 * @package Metasync
14 * @subpackage Metasync/includes
15 */
16
17 class Metasync_Access_Control_UI {
18
19 /**
20 * Render access control row for a single feature
21 *
22 * @param string $feature_key Feature identifier
23 * @param string $feature_label Feature display name
24 * @return void
25 */
26 public static function render_feature_row($feature_key, $feature_label) {
27 $config = Metasync_Access_Control::get_feature_config($feature_key);
28 $row_id = 'access-control-' . $feature_key;
29 ?>
30 <tr class="metasync-access-control-row">
31 <th scope="row">
32 <label for="<?php echo esc_attr($row_id); ?>">
33 <?php echo esc_html($feature_label); ?>
34 </label>
35 </th>
36 <td>
37 <div class="metasync-access-control-wrapper">
38 <!-- Enable/Disable Access Control -->
39 <div class="access-control-toggle">
40 <label class="metasync-switch">
41 <input type="checkbox"
42 name="metasync_options[whitelabel][access_control][<?php echo esc_attr($feature_key); ?>][enabled]"
43 value="1"
44 id="<?php echo esc_attr($row_id); ?>"
45 <?php checked($config['enabled'], true); ?>
46 class="metasync-access-toggle-input"
47 data-feature-key="<?php echo esc_attr($feature_key); ?>">
48 <span class="metasync-slider"></span>
49 </label>
50 <span class="toggle-label">
51 <?php echo $config['enabled'] ? 'Restricted' : 'Available to All'; ?>
52 </span>
53 </div>
54
55 <!-- Access Control Options (shown when enabled) -->
56 <div class="access-control-options"
57 id="access-options-<?php echo esc_attr($feature_key); ?>"
58 style="display: <?php echo $config['enabled'] ? 'block' : 'none'; ?>;">
59
60 <!-- Access Type Selection -->
61 <div class="access-type-selector">
62 <label class="access-label">Restrict Access To:</label>
63 <div class="access-radio-group">
64 <label class="radio-option">
65 <input type="radio"
66 name="metasync_options[whitelabel][access_control][<?php echo esc_attr($feature_key); ?>][type]"
67 value="none"
68 <?php checked($config['type'], 'none'); ?>
69 class="metasync-access-type-input"
70 data-feature-key="<?php echo esc_attr($feature_key); ?>">
71 <span>Hide from Everyone</span>
72 </label>
73
74 <label class="radio-option">
75 <input type="radio"
76 name="metasync_options[whitelabel][access_control][<?php echo esc_attr($feature_key); ?>][type]"
77 value="role"
78 <?php checked($config['type'], 'role'); ?>
79 class="metasync-access-type-input"
80 data-feature-key="<?php echo esc_attr($feature_key); ?>">
81 <span>Specific User Roles</span>
82 </label>
83
84 <label class="radio-option">
85 <input type="radio"
86 name="metasync_options[whitelabel][access_control][<?php echo esc_attr($feature_key); ?>][type]"
87 value="user"
88 <?php checked($config['type'], 'user'); ?>
89 class="metasync-access-type-input"
90 data-feature-key="<?php echo esc_attr($feature_key); ?>">
91 <span>Specific Users</span>
92 </label>
93 </div>
94 </div>
95
96 <!-- Role Selection (shown when type is 'role') -->
97 <div class="role-selection-container"
98 id="role-selection-<?php echo esc_attr($feature_key); ?>"
99 style="display: <?php echo $config['type'] === 'role' ? 'block' : 'none'; ?>;">
100 <?php self::render_role_selector($feature_key, $config['allowed_roles']); ?>
101 </div>
102
103 <!-- User Selection (shown when type is 'user') -->
104 <div class="user-selection-container"
105 id="user-selection-<?php echo esc_attr($feature_key); ?>"
106 style="display: <?php echo $config['type'] === 'user' ? 'block' : 'none'; ?>;">
107 <?php self::render_user_selector($feature_key, $config['allowed_users']); ?>
108 </div>
109 </div>
110 </div>
111 </td>
112 </tr>
113 <?php
114 }
115
116 /**
117 * Render role selector checkboxes
118 *
119 * @param string $feature_key Feature identifier
120 * @param array $selected_roles Currently selected roles
121 * @return void
122 */
123 private static function render_role_selector($feature_key, $selected_roles = array()) {
124 $roles = Metasync_Access_Control::get_wordpress_roles();
125 ?>
126 <div class="role-checkboxes">
127 <label class="access-label">Select User Roles:</label>
128 <p class="description" style="margin-top: 0; margin-bottom: 10px;">
129 Only users with the selected roles will have access to this feature. All other users will not see it.
130 </p>
131 <div class="checkbox-grid">
132 <?php foreach ($roles as $role_slug => $role_name): ?>
133 <label class="checkbox-option">
134 <input type="checkbox"
135 name="metasync_options[whitelabel][access_control][<?php echo esc_attr($feature_key); ?>][allowed_roles][]"
136 value="<?php echo esc_attr($role_slug); ?>"
137 <?php checked(in_array($role_slug, $selected_roles)); ?>>
138 <span><?php echo esc_html($role_name); ?></span>
139 </label>
140 <?php endforeach; ?>
141 </div>
142 </div>
143 <?php
144 }
145
146 /**
147 * Render user selector dropdown with multi-select
148 *
149 * @param string $feature_key Feature identifier
150 * @param array $selected_users Currently selected user IDs
151 * @return void
152 */
153 private static function render_user_selector($feature_key, $selected_users = array()) {
154 $users = Metasync_Access_Control::get_users();
155 ?>
156 <div class="user-select-container">
157 <label class="access-label">Select Users:</label>
158 <p class="description" style="margin-top: 0; margin-bottom: 10px;">
159 Only the selected users will have access to this feature. All other users (even administrators) will not see it.
160 </p>
161 <select name="metasync_options[whitelabel][access_control][<?php echo esc_attr($feature_key); ?>][allowed_users][]"
162 class="metasync-user-select"
163 multiple="multiple"
164 size="8">
165 <?php foreach ($users as $user): ?>
166 <option value="<?php echo esc_attr($user->ID); ?>"
167 <?php selected(in_array($user->ID, $selected_users)); ?>>
168 <?php echo esc_html($user->display_name); ?> (<?php echo esc_html($user->user_email); ?>)
169 </option>
170 <?php endforeach; ?>
171 </select>
172 <p class="description" style="margin-top: 8px; font-style: italic;">
173 Tip: Hold Ctrl/Cmd to select multiple users
174 </p>
175 </div>
176 <?php
177 }
178
179 /**
180 * Render complete access control table for all features
181 *
182 * @return void
183 */
184 public static function render_access_control_table() {
185 $features = Metasync_Access_Control::get_features();
186 ?>
187 <div class="metasync-access-control-section">
188 <h2>Advanced Access Control</h2>
189 <p style="color: var(--dashboard-text-secondary); margin-bottom: 20px;">
190 Control who can access each feature. You can restrict access by user role or specific users.
191 </p>
192
193 <table class="form-table metasync-access-control-table" role="presentation">
194 <tbody>
195 <?php foreach ($features as $feature_key => $feature_label): ?>
196 <?php self::render_feature_row($feature_key, $feature_label); ?>
197 <?php endforeach; ?>
198 </tbody>
199 </table>
200 </div>
201
202 <?php self::render_inline_styles(); ?>
203 <?php self::render_inline_scripts(); ?>
204 <?php
205 }
206
207 /**
208 * Render inline CSS styles for access control UI
209 *
210 * @return void
211 */
212 private static function render_inline_styles() {
213 ?>
214 <style>
215 .metasync-access-control-section {
216 background: var(--dashboard-card-bg);
217 padding: 25px;
218 border-radius: 8px;
219 margin-top: 25px;
220 box-shadow: 0 2px 4px rgba(0, 0, 0, 0.1);
221 }
222
223 .metasync-access-control-section h2 {
224 color: var(--dashboard-text-primary);
225 margin-top: 0;
226 }
227
228 .metasync-access-control-wrapper {
229 display: flex;
230 flex-direction: column;
231 gap: 15px;
232 }
233
234 .access-control-toggle {
235 display: flex;
236 align-items: center;
237 gap: 12px;
238 }
239
240 .metasync-switch {
241 position: relative;
242 display: inline-block;
243 width: 50px;
244 height: 24px;
245 }
246
247 .metasync-switch input {
248 opacity: 0;
249 width: 0;
250 height: 0;
251 }
252
253 .metasync-slider {
254 position: absolute;
255 cursor: pointer;
256 top: 0;
257 left: 0;
258 right: 0;
259 bottom: 0;
260 background-color: #ccc;
261 transition: .3s;
262 border-radius: 24px;
263 }
264
265 .metasync-slider:before {
266 position: absolute;
267 content: "";
268 height: 18px;
269 width: 18px;
270 left: 3px;
271 bottom: 3px;
272 background-color: white;
273 transition: .3s;
274 border-radius: 50%;
275 }
276
277 .metasync-switch input:checked + .metasync-slider {
278 background-color: #2196F3;
279 }
280
281 .metasync-switch input:checked + .metasync-slider:before {
282 transform: translateX(26px);
283 }
284
285 .toggle-label {
286 font-weight: 500;
287 color: var(--dashboard-text-primary);
288 }
289
290 .access-control-options {
291 padding: 15px;
292 background: var(--dashboard-bg);
293 border-radius: 6px;
294 border: 1px solid var(--dashboard-border);
295 }
296
297 .access-type-selector {
298 margin-bottom: 15px;
299 }
300
301 .access-label {
302 display: block;
303 font-weight: 600;
304 margin-bottom: 10px;
305 color: var(--dashboard-text-primary);
306 }
307
308 .access-radio-group {
309 display: flex;
310 flex-direction: column;
311 gap: 10px;
312 }
313
314 .radio-option,
315 .checkbox-option {
316 display: flex;
317 align-items: center;
318 gap: 8px;
319 padding: 8px 12px;
320 background: var(--dashboard-card-bg);
321 border-radius: 4px;
322 cursor: pointer;
323 transition: background 0.2s;
324 }
325
326 .radio-option:hover,
327 .checkbox-option:hover {
328 background: var(--dashboard-hover-bg, rgba(0, 0, 0, 0.05));
329 }
330
331 .radio-option input,
332 .checkbox-option input {
333 cursor: pointer;
334 }
335
336 .radio-option span,
337 .checkbox-option span {
338 color: var(--dashboard-text-primary);
339 }
340
341 .role-selection-container,
342 .user-selection-container {
343 padding-top: 15px;
344 border-top: 1px solid var(--dashboard-border);
345 margin-top: 15px;
346 }
347
348 .checkbox-grid {
349 display: grid;
350 grid-template-columns: repeat(auto-fill, minmax(200px, 1fr));
351 gap: 10px;
352 }
353
354 .user-select-container {
355 display: flex;
356 flex-direction: column;
357 gap: 8px;
358 }
359
360 .metasync-user-select {
361 width: 100%;
362 max-width: 500px;
363 padding: 8px;
364 border: 1px solid var(--dashboard-border);
365 border-radius: 4px;
366 background-color: var(--dashboard-bg) !important;
367 color: var(--dashboard-text-primary) !important;
368 }
369
370 /* Dark mode specific fixes */
371 [data-theme="dark"] .metasync-user-select {
372 background-color: #1e1e1e !important;
373 color: #e0e0e0 !important;
374 border-color: #444 !important;
375 }
376
377 .metasync-user-select option {
378 padding: 8px;
379 background-color: var(--dashboard-bg) !important;
380 color: var(--dashboard-text-primary) !important;
381 }
382
383 [data-theme="dark"] .metasync-user-select option {
384 background-color: #1e1e1e !important;
385 color: #e0e0e0 !important;
386 }
387
388 .metasync-user-select option:checked {
389 background-color: #2196F3 !important;
390 color: #ffffff !important;
391 }
392
393 [data-theme="dark"] .metasync-user-select option:checked {
394 background-color: #0d7dd8 !important;
395 color: #ffffff !important;
396 }
397
398 .description {
399 font-size: 12px;
400 color: var(--dashboard-text-secondary);
401 margin: 0;
402 }
403
404 .metasync-access-control-row {
405 border-bottom: 1px solid var(--dashboard-border);
406 }
407
408 .metasync-access-control-row:last-child {
409 border-bottom: none;
410 }
411 </style>
412 <?php
413 }
414
415 /**
416 * Render inline JavaScript for access control interactions.
417 *
418 * NOTE: Scripts have been extracted to includes/js/metasync-access-control.js
419 * and are enqueued via wp_enqueue_script() in class-metasync-admin.php (Phase 5, #887).
420 *
421 * @return void
422 */
423 private static function render_inline_scripts() {
424 // Intentionally empty — JS now loaded via wp_enqueue_script().
425 }
426 }
427