PluginProbe ʕ •ᴥ•ʔ
Post Views Counter / 1.5.6
Post Views Counter v1.5.6
1.7.13 1.7.12 1.7.11 trunk 1.0.0 1.0.1 1.0.10 1.0.11 1.0.12 1.0.2 1.0.3 1.0.4 1.0.5 1.0.6 1.0.7 1.0.8 1.0.9 1.1.0 1.1.1 1.1.2 1.1.3 1.1.4 1.2.0 1.2.1 1.2.10 1.2.11 1.2.12 1.2.13 1.2.14 1.2.2 1.2.3 1.2.4 1.2.5 1.2.6 1.2.7 1.2.8 1.2.9 1.3 1.3.1 1.3.10 1.3.11 1.3.12 1.3.13 1.3.2 1.3.2.1 1.3.3 1.3.4 1.3.5 1.3.6 1.3.7 1.3.8 1.3.9 1.4 1.4.1 1.4.2 1.4.3 1.4.4 1.4.5 1.4.6 1.4.7 1.4.8 1.5.0 1.5.1 1.5.2 1.5.3 1.5.4 1.5.5 1.5.6 1.5.7 1.5.8 1.5.9 1.6.0 1.6.1 1.7.0 1.7.1 1.7.10 1.7.2 1.7.3 1.7.4 1.7.5 1.7.6 1.7.7 1.7.8 1.7.9
post-views-counter / includes / class-settings.php
post-views-counter / includes Last commit date
class-admin.php 8 months ago class-columns.php 8 months ago class-counter.php 8 months ago class-crawler-detect.php 8 months ago class-cron.php 8 months ago class-dashboard.php 8 months ago class-frontend.php 8 months ago class-functions.php 8 months ago class-query.php 8 months ago class-settings-api.php 8 months ago class-settings.php 8 months ago class-update.php 8 months ago class-widgets.php 8 months ago functions.php 8 months ago
class-settings.php
1585 lines
1 <?php
2 // exit if accessed directly
3 if ( ! defined( 'ABSPATH' ) )
4 exit;
5
6 /**
7 * Post_Views_Counter_Settings class.
8 *
9 * @class Post_Views_Counter_Settings
10 */
11 class Post_Views_Counter_Settings {
12
13 /**
14 * Class constructor.
15 *
16 * @return void
17 */
18 public function __construct() {
19 // actions
20 add_action( 'admin_init', [ $this, 'update_counter_mode' ], 12 );
21 add_action( 'pvc_settings_sidebar', [ $this, 'settings_sidebar' ], 12 );
22 add_action( 'pvc_settings_form', [ $this, 'settings_form' ], 10, 4 );
23
24 // filters
25 add_filter( 'post_views_counter_settings_data', [ $this, 'settings_data' ] );
26 add_filter( 'post_views_counter_settings_pages', [ $this, 'settings_page' ] );
27 add_filter( 'post_views_counter_settings_page_class', [ $this, 'settings_page_class' ] );
28 }
29
30 /**
31 * Add hidden inputs to redirect to valid page after changing menu position.
32 *
33 * @param string $setting
34 * @param string $page_type
35 * @param string $url_page
36 * @param string $tab_key
37 *
38 * @return void
39 */
40 public function settings_form( $setting, $page_type, $url_page, $tab_key ) {
41 // get main instance
42 $pvc = Post_Views_Counter();
43
44 // topmenu referer
45 $topmenu = '<input type="hidden" name="_wp_http_referer" data-pvc-menu="topmenu" value="' .esc_url( admin_url( 'admin.php?page=post-views-counter' . ( $tab_key !== '' ? '&tab=' . $tab_key : '' ) ) ) . '" />';
46
47 // submenu referer
48 $submenu = '<input type="hidden" name="_wp_http_referer" data-pvc-menu="submenu" value="' .esc_url( admin_url( 'options-general.php?page=post-views-counter' . ( $tab_key !== '' ? '&tab=' . $tab_key : '' ) ) ) . '" />';
49
50 if ( $pvc->options['other']['menu_position'] === 'sub' )
51 echo $topmenu . $submenu;
52 else
53 echo $submenu . $topmenu;
54 }
55
56 /**
57 * Display settings sidebar.
58 *
59 * @return void
60 */
61 public function settings_sidebar() {
62 // get main instance
63 $pvc = Post_Views_Counter();
64
65 if ( ! class_exists( 'Post_Views_Counter_Pro' ) ) {
66 echo '
67 <div class="post-views-sidebar">
68 <div class="post-views-credits">
69 <div class="inside">
70 <div class="inner">
71 <div class="pvc-sidebar-info">
72 <div class="pvc-sidebar-head">
73 <h3 class="pvc-sidebar-title">Get Post Views Counter Pro</h3>
74 </div>
75 <div class="pvc-sidebar-body">
76 <p><span class="pvc-icon pvc-icon-check"></span>' . __( '<b>Collect more accurate data</b> about the number of views of your site, regardless of what the user is visiting.', 'post-views-counter' ) . '</p>
77 <p><span class="pvc-icon pvc-icon-check"></span>' . __( '<b>Unlock optimization features</b> and caching plugins compatibility to speed up view count tracking.', 'post-views-counter' ) . '</p>
78 <p><span class="pvc-icon pvc-icon-check"></span>' . __( '<b>Take your insights to the next level</b> with customizable Views by Date, Post and Author reporting.', 'post-views-counter' ) . '</p>
79 <p><span class="pvc-icon pvc-icon-check"></span>' . __( '<b>Order posts by views count</b> using built-in Elementor Pro, Divi Theme and GenerateBlocks integration.', 'post-views-counter' ) . '</p>
80 </div>
81 <div class="pvc-pricing-footer">
82 <a href="https://postviewscounter.com/upgrade/?utm_source=post-views-counter-lite&utm_medium=button&utm_campaign=upgrade-to-pro" class="button button-secondary button-hero pvc-button" target="_blank">' . esc_html__( 'Upgrade to Pro', 'post-views-counter' ) . ' &rarr;</a>
83 <p>Starting from $29 per year<br />14-day money back guarantee.</p>
84 </div>
85 </div>
86 </div>
87 </div>
88 </div>
89 </div>';
90 }
91 }
92
93 /**
94 * Update counter mode.
95 *
96 * @return void
97 */
98 public function update_counter_mode() {
99 // get main instance
100 $pvc = Post_Views_Counter();
101
102 // get settings
103 $settings = $pvc->settings_api->get_settings();
104
105 // fast ajax as active but not available counter mode?
106 if ( $pvc->options['general']['counter_mode'] === 'ajax' && in_array( 'ajax', $settings['post-views-counter']['fields']['counter_mode']['disabled'], true ) ) {
107 // set standard javascript ajax calls
108 $pvc->options['general']['counter_mode'] = 'js';
109
110 // update database options
111 update_option( 'post_views_counter_settings_general', $pvc->options['general'] );
112 }
113 }
114
115 /**
116 * Get available counter modes.
117 *
118 * @return array
119 */
120 public function get_counter_modes() {
121 // counter modes
122 $modes = [
123 'php' => __( 'PHP', 'post-views-counter' ),
124 'js' => __( 'JavaScript', 'post-views-counter' ),
125 'rest_api' => __( 'REST API', 'post-views-counter' ),
126 'ajax' => __( 'Fast AJAX', 'post-views-counter' )
127 ];
128
129 return apply_filters( 'pvc_get_counter_modes', $modes );
130 }
131
132 /**
133 * Add settings data.
134 *
135 * @param array $settings
136 *
137 * @return array
138 */
139 public function settings_data( $settings ) {
140 // get main instance
141 $pvc = Post_Views_Counter();
142
143 // time types
144 $time_types = [
145 'minutes' => __( 'minutes', 'post-views-counter' ),
146 'hours' => __( 'hours', 'post-views-counter' ),
147 'days' => __( 'days', 'post-views-counter' ),
148 'weeks' => __( 'weeks', 'post-views-counter' ),
149 'months' => __( 'months', 'post-views-counter' ),
150 'years' => __( 'years', 'post-views-counter' )
151 ];
152
153 // user groups
154 $groups = [
155 'robots' => __( 'crawlers', 'post-views-counter' ),
156 'ai_bots' => __( 'AI bots', 'post-views-counter' ),
157 'users' => __( 'logged in users', 'post-views-counter' ),
158 'guests' => __( 'guests', 'post-views-counter' ),
159 'roles' => __( 'selected user roles', 'post-views-counter' )
160 ];
161
162 // get user roles
163 $user_roles = $pvc->functions->get_user_roles();
164
165 // get post types
166 $post_types = $pvc->functions->get_post_types();
167
168 // check object cache
169 $wp_using_ext_object_cache = wp_using_ext_object_cache();
170
171 // add settings
172 $settings['post-views-counter'] = [
173 'label' => __( 'Post Views Counter Settings', 'post-views-counter' ),
174 'form' => [
175 'reports' => [
176 'buttons' => false
177 ]
178 ],
179 'option_name' => [
180 'general' => 'post_views_counter_settings_general',
181 'display' => 'post_views_counter_settings_display',
182 'reports' => 'post_views_counter_settings_reports',
183 'other' => 'post_views_counter_settings_other'
184 ],
185 'validate' => [ $this, 'validate_settings' ],
186 'sections' => [
187 'post_views_counter_general_settings' => [
188 'tab' => 'general'
189 ],
190 'post_views_counter_display_settings' => [
191 'tab' => 'display'
192 ],
193 'post_views_counter_reports_settings' => [
194 'tab' => 'reports',
195 'callback' => [ $this, 'section_reports_placeholder' ]
196 ],
197 'post_views_counter_other_settings' => [
198 'tab' => 'other'
199 ]
200 ],
201 'fields' => [
202 'post_types_count' => [
203 'tab' => 'general',
204 'title' => __( 'Post Types Count', 'post-views-counter' ),
205 'section' => 'post_views_counter_general_settings',
206 'type' => 'checkbox',
207 'display_type' => 'horizontal',
208 'description' => __( 'Select post types for which post views will be counted.', 'post-views-counter' ),
209 'options' => $post_types
210 ],
211 'taxonomies_count' => [
212 'tab' => 'general',
213 'title' => __( 'Taxonomies Count', 'post-views-counter' ),
214 'section' => 'post_views_counter_general_settings',
215 'type' => 'custom',
216 'label' => __( 'Enable to count taxonomy terms visits.', 'post-views-counter' ),
217 'class' => 'pvc-pro',
218 'skip_saving' => true,
219 'callback' => [ $this, 'setting_taxonomies_count' ]
220 ],
221 'users_count' => [
222 'tab' => 'general',
223 'title' => __( 'Authors Count', 'post-views-counter' ),
224 'section' => 'post_views_counter_general_settings',
225 'type' => 'custom',
226 'label' => __( 'Enable to count authors archive visits.', 'post-views-counter' ),
227 'class' => 'pvc-pro',
228 'skip_saving' => true,
229 'callback' => [ $this, 'setting_users_count' ]
230 ],
231 'other_count' => [
232 'tab' => 'general',
233 'title' => __( 'Other Count', 'post-views-counter' ),
234 'section' => 'post_views_counter_general_settings',
235 'type' => 'boolean',
236 'label' => __( 'Enable to count visits of front page, post type and date archives, 404 and search pages.', 'post-views-counter' ),
237 'class' => 'pvc-pro',
238 'disabled' => true,
239 'skip_saving' => true,
240 'value' => false
241 ],
242 'counter_mode' => [
243 'tab' => 'general',
244 'title' => __( 'Counter Mode', 'post-views-counter' ),
245 'section' => 'post_views_counter_general_settings',
246 'type' => 'radio',
247 'description' => __( 'Select the method of collecting post views data. If you are using any of the caching plugins select JavaScript, REST API or Fast AJAX (up to <code>10+</code> times faster!).', 'post-views-counter' ),
248 'class' => 'pvc-pro-extended',
249 'options' => $this->get_counter_modes(),
250 'disabled' => [ 'ajax' ]
251 ],
252 'data_storage' => [
253 'tab' => 'general',
254 'title' => __( 'Data Storage', 'post-views-counter' ),
255 'section' => 'post_views_counter_general_settings',
256 'type' => 'radio',
257 'class' => 'pvc-pro',
258 'skip_saving' => true,
259 'description' => __( "Choose how to store the content views data in the user's browser - with or without cookies.", 'post-views-counter' ),
260 'options' => [
261 'cookies' => __( 'Cookies', 'post-views-counter' ),
262 'cookieless' => __( 'Cookieless', 'post-views-counter' )
263 ],
264 'disabled' => [ 'cookies', 'cookieless' ],
265 'value' => 'cookies'
266 ],
267 'amp_support' => [
268 'tab' => 'general',
269 'title' => __( 'AMP Support', 'post-views-counter' ),
270 'section' => 'post_views_counter_general_settings',
271 'type' => 'boolean',
272 'class' => 'pvc-pro',
273 'disabled' => true,
274 'skip_saving' => true,
275 'value' => false,
276 'label' => __( 'Enable to support Google AMP.', 'post-views-counter' ),
277 'description' => __( 'This feature requires official WordPress Google AMP plugin to be installed and activated.', 'post-views-counter' )
278 ],
279 'time_between_counts' => [
280 'tab' => 'general',
281 'title' => __( 'Count Interval', 'post-views-counter' ),
282 'section' => 'post_views_counter_general_settings',
283 'type' => 'custom',
284 'description' => '',
285 'min' => 0,
286 'max' => 999999,
287 'options' => $time_types,
288 'callback' => [ $this, 'setting_time_between_counts' ],
289 'validate' => [ $this, 'validate_time_between_counts' ]
290 ],
291 'count_time' => [
292 'tab' => 'general',
293 'title' => __( 'Count Time', 'post-views-counter' ),
294 'section' => 'post_views_counter_general_settings',
295 'type' => 'radio',
296 'class' => 'pvc-pro',
297 'skip_saving' => true,
298 'description' => __( 'Whether to store the views using GMT timezone or adjust it to the GMT offset of the site.', 'post-views-counter' ),
299 'options' => [
300 'gmt' => __( 'GMT Time', 'post-views-counter' ),
301 'local' => __( 'Local Time', 'post-views-counter' )
302 ],
303 'disabled' => [ 'gmt', 'local' ],
304 'value' => 'gmt'
305 ],
306 'strict_counts' => [
307 'tab' => 'general',
308 'title' => __( 'Strict counts', 'post-views-counter' ),
309 'section' => 'post_views_counter_general_settings',
310 'type' => 'boolean',
311 'class' => 'pvc-pro',
312 'disabled' => true,
313 'skip_saving' => true,
314 'value' => false,
315 'description' => '',
316 'label' => __( 'Enable to prevent bypassing the counts interval (for e.g. using incognito browser window or by clearing cookies).', 'post-views-counter' )
317 ],
318 'reset_counts' => [
319 'tab' => 'general',
320 'title' => __( 'Cleanup Interval', 'post-views-counter' ),
321 'section' => 'post_views_counter_general_settings',
322 'type' => 'custom',
323 'description' => sprintf( __( 'Delete single day post views data older than specified above. Enter %s if you want to preserve your daily views data regardless of its age.', 'post-views-counter' ), '<code>0</code>' ),
324 'min' => 0,
325 'max' => 999999,
326 'options' => $time_types,
327 'callback' => [ $this, 'setting_reset_counts' ],
328 'validate' => [ $this, 'validate_reset_counts' ]
329 ],
330 'caching_compatibility' => [
331 'tab' => 'general',
332 'title' => __( 'Caching Compatibility', 'post-views-counter' ),
333 'section' => 'post_views_counter_general_settings',
334 'type' => 'boolean',
335 'class' => 'pvc-pro',
336 'disabled' => true,
337 'value' => false,
338 'skip_saving' => true,
339 'label' => __( 'Enable to apply changes improving compatibility with caching plugins.', 'post-views-counter' ),
340 'description' => $this->get_caching_compatibility_description()
341 ],
342 'object_cache' => [
343 'tab' => 'general',
344 'title' => __( 'Object Cache Support', 'post-views-counter' ),
345 'section' => 'post_views_counter_general_settings',
346 'type' => 'boolean',
347 'class' => 'pvc-pro',
348 'disabled' => true,
349 'value' => false,
350 'skip_saving' => true,
351 'label' => sprintf( __( 'Enable to use object cache optimization.', 'post-views-counter' ), '<code>Redis</code>', '<code>Memcached</code>' ),
352 'description' => sprintf( __( 'This feature requires a persistent object cache like %s or %s to be installed and activated.', 'post-views-counter' ), '<code>Redis</code>', '<code>Memcached</code>' ) . '<br />' . __( 'Current status', 'post-views-counter' ) . ': <span class="' . ( $wp_using_ext_object_cache ? '' : 'un' ) . 'available">' . ( $wp_using_ext_object_cache ? __( 'available', 'post-views-counter' ) : __( 'unavailable', 'post-views-counter' ) ) . '</span>.'
353 ],
354 'exclude' => [
355 'tab' => 'general',
356 'title' => __( 'Exclude Visitors', 'post-views-counter' ),
357 'section' => 'post_views_counter_general_settings',
358 'type' => 'custom',
359 'description' => '',
360 'class' => 'pvc-pro-extended',
361 'options' => [
362 'groups' => $groups,
363 'roles' => $user_roles
364 ],
365 'disabled' => [
366 'groups' => [ 'ai_bots' ]
367 ],
368 'callback' => [ $this, 'setting_exclude' ],
369 'validate' => [ $this, 'validate_exclude' ]
370 ],
371 'exclude_ips' => [
372 'tab' => 'general',
373 'title' => __( 'Exclude IPs', 'post-views-counter' ),
374 'section' => 'post_views_counter_general_settings',
375 'type' => 'custom',
376 'description' => '',
377 'callback' => [ $this, 'setting_exclude_ips' ],
378 'validate' => [ $this, 'validate_exclude_ips' ]
379 ],
380 'label' => [
381 'tab' => 'display',
382 'title' => __( 'Views Label', 'post-views-counter' ),
383 'section' => 'post_views_counter_display_settings',
384 'type' => 'input',
385 'description' => __( 'Enter the label for the post views counter field.', 'post-views-counter' ),
386 'subclass' => 'regular-text',
387 'validate' => [ $this, 'validate_label' ],
388 'reset' => [ $this, 'reset_label' ]
389 ],
390 'display_period' => [
391 'tab' => 'display',
392 'title' => __( 'Views Period', 'post-views-counter' ),
393 'section' => 'post_views_counter_display_settings',
394 'type' => 'select',
395 'class' => 'pvc-pro',
396 'disabled' => true,
397 'skip_saving' => true,
398 'description' => __( 'Select the time period to be included when displaying the number of views. The default display is the total number of views of the post.', 'post-views-counter' ),
399 'options' => [
400 'total' => __( 'Total Views', 'post-views-counter' )
401 ]
402 ],
403 'display_style' => [
404 'tab' => 'display',
405 'title' => __( 'Display Style', 'post-views-counter' ),
406 'section' => 'post_views_counter_display_settings',
407 'type' => 'custom',
408 'description' => __( 'Choose how to display the post views counter.', 'post-views-counter' ),
409 'callback' => [ $this, 'setting_display_style' ],
410 'validate' => [ $this, 'validate_display_style' ],
411 'options' => [
412 'icon' => __( 'icon', 'post-views-counter' ),
413 'text' => __( 'label', 'post-views-counter' )
414 ]
415 ],
416 'icon_class' => [
417 'tab' => 'display',
418 'title' => __( 'Icon Class', 'post-views-counter' ),
419 'section' => 'post_views_counter_display_settings',
420 'type' => 'class',
421 'default' => '',
422 'description' => sprintf( __( 'Enter the post views icon class. Any of the <a href="%s" target="_blank">Dashicons</a> classes are available.', 'post-views-counter' ), 'https://developer.wordpress.org/resource/dashicons/' ),
423 'subclass' => 'regular-text'
424 ],
425 'position' => [
426 'tab' => 'display',
427 'title' => __( 'Position', 'post-views-counter' ),
428 'section' => 'post_views_counter_display_settings',
429 'type' => 'select',
430 'description' => sprintf( __( 'Select where would you like to display the post views counter. Use %s shortcode for manual display.', 'post-views-counter' ), '<code>[post-views]</code>' ),
431 'options' => [
432 'before' => __( 'before the content', 'post-views-counter' ),
433 'after' => __( 'after the content', 'post-views-counter' ),
434 'manual' => __( 'manual', 'post-views-counter' )
435 ]
436 ],
437 'post_views_column' => [
438 'tab' => 'display',
439 'title' => __( 'Admin Column', 'post-views-counter' ),
440 'section' => 'post_views_counter_display_settings',
441 'type' => 'boolean',
442 'description' => '',
443 'label' => __( 'Enable to display views count admin column.', 'post-views-counter' )
444 ],
445 'restrict_edit_views' => [
446 'tab' => 'display',
447 'title' => __( 'Admin Edit', 'post-views-counter' ),
448 'section' => 'post_views_counter_display_settings',
449 'type' => 'boolean',
450 'description' => '',
451 'label' => __( 'Enable to allow views count editing.', 'post-views-counter' )
452 ],
453 'dynamic_loading' => [
454 'tab' => 'display',
455 'title' => __( 'Dynamic Loading', 'post-views-counter' ),
456 'section' => 'post_views_counter_display_settings',
457 'type' => 'boolean',
458 'class' => 'pvc-pro',
459 'disabled' => true,
460 'skip_saving' => true,
461 'value' => false,
462 'label' => __( 'Enable dynamic loading and prevent caching of the displayed views count.', 'post-views-counter' )
463 ],
464 'use_format' => [
465 'tab' => 'display',
466 'title' => __( 'Format Number', 'post-views-counter' ),
467 'section' => 'post_views_counter_display_settings',
468 'type' => 'boolean',
469 'label' => __( 'Enable to display the views number formatted based on the locale (using the WP number_format_i18n function).', 'post-views-counter' )
470 ],
471 'taxonomies_display' => [
472 'tab' => 'display',
473 'title' => __( 'Taxonomies', 'post-views-counter' ),
474 'section' => 'post_views_counter_display_settings',
475 'type' => 'custom',
476 'class' => 'pvc-pro',
477 'skip_saving' => true,
478 'options' => $pvc->functions->get_taxonomies( 'labels' ),
479 'callback' => [ $this, 'setting_taxonomies_display' ]
480 ],
481 'user_display' => [
482 'tab' => 'display',
483 'title' => __( 'Authors', 'post-views-counter' ),
484 'section' => 'post_views_counter_display_settings',
485 'type' => 'boolean',
486 'class' => 'pvc-pro',
487 'disabled' => true,
488 'skip_saving' => true,
489 'value' => false,
490 'label' => __( 'Display number of views on authors archive pages.', 'post-views-counter' )
491 ],
492 'post_types_display' => [
493 'tab' => 'display',
494 'title' => __( 'Post Type', 'post-views-counter' ),
495 'section' => 'post_views_counter_display_settings',
496 'type' => 'checkbox',
497 'display_type' => 'horizontal',
498 'description' => __( 'Select post types for which the views count will be displayed.', 'post-views-counter' ),
499 'options' => $post_types
500 ],
501 'page_types_display' => [
502 'tab' => 'display',
503 'title' => __( 'Page Type', 'post-views-counter' ),
504 'section' => 'post_views_counter_display_settings',
505 'type' => 'checkbox',
506 'display_type' => 'horizontal',
507 'description' => __( 'Select page types where the views count will be displayed.', 'post-views-counter' ),
508 'options' => apply_filters(
509 'pvc_page_types_display_options',
510 [
511 'home' => __( 'Home', 'post-views-counter' ),
512 'archive' => __( 'Archives', 'post-views-counter' ),
513 'singular' => __( 'Single pages', 'post-views-counter' ),
514 'search' => __( 'Search results', 'post-views-counter' ),
515 ]
516 )
517 ],
518 'restrict_display' => [
519 'tab' => 'display',
520 'title' => __( 'User Type', 'post-views-counter' ),
521 'section' => 'post_views_counter_display_settings',
522 'type' => 'custom',
523 'description' => '',
524 'options' => [
525 'groups' => $groups,
526 'roles' => $user_roles
527 ],
528 'callback' => [ $this, 'setting_restrict_display' ],
529 'validate' => [ $this, 'validate_restrict_display' ]
530 ],
531 'toolbar_statistics' => [
532 'tab' => 'display',
533 'title' => __( 'Toolbar Chart', 'post-views-counter' ),
534 'section' => 'post_views_counter_display_settings',
535 'type' => 'boolean',
536 'description' => __( 'The post views chart will be displayed for the post types that are being counted.', 'post-views-counter' ),
537 'label' => __( 'Enable to display the post views chart at the toolbar.', 'post-views-counter' )
538 ],
539 'license' => [
540 'tab' => 'other',
541 'title' => __( 'License', 'post-views-counter' ),
542 'section' => 'post_views_counter_other_settings',
543 'disabled' => true,
544 'value' => $pvc->options['other']['license'],
545 'type' => 'input',
546 'description' => __( 'Enter your Post Views Counter Pro license key (requires Pro version to be installed and active).', 'post-views-counter' ),
547 'subclass' => 'regular-text',
548 'validate' => [ $this, 'validate_license' ],
549 'append' => '<span class="pvc-icon license-icon"></span>'
550 ],
551 'menu_position' => [
552 'tab' => 'other',
553 'title' => __( 'Menu Position', 'post-views-counter' ),
554 'section' => 'post_views_counter_other_settings',
555 'type' => 'radio',
556 'options' => [
557 'top' => __( 'Top menu', 'post-views-counter' ),
558 'sub' => __( 'Settings submenu', 'post-views-counter' )
559 ],
560 'description' => __( "Choose where to display the plugin's menu.", 'post-views-counter' ),
561 ],
562 'import_views' => [
563 'tab' => 'other',
564 'title' => __( 'Import Views', 'post-views-counter' ),
565 'section' => 'post_views_counter_other_settings',
566 'type' => 'custom',
567 'description' => '',
568 'skip_saving' => true,
569 'callback' => [ $this, 'setting_import_views' ]
570 ],
571 'delete_views' => [
572 'tab' => 'other',
573 'title' => __( 'Delete Views', 'post-views-counter' ),
574 'section' => 'post_views_counter_other_settings',
575 'type' => 'custom',
576 'description' => '',
577 'skip_saving' => true,
578 'callback' => [ $this, 'setting_delete_views' ]
579 ],
580 'deactivation_delete' => [
581 'tab' => 'other',
582 'title' => __( 'Deactivation', 'post-views-counter' ),
583 'section' => 'post_views_counter_other_settings',
584 'type' => 'boolean',
585 'description' => __( 'If you deactivate the plugin with this option enabled all plugin data will be deleted along with the number of post views.', 'post-views-counter' ),
586 'label' => __( 'Enable to delete all plugin data on deactivation.', 'post-views-counter' )
587 ]
588 ]
589 ];
590
591 return $settings;
592 }
593
594 /**
595 * Add settings page.
596 *
597 * @param array $pages
598 *
599 * @return array
600 */
601 public function settings_page( $pages ) {
602 // get main instance
603 $pvc = Post_Views_Counter();
604
605 // default page
606 $pages['post-views-counter'] = [
607 'menu_slug' => 'post-views-counter',
608 'page_title' => __( 'Post Views Counter Settings', 'post-views-counter' ),
609 'menu_title' => $pvc->options['other']['menu_position'] === 'sub' ? __( 'Post Views Counter', 'post-views-counter' ) : __( 'Post Views', 'post-views-counter' ),
610 'capability' => apply_filters( 'pvc_settings_capability', 'manage_options' ),
611 'callback' => null,
612 'tabs' => [
613 'general' => [
614 'label' => __( 'Counting', 'post-views-counter' ),
615 'option_name' => 'post_views_counter_settings_general'
616 ],
617 'display' => [
618 'label' => __( 'Display', 'post-views-counter' ),
619 'option_name' => 'post_views_counter_settings_display'
620 ],
621 'reports' => [
622 'label' => __( 'Reports', 'post-views-counter' ),
623 'option_name' => 'post_views_counter_settings_reports'
624 ],
625 'other' => [
626 'label' => __( 'Other', 'post-views-counter' ),
627 'option_name' => 'post_views_counter_settings_other'
628 ]
629 ]
630 ];
631
632 // update admin title
633 add_filter( 'admin_title', [ $this, 'admin_title' ], 10, 2 );
634
635 // submenu?
636 if ( $pvc->options['other']['menu_position'] === 'sub' ) {
637 $pages['post-views-counter']['type'] = 'settings_page';
638 // topmenu?
639 } else {
640 // highlight submenus
641 add_filter( 'submenu_file', [ $this, 'submenu_file' ], 10, 2 );
642
643 // add parameters
644 $pages['post-views-counter']['type'] = 'page';
645 $pages['post-views-counter']['icon'] = 'dashicons-chart-bar';
646 $pages['post-views-counter']['position'] = '99.301';
647
648 // add subpages
649 $pages['post-views-counter-general'] = [
650 'menu_slug' => 'post-views-counter',
651 'parent_slug' => 'post-views-counter',
652 'type' => 'subpage',
653 'page_title' => __( 'Counting', 'post-views-counter' ),
654 'menu_title' => __( 'Counting', 'post-views-counter' ),
655 'capability' => apply_filters( 'pvc_settings_capability', 'manage_options' ),
656 'callback' => null
657 ];
658
659 $pages['post-views-counter-display'] = [
660 'menu_slug' => 'post-views-counter&tab=display',
661 'parent_slug' => 'post-views-counter',
662 'type' => 'subpage',
663 'page_title' => __( 'Display', 'post-views-counter' ),
664 'menu_title' => __( 'Display', 'post-views-counter' ),
665 'capability' => apply_filters( 'pvc_settings_capability', 'manage_options' ),
666 'callback' => null
667 ];
668
669 $pages['post-views-counter-reports'] = [
670 'menu_slug' => 'post-views-counter&tab=reports',
671 'parent_slug' => 'post-views-counter',
672 'type' => 'subpage',
673 'page_title' => __( 'Reports', 'post-views-counter' ),
674 'menu_title' => __( 'Reports', 'post-views-counter' ),
675 'capability' => apply_filters( 'pvc_settings_capability', 'manage_options' ),
676 'callback' => null
677 ];
678
679 $pages['post-views-counter-other'] = [
680 'menu_slug' => 'post-views-counter&tab=other',
681 'parent_slug' => 'post-views-counter',
682 'type' => 'subpage',
683 'page_title' => __( 'Other', 'post-views-counter' ),
684 'menu_title' => __( 'Other', 'post-views-counter' ),
685 'capability' => apply_filters( 'pvc_settings_capability', 'manage_options' ),
686 'callback' => null
687 ];
688 }
689
690 return $pages;
691 }
692
693 /**
694 * Settings page CSS class(es).
695 *
696 * @param array $class
697 * @return array
698 */
699 public function settings_page_class( $class ) {
700 $is_pro = class_exists( 'Post_Views_Counter_Pro' );
701
702 if ( ! $is_pro )
703 $class[] = 'has-sidebar';
704
705 return $class;
706 }
707
708 /**
709 * Highlight submenu items.
710 *
711 * @param string|null $submenu_file
712 * @param string $parent_file
713 *
714 * @return string|null
715 */
716 public function submenu_file( $submenu_file, $parent_file ) {
717 if ( $parent_file === 'post-views-counter' ) {
718 $tab = isset( $_GET['tab'] ) ? sanitize_key( $_GET['tab'] ) : 'general';
719
720 if ( $tab !== 'general' )
721 return 'post-views-counter&tab=' . $tab;
722 }
723
724 return $submenu_file;
725 }
726
727 /**
728 * Update admin title.
729 *
730 * @global array $submenu
731 * @global string $pagenow
732 *
733 * @param string $admin_title
734 * @param string $title
735 *
736 * @return string
737 */
738 public function admin_title( $admin_title, $title ) {
739 global $submenu, $pagenow;
740
741 // get main instance
742 $pvc = Post_Views_Counter();
743
744 if ( isset( $_GET['page'] ) && $_GET['page'] === 'post-views-counter' ) {
745 if ( $pvc->options['other']['menu_position'] === 'sub' && $pagenow === 'options-general.php' ) {
746 // get tab
747 $tab = isset( $_GET['tab'] ) ? sanitize_key( $_GET['tab'] ) : 'general';
748
749 // get settings pages
750 $pages = $pvc->settings_api->get_pages();
751
752 if ( array_key_exists( $tab, $pages['post-views-counter']['tabs'] ) ) {
753 // update title
754 $admin_title = preg_replace( '/' . $pages['post-views-counter']['page_title'] . '/', $pages['post-views-counter']['page_title'] . ' - ' . $pages['post-views-counter']['tabs'][$tab]['label'], $admin_title, 1 );
755 }
756 } else if ( $pvc->options['other']['menu_position'] === 'top' && get_admin_page_parent() === 'post-views-counter' && ! empty( $submenu['post-views-counter'] ) ) {
757 // get tab
758 $tab = isset( $_GET['tab'] ) ? sanitize_key( $_GET['tab'] ) : 'general';
759
760 // get settings pages
761 $pages = $pvc->settings_api->get_pages();
762
763 if ( array_key_exists( 'post-views-counter-' . $tab, $pages ) ) {
764 // update title
765 $admin_title = $pages['post-views-counter']['page_title'] . ' - ' . preg_replace( '/' . $title . '/', $pages['post-views-counter-' . $tab]['page_title'], $admin_title, 1 );
766 }
767 }
768 }
769
770 return $admin_title;
771 }
772
773 /**
774 * Validate options.
775 *
776 * @global object $wpdb
777 *
778 * @param array $input
779 *
780 * @return array
781 */
782 public function validate_settings( $input ) {
783 // check capability
784 if ( ! current_user_can( 'manage_options' ) )
785 return $input;
786
787 global $wpdb;
788
789 // get main instance
790 $pvc = Post_Views_Counter();
791
792 // use internal settings api to validate settings first
793 $input = $pvc->settings_api->validate_settings( $input );
794
795 // update meta key on save changes
796 if ( isset( $_POST['post_views_counter_import_meta_key'] ) && isset( $_POST['save_post_views_counter_settings_other'] ) )
797 $input['import_meta_key'] = sanitize_key( $_POST['post_views_counter_import_meta_key'] );
798
799 // import post views data from another plugin
800 if ( isset( $_POST['post_views_counter_import_wp_postviews'] ) ) {
801 // make sure we do not change anything in the settings
802 $input = $pvc->options['other'];
803
804 // get views key
805 $meta_key = sanitize_key( apply_filters( 'pvc_import_meta_key', ( isset( $_POST['post_views_counter_import_meta_key'] ) ? $_POST['post_views_counter_import_meta_key'] : $pvc->options['other']['import_meta_key'] ) ) );
806
807 // set meta_key option
808 $input['import_meta_key'] = $meta_key;
809
810 // get views
811 $views = $wpdb->get_results( $wpdb->prepare( "SELECT post_id, meta_value FROM " . $wpdb->postmeta . " WHERE meta_key = %s", $meta_key ), ARRAY_A, 0 );
812
813 // any views?
814 if ( ! empty( $views ) ) {
815 $sql = [];
816
817 foreach ( $views as $view ) {
818 $sql[] = $wpdb->prepare( "(%d, 4, 'total', %d)", (int) $view['post_id'], (int) $view['meta_value'] );
819 }
820
821 $wpdb->query( "INSERT INTO " . $wpdb->prefix . "post_views(id, type, period, count) VALUES " . implode( ',', $sql ) . " ON DUPLICATE KEY UPDATE count = " . ( isset( $_POST['post_views_counter_import_wp_postviews_override'] ) ? '' : 'count + ' ) . "VALUES(count)" );
822
823 add_settings_error( 'wp_postviews_import', 'wp_postviews_import', __( 'Post views data imported successfully.', 'post-views-counter' ), 'updated' );
824 } else
825 add_settings_error( 'wp_postviews_import', 'wp_postviews_import', __( 'There was no post views data to import.', 'post-views-counter' ), 'updated' );
826 // delete all post views data
827 } elseif ( isset( $_POST['post_views_counter_reset_views'] ) ) {
828 // make sure we do not change anything in the settings
829 $input = $pvc->options['other'];
830
831 if ( $wpdb->query( 'TRUNCATE TABLE ' . $wpdb->prefix . 'post_views' ) )
832 add_settings_error( 'reset_post_views', 'reset_post_views', __( 'All existing data deleted successfully.', 'post-views-counter' ), 'updated' );
833 else
834 add_settings_error( 'reset_post_views', 'reset_post_views', __( 'Error occurred. All existing data were not deleted.', 'post-views-counter' ), 'error' );
835 // save general settings
836 } elseif ( isset( $_POST['save_post_views_counter_settings_general'] ) ) {
837 $input['update_version'] = $pvc->options['general']['update_version'];
838 $input['update_notice'] = $pvc->options['general']['update_notice'];
839 $input['update_delay_date'] = $pvc->options['general']['update_delay_date'];
840 // reset general settings
841 } elseif ( isset( $_POST['reset_post_views_counter_settings_general'] ) ) {
842 $input['update_version'] = $pvc->options['general']['update_version'];
843 $input['update_notice'] = $pvc->options['general']['update_notice'];
844 $input['update_delay_date'] = $pvc->options['general']['update_delay_date'];
845 }
846
847 return $input;
848 }
849
850 /**
851 * Get caching compatibility description.
852 *
853 * @return array
854 */
855 public function get_caching_compatibility_description() {
856 // caching compatibility description
857 $caching_compatibility_desc = '';
858
859 // get active caching plugins
860 $active_plugins = $this->get_active_caching_plugins();
861
862 if ( ! empty( $active_plugins ) ) {
863 $empty_active_caching_plugins = false;
864 $active_plugins_html = [];
865
866 $caching_compatibility_desc .= esc_html__( 'Currently detected active caching plugins', 'post-views-counter' ) . ': ';
867
868 foreach ( $active_plugins as $plugin ) {
869 $active_plugins_html[] = '<code>' . esc_html( $plugin ) . '</code>';
870 }
871
872 $caching_compatibility_desc .= implode( ', ', $active_plugins_html ) . '.';
873 } else {
874 $empty_active_caching_plugins = true;
875
876 $caching_compatibility_desc .= esc_html__( 'No compatible caching plugins found.', 'post-views-counter' );
877 }
878
879 return $caching_compatibility_desc . '<br />' . __( 'Current status', 'post-views-counter' ) . ': <span class="' . ( ! $empty_active_caching_plugins ? '' : 'un' ) . 'available">' . ( ! $empty_active_caching_plugins ? __( 'available', 'post-views-counter' ) : __( 'unavailable', 'post-views-counter' ) ) . '</span>.';
880 }
881
882 /**
883 * Extend active caching plugins.
884 *
885 * @param string $plugins
886 *
887 * @return array
888 */
889 public function extend_active_caching_plugins( $plugins ) {
890 // breeze
891 if ( $this->is_plugin_active( 'breeze' ) )
892 $plugins[] = 'Breeze';
893
894 return $plugins;
895 }
896
897 /**
898 * Check whether specified plugin is active.
899 *
900 * @param bool $is_plugin_active
901 * @param string $plugin
902 *
903 * @return bool
904 */
905 public function extend_is_plugin_active( $is_plugin_active, $plugin ) {
906 // breeze
907 if ( $plugin === 'breeze' && class_exists( 'Breeze_PurgeCache' ) && class_exists( 'Breeze_Options_Reader' ) && function_exists( 'breeze_get_option' ) && function_exists( 'breeze_update_option' ) && defined( 'BREEZE_VERSION' ) && version_compare( BREEZE_VERSION, '2.0.30', '>=' ) )
908 $is_plugin_active = true;
909
910 return $is_plugin_active;
911 }
912
913 /**
914 * Get active caching plugins.
915 *
916 * @return array
917 */
918 public function get_active_caching_plugins() {
919 $active_plugins = [];
920
921 // autoptimize
922 if ( $this->is_plugin_active( 'autoptimize' ) )
923 $active_plugins[] = 'Autoptimize';
924
925 // hummingbird
926 if ( $this->is_plugin_active( 'hummingbird' ) )
927 $active_plugins[] = 'Hummingbird';
928
929 // litespeed
930 if ( $this->is_plugin_active( 'litespeed' ) )
931 $active_plugins[] = 'LiteSpeed Cache';
932
933 // speed optimizer
934 if ( $this->is_plugin_active( 'speedoptimizer' ) )
935 $active_plugins[] = 'Speed Optimizer';
936
937 // speedycache
938 if ( $this->is_plugin_active( 'speedycache' ) )
939 $active_plugins[] = 'SpeedyCache';
940
941 // wp fastest cache
942 if ( $this->is_plugin_active( 'wpfastestcache' ) )
943 $active_plugins[] = 'WP Fastest Cache';
944
945 // wp-optimize
946 if ( $this->is_plugin_active( 'wpoptimize' ) )
947 $active_plugins[] = 'WP-Optimize';
948
949 // wp rocket
950 if ( $this->is_plugin_active( 'wprocket' ) )
951 $active_plugins[] = 'WP Rocket';
952
953 // wp super cache
954 // if ( $this->is_plugin_active( 'wpsupercache' ) )
955 // $active_plugins[] = 'WP Super Cache';
956
957 return apply_filters( 'pvc_active_caching_plugins', $active_plugins );
958 }
959
960 /**
961 * Check whether specified plugin is active.
962 *
963 * @global object $siteground_optimizer_loader
964 * @global int $wpsc_version
965 *
966 * @param string $plugin
967 *
968 * @return bool
969 */
970 public function is_plugin_active( $plugin = '' ) {
971 // set default flag
972 $is_plugin_active = false;
973
974 switch ( $plugin ) {
975 // autoptimize
976 case 'autoptimize':
977 if ( function_exists( 'autoptimize' ) && defined( 'AUTOPTIMIZE_PLUGIN_VERSION' ) && version_compare( AUTOPTIMIZE_PLUGIN_VERSION, '2.4', '>=' ) )
978 $is_plugin_active = true;
979 break;
980
981 // hummingbird
982 case 'hummingbird':
983 if ( class_exists( 'Hummingbird\\WP_Hummingbird' ) && defined( 'WPHB_VERSION' ) && version_compare( WPHB_VERSION, '2.1.0', '>=' ) )
984 $is_plugin_active = true;
985 break;
986
987 // litespeed
988 case 'litespeed':
989 if ( class_exists( 'LiteSpeed\Core' ) && defined( 'LSCWP_CUR_V' ) && version_compare( LSCWP_CUR_V, '3.0', '>=' ) )
990 $is_plugin_active = true;
991 break;
992
993 // speed optimizer
994 case 'speedoptimizer':
995 global $siteground_optimizer_loader;
996
997 if ( ! empty( $siteground_optimizer_loader ) && is_object( $siteground_optimizer_loader ) && is_a( $siteground_optimizer_loader, 'SiteGround_Optimizer\Loader\Loader' ) && defined( '\SiteGround_Optimizer\VERSION' ) && version_compare( \SiteGround_Optimizer\VERSION, '5.5', '>=' ) )
998 $is_plugin_active = true;
999 break;
1000
1001 // speedycache
1002 case 'speedycache':
1003 if ( class_exists( 'SpeedyCache' ) && defined( 'SPEEDYCACHE_VERSION' ) && function_exists( 'speedycache_delete_cache' ) && version_compare( SPEEDYCACHE_VERSION, '1.0.0', '>=' ) )
1004 $is_plugin_active = true;
1005 break;
1006
1007 // wp fastest cache
1008 case 'wpfastestcache':
1009 if ( function_exists( 'wpfc_clear_all_cache' ) )
1010 $is_plugin_active = true;
1011 break;
1012
1013 // wp-optimize
1014 case 'wpoptimize':
1015 if ( function_exists( 'WP_Optimize' ) && defined( 'WPO_VERSION' ) && version_compare( WPO_VERSION, '3.0.12', '>=' ) )
1016 $is_plugin_active = true;
1017 break;
1018
1019 // wp rocket
1020 case 'wprocket':
1021 if ( function_exists( 'rocket_init' ) && defined( 'WP_ROCKET_VERSION' ) && version_compare( WP_ROCKET_VERSION, '3.8', '>=' ) )
1022 $is_plugin_active = true;
1023 break;
1024
1025 // wp super cache
1026 // case 'wpsupercache':
1027 // global $wpsc_version;
1028
1029 // if ( ( ! empty( $wpsc_version ) && $wpsc_version >= 169 ) || ( defined( 'WPSC_VERSION' ) && version_compare( WPSC_VERSION, '1.6.9', '>=' ) ) )
1030 // $is_plugin_active = true;
1031 // break;
1032
1033 // other caching plugin
1034 default:
1035 $is_plugin_active = apply_filters( 'pvc_is_plugin_active', false, $plugin );
1036 }
1037
1038 return $is_plugin_active;
1039 }
1040
1041 /**
1042 * Setting: taxonomies count.
1043 *
1044 * @param array $field
1045 * @return string
1046 */
1047 public function setting_taxonomies_count( $field ) {
1048 $html = '
1049 <label><input id="post_views_counter_general_taxonomies_count" type="checkbox" name="" value="" disabled />' . esc_html( $field['label'] ) . '</label>';
1050
1051 return $html;
1052 }
1053
1054 /**
1055 * Setting: users count.
1056 *
1057 * @param array $field
1058 * @return string
1059 */
1060 public function setting_users_count( $field ) {
1061 // get base instance
1062 $pvc = Post_Views_Counter();
1063
1064 $html = '
1065 <label><input id="post_views_counter_general_users_count" type="checkbox" name="" value="" disabled />' . esc_html( $field['label'] ) . '</label>';
1066
1067 return $html;
1068 }
1069
1070 /**
1071 * Setting: taxonomies count.
1072 *
1073 * @param array $field
1074 * @return string
1075 */
1076 public function setting_taxonomies_display( $field ) {
1077 // get base instance
1078 $pvc = Post_Views_Counter();
1079
1080 $html = '';
1081
1082 foreach ( $field['options'] as $taxonomy => $label ) {
1083 $html .= '
1084 <label><input type="checkbox" name="" value="" disabled />' . esc_html( $label ) . '</label>';
1085 }
1086
1087 $html .= '
1088 <p class="description">' . esc_html__( 'Select taxonomies for which the views count will be displayed.', 'post-views-counter' ) . '</p>';
1089
1090 return $html;
1091 }
1092
1093 /**
1094 * Validate label.
1095 *
1096 * @param array $input
1097 * @param array $field
1098 * @return array
1099 */
1100 public function validate_label( $input, $field ) {
1101 // get main instance
1102 $pvc = Post_Views_Counter();
1103
1104 if ( ! isset( $input ) )
1105 $input = $pvc->defaults['display']['label'];
1106
1107 // use internal settings API to validate settings first
1108 $input = $pvc->settings_api->validate_field( $input, 'input', $field );
1109
1110 if ( function_exists( 'icl_register_string' ) )
1111 icl_register_string( 'Post Views Counter', 'Post Views Label', $input );
1112
1113 return $input;
1114 }
1115
1116 /**
1117 * Restore post views label to default value.
1118 *
1119 * @param array $default
1120 * @param array $field
1121 * @return array
1122 */
1123 public function reset_label( $default, $field ) {
1124 if ( function_exists( 'icl_register_string' ) )
1125 icl_register_string( 'Post Views Counter', 'Post Views Label', $default );
1126
1127 return $default;
1128 }
1129
1130 /**
1131 * Setting: display style.
1132 *
1133 * @param array $field
1134 * @return string
1135 */
1136 public function setting_display_style( $field ) {
1137 // get main instance
1138 $pvc = Post_Views_Counter();
1139
1140 $html = '
1141 <input type="hidden" name="post_views_counter_settings_display[display_style]" value="empty" />';
1142
1143 foreach ( $field['options'] as $key => $label ) {
1144 $html .= '
1145 <label><input id="post_views_counter_display_display_style_' . esc_attr( $key ) . '" type="checkbox" name="post_views_counter_settings_display[display_style][]" value="' . esc_attr( $key ) . '" ' . checked( ! empty( $pvc->options['display']['display_style'][$key] ), true, false ) . ' />' . esc_html( $label ) . '</label> ';
1146 }
1147
1148 return $html;
1149 }
1150
1151 /**
1152 * Validate display style.
1153 *
1154 * @param array $input
1155 * @param array $field
1156 * @return array
1157 */
1158 public function validate_display_style( $input, $field ) {
1159 // get main instance
1160 $pvc = Post_Views_Counter();
1161
1162 $data = [];
1163
1164 foreach ( $field['options'] as $value => $label ) {
1165 $data[$value] = false;
1166 }
1167
1168 // any data?
1169 if ( ! empty( $input['display_style'] && $input['display_style'] !== 'empty' && is_array( $input['display_style'] ) ) ) {
1170 foreach ( $input['display_style'] as $value ) {
1171 if ( array_key_exists( $value, $field['options'] ) )
1172 $data[$value] = true;
1173 }
1174 }
1175
1176 $input['display_style'] = $data;
1177
1178 return $input;
1179 }
1180
1181 /**
1182 * Setting: count interval.
1183 *
1184 * @param array $field
1185 * @return string
1186 */
1187 public function setting_time_between_counts( $field ) {
1188 // get main instance
1189 $pvc = Post_Views_Counter();
1190
1191 $html = '
1192 <input size="6" type="number" min="' . ( (int) $field['min'] ) . '" max="' . ( (int) $field['max'] ) . '" name="post_views_counter_settings_general[time_between_counts][number]" value="' . esc_attr( $pvc->options['general']['time_between_counts']['number'] ) . '" />
1193 <select name="post_views_counter_settings_general[time_between_counts][type]">';
1194
1195 foreach ( $field['options'] as $type => $type_name ) {
1196 $html .= '
1197 <option value="' . esc_attr( $type ) . '" ' . selected( $type, $pvc->options['general']['time_between_counts']['type'], false ) . '>' . esc_html( $type_name ) . '</option>';
1198 }
1199
1200 $html .= '
1201 </select>
1202 <p class="description">' . sprintf( __( 'Enter the time between single user visit count. Enter %s if you want to count every page view.', 'post-views-counter' ), '<code>0</code>' ) . '</p>';
1203
1204 return $html;
1205 }
1206
1207 /**
1208 * Validate count interval.
1209 *
1210 * @param array $input
1211 * @param array $field
1212 * @return array
1213 */
1214 public function validate_time_between_counts( $input, $field ) {
1215 // get main instance
1216 $pvc = Post_Views_Counter();
1217
1218 // number
1219 $input['time_between_counts']['number'] = isset( $input['time_between_counts']['number'] ) ? (int) $input['time_between_counts']['number'] : $pvc->defaults['general']['time_between_counts']['number'];
1220
1221 if ( $input['time_between_counts']['number'] < $field['min'] || $input['time_between_counts']['number'] > $field['max'] )
1222 $input['time_between_counts']['number'] = $pvc->defaults['general']['time_between_counts']['number'];
1223
1224 // type
1225 $input['time_between_counts']['type'] = isset( $input['time_between_counts']['type'], $field['options'][$input['time_between_counts']['type']] ) ? $input['time_between_counts']['type'] : $pvc->defaults['general']['time_between_counts']['type'];
1226
1227 return $input;
1228 }
1229
1230 /**
1231 * Setting: reset data interval.
1232 *
1233 * @param array $field
1234 * @return string
1235 */
1236 public function setting_reset_counts( $field ) {
1237 // get main instance
1238 $pvc = Post_Views_Counter();
1239
1240 $html = '
1241 <input size="6" type="number" min="' . ( (int) $field['min'] ) . '" max="' . ( (int) $field['max'] ) . '" name="post_views_counter_settings_general[reset_counts][number]" value="' . esc_attr( $pvc->options['general']['reset_counts']['number'] ) . '" />
1242 <select name="post_views_counter_settings_general[reset_counts][type]">';
1243
1244 foreach ( array_slice( $field['options'], 2, null, true ) as $type => $type_name ) {
1245 $html .= '
1246 <option value="' . esc_attr( $type ) . '" ' . selected( $type, $pvc->options['general']['reset_counts']['type'], false ) . '>' . esc_html( $type_name ) . '</option>';
1247 }
1248
1249 $html .= '
1250 </select>';
1251
1252 return $html;
1253 }
1254
1255 /**
1256 * Validate reset data interval.
1257 *
1258 * @param array $input
1259 * @param array $field
1260 * @return array
1261 */
1262 public function validate_reset_counts( $input, $field ) {
1263 // get main instance
1264 $pvc = Post_Views_Counter();
1265
1266 // number
1267 $input['reset_counts']['number'] = isset( $input['reset_counts']['number'] ) ? (int) $input['reset_counts']['number'] : $pvc->defaults['general']['reset_counts']['number'];
1268
1269 if ( $input['reset_counts']['number'] < $field['min'] || $input['reset_counts']['number'] > $field['max'] )
1270 $input['reset_counts']['number'] = $pvc->defaults['general']['reset_counts']['number'];
1271
1272 // type
1273 $input['reset_counts']['type'] = isset( $input['reset_counts']['type'], $field['options'][$input['reset_counts']['type']] ) ? $input['reset_counts']['type'] : $pvc->defaults['general']['reset_counts']['type'];
1274
1275 // run cron on next visit?
1276 $input['cron_run'] = ( $input['reset_counts']['number'] > 0 );
1277
1278 // cron update?
1279 $input['cron_update'] = ( $input['cron_run'] && ( $pvc->options['general']['reset_counts']['number'] !== $input['reset_counts']['number'] || $pvc->options['general']['reset_counts']['type'] !== $input['reset_counts']['type'] ) );
1280
1281 return $input;
1282 }
1283
1284 /**
1285 * Setting: object cache.
1286 *
1287 * @param array $field
1288 * @return string
1289 */
1290 public function setting_object_cache( $field ) {
1291 // get main instance
1292 $pvc = Post_Views_Counter();
1293
1294 // check object cache
1295 $wp_using_ext_object_cache = wp_using_ext_object_cache();
1296
1297 $html = '
1298 <input size="4" type="number" min="' . ( (int) $field['min'] ) . '" max="' . ( (int) $field['max'] ) . '" name="" value="0" disabled /> <span>' . __( 'minutes', 'post-views-counter' ) . '</span>
1299 <p class="">' . __( 'Persistent Object Cache', 'post-views-counter' ) . ': <span class="' . ( $wp_using_ext_object_cache ? '' : 'un' ) . 'available">' . ( $wp_using_ext_object_cache ? __( 'available', 'post-views-counter' ) : __( 'unavailable', 'post-views-counter' ) ) . '</span></p>
1300 <p class="description">' . sprintf( __( 'How often to flush cached view counts from the object cache into the database. This feature is used only if a persistent object cache like %s or %s is detected and the interval is greater than %s. When used, view counts will be collected and stored in the object cache instead of the database and will then be asynchronously flushed to the database according to the specified interval. The maximum value is %s which means 24 hours.%sNotice:%s Potential data loss may occur if the object cache is cleared/unavailable for the duration of the interval.', 'post-views-counter' ), '<code>Redis</code>', '<code>Memcached</code>', '<code>0</code>', '<code>1440</code>', '<br /><strong> ', '</strong>' ) . '</p>';
1301
1302 return $html;
1303 }
1304
1305 /**
1306 * Setting: exclude visitors.
1307 *
1308 * @param array $field
1309 * @return string
1310 */
1311 public function setting_exclude( $field ) {
1312 // get main instance
1313 $pvc = Post_Views_Counter();
1314
1315 $html = '';
1316
1317 foreach ( $field['options']['groups'] as $type => $type_name ) {
1318 $is_disabled = ! empty( $field['disabled']['groups'] ) && in_array( $type, $field['disabled']['groups'], true );
1319
1320 $html .= '
1321 <label for="' . esc_attr( 'pvc_exclude-' . $type ) . '"><input id="' . esc_attr( 'pvc_exclude-' . $type ) . '" type="checkbox" name="post_views_counter_settings_general[exclude][groups][' . esc_attr( $type ) . ']" value="1" ' . checked( in_array( $type, $pvc->options['general']['exclude']['groups'], true ) && ! $is_disabled, true, false ) . ' ' . disabled( $is_disabled, true, false ) . ' />' . esc_html( $type_name ) . '</label>';
1322 }
1323
1324 $html .= '
1325 <p class="description">' . __( 'Use it exclude specific user groups from post views count.', 'post-views-counter' ) . '</p>
1326 <div class="pvc_user_roles pvc_subfield"' . ( in_array( 'roles', $pvc->options['general']['exclude']['groups'], true ) ? '' : ' style="display: none;"' ) . '>';
1327
1328 foreach ( $field['options']['roles'] as $role => $role_name ) {
1329 $html .= '
1330 <label><input type="checkbox" name="post_views_counter_settings_general[exclude][roles][' . $role . ']" value="1" ' . checked( in_array( $role, $pvc->options['general']['exclude']['roles'], true ), true, false ) . ' />' . esc_html( $role_name ) . '</label>';
1331 }
1332
1333 $html .= '
1334 <p class="description">' . __( 'Use it to exclude specific user roles from post views count.', 'post-views-counter' ) . '</p>
1335 </div>';
1336
1337 return $html;
1338 }
1339
1340 /**
1341 * Validate exclude visitors.
1342 *
1343 * @param array $input
1344 * @param array $field
1345 * @return array
1346 */
1347 public function validate_exclude( $input, $field ) {
1348 // any groups?
1349 if ( isset( $input['exclude']['groups'] ) ) {
1350 $groups = [];
1351
1352 foreach ( $input['exclude']['groups'] as $group => $set ) {
1353 // disallow disabled checkboxes
1354 if ( ! empty( $field['disabled']['groups'] ) && in_array( $group, $field['disabled']['groups'], true ) )
1355 continue;
1356
1357 if ( isset( $field['options']['groups'][$group] ) )
1358 $groups[] = $group;
1359 }
1360
1361 $input['exclude']['groups'] = array_unique( $groups );
1362 } else
1363 $input['exclude']['groups'] = [];
1364
1365 // any roles?
1366 if ( in_array( 'roles', $input['exclude']['groups'], true ) && isset( $input['exclude']['roles'] ) ) {
1367 $roles = [];
1368
1369 foreach ( $input['exclude']['roles'] as $role => $set ) {
1370 if ( isset( $field['options']['roles'][$role] ) )
1371 $roles[] = $role;
1372 }
1373
1374 $input['exclude']['roles'] = array_unique( $roles );
1375 } else
1376 $input['exclude']['roles'] = [];
1377
1378 return $input;
1379 }
1380
1381 /**
1382 * Setting: exclude IP addresses.
1383 *
1384 * @return string
1385 */
1386 public function setting_exclude_ips() {
1387 // get ip addresses
1388 $ips = Post_Views_Counter()->options['general']['exclude_ips'];
1389
1390 $html = '';
1391
1392 // any ip addresses?
1393 if ( ! empty( $ips ) ) {
1394 foreach ( $ips as $key => $ip ) {
1395 $html .= '
1396 <div class="ip-box">
1397 <input type="text" name="post_views_counter_settings_general[exclude_ips][]" value="' . esc_attr( $ip ) . '" /> <a href="#" class="remove-exclude-ip" title="' . esc_attr__( 'Remove', 'post-views-counter' ) . '">' . esc_html__( 'Remove', 'post-views-counter' ) . '</a>
1398 </div>';
1399 }
1400 } else {
1401 $html .= '
1402 <div class="ip-box">
1403 <input type="text" name="post_views_counter_settings_general[exclude_ips][]" value="" /> <a href="#" class="remove-exclude-ip" title="' . esc_attr__( 'Remove', 'post-views-counter' ) . '" style="display: none">' . esc_html__( 'Remove', 'post-views-counter' ) . '</a>
1404 </div>';
1405 }
1406
1407 $html .= '
1408 <p><input type="button" class="button button-secondary add-exclude-ip" value="' . esc_attr__( 'Add new', 'post-views-counter' ) . '" /> <input type="button" class="button button-secondary add-current-ip" value="' . esc_attr__( 'Add my current IP', 'post-views-counter' ) . '" data-rel="' . esc_attr( $_SERVER['REMOTE_ADDR'] ) . '" /></p>
1409 <p class="description">' . esc_html__( 'Enter the IP addresses to be excluded from post views count.', 'post-views-counter' ) . '</p>';
1410
1411 return $html;
1412 }
1413
1414 /**
1415 * Validate exclude IP addresses.
1416 *
1417 * @param array $input
1418 * @param array $field
1419 * @return array
1420 */
1421 public function validate_exclude_ips( $input, $field ) {
1422 // any ip addresses?
1423 if ( isset( $input['exclude_ips'] ) ) {
1424 $ips = [];
1425
1426 foreach ( $input['exclude_ips'] as $ip ) {
1427 if ( strpos( $ip, '*' ) !== false ) {
1428 $new_ip = str_replace( '*', '0', $ip );
1429
1430 if ( filter_var( $new_ip, FILTER_VALIDATE_IP, FILTER_FLAG_IPV4 ) )
1431 $ips[] = $ip;
1432 } elseif ( filter_var( $ip, FILTER_VALIDATE_IP, FILTER_FLAG_IPV4 ) )
1433 $ips[] = $ip;
1434 }
1435
1436 $input['exclude_ips'] = array_unique( $ips );
1437 }
1438
1439 return $input;
1440 }
1441
1442 /**
1443 * Setting: tools.
1444 *
1445 * @return string
1446 */
1447 public function setting_import_views() {
1448 $html = '
1449 <div>
1450 <input type="text" class="regular-text" name="post_views_counter_import_meta_key" value="' . esc_attr( Post_Views_Counter()->options['other']['import_meta_key'] ) . '"/>
1451 <p class="description">' . esc_html__( 'Enter the meta key from which the views data is to be retrieved during import.', 'post-views-counter' ) . '</p>
1452 </div>
1453 <div class="pvc-subfield">
1454 <input type="submit" class="button button-secondary" name="post_views_counter_import_wp_postviews" value="' . esc_attr__( 'Import Views', 'post-views-counter' ) . '"/> <label><input id="pvc-wp-postviews" type="checkbox" name="post_views_counter_import_wp_postviews_override" value="1" />' . esc_html__( 'Override existing views data during import.', 'post-views-counter' ) . '</label>
1455 <p class="description">' . esc_html__( 'Click Import Views to start importing the views data.', 'post-views-counter' ) . '</p>
1456 </div>';
1457
1458 return $html;
1459 }
1460
1461 /**
1462 * Setting: delete views.
1463 *
1464 * @return string
1465 */
1466 public function setting_delete_views() {
1467 $html = '
1468 <input type="submit" class="button button-secondary" name="post_views_counter_reset_views" value="' . esc_attr__( 'Delete Views', 'post-views-counter' ) . '" />
1469 <p class="description">' . esc_html__( 'Delete ALL the existing post views data. Note that this is an irreversible process!', 'post-views-counter' ) . '</p>';
1470
1471 return $html;
1472 }
1473
1474 /**
1475 * Setting: user type.
1476 *
1477 * @param array $field
1478 *
1479 * @return string
1480 */
1481 public function setting_restrict_display( $field ) {
1482 // get main instance
1483 $pvc = Post_Views_Counter();
1484
1485 $html = '';
1486
1487 foreach ( $field['options']['groups'] as $type => $type_name ) {
1488 if ( $type === 'robots' || $type === 'ai_bots' )
1489 continue;
1490
1491 $html .= '
1492 <label><input id="pvc_restrict_display-' . esc_attr( $type ) . '" type="checkbox" name="post_views_counter_settings_display[restrict_display][groups][' . esc_attr( $type ) . ']" value="1" ' . checked( in_array( $type, $pvc->options['display']['restrict_display']['groups'], true ), true, false ) . ' />' . esc_html( $type_name ) . '</label>';
1493 }
1494
1495 $html .= '
1496 <p class="description">' . __( 'Use it to hide the post views counter from selected type of visitors.', 'post-views-counter' ) . '</p>
1497 <div class="pvc_user_roles pvc-subfield"' . ( in_array( 'roles', $pvc->options['display']['restrict_display']['groups'], true ) ? '' : ' style="display: none;"' ) . '>';
1498
1499 foreach ( $field['options']['roles'] as $role => $role_name ) {
1500 $html .= '
1501 <label><input type="checkbox" name="post_views_counter_settings_display[restrict_display][roles][' . esc_attr( $role ) . ']" value="1" ' . checked( in_array( $role, $pvc->options['display']['restrict_display']['roles'], true ), true, false ) . ' />' . esc_html( $role_name ) . '</label>';
1502 }
1503
1504 $html .= '
1505 <p class="description">' . __( 'Use it to hide the post views counter from selected user roles.', 'post-views-counter' ) . '</p>
1506 </div>';
1507
1508 return $html;
1509 }
1510
1511 /**
1512 * Validate user type.
1513 *
1514 * @param array $input
1515 * @param array $field
1516 *
1517 * @return array
1518 */
1519 public function validate_restrict_display( $input, $field ) {
1520 // any groups?
1521 if ( isset( $input['restrict_display']['groups'] ) ) {
1522 $groups = [];
1523
1524 foreach ( $input['restrict_display']['groups'] as $group => $set ) {
1525 if ( $group === 'robots' || $group === 'ai_bots' )
1526 continue;
1527
1528 if ( isset( $field['options']['groups'][$group] ) )
1529 $groups[] = $group;
1530 }
1531
1532 $input['restrict_display']['groups'] = array_unique( $groups );
1533 } else
1534 $input['restrict_display']['groups'] = [];
1535
1536 // any roles?
1537 if ( in_array( 'roles', $input['restrict_display']['groups'], true ) && isset( $input['restrict_display']['roles'] ) ) {
1538 $roles = [];
1539
1540 foreach ( $input['restrict_display']['roles'] as $role => $set ) {
1541 if ( isset( $field['options']['roles'][$role] ) )
1542 $roles[] = $role;
1543 }
1544
1545 $input['restrict_display']['roles'] = array_unique( $roles );
1546 } else
1547 $input['restrict_display']['roles'] = [];
1548
1549 return $input;
1550 }
1551
1552 /**
1553 * Reports page placeholder.
1554 */
1555 public function section_reports_placeholder() {
1556 echo '
1557 <form action="#">
1558 <div id="pvc-reports-placeholder">
1559 <img id="pvc-reports-bg" src="' . esc_url( POST_VIEWS_COUNTER_URL ) . '/css/page-reports.png" alt="Post Views Counter - Reports" />
1560 <div id="pvc-reports-upgrade">
1561 <div id="pvc-reports-modal">
1562 <h2>' . esc_html__( 'Display Reports and Export Views to CSV/XML', 'post-views-counter' ) . '</h2>
1563 <p>' . esc_html__( 'View detailed stats about the popularity of your content.', 'post-views-counter' ) . '</p>
1564 <p>' . esc_html__( 'Generate views reports in any date range you need.', 'post-views-counter' ) . '</p>
1565 <p>' . esc_html__( 'Export, download and share your website views data.', 'post-views-counter' ) . '</p>
1566 <p><a href="https://postviewscounter.com/upgrade/?utm_source=post-views-counter-lite&utm_medium=button&utm_campaign=upgrade-to-pro" class="button button-secondary button-hero pvc-button" target="_blank">' . esc_html__( 'Upgrade to Pro', 'post-views-counter' ) . '</a></p>
1567 </div>
1568 </div>
1569 </div>
1570 </form>';
1571 }
1572
1573 /**
1574 * Validate license.
1575 *
1576 * @param array $input
1577 * @param array $field
1578 * @return array
1579 */
1580 public function validate_license( $input, $field ) {
1581 // save value from database
1582 return $field['value'];
1583 }
1584 }
1585