PluginProbe
TablePress – Tables in WordPress made easy / 2.1.7
TablePress – Tables in WordPress made easy v2.1.7
3.3.4 3.3.3 3.3.2 3.3.1 trunk 1.12 1.14 1.9.2 2.0.4 2.1.7 2.1.8 2.2 2.2.1 2.2.2 2.2.3 2.2.4 2.2.5 2.3 2.3.1 2.3.2 2.4 2.4.1 2.4.2 2.4.3 2.4.4 All 44 releases
tablepress / classes / class-tablepress.php

class-tablepress.php in TablePress – Tables in WordPress made easy 2.1.7, at classes/class-tablepress.php

794 lines 29.8 KB
No matching file
Up and down to move Enter to open Esc to close
Raw Download Zip
1 <?php
2 /**
3 * TablePress Class
4 *
5 * @package TablePress
6 * @author Tobias Bäthge
7 * @since 1.0.0
8 */
9
10 // Prohibit direct script loading.
11 defined( 'ABSPATH' ) || die( 'No direct script access allowed!' );
12
13 /**
14 * TablePress class
15 *
16 * @package TablePress
17 * @author Tobias Bäthge
18 * @since 1.0.0
19 */
20 abstract class TablePress {
21
22 /**
23 * TablePress version.
24 *
25 * Increases whenever a new plugin version is released.
26 *
27 * @since 1.0.0
28 * @const string
29 */
30 const version = '2.1.7'; // phpcs:ignore Generic.NamingConventions.UpperCaseConstantName.ClassConstantNotUpperCase
31
32 /**
33 * TablePress internal plugin version ("options scheme" version).
34 *
35 * Increases whenever the scheme for the plugin options changes, or on a plugin update.
36 *
37 * @since 1.0.0
38 * @const int
39 */
40 const db_version = 63; // phpcs:ignore Generic.NamingConventions.UpperCaseConstantName.ClassConstantNotUpperCase
41
42 /**
43 * TablePress "table scheme" (data format structure) version.
44 *
45 * Increases whenever the scheme for a $table changes,
46 * used to be able to update plugin options and table scheme independently.
47 *
48 * @since 1.0.0
49 * @const int
50 */
51 const table_scheme_version = 3; // phpcs:ignore Generic.NamingConventions.UpperCaseConstantName.ClassConstantNotUpperCase
52
53 /**
54 * Instance of the Options Model.
55 *
56 * @since 1.3.0
57 * @var TablePress_Options_Model
58 */
59 public static $model_options;
60
61 /**
62 * Instance of the Table Model.
63 *
64 * @since 1.3.0
65 * @var TablePress_Table_Model
66 */
67 public static $model_table;
68
69 /**
70 * Instance of the controller.
71 *
72 * @since 1.0.0
73 * @var TablePress_*_Controller
74 */
75 public static $controller;
76
77 /**
78 * Name of the Shortcode to show a TablePress table.
79 *
80 * Should only be modified through the filter hook 'tablepress_table_shortcode'.
81 *
82 * @since 1.0.0
83 * @var string
84 */
85 public static $shortcode = 'table';
86
87 /**
88 * Name of the Shortcode to show extra information of a TablePress table.
89 *
90 * Should only be modified through the filter hook 'tablepress_table_info_shortcode'.
91 *
92 * @since 1.0.0
93 * @var string
94 */
95 public static $shortcode_info = 'table-info';
96
97 /**
98 * List of TablePress premium modules.
99 *
100 * @since 2.1.0
101 * @var array
102 */
103 public static $modules = array();
104
105 /**
106 * Start-up TablePress (run on WordPress "init") and load the controller for the current state.
107 *
108 * @since 1.0.0
109 */
110 public static function run() {
111 /**
112 * Fires before TablePress is loaded.
113 *
114 * The `tablepress_loaded` action hook might be a better choice in most situations, as TablePress options will then be available.
115 *
116 * @since 1.0.0
117 */
118 do_action( 'tablepress_run' );
119
120 // Check if minimum requirements are fulfilled, currently WordPress 5.8.
121 include ABSPATH . WPINC . '/version.php'; // Include an unmodified $wp_version.
122 if ( version_compare( str_replace( '-src', '', $wp_version ), '5.8', '<' ) ) {
123 // Show error notice to admins, if WP is not installed in the minimum required version, in which case TablePress will not work.
124 if ( current_user_can( 'update_plugins' ) ) {
125 add_action( 'admin_notices', array( 'TablePress', 'show_minimum_requirements_error_notice' ) );
126 }
127 // And exit TablePress.
128 return;
129 }
130
131 /**
132 * Filters the string that is used as the [table] Shortcode.
133 *
134 * @since 1.0.0
135 *
136 * @param string $shortcode The [table] Shortcode string.
137 */
138 self::$shortcode = apply_filters( 'tablepress_table_shortcode', self::$shortcode );
139 /**
140 * Filters the string that is used as the [table-info] Shortcode.
141 *
142 * @since 1.0.0
143 *
144 * @param string $shortcode_info The [table-info] Shortcode string.
145 */
146 self::$shortcode_info = apply_filters( 'tablepress_table_info_shortcode', self::$shortcode_info );
147
148 // Load modals for table and options, to be accessible from everywhere via `TablePress::$model_options` and `TablePress::$model_table`.
149 self::$model_options = self::load_model( 'options' );
150 self::$model_table = self::load_model( 'table' );
151
152 // Exit early, i.e. before a controller is loaded, if TablePress functionality is likely not needed.
153 $exit_early = false;
154 if ( ( isset( $_SERVER['SCRIPT_FILENAME'] ) && 'wp-login.php' === basename( $_SERVER['SCRIPT_FILENAME'] ) ) // Detect the WordPress Login screen.
155 || ( defined( 'XMLRPC_REQUEST' ) && XMLRPC_REQUEST )
156 || wp_doing_cron() ) {
157 $exit_early = true;
158 }
159 /**
160 * Filters whether TablePress should exit early, e.g. during wp-login.php, XML-RPC, and WP-Cron requests.
161 *
162 * @since 2.0.0
163 *
164 * @param bool $exit_early Whether TablePress should exit early.
165 */
166 if ( apply_filters( 'tablepress_exit_early', $exit_early ) ) {
167 return;
168 }
169
170 if ( is_admin() ) {
171 $controller = 'admin';
172 if ( wp_doing_ajax() ) {
173 $controller .= '_ajax';
174 }
175 self::load_controller( $controller );
176 }
177 // Load the frontend controller in all scenarios, so that Shortcode render functions are always available.
178 self::$controller = self::load_controller( 'frontend' );
179
180 /**
181 * Fires after TablePress is loaded.
182 *
183 * The `tablepress_run` action hook can be used if code has to run before TablePress is loaded.
184 *
185 * @since 2.0.0
186 */
187 do_action( 'tablepress_loaded' );
188 }
189
190 /**
191 * Load a file with require_once(), after running it through a filter.
192 *
193 * @since 1.0.0
194 *
195 * @param string $file Name of the PHP file.
196 * @param string $folder Name of the folder with the file.
197 */
198 public static function load_file( $file, $folder ) {
199 $full_path = TABLEPRESS_ABSPATH . $folder . '/' . $file;
200 /**
201 * Filters the full path of a file that shall be loaded.
202 *
203 * @since 1.0.0
204 *
205 * @param string $full_path Full path of the file that shall be loaded.
206 * @param string $file File name of the file that shall be loaded.
207 * @param string $folder Folder name of the file that shall be loaded.
208 */
209 $full_path = apply_filters( 'tablepress_load_file_full_path', $full_path, $file, $folder );
210 if ( $full_path ) {
211 require_once $full_path;
212 }
213 }
214
215 /**
216 * Create a new instance of the $class_name, which is stored in $file in the $folder subfolder
217 * of the plugin's directory.
218 *
219 * @since 1.0.0
220 *
221 * @param string $class_name Name of the class.
222 * @param string $file Name of the PHP file with the class.
223 * @param string $folder Name of the folder with $class_name's $file.
224 * @param mixed $params Optional. Parameters that are passed to the constructor of $class_name.
225 * @return object Initialized instance of the class.
226 */
227 public static function load_class( $class_name, $file, $folder, $params = null ) {
228 /**
229 * Filters name of the class that shall be loaded.
230 *
231 * @since 1.0.0
232 *
233 * @param string $class_name Name of the class that shall be loaded.
234 */
235 $class_name = apply_filters( 'tablepress_load_class_name', $class_name );
236 if ( ! class_exists( $class_name, false ) ) {
237 self::load_file( $file, $folder );
238 }
239 $the_class = new $class_name( $params );
240 return $the_class;
241 }
242
243 /**
244 * Create a new instance of the $model, which is stored in the "models" subfolder.
245 *
246 * @since 1.0.0
247 *
248 * @param string $model Name of the model.
249 * @return object Instance of the initialized model.
250 */
251 public static function load_model( $model ) {
252 // Model Base Class.
253 self::load_file( 'class-model.php', 'classes' );
254 // Make first letter uppercase for a better looking naming pattern.
255 $ucmodel = ucfirst( $model );
256 $the_model = self::load_class( "TablePress_{$ucmodel}_Model", "model-{$model}.php", 'models' );
257 return $the_model;
258 }
259
260 /**
261 * Create a new instance of the $view, which is stored in the "views" subfolder, and set it up with $data.
262 *
263 * @since 1.0.0
264 *
265 * @param string $view Name of the view to load.
266 * @param array $data Optional. Parameters/PHP variables that shall be available to the view.
267 * @return object Instance of the initialized view, already set up, just needs to be rendered.
268 */
269 public static function load_view( $view, array $data = array() ) {
270 // View Base Class.
271 self::load_file( 'class-view.php', 'classes' );
272 // Make first letter uppercase for a better looking naming pattern.
273 $ucview = ucfirst( $view );
274 $the_view = self::load_class( "TablePress_{$ucview}_View", "view-{$view}.php", 'views' );
275 $the_view->setup( $view, $data );
276 return $the_view;
277 }
278
279 /**
280 * Create a new instance of the $controller, which is stored in the "controllers" subfolder.
281 *
282 * @since 1.0.0
283 *
284 * @param string $controller Name of the controller.
285 * @return object Instance of the initialized controller.
286 */
287 public static function load_controller( $controller ) {
288 // Controller Base Class.
289 self::load_file( 'class-controller.php', 'classes' );
290 // Make first letter uppercase for a better looking naming pattern.
291 $uccontroller = ucfirst( $controller );
292 $the_controller = self::load_class( "TablePress_{$uccontroller}_Controller", "controller-{$controller}.php", 'controllers' );
293 return $the_controller;
294 }
295
296 /**
297 * Generate the complete nonce string, from the nonce base, the action and an item, e.g. tablepress_delete_table_3.
298 *
299 * @since 1.0.0
300 *
301 * @param string $action Action for which the nonce is needed.
302 * @param string|bool $item Optional. Item for which the action will be performed, like "table".
303 * @return string The resulting nonce string.
304 */
305 public static function nonce( $action, $item = false ) {
306 $nonce = "tablepress_{$action}";
307 if ( $item ) {
308 $nonce .= "_{$item}";
309 }
310 return $nonce;
311 }
312
313 /**
314 * Check whether a nonce string is valid.
315 *
316 * @since 1.0.0
317 *
318 * @param string $action Action for which the nonce should be checked.
319 * @param string|bool $item Optional. Item for which the action should be performed, like "table".
320 * @param string $query_arg Optional. Name of the nonce query string argument in $_POST.
321 * @param bool $ajax Whether the nonce comes from an AJAX request.
322 */
323 public static function check_nonce( $action, $item = false, $query_arg = '_wpnonce', $ajax = false ) {
324 $nonce_action = self::nonce( $action, $item );
325 if ( $ajax ) {
326 check_ajax_referer( $nonce_action, $query_arg );
327 } else {
328 check_admin_referer( $nonce_action, $query_arg );
329 }
330 }
331
332 /**
333 * Calculate the column index (number) of a column header string (example: A is 1, AA is 27, ...).
334 *
335 * For the opposite, @see number_to_letter().
336 *
337 * @since 1.0.0
338 *
339 * @param string $column Column string.
340 * @return int Column number, 1-based.
341 */
342 public static function letter_to_number( $column ) {
343 $column = strtoupper( $column );
344 $count = strlen( $column );
345 $number = 0;
346 for ( $i = 0; $i < $count; $i++ ) {
347 $number += ( ord( $column[ $count - 1 - $i ] ) - 64 ) * pow( 26, $i );
348 }
349 return $number;
350 }
351
352 /**
353 * "Calculate" the column header string of a column index (example: 2 is B, AB is 28, ...).
354 *
355 * For the opposite, @see letter_to_number().
356 *
357 * @since 1.0.0
358 *
359 * @param int $number Column number, 1-based.
360 * @return string Column string.
361 */
362 public static function number_to_letter( $number ) {
363 $column = '';
364 while ( $number > 0 ) {
365 $column = chr( 65 + ( ( $number - 1 ) % 26 ) ) . $column;
366 $number = floor( ( $number - 1 ) / 26 );
367 }
368 return $column;
369 }
370
371 /**
372 * Get a nice looking date and time string from the mySQL format of datetime strings for output.
373 *
374 * @since 1.0.0
375 *
376 * @param string $datetime_string DateTime string, often in mySQL format..
377 * @param string $separator_or_format Optional. Separator between date and time, or format string.
378 * @return string Nice looking string with the date and time.
379 */
380 public static function format_datetime( $datetime_string, $separator_or_format = ' ' ) {
381 $timezone = wp_timezone();
382 $datetime = date_create( $datetime_string, $timezone );
383 $timestamp = $datetime->getTimestamp();
384
385 switch ( $separator_or_format ) {
386 case ' ':
387 case '<br />':
388 $date = wp_date( get_option( 'date_format' ), $timestamp, $timezone );
389 $time = wp_date( get_option( 'time_format' ), $timestamp, $timezone );
390 $output = "{$date}{$separator_or_format}{$time}";
391 break;
392 default:
393 $output = wp_date( $separator_or_format, $timestamp, $timezone );
394 break;
395 }
396
397 return $output;
398 }
399
400 /**
401 * Get the name from a WP user ID (used to store information on last editor of a table).
402 *
403 * @since 1.0.0
404 *
405 * @param int $user_id WP user ID.
406 * @return string Nickname of the WP user with the $user_id.
407 */
408 public static function get_user_display_name( $user_id ) {
409 $user = get_userdata( $user_id );
410 return ( isset( $user->display_name ) ) ? $user->display_name : sprintf( '<em>%s</em>', __( 'unknown', 'tablepress' ) );
411 }
412
413 /**
414 * Sanitizes a CSS class to ensure it only contains valid characters.
415 *
416 * Strips the string down to A-Z, a-z, 0-9, :, _, -.
417 * This is an extension to WP's `sanitize_html_class()`, to also allow `:` which are used in some CSS frameworks.
418 *
419 * @since 1.11.0
420 *
421 * @param string $css_class The CSS class name to be sanitized.
422 * @return string The sanitized CSS class.
423 */
424 public static function sanitize_css_class( $css_class ) {
425 // Strip out any %-encoded octets.
426 $sanitized_css_class = preg_replace( '|%[a-fA-F0-9][a-fA-F0-9]|', '', $css_class );
427 // Limit to A-Z, a-z, 0-9, ':', '_', and '-'.
428 $sanitized_css_class = preg_replace( '/[^A-Za-z0-9:_-]/', '', $sanitized_css_class );
429 return $sanitized_css_class;
430 }
431
432 /**
433 * Retrieves all information of a WP_Error object as a string.
434 *
435 * @since 1.4.0
436 *
437 * @param WP_Error $wp_error A WP_Error object.
438 * @return string All error codes, messages, and data of the WP_Error.
439 */
440 public static function get_wp_error_string( $wp_error ) {
441 $error_strings = array();
442 $error_codes = $wp_error->get_error_codes();
443 // Reverse order to get latest errors first.
444 $error_codes = array_reverse( $error_codes );
445 foreach ( $error_codes as $error_code ) {
446 $error_strings[ $error_code ] = $error_code;
447 $error_messages = $wp_error->get_error_messages( $error_code );
448 $error_messages = implode( ', ', $error_messages );
449 if ( ! empty( $error_messages ) ) {
450 $error_strings[ $error_code ] .= " ({$error_messages})";
451 }
452 $error_data = $wp_error->get_error_data( $error_code );
453 if ( ! is_null( $error_data ) ) {
454 $error_strings[ $error_code ] .= " [{$error_data}]";
455 }
456 }
457 return implode( ";\n", $error_strings );
458 }
459
460 /**
461 * Generate the action URL, to be used as a link within the plugin (e.g. in the submenu navigation or List of Tables).
462 *
463 * @since 1.0.0
464 *
465 * @param array $params Optional. Parameters to form the query string of the URL.
466 * @param bool $add_nonce Optional. Whether the URL shall be nonced by WordPress.
467 * @param string $target Optional. Target File, e.g. "admin-post.php" for POST requests.
468 * @return string The URL for the given parameters (already run through esc_url() with $add_nonce === true!).
469 */
470 public static function url( array $params = array(), $add_nonce = false, $target = '' ) {
471 // Default action is "list", if no action given.
472 if ( ! isset( $params['action'] ) ) {
473 $params['action'] = 'list';
474 }
475 $nonce_action = $params['action'];
476
477 if ( '' !== $target ) {
478 $params['action'] = "tablepress_{$params['action']}";
479 } else {
480 $params['page'] = 'tablepress';
481 // Top-level parent page needs special treatment for better action strings.
482 if ( self::$controller->is_top_level_page ) {
483 $target = 'admin.php';
484 if ( ! in_array( $params['action'], array( 'list', 'edit' ), true ) ) {
485 $params['page'] = "tablepress_{$params['action']}";
486 }
487 if ( ! in_array( $params['action'], array( 'edit' ), true ) ) {
488 $params['action'] = false;
489 }
490 } else {
491 $target = self::$controller->parent_page;
492 }
493 }
494
495 // $default_params also determines the order of the values in the query string.
496 $default_params = array(
497 'page' => false,
498 'action' => false,
499 'item' => false,
500 );
501 $params = array_merge( $default_params, $params );
502
503 $url = add_query_arg( $params, admin_url( $target ) );
504 if ( $add_nonce ) {
505 $url = wp_nonce_url( $url, self::nonce( $nonce_action, $params['item'] ) ); // wp_nonce_url() does esc_html().
506 }
507 return $url;
508 }
509
510 /**
511 * Create a redirect URL from the $target_parameters and redirect the user.
512 *
513 * @since 1.0.0
514 *
515 * @param array $params Optional. Parameters from which the target URL is constructed.
516 * @param bool $add_nonce Optional. Whether the URL shall be nonced by WordPress.
517 */
518 public static function redirect( array $params = array(), $add_nonce = false ) {
519 $redirect = self::url( $params );
520 if ( $add_nonce ) {
521 if ( ! isset( $params['item'] ) ) {
522 $params['item'] = false;
523 }
524 // Don't use wp_nonce_url(), as that uses esc_html().
525 $redirect = add_query_arg( '_wpnonce', wp_create_nonce( self::nonce( $params['action'], $params['item'] ) ), $redirect );
526 }
527 wp_redirect( $redirect );
528 exit;
529 }
530
531 /**
532 * Show an error notice to admins, if TablePress's minimum requirements are not reached.
533 *
534 * @since 1.0.0
535 */
536 public static function show_minimum_requirements_error_notice() {
537 // Message is not translated as it is shown on every admin screen, for which we don't want to load translations.
538 echo '<div class="notice notice-error form-invalid"><p>' .
539 '<strong>Attention:</strong> ' .
540 'The installed version of WordPress is too old for the TablePress plugin! TablePress requires an up-to-date version! <strong>Please <a href="' . esc_url( admin_url( 'update-core.php' ) ) . '">update your WordPress installation</a></strong>!' .
541 "</p></div>\n";
542 }
543
544 /**
545 * Determines whether the site uses the block editor, so that certain text and input fields referring to Shortcodes can be displayed or not.
546 *
547 * @since 2.0.1
548 *
549 * @return bool True if the site uses the block editor, false otherwise.
550 */
551 public static function site_uses_block_editor() {
552 $site_uses_block_editor = use_block_editor_for_post_type( 'post' )
553 && ! is_plugin_active( 'beaver-builder-lite-version/fl-builder.php' )
554 && ! is_plugin_active( 'classic-editor/classic-editor.php' )
555 && ! is_plugin_active( 'classic-editor-addon/classic-editor-addon.php' )
556 && ! is_plugin_active( 'elementor/elementor.php' )
557 && ! is_plugin_active( 'siteorigin-panels/siteorigin-panels.php' );
558
559 /**
560 * Filters the outcome of the check whether the site uses the block editor.
561 *
562 * This can be used when certain conditions (e.g. new site builders) are not (yet) accounted for.
563 *
564 * @since 2.0.1
565 *
566 * @param bool $site_uses_block_editor True if the site uses the block editor, false otherwise.
567 */
568 $site_uses_block_editor = apply_filters( 'tablepress_site_uses_block_editor', $site_uses_block_editor );
569
570 return $site_uses_block_editor;
571 }
572
573 /**
574 * Initializes the list of TablePress premium modules.
575 *
576 * @since 2.1.0
577 */
578 public static function init_modules() {
579 self::$modules = array(
580 'advanced-access-rights' => array(
581 'name' => __( 'Advanced Access Rights', 'tablepress' ),
582 'description' => __( 'Restrict access to individual tables for individual users.', 'tablepress' ),
583 'category' => 'backend',
584 'class' => 'TablePress_Module_Advanced_Access_Rights',
585 'incompatible_classes' => array( 'TablePress_Advanced_Access_Rights_Controller' ),
586 'minimum_plan' => 'max',
587 'default_active' => false,
588 ),
589 'automatic-periodic-table-import' => array(
590 'name' => __( 'Automatic Periodic Table Import', 'tablepress' ),
591 'description' => __( 'Periodically update tables from a configured import source.', 'tablepress' ),
592 'category' => 'backend',
593 'class' => 'TablePress_Module_Automatic_Periodic_Table_Import',
594 'incompatible_classes' => array( 'TablePress_Table_Auto_Update' ),
595 'minimum_plan' => 'max',
596 'default_active' => true,
597 ),
598 'automatic-table-export' => array(
599 'name' => __( 'Automatic Table Export', 'tablepress' ),
600 'description' => __( 'Export and save tables to files on the server after they were modified.', 'tablepress' ),
601 'category' => 'backend',
602 'class' => 'TablePress_Module_Automatic_Table_Export',
603 'incompatible_classes' => array(),
604 'minimum_plan' => 'pro',
605 'default_active' => false,
606 ),
607 'cell-highlighting' => array(
608 'name' => __( 'Cell Highlighting', 'tablepress' ),
609 'description' => __( 'Add CSS classes to cells for highlighting based on their content.', 'tablepress' ),
610 'category' => 'frontend',
611 'class' => 'TablePress_Module_Cell_Highlighting',
612 'incompatible_classes' => array( 'TablePress_Cell_Highlighting' ),
613 'minimum_plan' => 'pro',
614 'default_active' => false,
615 ),
616 'column-order' => array(
617 'name' => __( 'Column Order', 'tablepress' ),
618 'description' => __( 'Order the columns in different ways when a table is shown.', 'tablepress' ),
619 'category' => 'data-management',
620 'class' => 'TablePress_Module_Column_Order',
621 'incompatible_classes' => array( 'TablePress_Column_Order' ),
622 'minimum_plan' => 'pro',
623 'default_active' => false,
624 ),
625 'datatables-advanced-loading' => array(
626 'name' => __( 'Advanced Loading', 'tablepress' ),
627 'description' => __( 'Load the table data from a JSON array for faster loading.', 'tablepress' ),
628 'category' => 'backend',
629 'class' => 'TablePress_Module_DataTables_Advanced_Loading',
630 'incompatible_classes' => array( 'TablePress_DataTables_Advanced_Loading' ),
631 'minimum_plan' => 'max',
632 'default_active' => false,
633 ),
634 'datatables-alphabetsearch' => array(
635 'name' => __( 'Alphabet Search', 'tablepress' ),
636 'description' => __( 'Show Alphabet buttons above the table to filter rows by their first letter.', 'tablepress' ),
637 'category' => 'search-filter',
638 'class' => 'TablePress_Module_DataTables_Alphabetsearch',
639 'incompatible_classes' => array(),
640 'minimum_plan' => 'pro',
641 'default_active' => false,
642 ),
643 'datatables-auto-filter' => array(
644 'name' => __( 'Automatic Filter', 'tablepress' ),
645 'description' => __( 'Pre-filter a table when it is shown.', 'tablepress' ),
646 'category' => 'search-filter',
647 'class' => 'TablePress_Module_DataTables_Auto_Filter',
648 'incompatible_classes' => array( 'TablePress_DataTables_Auto_Filter' ),
649 'minimum_plan' => 'pro',
650 'default_active' => false,
651 ),
652 'datatables-buttons' => array(
653 'name' => __( 'Buttons', 'tablepress' ),
654 'description' => __( 'Add buttons for downloading, copying, printing, and changing column visibility of tables.', 'tablepress' ),
655 'category' => 'frontend',
656 'class' => 'TablePress_Module_DataTables_Buttons',
657 'incompatible_classes' => array( 'TablePress_DataTables_Buttons' ),
658 'minimum_plan' => 'pro',
659 'default_active' => true,
660 ),
661 'datatables-columnfilterwidgets' => array(
662 'name' => __( 'Column Filter Dropdowns', 'tablepress' ),
663 'description' => __( 'Add a search dropdown for each column above the table.', 'tablepress' ),
664 'category' => 'search-filter',
665 'class' => 'TablePress_Module_DataTables_ColumnFilterWidgets',
666 'incompatible_classes' => array(),
667 'minimum_plan' => 'pro',
668 'default_active' => true,
669 ),
670 'datatables-column-filter' => array(
671 'name' => __( 'Individual Column Filtering', 'tablepress' ),
672 'description' => __( 'Add a search field for each column to the table head or foot row.', 'tablepress' ),
673 'category' => 'search-filter',
674 'class' => 'TablePress_Module_DataTables_Column_Filter',
675 'incompatible_classes' => array(),
676 'minimum_plan' => 'pro',
677 'default_active' => false,
678 ),
679 'datatables-counter-column' => array(
680 'name' => __( 'Counter Column', 'tablepress' ),
681 'description' => __( 'Make the first column an index or counter column with the row position.', 'tablepress' ),
682 'category' => 'frontend',
683 'class' => 'TablePress_Module_DataTables_Counter_Column',
684 'incompatible_classes' => array(),
685 'minimum_plan' => 'pro',
686 'default_active' => false,
687 ),
688 'datatables-fixedheader-fixedcolumns' => array(
689 'name' => __( 'Fixed Rows and Columns', 'tablepress' ),
690 'description' => __( 'Fix the header and footer row and the first and last column when scrolling the table.', 'tablepress' ),
691 'category' => 'frontend',
692 'class' => 'TablePress_Module_DataTables_FixedHeader_FixedColumns',
693 'incompatible_classes' => array(
694 'TablePress_DataTables_FixedHeader',
695 'TablePress_DataTables_FixedColumns',
696 ),
697 'minimum_plan' => 'pro',
698 'default_active' => true,
699 ),
700 'datatables-rowgroup' => array(
701 'name' => __( 'Row Grouping', 'tablepress' ),
702 'description' => __( 'Group table rows by a common keyword, category, or title.', 'tablepress' ),
703 'category' => 'frontend',
704 'class' => 'TablePress_Module_DataTables_RowGroup',
705 'incompatible_classes' => array( 'TablePress_DataTables_RowGroup' ),
706 'minimum_plan' => 'pro',
707 'default_active' => false,
708 ),
709 'datatables-searchbuilder' => array(
710 'name' => __( 'Custom Search Builder', 'tablepress' ),
711 'description' => __( 'Show a search builder interface for filtering from groups and using conditions.', 'tablepress' ),
712 'category' => 'search-filter',
713 'class' => 'TablePress_Module_DataTables_SearchBuilder',
714 'incompatible_classes' => array(),
715 'minimum_plan' => 'max',
716 'default_active' => false,
717 ),
718 'datatables-searchhighlight' => array(
719 'name' => __( 'Search Highlighting', 'tablepress' ),
720 'description' => __( 'Highlight found search terms in the table.', 'tablepress' ),
721 'category' => 'search-filter',
722 'class' => 'TablePress_Module_DataTables_SearchHighlight',
723 'incompatible_classes' => array(),
724 'minimum_plan' => 'pro',
725 'default_active' => false,
726 ),
727 'datatables-searchpanes' => array(
728 'name' => __( 'Search Panes', 'tablepress' ),
729 'description' => __( 'Show panes for filtering the columns.', 'tablepress' ),
730 'category' => 'search-filter',
731 'class' => 'TablePress_Module_DataTables_SearchPanes',
732 'incompatible_classes' => array(),
733 'minimum_plan' => 'pro',
734 'default_active' => false,
735 ),
736 'datatables-serverside-processing' => array(
737 'name' => __( 'Server-side Processing', 'tablepress' ),
738 'description' => __( 'Process sorting, filtering, and pagination on the server for faster loading of large tables.', 'tablepress' ),
739 'category' => 'backend',
740 'class' => 'TablePress_Module_DataTables_ServerSide_Processing',
741 'incompatible_classes' => array(),
742 'minimum_plan' => 'max',
743 'default_active' => true,
744 ),
745 'responsive-tables' => array(
746 'name' => __( 'Responsive Tables', 'tablepress' ),
747 'description' => __( 'Make your tables look good on different screen sizes.', 'tablepress' ),
748 'category' => 'frontend',
749 'class' => 'TablePress_Module_Responsive_Tables',
750 'incompatible_classes' => array( 'TablePress_Responsive_Tables' ),
751 'minimum_plan' => 'pro',
752 'default_active' => true,
753 ),
754 'rest-api' => array(
755 'name' => __( 'REST API', 'tablepress' ),
756 'description' => __( 'Read table data via the WordPress REST API, e.g. in external apps.', 'tablepress' ),
757 'category' => 'backend',
758 'class' => 'TablePress_Module_REST_API',
759 'incompatible_classes' => array( 'TablePress_REST_API_Controller' ),
760 'minimum_plan' => 'max',
761 'default_active' => false,
762 ),
763 'row-filtering' => array(
764 'name' => __( 'Row Filtering', 'tablepress' ),
765 'description' => __( 'Show only table rows that contain defined keywords.', 'tablepress' ),
766 'category' => 'data-management',
767 'class' => 'TablePress_Module_Row_Filtering',
768 'incompatible_classes' => array( 'TablePress_Row_Filter' ),
769 'minimum_plan' => 'pro',
770 'default_active' => true,
771 ),
772 'row-highlighting' => array(
773 'name' => __( 'Row Highlighting', 'tablepress' ),
774 'description' => __( 'Add CSS classes to rows for highlighting based on their content.', 'tablepress' ),
775 'category' => 'frontend',
776 'class' => 'TablePress_Module_Row_Highlighting',
777 'incompatible_classes' => array( 'TablePress_Row_Highlighting' ),
778 'minimum_plan' => 'pro',
779 'default_active' => false,
780 ),
781 'row-order' => array(
782 'name' => __( 'Row Order', 'tablepress' ),
783 'description' => __( 'Order the rows in different ways when a table is shown.', 'tablepress' ),
784 'category' => 'data-management',
785 'class' => 'TablePress_Module_Row_Order',
786 'incompatible_classes' => array( 'TablePress_Row_Order' ),
787 'minimum_plan' => 'pro',
788 'default_active' => false,
789 ),
790 );
791 }
792
793 } // class TablePress
794