PluginProbe
wpDataTables – WordPress Data Table, Dynamic Tables & Table Charts Plugin / 6.5.1.7
wpDataTables – WordPress Data Table, Dynamic Tables & Table Charts Plugin v6.5.1.7
6.5.1.7 6.5.1.6 6.5.1.5 6.5.1.4 6.5.1.3 6.5.1.2 6.5.1.1 6.5.0.9 6.5.0.8 6.5.0.7 6.5.0.6 trunk 3.4.2.40 3.4.2.41 3.4.2.42 3.4.2.43 3.4.2.44 3.4.2.45 3.4.2.46 3.4.2.47 3.4.2.48 3.4.2.49 3.4.2.50 6.3.2 6.3.3.1 All 47 releases
wpdatatables / source / class.permissions.admin.php

class.permissions.admin.php in wpDataTables – WordPress Data Table, Dynamic Tables & Table Charts Plugin 6.5.1.7, at source/class.permissions.admin.php

450 lines 18.2 KB
No matching file
Up and down to move Enter to open Esc to close
Raw Download Zip
1 <?php
2 if (!defined('ABSPATH')) die('Access denied.');
3
4
5 class WDTPermissionsAdmin
6 {
7 // Define capabilities
8 const CAPABILITY_VIEW_TABLES = 'wpdt_view_tables';
9 const CAPABILITY_VIEW_CHARTS = 'wpdt_view_charts';
10
11 public static function enqueueAssets($hook)
12 {
13 if (isset($_GET['page']) && $_GET['page'] === 'wpdatatables_permissions') {
14 // Enqueue permissions-specific scripts
15 wp_enqueue_script('wdt-permissions-js', plugins_url('../assets/js/wpdatatables/admin/permissions/permissions-admin.js', __FILE__), array('jquery', 'wdt-common'), WDT_CURRENT_VERSION, true);
16
17 wp_localize_script('wdt-permissions-js', 'wdtPermissions', array(
18 'ajax_url' => admin_url('admin-ajax.php'),
19 'nonce' => wp_create_nonce('wdt_permissions_nonce'),
20 ));
21 }
22 }
23
24 /**
25 * Register wpDataTables capabilities
26 * Makes them available in role management interfaces
27 */
28 public static function registerCapabilities()
29 {
30 // Add the capabilities directly to administrator role
31 // This makes them discoverable by role management plugins
32 $adminRole = get_role('administrator');
33 if ($adminRole) {
34 $adminRole->add_cap(self::CAPABILITY_VIEW_TABLES);
35 $adminRole->add_cap(self::CAPABILITY_VIEW_CHARTS);
36 }
37
38 // Add filter to include our custom capabilities in role editors
39 add_filter('members_get_capabilities', function ($capabilities) {
40 $capabilities[] = self::CAPABILITY_VIEW_TABLES;
41 $capabilities[] = self::CAPABILITY_VIEW_CHARTS;
42 return array_unique($capabilities);
43 });
44
45 // For other role editors, filter the available capabilities
46 add_filter('editable_roles', function ($roles) {
47 return $roles;
48 });
49 }
50
51 public static function registerMenu()
52 {
53 // Only admins can access
54 if (!current_user_can('manage_options')) return;
55 add_submenu_page(
56 'wpdatatables',
57 __('Permissions', 'wpdatatables'),
58 __('Permissions', 'wpdatatables'),
59 'manage_options',
60 'wpdatatables_permissions',
61 [self::class, 'renderPage']
62 );
63 }
64
65 public static function renderPage()
66 {
67 $activeTab = isset($_GET['tab']) && $_GET['tab'] === 'charts' ? 'charts' : 'tables';
68 require_once(WDT_ROOT_PATH . '/source/class.wdtpermissionslisttable.php');
69 $permissionsTable = new WDTPermissionsListTable(['type' => $activeTab]);
70 $permissionsTable->prepare_items();
71 include(WDT_ROOT_PATH . '/templates/admin/permissions/permissions.inc.php');
72 }
73
74 public static function loadPermissionsAjax()
75 {
76 check_ajax_referer('wdt_permissions_nonce', 'nonce');
77
78 if (!current_user_can('manage_options')) {
79 wp_send_json_error(['message' => 'Unauthorized']);
80 }
81
82 $tab = isset($_POST['tab']) ? sanitize_text_field($_POST['tab']) : 'tables';
83
84 // Load assigned permissions for tables or charts
85 if ($tab === 'tables') {
86 $html = self::getTablePermissionsListHtml();
87 } else {
88 $html = self::getChartPermissionsListHtml();
89 }
90
91 wp_send_json_success(['html' => $html]);
92 }
93
94 private static function getTablePermissionsListHtml()
95 {
96 // Get optional search term
97 $search = isset($_POST['s']) ? sanitize_text_field($_POST['s']) : '';
98
99 // Get all users with the wpdt_view_tables capability
100 $users = get_users();
101 if (!is_array($users) || empty($users)) {
102 return '<tr><td colspan="7" style="text-align: center; padding: 24px;">' .
103 esc_html__('No users found.', 'wpdatatables') .
104 '</td></tr>';
105 }
106
107 $html = '';
108 $foundAny = false;
109
110 foreach ($users as $user) {
111 // Skip administrators
112 if (in_array('administrator', (array)$user->roles, true)) {
113 continue;
114 }
115 // Apply search filter if present
116 if ($search) {
117 $match = false;
118 if (is_numeric($search) && intval($search) === intval($user->ID)) $match = true;
119 if (stripos($user->user_login, $search) !== false) $match = true;
120 if (stripos($user->user_email, $search) !== false) $match = true;
121 if (!$match) continue;
122 }
123 // Check if user has the capability by checking their actual capabilities
124 // This respects role hierarchy and capability grants/denials
125 if (!isset($user->allcaps[self::CAPABILITY_VIEW_TABLES]) || !$user->allcaps[self::CAPABILITY_VIEW_TABLES]) {
126 continue;
127 }
128
129 $foundAny = true;
130
131 // Get user roles
132 $roles = implode(', ', $user->roles);
133
134 // Get table access metadata for this user
135 $userTableAccess = get_user_meta($user->ID, 'wpdt_table_access', true);
136 $allTables = empty($userTableAccess) || isset($userTableAccess['all_tables']) && $userTableAccess['all_tables'];
137
138 // Get tables list
139 if ($allTables) {
140 $tablesDisplay = esc_html__('All', 'wpdatatables');
141 } else {
142 $tableIds = isset($userTableAccess['table_ids']) ? $userTableAccess['table_ids'] : array();
143 if (empty($tableIds)) {
144 $tablesDisplay = '';
145 } else {
146 // Get table titles
147 global $wpdb;
148 $placeholders = implode(',', array_fill(0, count($tableIds), '%d'));
149 $query = $wpdb->prepare("SELECT GROUP_CONCAT(title) as titles FROM {$wpdb->prefix}wpdatatables WHERE id IN ($placeholders)", ...$tableIds);
150 $result = $wpdb->get_var($query);
151 $tablesDisplay = $result ?: '';
152 }
153 }
154
155 $permissionsDisplay = esc_html__('View Tables', 'wpdatatables');
156
157 $html .= '<tr>';
158 $html .= '<td class="column-id">' . intval($user->ID) . '</td>';
159 $html .= '<td class="column-user"><a href="#">' . esc_html($user->user_login) . '</a></td>';
160 $html .= '<td class="column-roles">' . esc_html($roles) . '</td>';
161 $html .= '<td class="column-email">' . esc_html($user->user_email) . '</td>';
162 $html .= '<td class="column-tables">' . esc_html($tablesDisplay) . '</td>';
163 $html .= '<td class="column-permissions">' . esc_html($permissionsDisplay) . '</td>';
164 $html .= '<td class="column-actions">';
165 $html .= '<div class="wdt-function-flex">';
166 $html .= '<a href="#" class="wdt-edit-permission" data-id="' . intval($user->ID) . '" data-toggle="tooltip" title="' . esc_attr__('Edit', 'wpdatatables') . '"><i class="wpdt-icon-pen"></i></a>';
167 $html .= '<a href="#" class="wdt-delete-permission" data-id="' . intval($user->ID) . '" data-toggle="tooltip" title="' . esc_attr__('Delete', 'wpdatatables') . '"><i class="wpdt-icon-trash"></i></a>';
168 $html .= '</div>';
169 $html .= '</td>';
170 $html .= '</tr>';
171 }
172
173 if (!$foundAny) {
174 return '<tr><td colspan="7" style="text-align: center; padding: 24px;">' .
175 esc_html__('No permissions assigned yet.', 'wpdatatables') .
176 '</td></tr>';
177 }
178
179 return $html;
180 }
181
182 private static function getChartPermissionsListHtml()
183 {
184 // Get optional search term
185 $search = isset($_POST['s']) ? sanitize_text_field($_POST['s']) : '';
186
187 // Get all users with the wpdt_view_charts capability
188 $users = get_users();
189 if (!is_array($users) || empty($users)) {
190 return '<tr><td colspan="7" style="text-align: center; padding: 24px;">' .
191 esc_html__('No users found.', 'wpdatatables') .
192 '</td></tr>';
193 }
194
195 $html = '';
196 $foundAny = false;
197
198 foreach ($users as $user) {
199 // Skip administrators
200 if (in_array('administrator', (array)$user->roles, true)) {
201 continue;
202 }
203 // Apply search filter if present
204 if ($search) {
205 $match = false;
206 if (is_numeric($search) && intval($search) === intval($user->ID)) $match = true;
207 if (stripos($user->user_login, $search) !== false) $match = true;
208 if (stripos($user->user_email, $search) !== false) $match = true;
209 if (!$match) continue;
210 }
211 // Check if user has the capability by checking their actual capabilities
212 // This respects role hierarchy and capability grants/denials
213 if (!isset($user->allcaps[self::CAPABILITY_VIEW_CHARTS]) || !$user->allcaps[self::CAPABILITY_VIEW_CHARTS]) {
214 continue;
215 }
216
217 $foundAny = true;
218
219 // Get user roles
220 $roles = implode(', ', $user->roles);
221
222 // Get chart access metadata for this user
223 $userChartAccess = get_user_meta($user->ID, 'wpdt_chart_access', true);
224 $allCharts = empty($userChartAccess) || isset($userChartAccess['all_charts']) && $userChartAccess['all_charts'];
225
226 // Get charts list
227 if ($allCharts) {
228 $chartsDisplay = esc_html__('All', 'wpdatatables');
229 } else {
230 $chartIds = isset($userChartAccess['chart_ids']) ? $userChartAccess['chart_ids'] : array();
231 if (empty($chartIds)) {
232 $chartsDisplay = '';
233 } else {
234 // Get chart titles
235 global $wpdb;
236 $placeholders = implode(',', array_fill(0, count($chartIds), '%d'));
237 $query = $wpdb->prepare("SELECT GROUP_CONCAT(title) as titles FROM {$wpdb->prefix}wpdatacharts WHERE id IN ($placeholders)", ...$chartIds);
238 $result = $wpdb->get_var($query);
239 $chartsDisplay = $result ?: '';
240 }
241 }
242
243 $permissionsDisplay = esc_html__('View Charts', 'wpdatatables');
244
245 $html .= '<tr>';
246 $html .= '<td class="column-id">' . intval($user->ID) . '</td>';
247 $html .= '<td class="column-user"><a href="#">' . esc_html($user->user_login) . '</a></td>';
248 $html .= '<td class="column-roles">' . esc_html($roles) . '</td>';
249 $html .= '<td class="column-email">' . esc_html($user->user_email) . '</td>';
250 $html .= '<td class="column-tables">' . esc_html($chartsDisplay) . '</td>';
251 $html .= '<td class="column-permissions">' . esc_html($permissionsDisplay) . '</td>';
252 $html .= '<td class="column-actions">';
253 $html .= '<div class="wdt-function-flex">';
254 $html .= '<a href="#" class="wdt-edit-permission" data-id="' . intval($user->ID) . '" data-toggle="tooltip" title="' . esc_attr__('Edit', 'wpdatatables') . '"><i class="wpdt-icon-pen"></i></a>';
255 $html .= '<a href="#" class="wdt-delete-permission" data-id="' . intval($user->ID) . '" data-toggle="tooltip" title="' . esc_attr__('Delete', 'wpdatatables') . '"><i class="wpdt-icon-trash"></i></a>';
256 $html .= '</div>';
257 $html .= '</td>';
258 $html .= '</tr>';
259 }
260
261 if (!$foundAny) {
262 return '<tr><td colspan="7" style="text-align: center; padding: 24px;">' .
263 esc_html__('No permissions assigned yet.', 'wpdatatables') .
264 '</td></tr>';
265 }
266
267 return $html;
268 }
269
270 public static function savePermissionAjax()
271 {
272 check_ajax_referer('wdt_permissions_nonce', 'nonce');
273
274 if (!current_user_can('manage_options')) {
275 wp_send_json_error(['message' => 'Unauthorized']);
276 }
277
278 $tab = isset($_POST['tab']) ? sanitize_text_field($_POST['tab']) : 'tables';
279 $userId = isset($_POST['user_id']) ? intval($_POST['user_id']) : 0;
280 $enableSpecific = isset($_POST['enable_specific']) ? intval($_POST['enable_specific']) : 0;
281 $itemIds = isset($_POST['item_ids']) ? (array)$_POST['item_ids'] : array();
282
283 if (!$userId) {
284 wp_send_json_error(['message' => 'Invalid data']);
285 }
286
287 $user = get_userdata($userId);
288 if (!$user) {
289 wp_send_json_error(['message' => 'User not found']);
290 }
291
292 // Determine capability to grant
293 $capability = $tab === 'tables' ? self::CAPABILITY_VIEW_TABLES : self::CAPABILITY_VIEW_CHARTS;
294
295 // Grant capability to user
296 $user->add_cap($capability);
297
298 // Store table/chart access metadata
299 $metaKey = $tab === 'tables' ? 'wpdt_table_access' : 'wpdt_chart_access';
300 $accessData = array();
301
302 if ($enableSpecific && !empty($itemIds)) {
303 $itemIdKey = $tab === 'tables' ? 'table_ids' : 'chart_ids';
304 $accessData[$itemIdKey] = array_map('intval', $itemIds);
305 } else {
306 $allKey = $tab === 'tables' ? 'all_tables' : 'all_charts';
307 $accessData[$allKey] = true;
308 }
309
310 update_user_meta($userId, $metaKey, $accessData);
311
312 wp_send_json_success(['message' => 'Permission saved successfully']);
313 }
314
315 public static function updatePermissionAjax()
316 {
317 check_ajax_referer('wdt_permissions_nonce', 'nonce');
318
319 if (!current_user_can('manage_options')) {
320 wp_send_json_error(['message' => 'Unauthorized']);
321 }
322
323 $tab = isset($_POST['tab']) ? sanitize_text_field($_POST['tab']) : 'tables';
324 $userId = isset($_POST['user_id']) ? intval($_POST['user_id']) : 0;
325 $enableSpecific = isset($_POST['enable_specific']) ? intval($_POST['enable_specific']) : 0;
326 $itemIds = isset($_POST['item_ids']) ? (array)$_POST['item_ids'] : array();
327
328 if (!$userId) {
329 wp_send_json_error(['message' => 'Invalid data']);
330 }
331
332 $user = get_userdata($userId);
333 if (!$user) {
334 wp_send_json_error(['message' => 'User not found']);
335 }
336
337 // Determine capability
338 $capability = $tab === 'tables' ? self::CAPABILITY_VIEW_TABLES : self::CAPABILITY_VIEW_CHARTS;
339
340 // Ensure user has capability
341 $user->add_cap($capability);
342
343 // Update table/chart access metadata
344 $metaKey = $tab === 'tables' ? 'wpdt_table_access' : 'wpdt_chart_access';
345 $accessData = array();
346
347 if ($enableSpecific && !empty($itemIds)) {
348 $itemIdKey = $tab === 'tables' ? 'table_ids' : 'chart_ids';
349 $accessData[$itemIdKey] = array_map('intval', $itemIds);
350 } else {
351 $allKey = $tab === 'tables' ? 'all_tables' : 'all_charts';
352 $accessData[$allKey] = true;
353 }
354
355 update_user_meta($userId, $metaKey, $accessData);
356
357 wp_send_json_success(['message' => 'Permission updated successfully']);
358 }
359
360 public static function deletePermissionAjax()
361 {
362 check_ajax_referer('wdt_permissions_nonce', 'nonce');
363
364 if (!current_user_can('manage_options')) {
365 wp_send_json_error(['message' => 'Unauthorized']);
366 }
367
368 $tab = isset($_POST['tab']) ? sanitize_text_field($_POST['tab']) : 'tables';
369 $userId = isset($_POST['user_id']) ? intval($_POST['user_id']) : 0;
370
371 if (!$userId) {
372 wp_send_json_error(['message' => 'Invalid data']);
373 }
374
375 $user = get_userdata($userId);
376 if (!$user) {
377 wp_send_json_error(['message' => 'User not found']);
378 }
379
380 // Determine capability to remove
381 $capability = $tab === 'tables' ? self::CAPABILITY_VIEW_TABLES : self::CAPABILITY_VIEW_CHARTS;
382
383 // Remove capability from user
384 $user->remove_cap($capability);
385
386 // Delete associated metadata
387 $metaKey = $tab === 'tables' ? 'wpdt_table_access' : 'wpdt_chart_access';
388 delete_user_meta($userId, $metaKey);
389
390 wp_send_json_success(['message' => 'Permission deleted successfully']);
391 }
392
393 public static function getPermissionAjax()
394 {
395 check_ajax_referer('wdt_permissions_nonce', 'nonce');
396
397 if (!current_user_can('manage_options')) {
398 wp_send_json_error(['message' => 'Unauthorized']);
399 }
400
401 $tab = isset($_POST['tab']) ? sanitize_text_field($_POST['tab']) : 'tables';
402 $userId = isset($_POST['user_id']) ? intval($_POST['user_id']) : 0;
403
404 if (!$userId) {
405 wp_send_json_error(['message' => 'Invalid data']);
406 }
407
408 $user = get_userdata($userId);
409 if (!$user) {
410 wp_send_json_error(['message' => 'User not found']);
411 }
412
413 // Get capability
414 $capability = $tab === 'tables' ? self::CAPABILITY_VIEW_TABLES : self::CAPABILITY_VIEW_CHARTS;
415 $hasCapability = $user->has_cap($capability);
416
417 // Get table/chart access metadata
418 $metaKey = $tab === 'tables' ? 'wpdt_table_access' : 'wpdt_chart_access';
419 $accessData = get_user_meta($userId, $metaKey, true);
420
421 $result = array(
422 'user_id' => $userId,
423 'has_capability' => $hasCapability,
424 );
425
426 // Determine access type
427 if (empty($accessData)) {
428 $result['all_items'] = true;
429 $result['item_ids'] = array();
430 } else {
431 $allKey = $tab === 'tables' ? 'all_tables' : 'all_charts';
432 $itemIdKey = $tab === 'tables' ? 'table_ids' : 'chart_ids';
433
434 $result['all_items'] = isset($accessData[$allKey]) && $accessData[$allKey];
435 $result['item_ids'] = isset($accessData[$itemIdKey]) ? $accessData[$itemIdKey] : array();
436 }
437
438 wp_send_json_success($result);
439 }
440 }
441
442 add_action('admin_menu', ['WDTPermissionsAdmin', 'registerMenu']);
443 add_action('admin_enqueue_scripts', ['WDTPermissionsAdmin', 'enqueueAssets']);
444 add_action('init', ['WDTPermissionsAdmin', 'registerCapabilities'], 1);
445 add_action('wp_ajax_wpdatatables_load_permissions', ['WDTPermissionsAdmin', 'loadPermissionsAjax']);
446 add_action('wp_ajax_wpdatatables_save_permission', ['WDTPermissionsAdmin', 'savePermissionAjax']);
447 add_action('wp_ajax_wpdatatables_update_permission', ['WDTPermissionsAdmin', 'updatePermissionAjax']);
448 add_action('wp_ajax_wpdatatables_delete_permission', ['WDTPermissionsAdmin', 'deletePermissionAjax']);
449 add_action('wp_ajax_wpdatatables_get_permission', ['WDTPermissionsAdmin', 'getPermissionAjax']);
450