PluginProbe
TablePress – Tables in WordPress made easy / 1.12
TablePress – Tables in WordPress made easy v1.12
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-view.php

class-view.php in TablePress – Tables in WordPress made easy 1.12, at classes/class-view.php

469 lines 15.4 KB
No matching file
Up and down to move Enter to open Esc to close
Raw Download Zip
1 <?php
2 /**
3 * TablePress Base View with members and methods for all views
4 *
5 * @package TablePress
6 * @subpackage Views
7 * @author Tobias Bäthge
8 * @since 1.0.0
9 */
10
11 // Prohibit direct script loading.
12 defined( 'ABSPATH' ) || die( 'No direct script access allowed!' );
13
14 /**
15 * TablePress Base View class
16 * @package TablePress
17 * @subpackage Views
18 * @author Tobias Bäthge
19 * @since 1.0.0
20 */
21 abstract class TablePress_View {
22
23 /**
24 * Data for the view.
25 *
26 * @since 1.0.0
27 * @var array
28 */
29 protected $data = array();
30
31 /**
32 * Number of screen columns for post boxes.
33 *
34 * @since 1.0.0
35 * @var int
36 */
37 protected $screen_columns = 0;
38
39 /**
40 * User action for this screen.
41 *
42 * @since 1.0.0
43 * @var string
44 */
45 protected $action = '';
46
47 /**
48 * Instance of the Admin Page Helper Class, with necessary functions.
49 *
50 * @since 1.0.0
51 * @var TablePress_Admin_Page
52 */
53 protected $admin_page;
54
55 /**
56 * List of text boxes (similar to post boxes, but just with text and without extra functionality).
57 *
58 * @since 1.0.0
59 * @var array
60 */
61 protected $textboxes = array();
62
63 /**
64 * List of messages that are to be displayed as boxes below the page title.
65 *
66 * @since 1.0.0
67 * @var array
68 */
69 protected $header_messages = array();
70
71 /**
72 * Whether there are post boxes registered for this screen,
73 * is automatically set to true, when a meta box is added.
74 *
75 * @since 1.0.0
76 * @var bool
77 */
78 protected $has_meta_boxes = false;
79
80 /**
81 * List of WP feature pointers for this view.
82 *
83 * @since 1.0.0
84 * @var array
85 */
86 protected $wp_pointers = array();
87
88 /**
89 * Initialize the View class, by setting the correct screen columns and adding help texts.
90 *
91 * @since 1.0.0
92 */
93 public function __construct() {
94 $screen = get_current_screen();
95 if ( 0 !== $this->screen_columns ) {
96 $screen->add_option( 'layout_columns', array( 'max' => $this->screen_columns ) );
97 }
98 // Enable two column layout.
99 add_filter( "get_user_option_screen_layout_{$screen->id}", array( $this, 'set_current_screen_layout_columns' ) );
100
101 $screen->add_help_tab( array(
102 'id' => 'tablepress-help', // This should be unique for the screen.
103 'title' => __( 'TablePress Help', 'tablepress' ),
104 'content' => '<p>' . $this->help_tab_content() . '</p>'
105 . '<p>' . sprintf( __( 'More information about TablePress can be found on the <a href="%1$s">plugin website</a> or on its page in the <a href="%2$s">WordPress Plugin Directory</a>.', 'tablepress' ), 'https://tablepress.org/', 'https://wordpress.org/plugins/tablepress/' ) . ' '
106 . sprintf( __( 'For technical information, please see the <a href="%s">Documentation</a>.', 'tablepress' ), 'https://tablepress.org/documentation/' ) . ' '
107 . sprintf( __( '<a href="%1$s">Support</a> is provided through the <a href="%2$s">WordPress Support Forums</a>.', 'tablepress' ), 'https://tablepress.org/support/', 'https://wordpress.org/tags/tablepress' ) . ' '
108 . sprintf( __( 'Before asking for support, please carefully read the <a href="%s">Frequently Asked Questions</a>, where you will find answers to the most common questions, and search through the forums.', 'tablepress' ), 'https://tablepress.org/faq/' ) . '<br />'
109 . sprintf( __( 'If you like the plugin, <a href="%1$s"><strong>a donation</strong></a> is recommended.', 'tablepress' ), 'https://tablepress.org/donate/' ) . '</p>',
110 ) );
111 // "sidebar" in the help tab.
112 $screen->set_help_sidebar( '<p><strong>' . __( 'For more information:', 'tablepress' ) . '</strong></p><p><a href="https://tablepress.org/">TablePress Website</a></p><p><a href="https://tablepress.org/faq/">TablePress FAQ</a></p><p><a href="https://tablepress.org/documentation/">TablePress Documentation</a></p><p><a href="https://tablepress.org/support/">TablePress Support</a></p>' );
113 }
114
115 /**
116 * Change the value of the user option "screen_layout_{$screen->id}" through a filter.
117 *
118 * @since 1.0.0
119 *
120 * @param int|bool Current value of the user option.
121 * @return int New value for the user option.
122 */
123 public function set_current_screen_layout_columns( $result ) {
124 if ( false === $result ) {
125 // The user option does not yet exist.
126 $result = $this->screen_columns;
127 } elseif ( $result > $this->screen_columns ) {
128 // The value of the user option is bigger than what is possible on this screen (e.g. because the number of columns was reduced in an update).
129 $result = $this->screen_columns;
130 }
131 return $result;
132 }
133
134 /**
135 * Set up the view with data and do things that are necessary for all views.
136 *
137 * @since 1.0.0
138 *
139 * @param string $action Action for this view.
140 * @param array $data Data for this view.
141 */
142 public function setup( $action, array $data ) {
143 $this->action = $action;
144 $this->data = $data;
145
146 // Set page title.
147 $GLOBALS['title'] = sprintf( __( '%1$s &lsaquo; %2$s', 'tablepress' ), $this->data['view_actions'][ $this->action ]['page_title'], 'TablePress' );
148
149 // Admin page helpers, like script/style loading, could be moved to view.
150 $this->admin_page = TablePress::load_class( 'TablePress_Admin_Page', 'class-admin-page-helper.php', 'classes' );
151 $this->admin_page->enqueue_style( 'common' );
152 // RTL styles for the admin interface.
153 if ( is_rtl() ) {
154 $this->admin_page->enqueue_style( 'common-rtl', array( 'tablepress-common' ) );
155 }
156 $this->admin_page->enqueue_script( 'common', array( 'jquery', 'postbox' ), array(
157 'common' => array(
158 'ays_delete_single_table' => _n( 'Do you really want to delete this table?', 'Do you really want to delete these tables?', 1, 'tablepress' ),
159 'ays_delete_multiple_tables' => _n( 'Do you really want to delete this table?', 'Do you really want to delete these tables?', 2, 'tablepress' ),
160 )
161 ) );
162
163 $this->admin_page->add_admin_footer_text();
164
165 // Initialize WP feature pointers for TablePress.
166 $this->_init_wp_pointers();
167
168 // Necessary fields for all views.
169 $this->add_text_box( 'default_nonce_fields', array( $this, 'default_nonce_fields' ), 'header', false );
170 $this->add_text_box( 'action_nonce_field', array( $this, 'action_nonce_field' ), 'header', false );
171 $this->add_text_box( 'action_field', array( $this, 'action_field' ), 'header', false );
172 }
173
174 /**
175 * Register a header message for the view.
176 *
177 * @since 1.0.0
178 *
179 * @param string $text Text for the header message.
180 * @param string $class Optional. Additional CSS class for the header message.
181 * @param string $title Optional. Text for the header title.
182 */
183 protected function add_header_message( $text, $class = 'notice-success', $title = '' ) {
184 if ( ! stripos( $class, 'not-dismissible' ) ) {
185 $class .= ' is-dismissible';
186 }
187 if ( ! empty( $title ) ) {
188 $title = "<h3>{$title}</h3>";
189 }
190 if ( ! empty( $text ) ) {
191 $text = "<p>{$text}</p>";
192 }
193 $this->header_messages[] = "<div class=\"notice {$class}\">{$title}{$text}</div>\n";
194 }
195
196 /**
197 * Process header action messages, i.e. check if a message should be added to the page.
198 *
199 * @since 1.0.0
200 *
201 * @param array $action_messages Action messages for the screen.
202 */
203 protected function process_action_messages( array $action_messages ) {
204 if ( $this->data['message'] && isset( $action_messages[ $this->data['message'] ] ) ) {
205 $class = ( 'error' === substr( $this->data['message'], 0, 5 ) ) ? 'notice-error' : 'notice-success';
206 $this->add_header_message( "<strong>{$action_messages[ $this->data['message'] ]}</strong>", $class );
207 }
208 }
209
210 /**
211 * Register a text box for the view.
212 *
213 * @since 1.0.0
214 *
215 * @param string $id Unique HTML ID for the text box container (only visible with $wrap = true).
216 * @param callback $callback Callback that prints the contents of the text box.
217 * @param string $context Optional. Context/position of the text box (normal, side, additional, header, submit).
218 * @param bool $ wrap Whether the content of the text box shall be wrapped in a <div> container.
219 */
220 protected function add_text_box( $id, $callback, $context = 'normal', $wrap = false ) {
221 if ( ! isset( $this->textboxes[ $context ] ) ) {
222 $this->textboxes[ $context ] = array();
223 }
224
225 $long_id = "tablepress_{$this->action}-{$id}";
226 $this->textboxes[ $context ][ $id ] = array(
227 'id' => $long_id,
228 'callback' => $callback,
229 'context' => $context,
230 'wrap' => $wrap,
231 );
232 }
233
234 /**
235 * Register a post meta box for the view, that is drag/droppable with WordPress functionality.
236 *
237 * @since 1.0.0
238 *
239 * @param string $id Unique ID for the meta box.
240 * @param string $title Title for the meta box.
241 * @param callback $callback Callback that prints the contents of the post meta box.
242 * @param string $context Optional. Context/position of the post meta box (normal, side, additional).
243 * @param string $priority Optional. Order of the post meta box for the $context position (high, default, low).
244 * @param bool $callback_args Optional. Additional data for the callback function (e.g. useful when in different class).
245 */
246 protected function add_meta_box( $id, $title, $callback, $context = 'normal', $priority = 'default', $callback_args = null ) {
247 $this->has_meta_boxes = true;
248 add_meta_box( "tablepress_{$this->action}-{$id}", $title, $callback, null, $context, $priority, $callback_args );
249 }
250
251 /**
252 * Render all text boxes for the given context.
253 *
254 * @since 1.0.0
255 *
256 * @param string $context Context (normal, side, additional, header, submit) for which registered text boxes shall be rendered.
257 */
258 protected function do_text_boxes( $context ) {
259 if ( empty( $this->textboxes[ $context ] ) ) {
260 return;
261 }
262
263 foreach ( $this->textboxes[ $context ] as $box ) {
264 if ( $box['wrap'] ) {
265 echo "<div id=\"{$box['id']}\" class=\"textbox\">\n";
266 }
267 call_user_func( $box['callback'], $this->data, $box );
268 if ( $box['wrap'] ) {
269 echo "</div>\n";
270 }
271 }
272 }
273
274 /**
275 * Render all post meta boxes for the given context, if there are post meta boxes.
276 *
277 * @since 1.0.0
278 *
279 * @param string $context Context (normal, side, additional) for which registered post meta boxes shall be rendered.
280 */
281 protected function do_meta_boxes( $context ) {
282 if ( ! $this->has_meta_boxes ) {
283 return;
284 }
285 do_meta_boxes( null, $context, $this->data );
286 }
287
288 /**
289 * Print hidden fields with nonces for post meta box AJAX handling, if there are post meta boxes on the screen.
290 *
291 * The check is possible as this function is executed after post meta boxes have to be registered.
292 *
293 * @since 1.0.0
294 *
295 * @param array $data Data for this screen.
296 * @param array $box Information about the text box.
297 */
298 protected function default_nonce_fields( array $data, array $box ) {
299 if ( ! $this->has_meta_boxes ) {
300 return;
301 }
302 wp_nonce_field( 'closedpostboxes', 'closedpostboxesnonce', false );
303 echo "\n";
304 wp_nonce_field( 'meta-box-order', 'meta-box-order-nonce', false );
305 echo "\n";
306 }
307
308 /**
309 * Print hidden field with a nonce for the screen's action, to be transmitted in HTTP requests.
310 *
311 * @since 1.0.0
312 *
313 * @param array $data Data for this screen.
314 * @param array $box Information about the text box.
315 */
316 protected function action_nonce_field( array $data, array $box ) {
317 wp_nonce_field( TablePress::nonce( $this->action ) );
318 echo "\n";
319 }
320
321 /**
322 * Print hidden field with the screen action.
323 *
324 * @since 1.0.0
325 *
326 * @param array $data Data for this screen.
327 * @param array $box Information about the text box.
328 */
329 protected function action_field( array $data, array $box ) {
330 echo "<input type=\"hidden\" name=\"action\" value=\"tablepress_{$this->action}\" />\n";
331 }
332
333 /**
334 * Render the current view.
335 *
336 * @since 1.0.0
337 */
338 public function render() {
339 ?>
340 <div id="tablepress-page" class="wrap">
341 <?php
342 $this->print_nav_tab_menu();
343 // Print all header messages.
344 foreach ( $this->header_messages as $message ) {
345 echo $message;
346 }
347 // "Import" screen has file upload.
348 $enctype = ( 'import' === $this->action ) ? ' enctype="multipart/form-data"' : '';
349 ?>
350 <form action="<?php echo esc_url( admin_url( 'admin-post.php' ) ); ?>" method="post"<?php echo $enctype; ?>>
351 <?php
352 $this->do_text_boxes( 'header' );
353 ?>
354 <div id="poststuff">
355 <div id="post-body" class="metabox-holder columns-<?php echo ( isset( $GLOBALS['screen_layout_columns'] ) && ( 2 === $GLOBALS['screen_layout_columns'] ) ) ? '2' : '1'; ?>">
356 <div id="postbox-container-2" class="postbox-container">
357 <?php
358 $this->do_text_boxes( 'normal' );
359 $this->do_meta_boxes( 'normal' );
360
361 $this->do_text_boxes( 'additional' );
362 $this->do_meta_boxes( 'additional' );
363
364 // Print all submit buttons.
365 $this->do_text_boxes( 'submit' );
366 ?>
367 </div>
368 <div id="postbox-container-1" class="postbox-container">
369 <?php
370 // Print all boxes in the sidebar.
371 $this->do_text_boxes( 'side' );
372 $this->do_meta_boxes( 'side' );
373 ?>
374 </div>
375 </div>
376 <br class="clear" />
377 </div>
378 </form>
379 </div>
380 <?php
381 }
382
383 /**
384 * Render the navigation menu with links to the possible actions, highlighting the current one.
385 *
386 * @since 1.0.0
387 */
388 protected function print_nav_tab_menu() {
389 ?>
390 <div id="tablepress-nav" class="nav-tab-wrapper">
391 <h1 class="wp-heading-inline"><?php _e( 'TablePress', 'tablepress' ); ?></h1>
392 <?php
393 foreach ( $this->data['view_actions'] as $action => $entry ) {
394 if ( '' === $entry['nav_tab_title'] ) {
395 continue;
396 }
397 if ( ! current_user_can( $entry['required_cap'] ) ) {
398 continue;
399 }
400
401 $url = esc_url( TablePress::url( array( 'action' => $action ) ) );
402 $active = ( $action === $this->action ) ? ' nav-tab-active' : '';
403 $separator = ( 'options' === $action ) ? ' nav-tab-separator' : ''; // Make the "Plugin Options" entry a separator, for some spacing.
404 echo "<a class=\"nav-tab{$active}{$separator}\" href=\"{$url}\">{$entry['nav_tab_title']}</a>";
405 }
406 ?>
407 </div><hr class="wp-header-end" />
408 <?php
409 }
410
411 /**
412 * Print a submit button (only done when function is used as a callback for a text box).
413 *
414 * @since 1.0.0
415 *
416 * @param array $data Data for this screen.
417 * @param array $box Information about the text box.
418 */
419 protected function textbox_submit_button( array $data, array $box ) {
420 $caption = isset( $data['submit_button_caption'] ) ? $data['submit_button_caption'] : __( 'Save Changes', 'tablepress' );
421 ?>
422 <p class="submit"><input type="submit" value="<?php echo esc_attr( $caption ); ?>" class="button button-primary button-large" name="submit" /></p>
423 <?php
424 }
425
426 /**
427 * Return the content for the help tab for this screen.
428 *
429 * Has to be implemented for every view that is visible in the WP Dashboard!
430 *
431 * @since 1.0.0
432 */
433 protected function help_tab_content() {
434 // Has to be implemented for every view that is visible in the WP Dashboard!
435 return '';
436 }
437
438 /**
439 * Initialize the WP feature pointers for TablePress.
440 *
441 * @since 1.0.0
442 */
443 protected function _init_wp_pointers() {
444 // Check if there are WP pointers for this view.
445 if ( empty( $this->wp_pointers ) ) {
446 return;
447 }
448
449 // Get dismissed pointers.
450 $dismissed = explode( ',', (string) get_user_meta( get_current_user_id(), 'dismissed_wp_pointers', true ) );
451
452 $got_pointers = false;
453 foreach ( array_diff( $this->wp_pointers, $dismissed ) as $pointer ) {
454 // Bind pointer print function.
455 add_action( "admin_footer-{$GLOBALS['hook_suffix']}", array( $this, 'wp_pointer_' . $pointer ) );
456 $got_pointers = true;
457 }
458
459 if ( ! $got_pointers ) {
460 return;
461 }
462
463 // Add pointers script and style to queue.
464 wp_enqueue_style( 'wp-pointer' );
465 wp_enqueue_script( 'wp-pointer' );
466 }
467
468 } // class TablePress_View
469