PluginProbe
Essential Widgets / trunk
Essential Widgets vtrunk
3.2.1 3.3 3.2 trunk 1.0.0 1.0.1 1.1 1.2 1.2.1 1.2.2 1.3 1.4 1.4.1 1.5 1.6 1.7 1.7.1 1.7.2 1.7.3 1.7.4 1.8 1.9 2.0 2.1 2.2 All 31 releases
essential-widgets / includes / widgets / class-ew-pages.php

class-ew-pages.php in Essential Widgets trunk, at includes/widgets/class-ew-pages.php

474 lines 16.8 KB
No matching file
Up and down to move Enter to open Esc to close
Raw Download Zip
1 <?php
2
3 if (! defined('ABSPATH')) {
4 exit; // Exit if accessed directly.
5 }
6
7 /**
8 * Pages Widget
9 *
10 * @package Essential_Widgets
11 */
12
13
14 /**
15 * Makes a custom Widget for Displaying About
16 *
17 * Learn more: http://codex.wordpress.org/Widgets_API#Developing_Widgets
18 *
19 * @package Essential_Widgets
20 */
21 if (! function_exists('ew_get_meta_keys')) :
22 /**
23 * Returns a list of distinct, non-private post meta keys for use in the
24 * widget's "Order by meta key" dropdown.
25 *
26 * Named ew_get_meta_keys() (not get_meta_keys()) to avoid colliding with
27 * WordPress core's own get_meta_keys() in wp-admin/includes/post.php.
28 *
29 * @since 3.2
30 * @return array
31 */
32 function ew_get_meta_keys()
33 { // phpcs:ignore WordPress.NamingConventions.PrefixAllGlobals.NonPrefixedFunctionFound -- guarded with function_exists(); shared helper used by both the free and pro Pages widgets.
34 global $wpdb;
35
36 $cached_keys = get_transient('ew_meta_keys');
37 if (false !== $cached_keys) {
38 return $cached_keys;
39 }
40
41 // phpcs:ignore WordPress.DB.DirectDatabaseQuery.DirectQuery, WordPress.DB.DirectDatabaseQuery.NoCaching -- distinct meta key lookup has no WP_Query equivalent; result is cached via transient below.
42 $keys = $wpdb->get_col("SELECT DISTINCT meta_key FROM {$wpdb->postmeta} WHERE meta_key NOT LIKE '\_%' ORDER BY meta_key ASC");
43 $keys = is_array($keys) ? $keys : array();
44
45 set_transient('ew_meta_keys', $keys, HOUR_IN_SECONDS);
46
47 return $keys;
48 }
49 endif;
50
51 if (! class_exists('EW_Pages')) :
52 class EW_Pages extends WP_Widget // phpcs:ignore WordPress.NamingConventions.PrefixAllGlobals.NonPrefixedClassFound -- EW_ is this plugin's abbreviated prefix; wrapped in class_exists() guard.
53 {
54
55
56 /**
57 * Holds widget settings defaults, populated in constructor.
58 *
59 * @var array
60 */
61 protected $defaults;
62
63 public function __construct()
64 {
65
66 // Set up the defaults.
67 $this->defaults = array(
68 'title' => esc_attr__('Pages', 'essential-widgets'),
69 'post_type' => 'page',
70 'depth' => 0,
71 'number' => '',
72 'offset' => '',
73 'child_of' => '',
74 'include' => '',
75 'exclude' => '', // phpcs:ignore WordPressVIPMinimum.Performance.WPQueryParams.PostNotIn_exclude -- Required wp_list_pages() parameter, not a WP_Query post__not_in clause.
76 'exclude_tree' => '',
77 'meta_key' => '', // phpcs:ignore WordPress.DB.SlowDBQuery.slow_db_query_meta_key -- Required wp_list_pages() parameter.
78 'meta_value' => '', // phpcs:ignore WordPress.DB.SlowDBQuery.slow_db_query_meta_value -- Required wp_list_pages() parameter.
79 'authors' => '',
80 'link_before' => '',
81 'link_after' => '',
82 'show_date' => '',
83 'hierarchical' => true,
84 'sort_column' => 'post_title',
85 'sort_order' => 'ASC',
86 'date_format' => get_option('date_format'),
87 );
88
89 $widget_ops = array(
90 'classname' => 'essential-widgets ew-pages ewpages',
91 'description' => esc_html__('Displays a list of pages.', 'essential-widgets'),
92 );
93
94 $control_ops = array(
95 'id_base' => 'ew-pages',
96 );
97
98 parent::__construct(
99 'ew-pages', // Base ID
100 esc_html__('EW: Pages', 'essential-widgets'), // Name
101 $widget_ops,
102 $control_ops
103 );
104 }
105
106 /**
107 * Displays the widget control options in the Widgets admin screen.
108 *
109 * @since 1.0.0
110 * @access public
111 * @param array $instance
112 * @param void
113 */
114 public function form($instance)
115 {
116 // Merge the user-selected arguments with the defaults.
117 $instance = wp_parse_args((array) $instance, $this->defaults);
118
119 $post_types = get_post_types(
120 array(
121 'public' => true,
122 'hierarchical' => true,
123 ),
124 'objects'
125 );
126
127 $sort_order = array(
128 'ASC' => esc_attr__('Ascending', 'essential-widgets'),
129 'DESC' => esc_attr__('Descending', 'essential-widgets'),
130 );
131
132 $sort_column = array(
133 'post_author' => esc_attr__('Author', 'essential-widgets'),
134 'post_date' => esc_attr__('Date', 'essential-widgets'),
135 'ID' => esc_attr__('ID', 'essential-widgets'),
136 'menu_order' => esc_attr__('Menu Order', 'essential-widgets'),
137 'post_modified' => esc_attr__('Modified', 'essential-widgets'),
138 'post_name' => esc_attr__('Slug', 'essential-widgets'),
139 'post_title' => esc_attr__('Title', 'essential-widgets'),
140 );
141
142 $show_date = array(
143 '' => esc_attr__('Select', 'essential-widgets'),
144 'created' => esc_attr__('Created', 'essential-widgets'),
145 'modified' => esc_attr__('Modified', 'essential-widgets'),
146 );
147
148 $meta_key = array_merge(array(''), (array) get_meta_keys()); ?>
149
150 <p>
151 <label>
152 <?php esc_html_e('Title:', 'essential-widgets'); ?>
153 <input type="text" class="widefat" id="<?php echo esc_attr($this->get_field_id('title')); ?>" name="<?php echo esc_attr($this->get_field_name('title')); ?>" value="<?php echo esc_attr($instance['title']); ?>" placeholder="<?php echo esc_attr($this->defaults['title']); ?>" />
154 </label>
155 </p>
156
157 <p>
158 <label>
159 <?php esc_html_e('Post Type:', 'essential-widgets'); ?>
160
161 <select class="widefat" name="<?php echo esc_attr($this->get_field_name('post_type')); ?>">
162
163 <?php foreach ($post_types as $post_type) : ?>
164
165 <option value="<?php echo esc_attr($post_type->name); ?>" <?php selected($instance['post_type'], $post_type->name); ?>><?php echo esc_html($post_type->labels->singular_name); ?></option>
166
167 <?php endforeach; ?>
168
169 </select>
170 </label>
171 </p>
172
173 <p>
174 <label>
175 <?php esc_html_e('Order:', 'essential-widgets'); ?>
176
177 <select class="widefat" name="<?php echo esc_attr($this->get_field_name('sort_order')); ?>">
178
179 <?php foreach ($sort_order as $option_value => $option_label) : ?>
180
181 <option value="<?php echo esc_attr($option_value); ?>" <?php selected($instance['sort_order'], $option_value); ?>><?php echo esc_html($option_label); ?></option>
182
183 <?php endforeach; ?>
184
185 </select>
186 </label>
187 </p>
188
189 <p>
190 <label>
191 <?php esc_html_e('Order By:', 'essential-widgets'); ?>
192
193 <select class="widefat" name="<?php echo esc_attr($this->get_field_name('sort_column')); ?>">
194
195 <?php foreach ($sort_column as $option_value => $option_label) : ?>
196
197 <option value="<?php echo esc_attr($option_value); ?>" <?php selected($instance['sort_column'], $option_value); ?>><?php echo esc_html($option_label); ?></option>
198
199 <?php endforeach; ?>
200
201 </select>
202 </label>
203 </p>
204
205 <p>
206 <label>
207 <?php esc_html_e('Depth:', 'essential-widgets'); ?>
208 <input type="number" class="widefat" size="5" min="0" name="<?php echo esc_attr($this->get_field_name('depth')); ?>" value="<?php echo esc_attr($instance['depth']); ?>" placeholder="0" />
209 </label>
210 </p>
211
212 <p>
213 <label>
214 <?php esc_html_e('Number:', 'essential-widgets'); ?>
215 <input type="number" class="widefat" size="5" min="0" name="<?php echo esc_attr($this->get_field_name('number')); ?>" value="<?php echo esc_attr($instance['number']); ?>" placeholder="0" />
216 </label>
217 </p>
218
219 <p>
220 <label>
221 <?php esc_html_e('Offset:', 'essential-widgets'); ?>
222 <input type="number" class="widefat" size="5" min="0" name="<?php echo esc_attr($this->get_field_name('offset')); ?>" value="<?php echo esc_attr($instance['offset']); ?>" placeholder="0" />
223 </label>
224 </p>
225
226 <p>
227 <label>
228 <?php esc_html_e('Child Of:', 'essential-widgets'); ?>
229 <input type="text" class="widefat" name="<?php echo esc_attr($this->get_field_name('child_of')); ?>" value="<?php echo esc_attr($instance['child_of']); ?>" placeholder="0" />
230 </label>
231 </p>
232
233 <p>
234 <label>
235 <?php esc_html_e('Include:', 'essential-widgets'); ?>
236 <input type="text" class="widefat" name="<?php echo esc_attr($this->get_field_name('include')); ?>" value="<?php echo esc_attr($instance['include']); ?>" placeholder="1,2,3&hellip;" />
237 </label>
238 </p>
239
240 <p>
241 <label>
242 <?php esc_html_e('Exclude:', 'essential-widgets'); ?>
243 <input type="text" class="widefat" name="<?php echo esc_attr($this->get_field_name('exclude')); ?>" value="<?php echo esc_attr($instance['exclude']); ?>" placeholder="1,2,3&hellip;" />
244 </label>
245 </p>
246
247 <p class="button-primary ect-toggle-btn more">
248 <span class="ect-more-text"><?php esc_html_e('More Options', 'essential-widgets'); ?><i class="dashicons dashicons-arrow-down"></i></span>
249 <span class="ect-hide-text"><?php esc_html_e('Hide Options', 'essential-widgets'); ?><i class="dashicons dashicons-arrow-up"></i></span>
250
251 <div class="advanced-section">
252
253 <p>
254 <label>
255 <?php esc_html_e('Exclude Tree:', 'essential-widgets'); ?>
256 <input type="text" class="widefat" name="<?php echo esc_attr($this->get_field_name('exclude_tree')); ?>" value="<?php echo esc_attr($instance['exclude_tree']); ?>" placeholder="1,2,3&hellip;" />
257 </label>
258 </p>
259
260 <p>
261 <label>
262 <?php esc_html_e('Meta Key:', 'essential-widgets'); ?>
263
264 <select class="widefat" name="<?php echo esc_attr($this->get_field_name('meta_key')); ?>">
265
266 <?php foreach ($meta_key as $meta) : ?>
267
268 <option value="<?php echo esc_attr($meta); ?>" <?php selected($instance['meta_key'], $meta); ?>><?php echo esc_html($meta); ?></option>
269
270 <?php endforeach; ?>
271
272 </select>
273 </label>
274 </p>
275
276 <p>
277 <label>
278 <?php esc_html_e('Meta Value:', 'essential-widgets'); ?>
279 <input type="text" class="widefat" name="<?php echo esc_attr($this->get_field_name('meta_value')); ?>" value="<?php echo esc_attr($instance['meta_value']); ?>" />
280 </label>
281 </p>
282
283 <p>
284 <label>
285 <?php esc_html_e('Authors:', 'essential-widgets'); ?>
286 <input type="text" class="widefat" name="<?php echo esc_attr($this->get_field_name('authors')); ?>" value="<?php echo esc_attr($instance['authors']); ?>" placeholder="1,2,3&hellip;" />
287 </label>
288 </p>
289
290 <p>
291 <label>
292 <?php esc_html_e('Link Before:', 'essential-widgets'); ?>
293 <input type="text" class="widefat" name="<?php echo esc_attr($this->get_field_name('link_before')); ?>" value="<?php echo esc_attr($instance['link_before']); ?>" />
294 </label>
295 </p>
296
297 <p>
298 <label>
299 <?php esc_html_e('Link After:', 'essential-widgets'); ?>
300 <input type="text" class="widefat" name="<?php echo esc_attr($this->get_field_name('link_after')); ?>" value="<?php echo esc_attr($instance['link_after']); ?>" />
301 </label>
302 </p>
303
304 <p>
305 <label>
306 <?php esc_html_e('Show Date:', 'essential-widgets'); ?>
307
308 <select class="widefat" name="<?php echo esc_attr($this->get_field_name('show_date')); ?>">
309
310 <?php foreach ($show_date as $option_value => $option_label) : ?>
311
312 <option value="<?php echo esc_attr($option_value); ?>" <?php selected($instance['show_date'], $option_value); ?>><?php echo esc_html($option_label); ?></option>
313
314 <?php endforeach; ?>
315
316 </select>
317 </label>
318 </p>
319
320 <p>
321 <label>
322 <?php esc_html_e('Date Format:', 'essential-widgets'); ?>
323 <input type="text" class="widefat" name="<?php echo esc_attr($this->get_field_name('date_format')); ?>" value="<?php echo esc_attr($instance['date_format']); ?>" placeholder="<?php echo esc_attr(get_option('date_format')); ?>" />
324 </label>
325 </p>
326
327 <p>
328 <label>
329 <input type="checkbox" <?php checked($instance['hierarchical'], true); ?> name="<?php echo esc_attr($this->get_field_name('hierarchical')); ?>" />
330 <?php esc_html_e('Hierarchical?', 'essential-widgets'); ?>
331 </label>
332 </p>
333
334 </div><!-- .advanced-section -->
335
336 <div style="clear:both;">&nbsp;</div>
337 <?php
338 }
339
340 /**
341 * update the particular instant
342 *
343 * This function should check that $new_instance is set correctly.
344 * The newly calculated value of $instance should be returned.
345 * If "false" is returned, the instance won't be saved/updated.
346 *
347 * $new_instance New settings for this instance as input by the user via form()
348 * $old_instance Old settings for this instance
349 * Settings to save or bool false to cancel saving
350 */
351 public function update($new_instance, $old_instance)
352 {
353 $instance = $old_instance;
354
355 // Sanitize title.
356 $instance['title'] = sanitize_text_field($new_instance['title']);
357
358 // Strip tags.
359 $instance['meta_key'] = wp_strip_all_tags($new_instance['meta_key']); // phpcs:ignore WordPress.DB.SlowDBQuery.slow_db_query_meta_key -- Required wp_list_pages() parameter.
360 $instance['meta_value'] = wp_strip_all_tags($new_instance['meta_value']); // phpcs:ignore WordPress.DB.SlowDBQuery.slow_db_query_meta_value -- Required wp_list_pages() parameter.
361 $instance['date_format'] = wp_strip_all_tags($new_instance['date_format']);
362
363 // Sanitize key.
364 $instance['post_type'] = sanitize_key($new_instance['post_type']);
365
366 // Whitelist options.
367 $sort_order = array('ASC', 'DESC');
368 $sort_column = array('post_author', 'post_date', 'ID', 'menu_order', 'post_modified', 'post_name', 'post_title');
369 $show_date = array('', 'created', 'modified');
370
371 $instance['sort_column'] = in_array($new_instance['sort_column'], $sort_column, true) ? $new_instance['sort_column'] : 'post_title';
372 $instance['sort_order'] = in_array($new_instance['sort_order'], $sort_order, true) ? $new_instance['sort_order'] : 'ASC';
373 $instance['show_date'] = in_array($new_instance['show_date'], $show_date, true) ? $new_instance['show_date'] : '';
374
375 // Text boxes. Make sure user can use 'unfiltered_html'.
376 $instance['link_before'] = current_user_can('unfiltered_html') ? $new_instance['link_before'] : wp_kses_post($new_instance['link_before']);
377 $instance['link_after'] = current_user_can('unfiltered_html') ? $new_instance['link_after'] : wp_kses_post($new_instance['link_after']);
378
379 // Integers.
380 $instance['number'] = absint($new_instance['number']);
381 $instance['depth'] = absint($new_instance['depth']);
382 $instance['child_of'] = absint($new_instance['child_of']);
383 $instance['offset'] = absint($new_instance['offset']);
384
385 // Sanitize text field
386 $instance['include'] = sanitize_text_field($new_instance['include']);
387 $instance['exclude'] = sanitize_text_field($new_instance['exclude']); // phpcs:ignore WordPressVIPMinimum.Performance.WPQueryParams.PostNotIn_exclude -- Required wp_list_pages() parameter.
388 $instance['exclude_tree'] = sanitize_text_field($new_instance['exclude_tree']);
389 $instance['authors'] = sanitize_text_field($new_instance['authors']);
390
391 // Then restrict to numbers & commas
392 $instance['include'] = preg_replace('/[^0-9,]/', '', $new_instance['include']);
393 $instance['exclude'] = preg_replace('/[^0-9,]/', '', $new_instance['exclude']); // phpcs:ignore WordPressVIPMinimum.Performance.WPQueryParams.PostNotIn_exclude -- Required wp_list_pages() parameter.
394 $instance['exclude_tree'] = preg_replace('/[^0-9,]/', '', $new_instance['exclude_tree']);
395 $instance['authors'] = preg_replace('/[^0-9,]/', '', $new_instance['authors']);
396
397 // Checkboxes.
398 $instance['hierarchical'] = isset($new_instance['hierarchical']) ? 1 : 0;
399
400 // Return sanitized options.
401 return $instance;
402 }
403
404 /**
405 * Displays the Widget in the front-end.
406 *
407 * $args Display arguments including before_title, after_title, before_widget, and after_widget.
408 * $instance The settings for the particular instance of the widget
409 */
410 public function widget($args, $instance)
411 {
412 // Merge instance with defaults.
413 $instance = wp_parse_args($instance, $this->defaults);
414
415 // Escape widget wrapper attributes.
416 echo wp_kses_post($args['before_widget']);
417
418 // If a title was input by the user, display it safely.
419 if (! empty($instance['title'])) {
420 echo wp_kses_post($args['before_title']);
421
422 // Apply filters to title, then escape it for output
423 $title = apply_filters('widget_title', $instance['title'], $instance, $this->id_base);
424 echo esc_html($title);
425
426 echo wp_kses_post($args['after_title']);
427 }
428
429 // Output the main content of the widget (shortcode output)
430 echo wp_kses_post($this->shortcode($instance));
431
432 // Close the widget wrapper safely.
433 echo wp_kses_post($args['after_widget']);
434 }
435
436 public function shortcode($atts)
437 {
438 // Set the $title_li and $echo to false.
439 $atts['title_li'] = false;
440 $atts['echo'] = false;
441
442 $ew_pages = '';
443
444 // Only show this title in block element and not on widget.
445 if (isset($atts['is_block']) && true === $atts['is_block'] && !empty($atts['title'])) {
446 $ew_pages .= '<h2 class="ew-page-block-title">' . esc_html($atts['title']) . '</h2>';
447 }
448
449 // Output the page list.
450 $ew_pages .= '<ul class="pages">' . str_replace(
451 array("\r", "\n", "\t"),
452 '',
453 wp_list_pages($atts)
454 ) . '</ul>';
455
456 return wp_kses_post($ew_pages);
457 }
458 }
459 endif;
460
461
462 if (! function_exists('ew_pages_register')) :
463 /**
464 * Intiate About_Widget Class.
465 *
466 * @since 1.0.0
467 */
468 function ew_pages_register()
469 { // phpcs:ignore WordPress.NamingConventions.PrefixAllGlobals.NonPrefixedFunctionFound -- ew_ is this plugin's abbreviated prefix.
470 register_widget('EW_Pages');
471 }
472 add_action('widgets_init', 'ew_pages_register');
473 endif;
474