PluginProbe
WebberZone Top 10 — Popular Posts / trunk
WebberZone Top 10 — Popular Posts vtrunk
4.5.0 4.4.3 4.4.2 4.4.1 4.4.0 4.3.4 4.3.3 4.3.2 4.3.1 4.3.0 trunk 1.0 1.0.1 1.1 1.2 1.3 1.4 1.4.1 1.5 1.5.1 1.5.2 1.5.3 1.6 1.6.1 1.6.2 All 116 releases
top-10 / includes / admin / class-settings.php

class-settings.php in WebberZone Top 10 — Popular Posts trunk, at includes/admin/class-settings.php

2,171 lines 84.4 KB
No matching file
Up and down to move Enter to open Esc to close
Raw Download Zip
1 <?php
2 /**
3 * Settings class.
4 *
5 * @package WebberZone\Top_Ten\Admin
6 */
7
8 namespace WebberZone\Top_Ten\Admin;
9
10 use WebberZone\Top_Ten\Admin\Settings\Settings_API;
11 use WebberZone\Top_Ten\Admin\Settings\Settings_Sanitize;
12 use WebberZone\Top_Ten\Frontend\Display;
13 use WebberZone\Top_Ten\Frontend\Media_Handler;
14 use WebberZone\Top_Ten\Util\Helpers;
15 use WebberZone\Top_Ten\Util\Hook_Registry;
16
17 // If this file is called directly, abort.
18 if ( ! defined( 'WPINC' ) ) {
19 die;
20 }
21
22 /**
23 * Class to register the settings.
24 *
25 * @since 3.3.0
26 */
27 class Settings {
28
29
30 /**
31 * Settings API.
32 *
33 * @since 3.3.0
34 *
35 * @var Settings_API Settings API.
36 */
37 public $settings_api;
38
39 /**
40 * Statistics table.
41 *
42 * @since 3.3.0
43 *
44 * @var object Statistics table.
45 */
46 public $statistics;
47
48 /**
49 * Prefix which is used for creating the unique filters and actions.
50 *
51 * @since 3.3.0
52 *
53 * @var string Prefix.
54 */
55 public static $prefix = 'tptn';
56
57 /**
58 * Settings Key.
59 *
60 * @since 3.3.0
61 *
62 * @var string Settings Key.
63 */
64 public $settings_key = 'tptn_settings';
65
66 /**
67 * The slug name to refer to this menu by (should be unique for this menu).
68 *
69 * @since 3.3.0
70 *
71 * @var string Menu slug.
72 */
73 public $menu_slug = 'tptn_options_page';
74
75 /**
76 * Main constructor class.
77 *
78 * @since 3.3.0
79 */
80 public function __construct() {
81 Hook_Registry::add_action( 'admin_menu', array( $this, 'initialise_settings' ) );
82 Hook_Registry::add_filter( 'plugin_row_meta', array( $this, 'plugin_row_meta' ), 11, 2 );
83 Hook_Registry::add_filter( 'plugin_action_links_' . plugin_basename( TOP_TEN_PLUGIN_FILE ), array( $this, 'plugin_actions_links' ) );
84 Hook_Registry::add_filter( 'admin_enqueue_scripts', array( $this, 'admin_enqueue_scripts' ), 99 );
85 Hook_Registry::add_filter( self::$prefix . '_settings_sanitize', array( $this, 'change_settings_on_save' ), 99 );
86 Hook_Registry::add_filter( self::$prefix . '_after_setting_output', array( $this, 'display_admin_thumbnail' ), 10, 2 );
87 Hook_Registry::add_filter( self::$prefix . '_setting_field_description', array( $this, 'reset_default_thumb_setting' ), 10, 2 );
88 Hook_Registry::add_filter( self::$prefix . '_settings_page_header', array( $this, 'settings_page_header' ) );
89 Hook_Registry::add_filter( self::$prefix . '_after_setting_output', array( $this, 'after_setting_output' ), 10, 2 );
90 Hook_Registry::add_action( self::$prefix . '_settings_form_buttons', array( $this, 'add_wizard_button' ) );
91
92 Hook_Registry::add_action( 'wp_ajax_nopriv_' . self::$prefix . '_taxonomy_search_tom_select', array( __CLASS__, 'taxonomy_search_tom_select' ) );
93 Hook_Registry::add_action( 'wp_ajax_' . self::$prefix . '_taxonomy_search_tom_select', array( __CLASS__, 'taxonomy_search_tom_select' ) );
94 }
95
96 /**
97 * Initialise the settings API.
98 *
99 * @since 3.3.0
100 */
101 public function initialise_settings() {
102 $props = array(
103 'default_tab' => 'features',
104 'help_sidebar' => $this->get_help_sidebar(),
105 'help_tabs' => $this->get_help_tabs(),
106 'admin_footer_text' => $this->get_admin_footer_text(),
107 'menus' => $this->get_menus(),
108 'version' => TOP_TEN_VERSION,
109 );
110
111 $args = array(
112 'props' => $props,
113 'translation_strings' => $this->get_translation_strings(),
114 'settings_sections' => $this->get_settings_sections(),
115 'registered_settings' => $this->get_registered_settings(),
116 'upgraded_settings' => array(),
117 );
118
119 $this->settings_api = new Settings_API( $this->settings_key, self::$prefix, $args );
120 }
121
122 /**
123 * Array containing the settings' sections.
124 *
125 * @since 1.8.0
126 *
127 * @return array Settings array
128 */
129 public function get_translation_strings() {
130 $strings = array(
131 'page_header' => esc_html__( 'Top 10 Settings', 'top-10' ),
132 'reset_message' => esc_html__( 'Settings have been reset to their default values. Reload this page to view the updated settings.', 'top-10' ),
133 'success_message' => esc_html__( 'Settings updated.', 'top-10' ),
134 'save_changes' => esc_html__( 'Save Changes', 'top-10' ),
135 'reset_settings' => esc_html__( 'Reset all settings', 'top-10' ),
136 'reset_button_confirm' => esc_html__( 'Do you really want to reset all these settings to their default values?', 'top-10' ),
137 'modified_field' => esc_html__( 'Modified from default setting', 'top-10' ),
138 'modified_legend' => esc_html__( 'Setting modified from its default value', 'top-10' ),
139 'default_label' => esc_html__( 'Default', 'top-10' ),
140 'default_none' => esc_html__( 'None', 'top-10' ),
141 );
142
143 /**
144 * Filter the array containing the settings' sections.
145 *
146 * @since 1.8.0
147 *
148 * @param array $strings Translation strings.
149 */
150 return apply_filters( self::$prefix . '_translation_strings', $strings );
151 }
152
153 /**
154 * Get the admin menus.
155 *
156 * @return array Admin menus.
157 */
158 public function get_menus() {
159 $menus = array();
160
161 // Settings menu.
162 $menus[] = array(
163 'settings_page' => true,
164 'type' => 'submenu',
165 'parent_slug' => 'tptn_dashboard',
166 'page_title' => esc_html__( 'Top 10 Settings', 'top-10' ),
167 'menu_title' => esc_html__( 'Settings', 'top-10' ),
168 'menu_slug' => $this->menu_slug,
169 );
170
171 return $menus;
172 }
173
174 /**
175 * Array containing the settings' sections.
176 *
177 * @since 3.3.0
178 *
179 * @return array Settings array
180 */
181 public static function get_settings_sections() {
182 $settings_sections = array(
183 'features' => __( 'Features', 'top-10' ),
184 'general' => __( 'General', 'top-10' ),
185 'counter' => __( 'Counter/Tracker', 'top-10' ),
186 'list' => __( 'Posts list', 'top-10' ),
187 'thumbnail' => __( 'Thumbnail', 'top-10' ),
188 'styles' => __( 'Styles', 'top-10' ),
189 'maintenance' => __( 'Maintenance', 'top-10' ),
190 'feed' => __( 'Feed', 'top-10' ),
191 );
192
193 /**
194 * Filter the array containing the settings' sections.
195 *
196 * @since 1.2.0
197 *
198 * @param array $settings_sections Settings array
199 */
200 return apply_filters( self::$prefix . '_settings_sections', $settings_sections );
201 }
202
203
204 /**
205 * Raw defaults for every registered setting, keyed by option ID.
206 *
207 * Must exactly match what `tptn_settings_defaults()` computes from
208 * {@see self::get_registered_settings()}, but without building the full
209 * (translated) field definitions. Values are pre-normalized: checkboxes are
210 * `1`/`0`, not `true`/`false`. Computed defaults (e.g. `thumb_default`) are
211 * represented as `''` here since their real value cannot be known statically.
212 *
213 * @since 4.4.2
214 *
215 * @return array<string, mixed> Default value for every option ID.
216 */
217 public static function get_defaults() {
218 return array(
219 'features_header' => '',
220 'features_display_header' => '',
221 'enable_blocks' => 1,
222 'enable_legacy_widgets' => 1,
223 'enable_query_block' => 1,
224 'enable_featured_image_block' => 1,
225 'enable_popular_posts_pro_block' => 1,
226 'enable_page_builders' => 1,
227 'enable_popular_authors' => 1,
228 'features_tracking_header' => '',
229 'enable_feed' => 1,
230 'enable_fast_tracker' => 1,
231 'enable_sitewide_tracking' => 1,
232 'features_data_header' => '',
233 'enable_daily_table_rollup' => 1,
234 'features_admin_header' => '',
235 'enable_pro_dashboard_widgets' => 1,
236 'cache' => 1,
237 'cache_time' => HOUR_IN_SECONDS,
238 'lazy_load' => 0,
239 'uninstall_clean_options' => 1,
240 'uninstall_clean_tables' => 0,
241 'show_credit' => 0,
242 'admin_header' => '',
243 'show_metabox' => 1,
244 'show_metabox_admins' => 0,
245 'pv_in_admin' => 1,
246 'admin_column_post_types' => 'post,page',
247 'show_count_non_admins' => 1,
248 'show_dashboard_to_roles' => 'administrator',
249 'show_admin_bar' => 1,
250 'query_optimization' => '',
251 'max_execution_time' => 3000,
252 'counter_header' => '',
253 'add_to' => 'single,page',
254 'count_disp_form' => 'Visited %totalcount% times, %dailycount% visit(s) today',
255 'count_disp_form_zero' => 'No visits yet',
256 'number_format_count' => 1,
257 'number_format_style' => 'full',
258 'daily_midnight' => 1,
259 'range_desc' => '',
260 'daily_range' => '1',
261 'hour_range' => '0',
262 'dynamic_post_count' => 0,
263 'exclude_on_post_ids' => '',
264 'tracker_header' => '',
265 'trackers' => 'overall,daily',
266 'tracker_type' => 'query_based',
267 'tracking_method' => 'funnel',
268 'tracker_all_pages' => 0,
269 'track_sitewide' => 0,
270 'track_feed_views' => 0,
271 'track_users' => 'authors,editors,admins',
272 'logged_in' => 1,
273 'no_bots' => 0,
274 'debug_mode' => 0,
275 'use_global_settings' => 0,
276 'limit' => '10',
277 'how_old' => '0',
278 'post_types' => 'post',
279 'exclusion_header' => '',
280 'exclude_front' => 0,
281 'exclude_current_post' => 0,
282 'exclude_post_ids' => '',
283 'exclude_cat_slugs' => '',
284 'exclude_categories' => '',
285 'exclude_terms_include_parents' => 'none',
286 'exclude_on_cat_slugs' => '',
287 'customize_output_header' => '',
288 'title' => '<h3>Popular posts:</h3>',
289 'title_daily' => '<h3>Currently trending:</h3>',
290 'blank_output' => 'blank',
291 'blank_output_text' => 'No top posts yet',
292 'show_excerpt' => 0,
293 'excerpt_length' => '10',
294 'show_date' => 0,
295 'show_author' => 0,
296 'disp_list_count' => 0,
297 'show_ratings' => '',
298 'title_length' => '60',
299 'link_new_window' => 0,
300 'link_nofollow' => 0,
301 'html_wrapper_header' => '',
302 'before_list' => '<ul>',
303 'after_list' => '</ul>',
304 'before_list_item' => '<li>',
305 'after_list_item' => '</li>',
306 'post_thumb_op' => 'text_only',
307 'thumb_size' => 'tptn_thumbnail',
308 'thumb_width' => '250',
309 'thumb_height' => '250',
310 'thumb_crop' => 1,
311 'thumb_create_sizes' => 1,
312 'thumb_html' => 'html',
313 'thumb_meta' => 'post-image',
314 'scan_images' => 1,
315 'thumb_default_show' => 1,
316 'thumb_default' => '',
317 'tptn_styles' => 'no_style',
318 'custom_css' => '',
319 'cron_on' => 0,
320 'maintenance_days' => 0,
321 'log_retention_days' => 0,
322 'cron_range_desc' => '',
323 'cron_hour' => '0',
324 'cron_min' => '0',
325 'cron_recurrence' => 'weekly',
326 'feed_permalink_overall' => 'popular-posts',
327 'feed_permalink_daily' => 'popular-posts-daily',
328 'feed_limit' => '10',
329 'feed_daily_range' => '1',
330 'feed_category_slugs' => '',
331 'wzpa_number' => 10,
332 'wzpa_daily_range' => 1,
333 'wzpa_hour_range' => 0,
334 'wzpa_optioncount' => 0,
335 'wzpa_show_postcount' => 0,
336 'wzpa_show_fullname' => 0,
337 'wzpa_show_avatar' => 0,
338 'wzpa_exclude_admin' => 0,
339 'wzpa_post_type' => 'post',
340 'wzpa_cache' => 1,
341 'wzpa_styles_desc' => '',
342 'wzpa_styles' => 'no_style',
343 'wzpa_html_wrapper_header' => '',
344 'wzpa_before_list' => '<ul>',
345 'wzpa_after_list' => '</ul>',
346 'wzpa_before_list_item' => '<li>',
347 'wzpa_after_list_item' => '</li>',
348 );
349 }
350
351 /**
352 * Retrieve the array of plugin settings
353 *
354 * @since 3.3.0
355 *
356 * @return array Settings array
357 */
358 public static function get_registered_settings() {
359 $settings = array();
360 $sections = self::get_settings_sections();
361
362 foreach ( $sections as $section => $value ) {
363 $method_name = 'settings_' . $section;
364 if ( method_exists( __CLASS__, $method_name ) ) {
365 $settings[ $section ] = self::$method_name();
366 }
367 }
368
369 /**
370 * Filters the settings array
371 *
372 * @since 1.2.0
373 *
374 * @param array $tptn_setings Settings array
375 */
376 return apply_filters( self::$prefix . '_registered_settings', $settings );
377 }
378
379 /**
380 * Retrieve the array of General settings
381 *
382 * @since 3.3.0
383 *
384 * @return array General settings array
385 */
386 public static function settings_general() {
387 $settings = array(
388 'cache' => array(
389 'id' => 'cache',
390 'name' => esc_html__( 'Enable cache', 'top-10' ),
391 'desc' => esc_html__( 'If activated, Top 10 will use the Transients API to cache the popular posts output for the time specified below.', 'top-10' ),
392 'type' => 'checkbox',
393 'default' => true,
394 ),
395 'cache_time' => array(
396 'id' => 'cache_time',
397 'name' => esc_html__( 'Time to cache', 'top-10' ),
398 'desc' => esc_html__( 'Enter the number of seconds to cache the output.', 'top-10' ),
399 'type' => 'text',
400 'default' => HOUR_IN_SECONDS,
401 ),
402 'lazy_load' => array(
403 'id' => 'lazy_load',
404 'name' => esc_html__( 'Lazy load popular posts', 'top-10' ),
405 'desc' => esc_html__( 'Load popular posts using JavaScript when the list is about to enter the viewport. This speeds up initial page loads and lets full-page caches serve fresh lists. Search engines may not index links loaded this way. Applies to content, shortcodes, widgets and the Popular Posts block. Use lazy_load="0" in the shortcode or block attributes to disable it per instance. Not applied on feeds or AMP pages.', 'top-10' ),
406 'type' => 'checkbox',
407 'default' => false,
408 'pro' => true,
409 ),
410 'uninstall_clean_options' => array(
411 'id' => 'uninstall_clean_options',
412 'name' => esc_html__( 'Delete options on uninstall', 'top-10' ),
413 'desc' => esc_html__( 'If this is checked, all settings related to Top 10 are removed from the database if you choose to uninstall/delete the plugin.', 'top-10' ),
414 'type' => 'checkbox',
415 'default' => true,
416 ),
417 'uninstall_clean_tables' => array(
418 'id' => 'uninstall_clean_tables',
419 'name' => esc_html__( 'Delete counter data on uninstall', 'top-10' ),
420 'desc' => esc_html__( 'If this is checked, the tables containing the counter statistics are removed from the database if you choose to uninstall/delete the plugin. Keep this unchecked if you choose to reinstall the plugin and do not want to lose your counter data.', 'top-10' ),
421 'type' => 'checkbox',
422 'default' => false,
423 ),
424 'show_credit' => array(
425 'id' => 'show_credit',
426 'name' => esc_html__( 'Link to Top 10 plugin page', 'top-10' ),
427 'desc' => esc_html__( 'A no-follow link to the plugin homepage will be added as the last item of the popular posts.', 'top-10' ),
428 'type' => 'checkbox',
429 'default' => false,
430 ),
431 'admin_header' => array(
432 'id' => 'admin_header',
433 'name' => '<h3>' . esc_html__( 'Admin settings', 'top-10' ) . '</h3>',
434 'desc' => '',
435 'type' => 'header',
436 ),
437 'show_metabox' => array(
438 'id' => 'show_metabox',
439 'name' => esc_html__( 'Show metabox', 'top-10' ),
440 'desc' => esc_html__( 'This will add the Top 10 metabox on Edit Posts or Add New Posts screens. Also applies to Pages and Custom Post Types.', 'top-10' ),
441 'type' => 'checkbox',
442 'default' => true,
443 ),
444 'show_metabox_admins' => array(
445 'id' => 'show_metabox_admins',
446 'name' => esc_html__( 'Limit meta box to Admins', 'top-10' ),
447 'desc' => esc_html__( 'If selected, the meta box will be hidden from anyone who is not an Admin. By default, Contributors and above will be able to see the meta box. Applies only if the above option is selected.', 'top-10' ),
448 'type' => 'checkbox',
449 'default' => false,
450 ),
451 'pv_in_admin' => array(
452 'id' => 'pv_in_admin',
453 'name' => esc_html__( 'Display admin columns', 'top-10' ),
454 /* translators: %s: Custom period label (e.g. Daily, Custom (7 days)). */
455 'desc' => sprintf( esc_html__( 'Adds three columns called Total Views, %s Views and Views. You can selectively disable these by pulling down the Screen Options from the top right of the respective screens.', 'top-10' ), Helpers::get_daily_range_label() ),
456 'type' => 'checkbox',
457 'default' => true,
458 ),
459 'admin_column_post_types' => array(
460 'id' => 'admin_column_post_types',
461 'name' => esc_html__( 'Display columns on post types', 'top-10' ),
462 'desc' => esc_html__( 'Select which post types to display the admin columns. Unselect the above option if you would like to disable the columns.', 'top-10' ),
463 'type' => 'posttypes',
464 'default' => 'post,page',
465 'pro' => true,
466 ),
467 'show_count_non_admins' => array(
468 'id' => 'show_count_non_admins',
469 'name' => esc_html__( 'Show views to non-admins', 'top-10' ),
470 'desc' => esc_html__( "If you disable this then non-admins won't see the above columns or view the independent pages with the top posts.", 'top-10' ),
471 'type' => 'checkbox',
472 'default' => true,
473 ),
474 'show_dashboard_to_roles' => array(
475 'id' => 'show_dashboard_to_roles',
476 'name' => esc_html__( 'Also show dashboard to', 'top-10' ),
477 'desc' => esc_html__( 'Choose the user roles that should have access to the Top 10 dashboard, which showcases popular posts over time. These roles are linked to specific capabilities, and selecting a lower role will automatically grant access to higher roles.', 'top-10' ),
478 'type' => 'multicheck',
479 'default' => 'administrator',
480 'options' => self::get_user_roles( array( 'administrator' ) ),
481 'pro' => true,
482 ),
483 'show_admin_bar' => array(
484 'id' => 'show_admin_bar',
485 'name' => esc_html__( 'Show Admin Bar menu', 'top-10' ),
486 'desc' => esc_html__( 'Display the Top 10 menu in the WordPress admin bar with quick access to popular posts stats and tools.', 'top-10' ),
487 'type' => 'checkbox',
488 'default' => true,
489 'pro' => true,
490 ),
491 'query_optimization' => array(
492 'id' => 'query_optimization',
493 'name' => '<h3>' . esc_html__( 'Query Optimization', 'top-10' ) . '</h3>',
494 'desc' => esc_html__( 'Settings for optimizing database queries', 'top-10' ),
495 'type' => 'header',
496 ),
497 'max_execution_time' => array(
498 'id' => 'max_execution_time',
499 'name' => esc_html__( 'Max Execution Time', 'top-10' ),
500 'desc' => esc_html__( 'Maximum execution time for MySQL queries in milliseconds. Set to 0 to disable. Default is 3000 (3 seconds).', 'top-10' ),
501 'type' => 'number',
502 'default' => 3000,
503 'min' => 0,
504 'step' => 100,
505 'pro' => true,
506 ),
507 );
508
509 /**
510 * Filters the General settings array
511 *
512 * @since 3.3.0
513 *
514 * @param array $settings General settings array
515 */
516 return apply_filters( self::$prefix . '_settings_general', $settings );
517 }
518
519
520 /**
521 * Retrieve the array of Counter settings
522 *
523 * @since 3.3.0
524 *
525 * @return array Counter settings array
526 */
527 public static function settings_counter() {
528 $settings = array(
529 'counter_header' => array(
530 'id' => 'counter_header',
531 'name' => '<h3>' . esc_html__( 'Counter settings', 'top-10' ) . '</h3>',
532 'desc' => '',
533 'type' => 'header',
534 ),
535 'add_to' => array(
536 'id' => 'add_to',
537 'name' => esc_html__( 'Display number of views on', 'top-10' ) . ':',
538 /* translators: 1: Code. */
539 'desc' => sprintf( esc_html__( 'If you choose to disable this, please add the following code to your template file where you want it displayed: %1$s', 'top-10' ), "<code>&lt;?php if ( function_exists( 'echo_tptn_post_count' ) ) { echo_tptn_post_count(); } ?&gt;</code>" ),
540 'type' => 'multicheck',
541 'default' => 'single,page',
542 'options' => array(
543 'single' => esc_html__( 'Posts', 'top-10' ),
544 'page' => esc_html__( 'Pages', 'top-10' ),
545 'home' => esc_html__( 'Home page', 'top-10' ),
546 'feed' => esc_html__( 'Feeds', 'top-10' ),
547 'category_archives' => esc_html__( 'Category archives', 'top-10' ),
548 'tag_archives' => esc_html__( 'Tag archives', 'top-10' ),
549 'other_archives' => esc_html__( 'Other archives', 'top-10' ),
550 ),
551 ),
552 'count_disp_form' => array(
553 'id' => 'count_disp_form',
554 'name' => esc_html__( 'Format to display the post views', 'top-10' ),
555 /* translators: 1: Opening a tag, 2: Closing a tag, 3: Opening code tage, 4. Closing code tag. */
556 'desc' => sprintf( esc_html__( 'Use %1$s to display the total count, %2$s for daily count and %3$s for overall counts across all posts. Default display is %4$s', 'top-10' ), '<code>%totalcount%</code>', '<code>%dailycount%</code>', '<code>%overallcount%</code>', '<code>Visited %totalcount% times, %dailycount% visit(s) today</code>' ),
557 'type' => 'textarea',
558 'default' => 'Visited %totalcount% times, %dailycount% visit(s) today',
559 ),
560 'count_disp_form_zero' => array(
561 'id' => 'count_disp_form_zero',
562 'name' => esc_html__( 'No visits text', 'top-10' ),
563 'desc' => esc_html__( "This text is displayed when there are no hits for the post and it isn't a single page. For example, if you display post views on the Homepage or Archives, this text will be used. To override this, simply enter the same text as the above option.", 'top-10' ),
564 'type' => 'textarea',
565 'default' => 'No visits yet',
566 ),
567 'number_format_count' => array(
568 'id' => 'number_format_count',
569 'name' => esc_html__( 'Number format post count', 'top-10' ),
570 'desc' => esc_html__( 'Activating this option will convert the post counts into a number format based on the locale', 'top-10' ),
571 'type' => 'checkbox',
572 'default' => true,
573 ),
574 'number_format_style' => array(
575 'id' => 'number_format_style',
576 'name' => esc_html__( 'Number format style', 'top-10' ),
577 'desc' => esc_html__( 'Select Abbreviated to display large view counts in a compact form, e.g. 1.2k or 3.4M, wherever counts are displayed. Full displays the complete number.', 'top-10' ),
578 'type' => 'select',
579 'default' => 'full',
580 'options' => array(
581 'full' => esc_html__( 'Full', 'top-10' ),
582 'abbreviated' => esc_html__( 'Abbreviated (1.2k, 3.4M)', 'top-10' ),
583 ),
584 ),
585 'daily_midnight' => array(
586 'id' => 'daily_midnight',
587 'name' => esc_html__( 'Start daily counts at midnight', 'top-10' ),
588 'desc' => esc_html__( 'The daily counter displays visits starting at midnight. This option is enabled by default, similar to most standard counters. If you disable this option, you can use the hourly setting in the next option.', 'top-10' ),
589 'type' => 'checkbox',
590 'default' => true,
591 ),
592 'range_desc' => array(
593 'id' => 'range_desc',
594 'name' => esc_html__( 'Default custom period range', 'top-10' ),
595 'desc' => esc_html__( 'The following two options let you set the default range for the custom period. This can be overridden in the widget settings.', 'top-10' ),
596 'type' => 'descriptive_text',
597 ),
598 'daily_range' => array(
599 'id' => 'daily_range',
600 'name' => esc_html__( 'Day(s)', 'top-10' ),
601 'desc' => '',
602 'type' => 'number',
603 'default' => '1',
604 'min' => '0',
605 'size' => 'small',
606 ),
607 'hour_range' => array(
608 'id' => 'hour_range',
609 'name' => esc_html__( 'Hour(s)', 'top-10' ),
610 'desc' => '',
611 'type' => 'number',
612 'default' => '0',
613 'min' => '0',
614 'max' => '23',
615 'size' => 'small',
616 ),
617 'dynamic_post_count' => array(
618 'id' => 'dynamic_post_count',
619 'name' => esc_html__( 'Always display latest post count', 'top-10' ),
620 'desc' => esc_html__( 'This option uses JavaScript and will increase your page load time. Turn this off if you are not using caching plugins or are OK with displaying older cached counts.', 'top-10' ),
621 'type' => 'checkbox',
622 'default' => false,
623 ),
624 'exclude_on_post_ids' => array(
625 'id' => 'exclude_on_post_ids',
626 'name' => esc_html__( 'Exclude display on these post IDs', 'top-10' ),
627 'desc' => esc_html__( 'Comma-separated list of post or page IDs to exclude displaying the top posts on. e.g. 188,320,500', 'top-10' ),
628 'type' => 'numbercsv',
629 'default' => '',
630 ),
631 'tracker_header' => array(
632 'id' => 'tracker_header',
633 'name' => '<h3>' . esc_html__( 'Tracker settings', 'top-10' ) . '</h3>',
634 'desc' => '',
635 'type' => 'header',
636 ),
637 'trackers' => array(
638 'id' => 'trackers',
639 'name' => esc_html__( 'Enable trackers', 'top-10' ),
640 /* translators: 1: Code. */
641 'desc' => esc_html__( 'Top 10 tracks hits in two tables in the database. The overall table only tracks the total hits per post. The daily table tracks hits per post on an hourly basis.', 'top-10' ),
642 'type' => 'multicheck',
643 'default' => 'overall,daily',
644 'options' => array(
645 'overall' => esc_html__( 'Overall', 'top-10' ),
646 'daily' => esc_html__( 'Daily range', 'top-10' ),
647 ),
648 ),
649 'tracker_type' => array(
650 'id' => 'tracker_type',
651 'name' => esc_html__( 'Tracker type', 'top-10' ),
652 'desc' => '',
653 'type' => 'radiodesc',
654 'default' => 'query_based',
655 'options' => self::get_tracker_types(),
656 ),
657 'tracking_method' => array(
658 'id' => 'tracking_method',
659 'name' => esc_html__( 'Tracking method', 'top-10' ),
660 'desc' => esc_html__( 'Funnel tracking buffers views in a staging table that is merged into the count tables by a background job every few minutes and is recommended for most sites. Switch to Legacy tracking if view counts are not updating on your site, e.g. when WP-Cron is disabled or unreliable. Legacy tracking does not populate the visits log table.', 'top-10' ),
661 'type' => 'radiodesc',
662 'default' => 'funnel',
663 'options' => self::get_tracking_methods(),
664 ),
665 'tracker_all_pages' => array(
666 'id' => 'tracker_all_pages',
667 'name' => esc_html__( 'Load tracker on all pages', 'top-10' ),
668 'desc' => esc_html__( 'This will load the tracker js on all pages. Helpful if you are running minification/concatenation plugins.', 'top-10' ),
669 'type' => 'checkbox',
670 'default' => false,
671 ),
672 'track_sitewide' => array(
673 'id' => 'track_sitewide',
674 'name' => esc_html__( 'Track site-wide views', 'top-10' ),
675 'desc' => esc_html__( 'Track views for the front page, posts page, archives, and search results in addition to individual posts and pages. Site-wide contexts use fixed reserved IDs in the shared Top 10 tables: front page = PHP_INT_MAX; home page = PHP_INT_MAX - 1; search = PHP_INT_MAX - 2; category = PHP_INT_MAX - 4; tag = PHP_INT_MAX - 5; taxonomy = PHP_INT_MAX - 6; author = PHP_INT_MAX - 7; post type archive = PHP_INT_MAX - 8; date archive = PHP_INT_MAX - 9; archive = PHP_INT_MAX - 10; other = PHP_INT_MAX - 11. These IDs are the same on every site and counts remain separate by site (blog ID).', 'top-10' ),
676 'type' => 'checkbox',
677 'default' => false,
678 'pro' => true,
679 ),
680 'track_feed_views' => array(
681 'id' => 'track_feed_views',
682 'name' => esc_html__( 'Track feed views', 'top-10' ),
683 'desc' => esc_html__( 'Count post views from RSS/Atom feed readers via a tracking pixel. Views are added to the post\'s regular view count. Note: some feed readers block remote images by default; views are only counted when the reader loads images.', 'top-10' ),
684 'type' => 'checkbox',
685 'default' => false,
686 'pro' => true,
687 ),
688 'track_users' => array(
689 'id' => 'track_users',
690 'name' => esc_html__( 'Track user groups', 'top-10' ) . ':',
691 'desc' => esc_html__( 'Uncheck above to disable tracking if the current user falls into any one of these groups.', 'top-10' ),
692 'type' => 'multicheck',
693 'default' => 'authors,editors,admins',
694 'options' => array(
695 'authors' => esc_html__( 'Authors', 'top-10' ),
696 'editors' => esc_html__( 'Editors', 'top-10' ),
697 'admins' => esc_html__( 'Admins', 'top-10' ),
698 ),
699 ),
700 'logged_in' => array(
701 'id' => 'logged_in',
702 'name' => esc_html__( 'Track logged-in users', 'top-10' ),
703 'desc' => esc_html__( 'Uncheck to stop tracking logged in users. Only logged out visitors will be tracked if this is disabled. Unchecking this will override the above setting.', 'top-10' ),
704 'type' => 'checkbox',
705 'default' => true,
706 ),
707 'no_bots' => array(
708 'id' => 'no_bots',
709 'name' => esc_html__( 'Do not track bots', 'top-10' ),
710 'desc' => esc_html__( 'Enable this if you want Top 10 to attempt to stop tracking bots. The plugin includes a comprehensive set of known bot user agents but in some cases this might not be enough to stop tracking bots.', 'top-10' ),
711 'type' => 'checkbox',
712 'default' => false,
713 ),
714 'debug_mode' => array(
715 'id' => 'debug_mode',
716 'name' => esc_html__( 'Debug mode', 'top-10' ),
717 'desc' => esc_html__( 'Setting this to true will force the tracker to display an output in the browser. This is useful if you are having issues and are seeking support.', 'top-10' ),
718 'type' => 'checkbox',
719 'default' => false,
720 ),
721 );
722
723 /**
724 * Filters the Counter settings array
725 *
726 * @since 3.3.0
727 *
728 * @param array $settings Counter settings array
729 */
730 return apply_filters( self::$prefix . '_settings_counter', $settings );
731 }
732
733
734 /**
735 * Retrieve the array of List settings
736 *
737 * @since 3.3.0
738 *
739 * @return array List settings array
740 */
741 public static function settings_list() {
742 $settings = array(
743 'use_global_settings' => array(
744 'id' => 'use_global_settings',
745 'name' => esc_html__( 'Use global settings in block', 'top-10' ),
746 'desc' => esc_html__( 'If activated, the settings from this page are automatically inserted in the Popular Posts block. This also applies to existing blocks which do not have any attributes set if the post is edited.', 'top-10' ),
747 'type' => 'checkbox',
748 'default' => false,
749 'pro' => true,
750 ),
751 'limit' => array(
752 'id' => 'limit',
753 'name' => esc_html__( 'Number of posts to display', 'top-10' ),
754 'desc' => esc_html__( 'Maximum number of posts that will be displayed in the list. This option is used if you do not specify the number of posts in the widget or shortcodes', 'top-10' ),
755 'type' => 'number',
756 'default' => '10',
757 'size' => 'small',
758 ),
759 'how_old' => array(
760 'id' => 'how_old',
761 'name' => esc_html__( 'Published age of posts', 'top-10' ),
762 'desc' => esc_html__( 'This options allows you to only show posts that have been published within the above day range. Applies to both overall posts and daily posts lists. e.g. 365 days will only show posts published in the last year in the popular posts lists. Enter 0 for no restriction.', 'top-10' ),
763 'type' => 'number',
764 'default' => '0',
765 'size' => 'small',
766 ),
767 'post_types' => array(
768 'id' => 'post_types',
769 'name' => esc_html__( 'Post types to include', 'top-10' ),
770 'desc' => esc_html__( 'At least one option should be selected above. Select which post types you want to include in the list of posts. This field can be overridden using a comma separated list of post types when using the manual display.', 'top-10' ),
771 'type' => 'posttypes',
772 'default' => 'post',
773 ),
774 'exclusion_header' => array(
775 'id' => 'exclusion_header',
776 'name' => '<h3>' . esc_html__( 'Exclusion settings', 'top-10' ) . '</h3>',
777 'desc' => '',
778 'type' => 'header',
779 ),
780 'exclude_front' => array(
781 'id' => 'exclude_front',
782 'name' => esc_html__( 'Exclude Front page and Posts page', 'top-10' ),
783 'desc' => esc_html__( 'If you have designated specific pages for your Front page and Posts page via Settings > Reading, they will be tracked like any other page. Enable this option to exclude them from appearing in the popular posts lists. Note that tracking will still occur.', 'top-10' ),
784 'type' => 'checkbox',
785 'default' => false,
786 ),
787 'exclude_current_post' => array(
788 'id' => 'exclude_current_post',
789 'name' => esc_html__( 'Exclude current post', 'top-10' ),
790 'desc' => esc_html__( 'Enabling this will exclude the current post being browsed from being displayed in the popular posts list.', 'top-10' ),
791 'type' => 'checkbox',
792 'default' => false,
793 ),
794 'exclude_post_ids' => array(
795 'id' => 'exclude_post_ids',
796 'name' => esc_html__( 'Post/page IDs to exclude', 'top-10' ),
797 'desc' => esc_html__( 'Comma-separated list of post or page IDs to exclude from the list. e.g. 188,320,500', 'top-10' ),
798 'type' => 'numbercsv',
799 'default' => '',
800 'size' => 'large',
801 ),
802 'exclude_cat_slugs' => array(
803 'id' => 'exclude_cat_slugs',
804 'name' => esc_html__( 'Exclude Categories', 'top-10' ),
805 'desc' => esc_html__( 'Comma separated list of category slugs. The field above has an autocomplete so simply start typing in the starting letters and it will prompt you with options. Does not support custom taxonomies.', 'top-10' ),
806 'type' => 'csv',
807 'default' => '',
808 'size' => 'large',
809 'field_class' => 'ts_autocomplete',
810 'field_attributes' => self::get_taxonomy_search_field_attributes( 'category' ),
811 ),
812 'exclude_categories' => array(
813 'id' => 'exclude_categories',
814 'name' => esc_html__( 'Exclude category IDs', 'top-10' ),
815 'desc' => esc_html__( 'This is a readonly field that is automatically populated based on the above input when the settings are saved. These might differ from the IDs visible in the Categories page which use the term_id. Top 10 uses the term_taxonomy_id which is unique to this taxonomy.', 'top-10' ),
816 'type' => 'text',
817 'default' => '',
818 'size' => 'large',
819 'readonly' => true,
820 ),
821 'exclude_terms_include_parents' => array(
822 'id' => 'exclude_terms_include_parents',
823 'name' => esc_html__( 'Include parent categories', 'top-10' ),
824 'desc' => esc_html__( 'Exclude popular posts from parent categories or all ancestors for nested categories.', 'top-10' ),
825 'type' => 'radio',
826 'default' => 'none',
827 'options' => array(
828 'none' => esc_html__( 'None', 'top-10' ),
829 'parent' => esc_html__( 'Only parent categories', 'top-10' ),
830 'all' => esc_html__( 'All ancestors', 'top-10' ),
831 ),
832 'pro' => true,
833 ),
834 'exclude_on_cat_slugs' => array(
835 'id' => 'exclude_on_cat_slugs',
836 'name' => esc_html__( 'Exclude on Categories', 'top-10' ),
837 'desc' => esc_html__( 'Comma separated list of category slugs. The field above has an autocomplete so simply start typing in the starting letters and it will prompt you with options. Does not support custom taxonomies.', 'top-10' ),
838 'type' => 'csv',
839 'default' => '',
840 'size' => 'large',
841 'field_class' => 'ts_autocomplete',
842 'field_attributes' => self::get_taxonomy_search_field_attributes( 'category' ),
843 ),
844 'customize_output_header' => array(
845 'id' => 'customize_output_header',
846 'name' => '<h3>' . esc_html__( 'Customize the output', 'top-10' ) . '</h3>',
847 'desc' => '',
848 'type' => 'header',
849 ),
850 'title' => array(
851 'id' => 'title',
852 'name' => esc_html__( 'Heading of posts', 'top-10' ),
853 'desc' => esc_html__( 'Displayed before the list of the posts as a the master heading', 'top-10' ),
854 'type' => 'text',
855 'default' => '<h3>' . esc_html__( 'Popular posts:', 'top-10' ) . '</h3>',
856 'size' => 'large',
857 ),
858 'title_daily' => array(
859 'id' => 'title_daily',
860 'name' => esc_html__( 'Heading of posts for daily/custom period lists', 'top-10' ),
861 'desc' => esc_html__( 'Displayed before the list of the posts as a the master heading', 'top-10' ),
862 'type' => 'text',
863 'default' => '<h3>' . esc_html__( 'Currently trending:', 'top-10' ) . '</h3>',
864 'size' => 'large',
865 ),
866 'blank_output' => array(
867 'id' => 'blank_output',
868 'name' => esc_html__( 'Show when no posts are found', 'top-10' ),
869 /* translators: 1: Code. */
870 'desc' => '',
871 'type' => 'radio',
872 'default' => 'blank',
873 'options' => array(
874 'blank' => esc_html__( 'Blank output', 'top-10' ),
875 'custom_text' => esc_html__( 'Display custom text', 'top-10' ),
876 ),
877 ),
878 'blank_output_text' => array(
879 'id' => 'blank_output_text',
880 'name' => esc_html__( 'Custom text', 'top-10' ),
881 'desc' => esc_html__( 'Enter the custom text that will be displayed if the second option is selected above', 'top-10' ),
882 'type' => 'textarea',
883 'default' => esc_html__( 'No top posts yet', 'top-10' ),
884 ),
885 'show_excerpt' => array(
886 'id' => 'show_excerpt',
887 'name' => esc_html__( 'Show post excerpt', 'top-10' ),
888 'desc' => '',
889 'type' => 'checkbox',
890 'default' => false,
891 ),
892 'excerpt_length' => array(
893 'id' => 'excerpt_length',
894 'name' => esc_html__( 'Length of excerpt (in words)', 'top-10' ),
895 'desc' => '',
896 'type' => 'number',
897 'default' => '10',
898 'size' => 'small',
899 ),
900 'show_date' => array(
901 'id' => 'show_date',
902 'name' => esc_html__( 'Show date', 'top-10' ),
903 'desc' => '',
904 'type' => 'checkbox',
905 'default' => false,
906 ),
907 'show_author' => array(
908 'id' => 'show_author',
909 'name' => esc_html__( 'Show author', 'top-10' ),
910 'desc' => '',
911 'type' => 'checkbox',
912 'default' => false,
913 ),
914 'disp_list_count' => array(
915 'id' => 'disp_list_count',
916 'name' => esc_html__( 'Show number of views', 'top-10' ),
917 'desc' => '',
918 'type' => 'checkbox',
919 'default' => false,
920 ),
921 'show_ratings' => array(
922 'id' => 'show_ratings',
923 'name' => esc_html__( 'Show WP-PostRatings rating', 'top-10' ),
924 'desc' => esc_html__( 'Display the rating from the WP-PostRatings plugin with each post in the list. This option only takes effect when the WP-PostRatings plugin is active. The Star rating output, including the text shown alongside the stars, comes from the "Ratings Voted Text" template which you can edit under WP-PostRatings » Settings » Templates.', 'top-10' ),
925 'type' => 'select',
926 'default' => '',
927 'options' => array(
928 '' => esc_html__( 'Do not display', 'top-10' ),
929 'stars' => esc_html__( 'Star rating', 'top-10' ),
930 'score' => esc_html__( 'Average score, e.g. 4.25', 'top-10' ),
931 ),
932 ),
933 'title_length' => array(
934 'id' => 'title_length',
935 'name' => esc_html__( 'Limit post title length (in characters)', 'top-10' ),
936 'desc' => '',
937 'type' => 'number',
938 'default' => '60',
939 'size' => 'small',
940 ),
941 'link_new_window' => array(
942 'id' => 'link_new_window',
943 'name' => esc_html__( 'Open links in new window', 'top-10' ),
944 'desc' => '',
945 'type' => 'checkbox',
946 'default' => false,
947 ),
948 'link_nofollow' => array(
949 'id' => 'link_nofollow',
950 'name' => esc_html__( 'Add nofollow to links', 'top-10' ),
951 'desc' => '',
952 'type' => 'checkbox',
953 'default' => false,
954 ),
955 'html_wrapper_header' => array(
956 'id' => 'html_wrapper_header',
957 'name' => '<h3>' . esc_html__( 'HTML to display', 'top-10' ) . '</h3>',
958 'desc' => '',
959 'type' => 'header',
960 ),
961 'before_list' => array(
962 'id' => 'before_list',
963 'name' => esc_html__( 'Before the list of posts', 'top-10' ),
964 'desc' => '',
965 'type' => 'text',
966 'default' => '<ul>',
967 'size' => 'large',
968 ),
969 'after_list' => array(
970 'id' => 'after_list',
971 'name' => esc_html__( 'After the list of posts', 'top-10' ),
972 'desc' => '',
973 'type' => 'text',
974 'default' => '</ul>',
975 'size' => 'large',
976 ),
977 'before_list_item' => array(
978 'id' => 'before_list_item',
979 'name' => esc_html__( 'Before each list item', 'top-10' ),
980 'desc' => '',
981 'type' => 'text',
982 'default' => '<li>',
983 'size' => 'large',
984 ),
985 'after_list_item' => array(
986 'id' => 'after_list_item',
987 'name' => esc_html__( 'After each list item', 'top-10' ),
988 'desc' => '',
989 'type' => 'text',
990 'default' => '</li>',
991 'size' => 'large',
992 ),
993 );
994
995 /**
996 * Filters the List settings array
997 *
998 * @since 3.3.0
999 *
1000 * @param array $settings List settings array
1001 */
1002 return apply_filters( self::$prefix . '_settings_list', $settings );
1003 }
1004
1005
1006 /**
1007 * Retrieve the array of Thumbnail settings
1008 *
1009 * @since 3.3.0
1010 *
1011 * @return array Thumbnail settings array
1012 */
1013 public static function settings_thumbnail() {
1014 $settings = array(
1015 'post_thumb_op' => array(
1016 'id' => 'post_thumb_op',
1017 'name' => esc_html__( 'Location of the post thumbnail', 'top-10' ),
1018 'desc' => '',
1019 'type' => 'radio',
1020 'default' => 'text_only',
1021 'options' => array(
1022 'inline' => esc_html__( 'Display thumbnails inline with posts, before title', 'top-10' ),
1023 'after' => esc_html__( 'Display thumbnails inline with posts, after title', 'top-10' ),
1024 'thumbs_only' => esc_html__( 'Display only thumbnails, no text', 'top-10' ),
1025 'text_only' => esc_html__( 'Do not display thumbnails, only text', 'top-10' ),
1026 ),
1027 ),
1028 'thumb_size' => array(
1029 'id' => 'thumb_size',
1030 'name' => esc_html__( 'Thumbnail size', 'top-10' ),
1031 'desc' => esc_html__( 'You can choose from existing image sizes above or create a custom size (tptn_thumbnail). If you select a custom size, enter the width, height, and crop settings below. For best results, use a cropped image. Note that changing the width and/or height below will not automatically resize existing images. You will need to regenerate the images using a plugin or WP CLI: wp media regenerate.', 'top-10' ),
1032 'type' => 'thumbsizes',
1033 'default' => 'tptn_thumbnail',
1034 'options' => Media_Handler::get_all_image_sizes(),
1035 ),
1036 'thumb_width' => array(
1037 'id' => 'thumb_width',
1038 'name' => esc_html__( 'Thumbnail width', 'top-10' ),
1039 'desc' => '',
1040 'type' => 'number',
1041 'default' => '250',
1042 'size' => 'small',
1043 ),
1044 'thumb_height' => array(
1045 'id' => 'thumb_height',
1046 'name' => esc_html__( 'Thumbnail height', 'top-10' ),
1047 'desc' => '',
1048 'type' => 'number',
1049 'default' => '250',
1050 'size' => 'small',
1051 ),
1052 'thumb_crop' => array(
1053 'id' => 'thumb_crop',
1054 'name' => esc_html__( 'Hard crop thumbnails', 'top-10' ),
1055 'desc' => esc_html__( 'Check this box to hard crop the thumbnails. i.e. force the width and height above vs. maintaining proportions.', 'top-10' ),
1056 'type' => 'checkbox',
1057 'default' => true,
1058 ),
1059 'thumb_create_sizes' => array(
1060 'id' => 'thumb_create_sizes',
1061 'name' => esc_html__( 'Generate thumbnail sizes', 'top-10' ),
1062 'desc' => esc_html__( 'If you select this option and tptn_thumbnail is chosen above, the plugin will register the image size with WordPress to create new thumbnails. Note that this does not update old images, as explained above.', 'top-10' ),
1063 'type' => 'checkbox',
1064 'default' => true,
1065 ),
1066 'thumb_html' => array(
1067 'id' => 'thumb_html',
1068 'name' => esc_html__( 'Thumbnail size attributes', 'top-10' ),
1069 'desc' => '',
1070 'type' => 'radio',
1071 'default' => 'html',
1072 'options' => array(
1073 /* translators: %s: Code. */
1074 'css' => sprintf( esc_html__( 'Use CSS to set the width and height: e.g. %s', 'top-10' ), '<code>style="max-width:250px;max-height:250px"</code>' ),
1075 /* translators: %s: Code. */
1076 'html' => sprintf( esc_html__( 'Use HTML attributes to set the width and height: e.g. %s', 'top-10' ), '<code>width="250" height="250"</code>' ),
1077 'none' => esc_html__( 'No width or height set. You will need to use external styles to force any width or height of your choice.', 'top-10' ),
1078 ),
1079 ),
1080 'thumb_meta' => array(
1081 'id' => 'thumb_meta',
1082 'name' => esc_html__( 'Thumbnail meta field name', 'top-10' ),
1083 'desc' => esc_html__( 'The value of this field should contain the URL of the image and can be set in the metabox in the Edit Post screen', 'top-10' ),
1084 'type' => 'text',
1085 'default' => 'post-image',
1086 ),
1087 'scan_images' => array(
1088 'id' => 'scan_images',
1089 'name' => esc_html__( 'Get first image', 'top-10' ),
1090 'desc' => esc_html__( 'If enabled, the plugin will fetch the first image in the post content. Note that this might slow down your page loading time if the first image in the posts is large in file size.', 'top-10' ),
1091 'type' => 'checkbox',
1092 'default' => true,
1093 ),
1094 'thumb_default_show' => array(
1095 'id' => 'thumb_default_show',
1096 'name' => esc_html__( 'Use default thumbnail', 'top-10' ),
1097 'desc' => esc_html__( 'Check this box to show the default thumbnail from the next option if no thumbnail is found from the post.', 'top-10' ),
1098 'type' => 'checkbox',
1099 'default' => true,
1100 ),
1101 'thumb_default' => array(
1102 'id' => 'thumb_default',
1103 'name' => esc_html__( 'Default thumbnail', 'top-10' ),
1104 'desc' => esc_html__( 'Enter the full URL of the image that you wish to display if no thumbnail is found. This image will be displayed below.', 'top-10' ),
1105 'type' => 'file',
1106 'default' => Display::get_default_thumbnail(),
1107 'size' => 'large',
1108 'modified_indicator' => false,
1109 ),
1110 );
1111
1112 /**
1113 * Filters the Thumbnail settings array
1114 *
1115 * @since 3.3.0
1116 *
1117 * @param array $settings Thumbnail settings array
1118 */
1119 return apply_filters( self::$prefix . '_settings_thumbnail', $settings );
1120 }
1121
1122
1123 /**
1124 * Retrieve the array of Styles settings
1125 *
1126 * @since 3.3.0
1127 *
1128 * @return array Styles settings array
1129 */
1130 public static function settings_styles() {
1131 $settings = array(
1132 'tptn_styles' => array(
1133 'id' => 'tptn_styles',
1134 'name' => esc_html__( 'Popular posts style', 'top-10' ),
1135 'desc' => '',
1136 'type' => 'select',
1137 'default' => 'no_style',
1138 'options' => wp_list_pluck( self::get_styles(), 'name', 'id' ),
1139 ),
1140 'custom_css' => array(
1141 'id' => 'custom_css',
1142 'name' => esc_html__( 'Custom CSS', 'top-10' ),
1143 'desc' => sprintf(
1144 /* translators: 1: Opening a tag, 2: Closing a tag, 3: Opening code tage, 4. Closing code tag. */
1145 esc_html__( 'Do not include %3$sstyle%4$s tags. Check out %1$sthis article%2$s for available CSS classes to style.', 'top-10' ),
1146 '<a href="' . esc_url( 'https://webberzone.com/support/knowledgebase/using-and-customising-top-10/' ) . '" target="_blank">',
1147 '</a>',
1148 '<code>',
1149 '</code>'
1150 ),
1151 'type' => 'css',
1152 'default' => '',
1153 'field_class' => 'codemirror_css',
1154 ),
1155 );
1156
1157 /**
1158 * Filters the Styles settings array
1159 *
1160 * @since 3.3.0
1161 *
1162 * @param array $settings Styles settings array
1163 */
1164 return apply_filters( self::$prefix . '_settings_styles', $settings );
1165 }
1166
1167
1168 /**
1169 * Retrieve the array of Maintenance settings
1170 *
1171 * @since 3.3.0
1172 *
1173 * @return array Maintenance settings array
1174 */
1175 public static function settings_maintenance() {
1176 $settings = array(
1177 'cron_on' => array(
1178 'id' => 'cron_on',
1179 'name' => esc_html__( 'Enable scheduled maintenance', 'top-10' ),
1180 'desc' => sprintf(
1181 /* translators: 1: Constant holding number of days data is stored. */
1182 esc_html__( 'Regularly cleaning the database can enhance performance, especially for high-traffic blogs. Enabling maintenance will automatically delete entries older than %s days from the daily tables.', 'top-10' ),
1183 /** This filter is documented in includes/admin/class-cron.php */
1184 '<strong>' . (int) apply_filters( 'tptn_maintenance_days', TOP_TEN_STORE_DATA ) . '</strong>'
1185 ),
1186 'type' => 'checkbox',
1187 'default' => false,
1188 ),
1189 'maintenance_days' => array(
1190 'id' => 'maintenance_days',
1191 'name' => esc_html__( 'Daily table retention period', 'top-10' ),
1192 'desc' => sprintf(
1193 /* translators: 1: Constant holding number of days data is stored. */
1194 esc_html__( 'Enter the number of days to retain data in the daily tables before scheduled maintenance removes older entries. Enter 0 to use the default value of %s days.', 'top-10' ),
1195 '<strong>' . TOP_TEN_STORE_DATA . '</strong>'
1196 ),
1197 'type' => 'number',
1198 'default' => 0,
1199 'min' => 0,
1200 'size' => 'small',
1201 'pro' => true,
1202 ),
1203 'log_retention_days' => array(
1204 'id' => 'log_retention_days',
1205 'name' => esc_html__( 'Visits log retention period', 'top-10' ),
1206 'desc' => sprintf(
1207 /* translators: 1: Default number of days for visits log retention. */
1208 esc_html__( 'Enter the number of days to retain raw visit rows in the visits log table. The log stores one row per visit and grows faster than the daily table, so a shorter window is recommended. Enter 0 to use the default value of %s days.', 'top-10' ),
1209 '<strong>' . TOP_TEN_LOG_STORE_DATA . '</strong>'
1210 ),
1211 'type' => 'number',
1212 'default' => 0,
1213 'min' => 0,
1214 'size' => 'small',
1215 'pro' => true,
1216 ),
1217 'cron_range_desc' => array(
1218 'id' => 'cron_range_desc',
1219 'name' => esc_html__( 'Time to run maintenance', 'top-10' ),
1220 'desc' => esc_html__( 'The next two options allow you to set the time to run the cron.', 'top-10' ),
1221 'type' => 'descriptive_text',
1222 ),
1223 'cron_hour' => array(
1224 'id' => 'cron_hour',
1225 'name' => esc_html__( 'Hour', 'top-10' ),
1226 'desc' => '',
1227 'type' => 'number',
1228 'default' => '0',
1229 'min' => '0',
1230 'max' => '23',
1231 'size' => 'small',
1232 ),
1233 'cron_min' => array(
1234 'id' => 'cron_min',
1235 'name' => esc_html__( 'Minute', 'top-10' ),
1236 'desc' => '',
1237 'type' => 'number',
1238 'default' => '0',
1239 'min' => '0',
1240 'max' => '59',
1241 'size' => 'small',
1242 ),
1243 'cron_recurrence' => array(
1244 'id' => 'cron_recurrence',
1245 'name' => esc_html__( 'Run maintenance', 'top-10' ),
1246 'desc' => '',
1247 'type' => 'radio',
1248 'default' => 'weekly',
1249 'options' => array(
1250 'daily' => esc_html__( 'Daily', 'top-10' ),
1251 'weekly' => esc_html__( 'Weekly', 'top-10' ),
1252 'fortnightly' => esc_html__( 'Fortnightly', 'top-10' ),
1253 'monthly' => esc_html__( 'Monthly', 'top-10' ),
1254 ),
1255 ),
1256 );
1257
1258 /**
1259 * Filters the Maintenance settings array
1260 *
1261 * @since 3.3.0
1262 *
1263 * @param array $settings Maintenance settings array
1264 */
1265 return apply_filters( self::$prefix . '_settings_maintenance', $settings );
1266 }
1267
1268
1269 /**
1270 * Retrieve the array of Feed settings
1271 *
1272 * @since 2.8.0
1273 *
1274 * @return array Feed settings array
1275 */
1276 public static function settings_feed() {
1277 $settings = array(
1278 'feed_permalink_overall' => array(
1279 'id' => 'feed_permalink_overall',
1280 'name' => esc_html__( 'Permalink - Overall', 'top-10' ),
1281 /* translators: 1: Opening link tag, 2: Closing link tag. */
1282 'desc' => sprintf( esc_html__( 'This will set the path of the custom feed generated by the plugin for overall popular posts. You might need to %1$srefresh your permalinks%2$s when changing this option.', 'top-10' ), '<a href="' . admin_url( 'options-permalink.php' ) . '" target="_blank">', '</a>' ),
1283 'type' => 'text',
1284 'default' => 'popular-posts',
1285 'size' => 'large',
1286 ),
1287 'feed_permalink_daily' => array(
1288 'id' => 'feed_permalink_daily',
1289 /* translators: %s: Custom period label (e.g. Daily, Custom (7 days)). */
1290 'name' => sprintf( esc_html__( 'Permalink - %s', 'top-10' ), Helpers::get_daily_range_label( (int) \tptn_get_option( 'feed_daily_range', 1 ) ) ),
1291 /* translators: 1: Opening link tag, 2: Closing link tag. */
1292 'desc' => sprintf( esc_html__( 'This will set the path of the custom feed generated by the plugin for daily/custom period popular posts. You might need to %1$srefresh your permalinks%2$s when changing this option.', 'top-10' ), '<a href="' . admin_url( 'options-permalink.php' ) . '" target="_blank">', '</a>' ),
1293 'type' => 'text',
1294 'default' => 'popular-posts-daily',
1295 'size' => 'large',
1296 ),
1297 'feed_limit' => array(
1298 'id' => 'feed_limit',
1299 'name' => esc_html__( 'Number of posts to display', 'top-10' ),
1300 'desc' => esc_html__( 'Maximum number of posts that will be displayed in the custom feed.', 'top-10' ),
1301 'type' => 'number',
1302 'default' => '10',
1303 'size' => 'small',
1304 ),
1305 'feed_daily_range' => array(
1306 'id' => 'feed_daily_range',
1307 'name' => esc_html__( 'Custom period in day(s)', 'top-10' ),
1308 'desc' => '',
1309 'type' => 'number',
1310 'default' => '1',
1311 'min' => '0',
1312 'size' => 'small',
1313 ),
1314 'feed_category_slugs' => array(
1315 'id' => 'feed_category_slugs',
1316 'name' => esc_html__( 'Filter Categories', 'top-10' ),
1317 'desc' => esc_html__( 'Comma separated list of category slugs to include in the feed. The field has an autocomplete so simply start typing the starting letters and it will prompt you with options. Leave blank to include all categories.', 'top-10' ),
1318 'type' => 'csv',
1319 'default' => '',
1320 'size' => 'large',
1321 'field_class' => 'ts_autocomplete',
1322 'field_attributes' => self::get_taxonomy_search_field_attributes( 'category' ),
1323 'pro' => true,
1324 ),
1325 );
1326
1327 /**
1328 * Filters the Feed settings array
1329 *
1330 * @since 2.8.0
1331 *
1332 * @param array $settings Feed settings array
1333 */
1334 return apply_filters( self::$prefix . '_settings_feed', $settings );
1335 }
1336
1337 /**
1338 * Retrieve the array of Features settings
1339 *
1340 * All features are enabled by default. Disabling a feature stops its
1341 * classes from being loaded on any request.
1342 *
1343 * @since 4.4.0
1344 *
1345 * @return array Features settings array
1346 */
1347 public static function settings_features() {
1348 $settings = array(
1349 'features_header' => array(
1350 'id' => 'features_header',
1351 'name' => '<h3>' . esc_html__( 'Features', 'top-10' ) . '</h3>',
1352 'desc' => esc_html__( 'Turn off any features you do not use and the plugin will not load their code. All features are enabled by default. Blocks that are disabled will render as empty on the front end and show an unavailable notice in the block editor.', 'top-10' ),
1353 'type' => 'header',
1354 ),
1355 'features_display_header' => array(
1356 'id' => 'features_display_header',
1357 'name' => '<h3>' . esc_html__( 'Content and display', 'top-10' ) . '</h3>',
1358 'desc' => esc_html__( 'Control the blocks, widgets, page builders, and author tools registered by Top 10.', 'top-10' ),
1359 'type' => 'header',
1360 ),
1361 'enable_blocks' => array(
1362 'id' => 'enable_blocks',
1363 'name' => esc_html__( 'Popular Posts and Post Count blocks', 'top-10' ),
1364 'desc' => esc_html__( 'Registers the free Popular Posts and Post Count blocks for the block editor.', 'top-10' ),
1365 'type' => 'checkbox',
1366 'default' => 1,
1367 ),
1368 'enable_legacy_widgets' => array(
1369 'id' => 'enable_legacy_widgets',
1370 'name' => esc_html__( 'Legacy widgets', 'top-10' ),
1371 'desc' => esc_html__( 'Registers the classic Popular Posts and Views Count widgets. Disable this if you use blocks instead of classic widgets.', 'top-10' ),
1372 'type' => 'checkbox',
1373 'default' => 1,
1374 ),
1375 'enable_query_block' => array(
1376 'id' => 'enable_query_block',
1377 'name' => esc_html__( 'Query block', 'top-10' ),
1378 'desc' => esc_html__( 'Registers the Top 10 Query block and the pre-built block patterns.', 'top-10' ),
1379 'type' => 'checkbox',
1380 'default' => 1,
1381 'pro' => true,
1382 ),
1383 'enable_featured_image_block' => array(
1384 'id' => 'enable_featured_image_block',
1385 'name' => esc_html__( 'Featured Image block', 'top-10' ),
1386 'desc' => esc_html__( 'Extends the core Featured Image block with Top 10 options.', 'top-10' ),
1387 'type' => 'checkbox',
1388 'default' => 1,
1389 'pro' => true,
1390 ),
1391 'enable_popular_posts_pro_block' => array(
1392 'id' => 'enable_popular_posts_pro_block',
1393 'name' => esc_html__( 'Popular Posts Pro block', 'top-10' ),
1394 'desc' => esc_html__( 'Registers the Popular Posts Pro block for the block editor.', 'top-10' ),
1395 'type' => 'checkbox',
1396 'default' => 1,
1397 'pro' => true,
1398 ),
1399 'enable_page_builders' => array(
1400 'id' => 'enable_page_builders',
1401 'name' => esc_html__( 'Page builder integrations', 'top-10' ),
1402 'desc' => esc_html__( 'Registers the Popular Posts elements for Elementor, Bricks Builder, and WPBakery Page Builder.', 'top-10' ),
1403 'type' => 'checkbox',
1404 'default' => 1,
1405 'pro' => true,
1406 ),
1407 'enable_popular_authors' => array(
1408 'id' => 'enable_popular_authors',
1409 'name' => esc_html__( 'Popular Authors', 'top-10' ),
1410 'desc' => esc_html__( 'Enables the Popular Authors blocks, shortcodes, widgets and settings.', 'top-10' ),
1411 'type' => 'checkbox',
1412 'default' => 1,
1413 'pro' => true,
1414 ),
1415 'features_tracking_header' => array(
1416 'id' => 'features_tracking_header',
1417 'name' => '<h3>' . esc_html__( 'Tracking and feeds', 'top-10' ) . '</h3>',
1418 'desc' => esc_html__( 'Control how Top 10 records views and provides popular posts feeds.', 'top-10' ),
1419 'type' => 'header',
1420 ),
1421 'enable_feed' => array(
1422 'id' => 'enable_feed',
1423 'name' => esc_html__( 'Popular posts feeds', 'top-10' ),
1424 'desc' => esc_html__( 'Adds custom RSS feeds for overall and daily popular posts. The feed settings are on the Feed tab.', 'top-10' ),
1425 'type' => 'checkbox',
1426 'default' => 1,
1427 ),
1428 'enable_fast_tracker' => array(
1429 'id' => 'enable_fast_tracker',
1430 'name' => esc_html__( 'Fast and High-traffic trackers', 'top-10' ),
1431 'desc' => esc_html__( 'Adds the Fast tracker and High-traffic tracker options to the Tracker type setting. If this is disabled while one of these trackers is in use, the tracker type will be reset to the default.', 'top-10' ),
1432 'type' => 'checkbox',
1433 'default' => 1,
1434 'pro' => true,
1435 ),
1436 'enable_sitewide_tracking' => array(
1437 'id' => 'enable_sitewide_tracking',
1438 'name' => esc_html__( 'Site-wide tracking', 'top-10' ),
1439 'desc' => esc_html__( 'Enables the site-wide tracking feature. When enabled, turn on Track site-wide views under Counter/Tracker to count front pages, posts pages, archives, and searches.', 'top-10' ),
1440 'type' => 'checkbox',
1441 'default' => 1,
1442 'pro' => true,
1443 ),
1444 'features_data_header' => array(
1445 'id' => 'features_data_header',
1446 'name' => '<h3>' . esc_html__( 'Data and maintenance', 'top-10' ) . '</h3>',
1447 'desc' => esc_html__( 'Control tools that manage and reduce stored view data.', 'top-10' ),
1448 'type' => 'header',
1449 ),
1450 'enable_daily_table_rollup' => array(
1451 'id' => 'enable_daily_table_rollup',
1452 'name' => esc_html__( 'Daily table size reduction', 'top-10' ),
1453 'desc' => esc_html__( 'Enables the Reduce Daily Table Size tool and the wp top10 db rollup command for combining older hourly records.', 'top-10' ),
1454 'type' => 'checkbox',
1455 'default' => 1,
1456 'pro' => true,
1457 ),
1458 'features_admin_header' => array(
1459 'id' => 'features_admin_header',
1460 'name' => '<h3>' . esc_html__( 'Administration', 'top-10' ) . '</h3>',
1461 'desc' => esc_html__( 'Control additional Top 10 administration features.', 'top-10' ),
1462 'type' => 'header',
1463 ),
1464 'enable_pro_dashboard_widgets' => array(
1465 'id' => 'enable_pro_dashboard_widgets',
1466 'name' => esc_html__( 'Pro dashboard widgets', 'top-10' ),
1467 'desc' => esc_html__( 'Adds the enhanced Top 10 Pro widgets to the WordPress dashboard.', 'top-10' ),
1468 'type' => 'checkbox',
1469 'default' => 1,
1470 'pro' => true,
1471 ),
1472 );
1473
1474 /**
1475 * Filters the Features settings array
1476 *
1477 * @since 4.4.0
1478 *
1479 * @param array $settings Features settings array
1480 */
1481 return apply_filters( self::$prefix . '_settings_features', $settings );
1482 }
1483
1484 /**
1485 * Get the various styles.
1486 *
1487 * @since 2.5.0
1488 * @return array Style options.
1489 */
1490 public static function get_styles() {
1491 $styles = array(
1492 array(
1493 'id' => 'no_style',
1494 'name' => esc_html__( 'No styles', 'top-10' ),
1495 'description' => esc_html__( 'Select this option if you plan to add your own styles', 'top-10' ) . '<br />',
1496 ),
1497 array(
1498 'id' => 'text_only',
1499 'name' => esc_html__( 'Text only', 'top-10' ),
1500 'description' => esc_html__( 'Disable thumbnails and no longer include the default style sheet included in the plugin', 'top-10' ) . '<br />',
1501 ),
1502 array(
1503 'id' => 'left_thumbs',
1504 'name' => esc_html__( 'Left thumbnails', 'top-10' ),
1505 'description' => esc_html__( 'Enabling this option will set the post thumbnail to be before text. Disabling this option will not revert any settings.', 'top-10' ),
1506 ),
1507 );
1508
1509 /**
1510 * Filter the array containing the types of styles to add your own.
1511 *
1512 * @since 2.5.0
1513 *
1514 * @param array $styles Different styles.
1515 */
1516 return apply_filters( self::$prefix . '_get_styles', $styles );
1517 }
1518
1519 /**
1520 * Get User Roles.
1521 *
1522 * @since 4.0.0
1523 *
1524 * @param array $remove_roles Roles to remove.
1525 * @return array User roles in the format 'role' => 'name'.
1526 */
1527 public static function get_user_roles( $remove_roles = array() ) {
1528 // Get the global $wp_roles object using the wp_roles() function.
1529 $wp_roles = wp_roles();
1530
1531 // Initialize the array to store roles in the desired format.
1532 $roles_array = array();
1533
1534 if ( ! empty( $wp_roles->roles ) ) {
1535 // Loop through all roles and store them in 'role' => 'name' format.
1536 foreach ( $wp_roles->roles as $role_key => $role_details ) {
1537 if ( in_array( $role_key, $remove_roles, true ) ) {
1538 continue;
1539 }
1540 $roles_array[ $role_key ] = esc_html( $role_details['name'] );
1541 }
1542 } else {
1543 // Fallback to default WordPress roles.
1544 $default_roles = array(
1545 'administrator' => esc_html__( 'Administrator' ),
1546 'editor' => esc_html__( 'Editor' ),
1547 'author' => esc_html__( 'Author' ),
1548 'contributor' => esc_html__( 'Contributor' ),
1549 'subscriber' => esc_html__( 'Subscriber' ),
1550 );
1551
1552 foreach ( $default_roles as $role_key => $role_name ) {
1553 if ( ! in_array( $role_key, $remove_roles, true ) ) {
1554 $roles_array[ $role_key ] = $role_name;
1555 }
1556 }
1557 }
1558
1559 return $roles_array;
1560 }
1561
1562 /**
1563 * Adding WordPress plugin action links.
1564 *
1565 * @since 3.3.0
1566 *
1567 * @param array $links Array of links.
1568 * @return array
1569 */
1570 public function plugin_actions_links( $links ) {
1571
1572 return array_merge(
1573 array(
1574 'settings' => '<a href="' . admin_url( 'admin.php?page=' . $this->menu_slug ) . '">' . esc_html__( 'Settings', 'top-10' ) . '</a>',
1575 ),
1576 $links
1577 );
1578 }
1579
1580 /**
1581 * Add meta links on Plugins page.
1582 *
1583 * @since 3.3.0
1584 *
1585 * @param array $links Array of Links.
1586 * @param string $file Current file.
1587 * @return array
1588 */
1589 public function plugin_row_meta( $links, $file ) {
1590
1591 if ( false !== strpos( $file, 'top-10.php' ) ) {
1592 $new_links = array(
1593 'support' => '<a href = "https://wordpress.org/support/plugin/top-10">' . esc_html__( 'Support', 'top-10' ) . '</a>',
1594 'donate' => '<a href = "https://wzn.io/donate-wz">' . esc_html__( 'Donate', 'top-10' ) . '</a>',
1595 'contribute' => '<a href = "https://github.com/WebberZone/top-10">' . esc_html__( 'Contribute', 'top-10' ) . '</a>',
1596 );
1597
1598 $links = array_merge( $links, $new_links );
1599 }
1600 return $links;
1601 }
1602
1603 /**
1604 * Get the help sidebar content to display on the plugin settings page.
1605 *
1606 * @since 1.8.0
1607 */
1608 public function get_help_sidebar() {
1609 $help_sidebar =
1610 /* translators: 1: Plugin support site link. */
1611 '<p>' . sprintf( __( 'For more information or how to get support visit the <a href="%s">support site</a>.', 'top-10' ), esc_url( 'https://webberzone.com/support/' ) ) . '</p>' .
1612 /* translators: 1: WordPress.org support forums link. */
1613 '<p>' . sprintf( __( 'Support queries should be posted in the <a href="%s">WordPress.org support forums</a>.', 'top-10' ), esc_url( 'https://wordpress.org/support/plugin/top-10' ) ) . '</p>' .
1614 '<p>' . sprintf(
1615 /* translators: 1: Github issues link, 2: Github plugin page link. */
1616 __( '<a href="%1$s">Post an issue</a> on <a href="%2$s">GitHub</a> (bug reports only).', 'top-10' ),
1617 esc_url( 'https://github.com/ajaydsouza/top-10/issues' ),
1618 esc_url( 'https://github.com/ajaydsouza/top-10' )
1619 ) . '</p>';
1620
1621 /**
1622 * Filter to modify the help sidebar content.
1623 *
1624 * @since 1.8.0
1625 *
1626 * @param string $help_sidebar Help sidebar content.
1627 */
1628 return apply_filters( self::$prefix . '_settings_help', $help_sidebar );
1629 }
1630
1631 /**
1632 * Get the help tabs to display on the plugin settings page.
1633 *
1634 * @since 1.8.0
1635 */
1636 public function get_help_tabs() {
1637 $help_tabs = array(
1638 array(
1639 'id' => 'tptn-settings-general-help',
1640 'title' => esc_html__( 'General', 'top-10' ),
1641 'content' =>
1642 '<p><strong>' . esc_html__( 'This tab provides global settings for how Top 10 works across your site.', 'top-10' ) . '</strong></p>' .
1643 '<p>' . esc_html__( 'Configure caching, uninstall behaviour, admin columns, the dashboard, and other high-level options. You must click the Save Changes button at the bottom of the screen for new settings to take effect.', 'top-10' ) . '</p>',
1644 ),
1645 array(
1646 'id' => 'tptn-settings-counter-help',
1647 'title' => esc_html__( 'Counter / Tracker', 'top-10' ),
1648 'content' =>
1649 '<p><strong>' . esc_html__( 'This tab controls how Top 10 tracks and displays view counts.', 'top-10' ) . '</strong></p>' .
1650 '<p>' . esc_html__( 'Choose where to display view counts, how they are formatted, which visits are tracked, and how the tracker works (REST API, query variables, or Ajax).', 'top-10' ) . '</p>',
1651 ),
1652 array(
1653 'id' => 'tptn-settings-list-help',
1654 'title' => esc_html__( 'Posts list', 'top-10' ),
1655 'content' =>
1656 '<p><strong>' . esc_html__( 'This tab controls the popular posts list output.', 'top-10' ) . '</strong></p>' .
1657 '<p>' . esc_html__( 'Configure the number of posts, age of posts, post types, exclusions, and what information is shown (title, date, author, views, excerpts, and HTML wrappers).', 'top-10' ) . '</p>',
1658 ),
1659 array(
1660 'id' => 'tptn-settings-thumbnail-help',
1661 'title' => esc_html__( 'Thumbnail', 'top-10' ),
1662 'content' =>
1663 '<p><strong>' . esc_html__( 'This tab manages thumbnail settings for the popular posts list.', 'top-10' ) . '</strong></p>' .
1664 '<p>' . esc_html__( 'Choose whether thumbnails are displayed, select the image size, configure custom dimensions, cropping, the default thumbnail, and fallback behaviour when no thumbnail is found.', 'top-10' ) . '</p>',
1665 ),
1666 array(
1667 'id' => 'tptn-settings-styles-help',
1668 'title' => esc_html__( 'Styles', 'top-10' ),
1669 'content' =>
1670 '<p><strong>' . esc_html__( 'This tab controls how the popular posts list is styled.', 'top-10' ) . '</strong></p>' .
1671 '<p>' . esc_html__( 'Select a built-in style or disable styles if you want to fully control the look using your own CSS.', 'top-10' ) . '</p>',
1672 ),
1673 array(
1674 'id' => 'tptn-settings-maintenance-help',
1675 'title' => esc_html__( 'Maintenance', 'top-10' ),
1676 'content' =>
1677 '<p><strong>' . esc_html__( 'This tab handles tools and maintenance-related options.', 'top-10' ) . '</strong></p>' .
1678 '<p>' . esc_html__( 'Use this screen to reset settings, clear cached popular posts, and manage database-related options such as pruning or rebuilding counts.', 'top-10' ) . '</p>',
1679 ),
1680 array(
1681 'id' => 'tptn-settings-feed-help',
1682 'title' => esc_html__( 'Feed', 'top-10' ),
1683 'content' =>
1684 '<p><strong>' . esc_html__( 'This tab controls how Top 10 content appears in your site feed.', 'top-10' ) . '</strong></p>' .
1685 '<p>' . esc_html__( 'Configure copyright text and additional HTML that is added before or after the content in your feeds.', 'top-10' ) . '</p>',
1686 ),
1687 );
1688
1689 /**
1690 * Filter to add more help tabs.
1691 *
1692 * @since 1.8.0
1693 *
1694 * @param array $help_tabs Associative array of help tabs.
1695 */
1696 return apply_filters( self::$prefix . '_settings_help', $help_tabs );
1697 }
1698
1699 /**
1700 * Function returns the different types of trackers.
1701 *
1702 * @since 3.3.0
1703 * @return array Tracker types.
1704 */
1705 public static function get_tracker_types() {
1706
1707 $trackers = array(
1708 array(
1709 'id' => 'rest_based',
1710 'name' => __( 'REST API based', 'top-10' ),
1711 'description' => __( 'Uses the REST API to record visits', 'top-10' ),
1712 ),
1713 array(
1714 'id' => 'query_based',
1715 'name' => __( 'Query variable based', 'top-10' ),
1716 'description' => __( 'Uses query variables to record visits', 'top-10' ),
1717 ),
1718 array(
1719 'id' => 'ajaxurl',
1720 'name' => __( 'Ajaxurl based', 'top-10' ),
1721 'description' => __( 'Uses admin-ajax.php which is inbuilt within WordPress to process the tracker', 'top-10' ),
1722 ),
1723 );
1724
1725 /**
1726 * Filter the array containing the types of trackers to add your own.
1727 *
1728 * @since 2.4.0
1729 *
1730 * @param array $trackers Different trackers.
1731 */
1732 return apply_filters( self::$prefix . '_get_tracker_types', $trackers );
1733 }
1734
1735 /**
1736 * Function returns the different tracking methods.
1737 *
1738 * @since 4.3.3
1739 * @return array Tracking methods.
1740 */
1741 public static function get_tracking_methods() {
1742
1743 $methods = array(
1744 array(
1745 'id' => 'funnel',
1746 'name' => __( 'Funnel tracking', 'top-10' ),
1747 'description' => __( 'Views are buffered and merged into the count tables every few minutes (default)', 'top-10' ),
1748 ),
1749 array(
1750 'id' => 'legacy',
1751 'name' => __( 'Legacy tracking', 'top-10' ),
1752 'description' => __( 'Views are written directly to the count tables on every visit (behaviour of versions before 4.3)', 'top-10' ),
1753 ),
1754 );
1755
1756 /**
1757 * Filter the array containing the tracking methods.
1758 *
1759 * @since 4.3.3
1760 *
1761 * @param array $methods Tracking methods.
1762 */
1763 return apply_filters( self::$prefix . '_get_tracking_methods', $methods );
1764 }
1765
1766
1767
1768
1769 /**
1770 * Add footer text on the plugin page.
1771 *
1772 * @since 2.0.0
1773 */
1774 public static function get_admin_footer_text() {
1775 return sprintf(
1776 /* translators: 1: Opening achor tag with Plugin page link, 2: Closing anchor tag, 3: Opening anchor tag with review link. */
1777 __( 'Thank you for using %1$sWebberZone Top 10%2$s! Please %3$srate us%2$s on WordPress.org', 'top-10' ),
1778 '<a href="https://webberzone.com/plugins/top-10/" target="_blank">',
1779 '</a>',
1780 '<a href="https://wordpress.org/support/plugin/top-10/reviews/#new-post" target="_blank">'
1781 );
1782 }
1783
1784 /**
1785 * Enqueue scripts and styles.
1786 *
1787 * @since 3.3.0
1788 *
1789 * @param string $hook Current hook.
1790 */
1791 public function admin_enqueue_scripts( $hook ) {
1792
1793 if ( ! isset( $this->settings_api->settings_page ) || $this->settings_api->settings_page !== $hook ) {
1794 return;
1795 }
1796
1797 wp_enqueue_script( 'top-ten-admin-js' );
1798 wp_enqueue_style( 'top-ten-admin-css' );
1799 wp_enqueue_style( 'wp-spinner' );
1800 wp_localize_script(
1801 'top-ten-admin-js',
1802 'tptn_admin',
1803 array(
1804 'thumb_default' => Display::get_default_thumbnail(),
1805 )
1806 );
1807 wp_localize_script(
1808 'top-ten-admin-js',
1809 'top_ten_admin_data',
1810 array(
1811 'security' => wp_create_nonce( 'tptn-admin' ),
1812 'strings' => array(
1813 'confirm_message' => esc_html__( 'Are you sure you want to clear the cache?', 'top-10' ),
1814 'clearing_text' => esc_html__( 'Clearing...', 'top-10' ),
1815 'success_message' => esc_html__( 'Cache cleared successfully!', 'top-10' ),
1816 'fail_message' => esc_html__( 'Failed to clear cache. Please try again.', 'top-10' ),
1817 'request_fail_message' => esc_html__( 'Request failed: ', 'top-10' ),
1818 'left_thumbs_message' => esc_html__( 'Note: This setting cannot be changed as the Popular posts style is set to Left thumbnails. You can change the style in the Styles tab.', 'top-10' ),
1819 'grid_thumbs_message' => esc_html__( 'Note: This setting cannot be changed as the Popular posts style is set to Grid thumbnails. You can change the style in the Styles tab.', 'top-10' ),
1820 'text_only_message' => esc_html__( 'Note: This setting cannot be changed as the Popular posts style is set to Text only. You can change the style in the Styles tab.', 'top-10' ),
1821 ),
1822 )
1823 );
1824 }
1825
1826 /**
1827 * Modify settings when they are being saved.
1828 *
1829 * @since 3.3.0
1830 *
1831 * @param array $settings Settings array.
1832 * @return array Sanitized settings array.
1833 */
1834 public function change_settings_on_save( $settings ) {
1835
1836 Settings_Sanitize::sanitize_tax_slugs( $settings, 'exclude_cat_slugs', 'exclude_categories' );
1837 Settings_Sanitize::sanitize_tax_slugs( $settings, 'exclude_on_cat_slugs', 'exclude_on_categories' );
1838 Settings_Sanitize::sanitize_tax_slugs( $settings, 'feed_category_slugs', 'feed_categories' );
1839
1840 // Save cron settings.
1841 $settings['cron_hour'] = min( 23, absint( $settings['cron_hour'] ) );
1842 $settings['cron_min'] = min( 59, absint( $settings['cron_min'] ) );
1843
1844 if ( ! empty( $settings['cron_on'] ) ) {
1845 \WebberZone\Top_Ten\Admin\Cron::enable_run( $settings['cron_hour'], $settings['cron_min'], $settings['cron_recurrence'] );
1846 } else {
1847 \WebberZone\Top_Ten\Admin\Cron::disable_run();
1848 }
1849
1850 // Force thumb_width and thumb_height if either are zero.
1851 if ( empty( $settings['thumb_width'] ) || empty( $settings['thumb_height'] ) ) {
1852 list( $settings['thumb_width'], $settings['thumb_height'] ) = Media_Handler::get_thumb_size( $settings['thumb_size'] );
1853 }
1854
1855 // Overwrite settings based on selected style; guard against missing keys on reset.
1856 $style = $settings['tptn_styles'] ?? '';
1857
1858 $inline_thumb_styles = array(
1859 'left_thumbs' => esc_html__( 'Note: Thumbnail location can only be Inline, After, or Thumbnails only when the Popular posts style is set to Left thumbnails. You can change the style in the Styles tab.', 'top-10' ),
1860 'grid_thumbs' => esc_html__( 'Note: Thumbnail location can only be Inline, After, or Thumbnails only when the Popular posts style is set to Grid thumbnails. You can change the style in the Styles tab.', 'top-10' ),
1861 );
1862
1863 if ( array_key_exists( $style, $inline_thumb_styles ) ) {
1864 $post_thumb_op = $settings['post_thumb_op'] ?? '';
1865 if ( 'inline' !== $post_thumb_op && 'after' !== $post_thumb_op && 'thumbs_only' !== $post_thumb_op ) {
1866 $settings['post_thumb_op'] = 'inline';
1867 }
1868
1869 add_settings_error(
1870 self::$prefix . '-notices',
1871 '',
1872 $inline_thumb_styles[ $style ],
1873 'warning'
1874 );
1875 }
1876 // Overwrite settings if text_only style is selected.
1877 if ( 'text_only' === $style ) {
1878 $settings['post_thumb_op'] = 'text_only';
1879
1880 add_settings_error(
1881 self::$prefix . '-notices',
1882 '',
1883 esc_html__( 'Note: Thumbnail location set to Text only as the Popular posts style is set to Text only. You can change the style in the Styles tab.', 'top-10' ),
1884 'warning'
1885 );
1886 }
1887
1888 // If the fast/high-traffic trackers are disabled, reset the tracker type to the default.
1889 if ( isset( $settings['enable_fast_tracker'] ) && empty( $settings['enable_fast_tracker'] ) && isset( $settings['tracker_type'] ) && in_array( $settings['tracker_type'], array( 'fast_tracker', 'high_traffic_tracker' ), true ) ) {
1890 $settings['tracker_type'] = 'query_based';
1891
1892 add_settings_error(
1893 self::$prefix . '-notices',
1894 '',
1895 esc_html__( 'Note: Tracker type has been reset to the default as the Fast and High-traffic trackers feature is disabled.', 'top-10' ),
1896 'warning'
1897 );
1898 }
1899
1900 // Delete the cache.
1901 \WebberZone\Top_Ten\Util\Cache::delete();
1902
1903 return $settings;
1904 }
1905
1906 /**
1907 * Display the default thumbnail below the setting.
1908 *
1909 * @since 3.3.0
1910 *
1911 * @param string $html Current HTML.
1912 * @param array $args Argument array of the setting.
1913 * @return string
1914 */
1915 public function display_admin_thumbnail( $html, $args ) {
1916
1917 $thumb_default = \tptn_get_option( 'thumb_default' );
1918
1919 if ( 'thumb_default' === $args['id'] && '' !== $thumb_default ) {
1920 $html .= '<br />';
1921 $html .= sprintf( '<img src="%1$s" style="max-width:200px" title="%2$s" alt="%2$s" />', esc_attr( $thumb_default ), esc_html__( 'Default thumbnail', 'top-10' ) );
1922 }
1923
1924 return $html;
1925 }
1926
1927 /**
1928 * Display the default thumbnail below the setting.
1929 *
1930 * @since 3.3.0
1931 *
1932 * @param string $html Current HTML.
1933 * @param array $args Argument array of the setting.
1934 * @return string
1935 */
1936 public function reset_default_thumb_setting( $html, $args ) {
1937
1938 $thumb_default = \tptn_get_option( 'thumb_default' );
1939
1940 if ( 'thumb_default' === $args['id'] && Display::get_default_thumbnail() !== $thumb_default ) {
1941 $html = '<span class="dashicons dashicons-undo reset-default-thumb" style="cursor: pointer;" title="' . __( 'Reset' ) . '"></span> <br />' . $html;
1942 }
1943
1944 return $html;
1945 }
1946
1947 /**
1948 * Add a link to the Tools page from the settings page.
1949 *
1950 * @since 3.5.0
1951 */
1952 public static function settings_page_header() {
1953 global $tptn_freemius;
1954 ?>
1955 <p>
1956 <?php if ( ! $tptn_freemius->is_paying() ) { ?>
1957 <a class="tptn_button tptn_button_gold" href="<?php echo esc_url( $tptn_freemius->get_upgrade_url() ); ?>">
1958 <?php esc_html_e( 'Upgrade to Pro', 'top-10' ); ?>
1959 </a>
1960 <?php } ?>
1961 </p>
1962
1963 <?php
1964 }
1965
1966 /**
1967 * Updated the settings fields to display a pro version link.
1968 *
1969 * @param string $output Settings field HTML.
1970 * @param array $args Settings field arguments.
1971 * @return string Updated HTML.
1972 */
1973 public static function after_setting_output( $output, $args ) {
1974 if ( isset( $args['pro'] ) && $args['pro'] ) {
1975 $output .= sprintf(
1976 '<a class="tptn_button tptn_button_gold" target="_blank" href="%s" title="%s">%s</a>',
1977 esc_url( \WebberZone\Top_Ten\tptn_freemius()->get_upgrade_url() ),
1978 esc_attr__( 'Upgrade to Pro', 'top-10' ),
1979 esc_html__( 'Upgrade to Pro', 'top-10' )
1980 );
1981 }
1982
1983 if ( isset( $args['id'] ) && 'tptn_styles' === $args['id'] ) {
1984 $post_thumb_op = \tptn_get_option( 'post_thumb_op' );
1985 $tptn_style = \tptn_get_option( 'tptn_styles' );
1986
1987 if ( 'text_only' === $post_thumb_op && 'text_only' !== $tptn_style ) {
1988 $output .= sprintf(
1989 '<p class="description" style="color:#9B0800;">%s</p>',
1990 esc_html__( 'Note: Thumbnail location is set to "Do not display thumbnails, only text". This may override the selected style.', 'top-10' )
1991 );
1992 }
1993 }
1994
1995 return $output;
1996 }
1997
1998 /**
1999 * Add a button to the settings page to start the settings wizard.
2000 *
2001 * @since 4.2.0
2002 */
2003 public function add_wizard_button() {
2004 printf(
2005 '<br /><a aria-label="%s" class="button button-secondary" href="%s" title="%s" style="margin-top: 10px;">%s</a>',
2006 esc_attr__( 'Start Settings Wizard', 'top-10' ),
2007 esc_url( admin_url( 'admin.php?page=tptn_wizard' ) ),
2008 esc_attr__( 'Start Settings Wizard', 'top-10' ),
2009 esc_html__( 'Start Settings Wizard', 'top-10' )
2010 );
2011 }
2012
2013 /**
2014 * Handle Tom Select taxonomy search AJAX requests.
2015 *
2016 * @since 4.2.0
2017 *
2018 * @return void
2019 */
2020 public static function taxonomy_search_tom_select() {
2021 // Verify nonce.
2022 if ( ! isset( $_REQUEST['nonce'] ) ) {
2023 wp_send_json_error( array( 'message' => 'Missing nonce' ) );
2024 }
2025
2026 $nonce_valid = wp_verify_nonce( sanitize_key( $_REQUEST['nonce'] ), self::$prefix . '_taxonomy_search_tom_select' );
2027
2028 if ( ! $nonce_valid ) {
2029 wp_send_json_error(
2030 array(
2031 'message' => 'Invalid nonce',
2032 'received_nonce' => sanitize_key( $_REQUEST['nonce'] ),
2033 'expected_action' => self::$prefix . '_taxonomy_search_tom_select',
2034 )
2035 );
2036 }
2037
2038 if ( ! isset( $_REQUEST['endpoint'] ) ) { // phpcs:ignore WordPress.Security.NonceVerification.Recommended
2039 wp_send_json_error( 'Missing endpoint' );
2040 }
2041
2042 $endpoint = sanitize_key( $_REQUEST['endpoint'] ); // phpcs:ignore WordPress.Security.NonceVerification.Recommended
2043
2044 $search_term = isset( $_REQUEST['q'] ) ? sanitize_text_field( wp_unslash( $_REQUEST['q'] ) ) : ''; // phpcs:ignore WordPress.Security.NonceVerification.Recommended
2045
2046 $comma = _x( ',', 'tag delimiter', 'top-10' );
2047 if ( ',' !== $comma ) {
2048 $search_term = str_replace( $comma, ',', $search_term );
2049 }
2050 if ( false !== strpos( $search_term, ',' ) ) {
2051 $search_term = explode( ',', $search_term );
2052 $search_term = $search_term[ count( $search_term ) - 1 ];
2053 }
2054 $search_term = trim( $search_term, " \t\n\r\0\x0B" );
2055
2056 if ( 'public_taxonomies' === $endpoint ) {
2057 $taxonomies = (array) get_taxonomies( array( 'public' => true ), 'objects' );
2058 $taxonomy = array();
2059 $tax = null;
2060
2061 foreach ( $taxonomies as $taxonomy_name => $taxonomy_object ) {
2062 if ( empty( $taxonomy_object->cap->assign_terms ) ) {
2063 continue;
2064 }
2065
2066 if ( ! current_user_can( $taxonomy_object->cap->assign_terms ) ) {
2067 continue;
2068 }
2069
2070 $taxonomy[] = $taxonomy_object->name;
2071 }
2072
2073 if ( empty( $taxonomy ) ) {
2074 wp_send_json_success( array() );
2075 }
2076
2077 $tax = get_taxonomy( $taxonomy[0] );
2078 } else {
2079 $taxonomy = $endpoint;
2080 $tax = get_taxonomy( $taxonomy );
2081
2082 if ( ! $tax ) {
2083 wp_send_json_error( 'Invalid taxonomy' );
2084 }
2085
2086 if ( ! current_user_can( $tax->cap->assign_terms ) ) {
2087 wp_send_json_error( 'Insufficient permissions' );
2088 }
2089 }
2090
2091 /**
2092 * This filter has been defined in /wp-admin/includes/ajax-actions.php
2093 */
2094 $term_search_min_chars = (int) apply_filters( 'term_search_min_chars', 2, $tax, $search_term );
2095
2096 /*
2097 * Require $term_search_min_chars chars for matching (default: 2)
2098 * ensure it's a non-negative, non-zero integer.
2099 */
2100 if ( ( 0 === $term_search_min_chars ) || ( strlen( $search_term ) < $term_search_min_chars ) ) {
2101 wp_send_json_success( array() );
2102 }
2103
2104 $terms = get_terms(
2105 array(
2106 'taxonomy' => $taxonomy,
2107 'name__like' => $search_term,
2108 'hide_empty' => false,
2109 )
2110 );
2111
2112 $results = array();
2113 foreach ( (array) $terms as $term ) {
2114 $formatted_string = "{$term->name} ({$term->taxonomy}:{$term->term_taxonomy_id})";
2115 $results[] = array(
2116 'value' => $formatted_string,
2117 'text' => $term->name,
2118 );
2119 }
2120
2121 wp_send_json_success( $results );
2122 }
2123
2124 /**
2125 * Get field attributes for Tom Select taxonomy search fields.
2126 *
2127 * @since 4.2.0
2128 *
2129 * @param string $taxonomy The taxonomy to search.
2130 * @param array $ts_config Optional Tom Select configuration.
2131 * @return array Field attributes array.
2132 */
2133 private static function get_taxonomy_search_field_attributes( $taxonomy, $ts_config = array() ) {
2134 $attributes = array(
2135 'data-wp-prefix' => strtoupper( (string) self::$prefix ),
2136 'data-wp-action' => self::$prefix . '_taxonomy_search_tom_select',
2137 'data-wp-nonce' => wp_create_nonce( self::$prefix . '_taxonomy_search_tom_select' ),
2138 'data-wp-endpoint' => $taxonomy,
2139 );
2140
2141 if ( ! empty( $ts_config ) ) {
2142 $attributes['data-ts-config'] = wp_json_encode( $ts_config );
2143 }
2144
2145 return $attributes;
2146 }
2147
2148 /**
2149 * Get field attributes for Tom Select meta key search fields.
2150 *
2151 * @since 4.2.0
2152 *
2153 * @param array $ts_config Optional Tom Select configuration.
2154 * @return array Field attributes array.
2155 */
2156 private static function get_meta_keys_search_field_attributes( $ts_config = array() ) {
2157 $attributes = array(
2158 'data-wp-prefix' => strtoupper( (string) self::$prefix ),
2159 'data-wp-action' => self::$prefix . '_taxonomy_search_tom_select',
2160 'data-wp-nonce' => wp_create_nonce( self::$prefix . '_taxonomy_search_tom_select' ),
2161 'data-wp-endpoint' => 'meta_keys',
2162 );
2163
2164 if ( ! empty( $ts_config ) ) {
2165 $attributes['data-ts-config'] = wp_json_encode( $ts_config );
2166 }
2167
2168 return $attributes;
2169 }
2170 }
2171