PluginProbe ʕ •ᴥ•ʔ
Post Views Counter / 1.5.9
Post Views Counter v1.5.9
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 7 months ago class-columns.php 7 months ago class-counter.php 7 months ago class-crawler-detect.php 7 months ago class-cron.php 7 months ago class-dashboard.php 7 months ago class-frontend.php 7 months ago class-functions.php 7 months ago class-query.php 7 months ago class-settings-api.php 7 months ago class-settings.php 7 months ago class-toolbar.php 7 months ago class-update.php 7 months ago class-widgets.php 7 months ago functions.php 7 months ago
class-settings.php
1596 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 'technology_count' => [
243 'tab' => 'general',
244 'title' => __( 'Sources Count', 'post-views-counter' ),
245 'section' => 'post_views_counter_general_settings',
246 'type' => 'boolean',
247 'label' => __( 'Enable to collect traffic information about browsers, devices, operating systems and referrers your website visitors are using.', 'post-views-counter' ),
248 'class' => 'pvc-pro',
249 'disabled' => true,
250 'skip_saving' => true,
251 'value' => false
252 ],
253 'counter_mode' => [
254 'tab' => 'general',
255 'title' => __( 'Counter Mode', 'post-views-counter' ),
256 'section' => 'post_views_counter_general_settings',
257 'type' => 'radio',
258 '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' ),
259 'class' => 'pvc-pro-extended',
260 'options' => $this->get_counter_modes(),
261 'disabled' => [ 'ajax' ]
262 ],
263 'data_storage' => [
264 'tab' => 'general',
265 'title' => __( 'Data Storage', 'post-views-counter' ),
266 'section' => 'post_views_counter_general_settings',
267 'type' => 'radio',
268 'class' => 'pvc-pro',
269 'skip_saving' => true,
270 'description' => __( "Choose how to store the content views data in the user's browser - with or without cookies.", 'post-views-counter' ),
271 'options' => [
272 'cookies' => __( 'Cookies', 'post-views-counter' ),
273 'cookieless' => __( 'Cookieless', 'post-views-counter' )
274 ],
275 'disabled' => [ 'cookies', 'cookieless' ],
276 'value' => 'cookies'
277 ],
278 'amp_support' => [
279 'tab' => 'general',
280 'title' => __( 'AMP Support', 'post-views-counter' ),
281 'section' => 'post_views_counter_general_settings',
282 'type' => 'boolean',
283 'class' => 'pvc-pro',
284 'disabled' => true,
285 'skip_saving' => true,
286 'value' => false,
287 'label' => __( 'Enable to support Google AMP.', 'post-views-counter' ),
288 'description' => __( 'This feature requires official WordPress Google AMP plugin to be installed and activated.', 'post-views-counter' )
289 ],
290 'time_between_counts' => [
291 'tab' => 'general',
292 'title' => __( 'Count Interval', 'post-views-counter' ),
293 'section' => 'post_views_counter_general_settings',
294 'type' => 'custom',
295 'description' => '',
296 'min' => 0,
297 'max' => 999999,
298 'options' => $time_types,
299 'callback' => [ $this, 'setting_time_between_counts' ],
300 'validate' => [ $this, 'validate_time_between_counts' ]
301 ],
302 'count_time' => [
303 'tab' => 'general',
304 'title' => __( 'Count Time', 'post-views-counter' ),
305 'section' => 'post_views_counter_general_settings',
306 'type' => 'radio',
307 'class' => 'pvc-pro',
308 'skip_saving' => true,
309 'description' => __( 'Whether to store the views using GMT timezone or adjust it to the GMT offset of the site.', 'post-views-counter' ),
310 'options' => [
311 'gmt' => __( 'GMT Time', 'post-views-counter' ),
312 'local' => __( 'Local Time', 'post-views-counter' )
313 ],
314 'disabled' => [ 'gmt', 'local' ],
315 'value' => 'gmt'
316 ],
317 'strict_counts' => [
318 'tab' => 'general',
319 'title' => __( 'Strict counts', 'post-views-counter' ),
320 'section' => 'post_views_counter_general_settings',
321 'type' => 'boolean',
322 'class' => 'pvc-pro',
323 'disabled' => true,
324 'skip_saving' => true,
325 'value' => false,
326 'description' => '',
327 'label' => __( 'Enable to prevent bypassing the counts interval (for e.g. using incognito browser window or by clearing cookies).', 'post-views-counter' )
328 ],
329 'reset_counts' => [
330 'tab' => 'general',
331 'title' => __( 'Cleanup Interval', 'post-views-counter' ),
332 'section' => 'post_views_counter_general_settings',
333 'type' => 'custom',
334 '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>' ),
335 'min' => 0,
336 'max' => 999999,
337 'options' => $time_types,
338 'callback' => [ $this, 'setting_reset_counts' ],
339 'validate' => [ $this, 'validate_reset_counts' ]
340 ],
341 'caching_compatibility' => [
342 'tab' => 'general',
343 'title' => __( 'Caching Compatibility', 'post-views-counter' ),
344 'section' => 'post_views_counter_general_settings',
345 'type' => 'boolean',
346 'class' => 'pvc-pro',
347 'disabled' => true,
348 'value' => false,
349 'skip_saving' => true,
350 'label' => __( 'Enable to apply changes improving compatibility with caching plugins.', 'post-views-counter' ),
351 'description' => $this->get_caching_compatibility_description()
352 ],
353 'object_cache' => [
354 'tab' => 'general',
355 'title' => __( 'Object Cache Support', 'post-views-counter' ),
356 'section' => 'post_views_counter_general_settings',
357 'type' => 'boolean',
358 'class' => 'pvc-pro',
359 'disabled' => true,
360 'value' => false,
361 'skip_saving' => true,
362 'label' => sprintf( __( 'Enable to use object cache optimization.', 'post-views-counter' ), '<code>Redis</code>', '<code>Memcached</code>' ),
363 '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>.'
364 ],
365 'exclude' => [
366 'tab' => 'general',
367 'title' => __( 'Exclude Visitors', 'post-views-counter' ),
368 'section' => 'post_views_counter_general_settings',
369 'type' => 'custom',
370 'description' => '',
371 'class' => 'pvc-pro-extended',
372 'options' => [
373 'groups' => $groups,
374 'roles' => $user_roles
375 ],
376 'disabled' => [
377 'groups' => [ 'ai_bots' ]
378 ],
379 'callback' => [ $this, 'setting_exclude' ],
380 'validate' => [ $this, 'validate_exclude' ]
381 ],
382 'exclude_ips' => [
383 'tab' => 'general',
384 'title' => __( 'Exclude IPs', 'post-views-counter' ),
385 'section' => 'post_views_counter_general_settings',
386 'type' => 'custom',
387 'description' => '',
388 'callback' => [ $this, 'setting_exclude_ips' ],
389 'validate' => [ $this, 'validate_exclude_ips' ]
390 ],
391 'label' => [
392 'tab' => 'display',
393 'title' => __( 'Views Label', 'post-views-counter' ),
394 'section' => 'post_views_counter_display_settings',
395 'type' => 'input',
396 'description' => __( 'Enter the label for the post views counter field.', 'post-views-counter' ),
397 'subclass' => 'regular-text',
398 'validate' => [ $this, 'validate_label' ],
399 'reset' => [ $this, 'reset_label' ]
400 ],
401 'display_period' => [
402 'tab' => 'display',
403 'title' => __( 'Views Period', 'post-views-counter' ),
404 'section' => 'post_views_counter_display_settings',
405 'type' => 'select',
406 'class' => 'pvc-pro',
407 'disabled' => true,
408 'skip_saving' => true,
409 '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' ),
410 'options' => [
411 'total' => __( 'Total Views', 'post-views-counter' )
412 ]
413 ],
414 'display_style' => [
415 'tab' => 'display',
416 'title' => __( 'Display Style', 'post-views-counter' ),
417 'section' => 'post_views_counter_display_settings',
418 'type' => 'custom',
419 'description' => __( 'Choose how to display the post views counter.', 'post-views-counter' ),
420 'callback' => [ $this, 'setting_display_style' ],
421 'validate' => [ $this, 'validate_display_style' ],
422 'options' => [
423 'icon' => __( 'icon', 'post-views-counter' ),
424 'text' => __( 'label', 'post-views-counter' )
425 ]
426 ],
427 'icon_class' => [
428 'tab' => 'display',
429 'title' => __( 'Icon Class', 'post-views-counter' ),
430 'section' => 'post_views_counter_display_settings',
431 'type' => 'class',
432 'default' => '',
433 '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/' ),
434 'subclass' => 'regular-text'
435 ],
436 'position' => [
437 'tab' => 'display',
438 'title' => __( 'Position', 'post-views-counter' ),
439 'section' => 'post_views_counter_display_settings',
440 'type' => 'select',
441 '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>' ),
442 'options' => [
443 'before' => __( 'before the content', 'post-views-counter' ),
444 'after' => __( 'after the content', 'post-views-counter' ),
445 'manual' => __( 'manual', 'post-views-counter' )
446 ]
447 ],
448 'post_views_column' => [
449 'tab' => 'display',
450 'title' => __( 'Admin Column', 'post-views-counter' ),
451 'section' => 'post_views_counter_display_settings',
452 'type' => 'boolean',
453 'description' => '',
454 'label' => __( 'Enable to display views count admin column.', 'post-views-counter' )
455 ],
456 'restrict_edit_views' => [
457 'tab' => 'display',
458 'title' => __( 'Admin Edit', 'post-views-counter' ),
459 'section' => 'post_views_counter_display_settings',
460 'type' => 'boolean',
461 'description' => '',
462 'label' => __( 'Enable to allow views count editing.', 'post-views-counter' )
463 ],
464 'dynamic_loading' => [
465 'tab' => 'display',
466 'title' => __( 'Dynamic Loading', 'post-views-counter' ),
467 'section' => 'post_views_counter_display_settings',
468 'type' => 'boolean',
469 'class' => 'pvc-pro',
470 'disabled' => true,
471 'skip_saving' => true,
472 'value' => false,
473 'label' => __( 'Enable dynamic loading and prevent caching of the displayed views count.', 'post-views-counter' )
474 ],
475 'use_format' => [
476 'tab' => 'display',
477 'title' => __( 'Format Number', 'post-views-counter' ),
478 'section' => 'post_views_counter_display_settings',
479 'type' => 'boolean',
480 'label' => __( 'Enable to display the views number formatted based on the locale (using the WP number_format_i18n function).', 'post-views-counter' )
481 ],
482 'taxonomies_display' => [
483 'tab' => 'display',
484 'title' => __( 'Taxonomies', 'post-views-counter' ),
485 'section' => 'post_views_counter_display_settings',
486 'type' => 'custom',
487 'class' => 'pvc-pro',
488 'skip_saving' => true,
489 'options' => $pvc->functions->get_taxonomies( 'labels' ),
490 'callback' => [ $this, 'setting_taxonomies_display' ]
491 ],
492 'user_display' => [
493 'tab' => 'display',
494 'title' => __( 'Authors', 'post-views-counter' ),
495 'section' => 'post_views_counter_display_settings',
496 'type' => 'boolean',
497 'class' => 'pvc-pro',
498 'disabled' => true,
499 'skip_saving' => true,
500 'value' => false,
501 'label' => __( 'Display number of views on authors archive pages.', 'post-views-counter' )
502 ],
503 'post_types_display' => [
504 'tab' => 'display',
505 'title' => __( 'Post Type', 'post-views-counter' ),
506 'section' => 'post_views_counter_display_settings',
507 'type' => 'checkbox',
508 'display_type' => 'horizontal',
509 'description' => __( 'Select post types for which the views count will be displayed.', 'post-views-counter' ),
510 'options' => $post_types
511 ],
512 'page_types_display' => [
513 'tab' => 'display',
514 'title' => __( 'Page Type', 'post-views-counter' ),
515 'section' => 'post_views_counter_display_settings',
516 'type' => 'checkbox',
517 'display_type' => 'horizontal',
518 'description' => __( 'Select page types where the views count will be displayed.', 'post-views-counter' ),
519 'options' => apply_filters(
520 'pvc_page_types_display_options',
521 [
522 'home' => __( 'Home', 'post-views-counter' ),
523 'archive' => __( 'Archives', 'post-views-counter' ),
524 'singular' => __( 'Single pages', 'post-views-counter' ),
525 'search' => __( 'Search results', 'post-views-counter' ),
526 ]
527 )
528 ],
529 'restrict_display' => [
530 'tab' => 'display',
531 'title' => __( 'User Type', 'post-views-counter' ),
532 'section' => 'post_views_counter_display_settings',
533 'type' => 'custom',
534 'description' => '',
535 'options' => [
536 'groups' => $groups,
537 'roles' => $user_roles
538 ],
539 'callback' => [ $this, 'setting_restrict_display' ],
540 'validate' => [ $this, 'validate_restrict_display' ]
541 ],
542 'toolbar_statistics' => [
543 'tab' => 'display',
544 'title' => __( 'Toolbar Chart', 'post-views-counter' ),
545 'section' => 'post_views_counter_display_settings',
546 'type' => 'boolean',
547 'description' => __( 'The post views chart will be displayed for the post types that are being counted.', 'post-views-counter' ),
548 'label' => __( 'Enable to display the post views chart at the toolbar.', 'post-views-counter' )
549 ],
550 'license' => [
551 'tab' => 'other',
552 'title' => __( 'License', 'post-views-counter' ),
553 'section' => 'post_views_counter_other_settings',
554 'disabled' => true,
555 'value' => $pvc->options['other']['license'],
556 'type' => 'input',
557 'description' => __( 'Enter your Post Views Counter Pro license key (requires Pro version to be installed and active).', 'post-views-counter' ),
558 'subclass' => 'regular-text',
559 'validate' => [ $this, 'validate_license' ],
560 'append' => '<span class="pvc-icon license-icon"></span>'
561 ],
562 'menu_position' => [
563 'tab' => 'other',
564 'title' => __( 'Menu Position', 'post-views-counter' ),
565 'section' => 'post_views_counter_other_settings',
566 'type' => 'radio',
567 'options' => [
568 'top' => __( 'Top menu', 'post-views-counter' ),
569 'sub' => __( 'Settings submenu', 'post-views-counter' )
570 ],
571 'description' => __( "Choose where to display the plugin's menu.", 'post-views-counter' ),
572 ],
573 'import_views' => [
574 'tab' => 'other',
575 'title' => __( 'Import Views', 'post-views-counter' ),
576 'section' => 'post_views_counter_other_settings',
577 'type' => 'custom',
578 'description' => '',
579 'skip_saving' => true,
580 'callback' => [ $this, 'setting_import_views' ]
581 ],
582 'delete_views' => [
583 'tab' => 'other',
584 'title' => __( 'Delete Views', 'post-views-counter' ),
585 'section' => 'post_views_counter_other_settings',
586 'type' => 'custom',
587 'description' => '',
588 'skip_saving' => true,
589 'callback' => [ $this, 'setting_delete_views' ]
590 ],
591 'deactivation_delete' => [
592 'tab' => 'other',
593 'title' => __( 'Deactivation', 'post-views-counter' ),
594 'section' => 'post_views_counter_other_settings',
595 'type' => 'boolean',
596 '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' ),
597 'label' => __( 'Enable to delete all plugin data on deactivation.', 'post-views-counter' )
598 ]
599 ]
600 ];
601
602 return $settings;
603 }
604
605 /**
606 * Add settings page.
607 *
608 * @param array $pages
609 *
610 * @return array
611 */
612 public function settings_page( $pages ) {
613 // get main instance
614 $pvc = Post_Views_Counter();
615
616 // default page
617 $pages['post-views-counter'] = [
618 'menu_slug' => 'post-views-counter',
619 'page_title' => __( 'Post Views Counter Settings', 'post-views-counter' ),
620 'menu_title' => $pvc->options['other']['menu_position'] === 'sub' ? __( 'Post Views Counter', 'post-views-counter' ) : __( 'Post Views', 'post-views-counter' ),
621 'capability' => apply_filters( 'pvc_settings_capability', 'manage_options' ),
622 'callback' => null,
623 'tabs' => [
624 'general' => [
625 'label' => __( 'Counting', 'post-views-counter' ),
626 'option_name' => 'post_views_counter_settings_general'
627 ],
628 'display' => [
629 'label' => __( 'Display', 'post-views-counter' ),
630 'option_name' => 'post_views_counter_settings_display'
631 ],
632 'reports' => [
633 'label' => __( 'Reports', 'post-views-counter' ),
634 'option_name' => 'post_views_counter_settings_reports'
635 ],
636 'other' => [
637 'label' => __( 'Other', 'post-views-counter' ),
638 'option_name' => 'post_views_counter_settings_other'
639 ]
640 ]
641 ];
642
643 // update admin title
644 add_filter( 'admin_title', [ $this, 'admin_title' ], 10, 2 );
645
646 // submenu?
647 if ( $pvc->options['other']['menu_position'] === 'sub' ) {
648 $pages['post-views-counter']['type'] = 'settings_page';
649 // topmenu?
650 } else {
651 // highlight submenus
652 add_filter( 'submenu_file', [ $this, 'submenu_file' ], 10, 2 );
653
654 // add parameters
655 $pages['post-views-counter']['type'] = 'page';
656 $pages['post-views-counter']['icon'] = 'dashicons-chart-bar';
657 $pages['post-views-counter']['position'] = '99.301';
658
659 // add subpages
660 $pages['post-views-counter-general'] = [
661 'menu_slug' => 'post-views-counter',
662 'parent_slug' => 'post-views-counter',
663 'type' => 'subpage',
664 'page_title' => __( 'Counting', 'post-views-counter' ),
665 'menu_title' => __( 'Counting', 'post-views-counter' ),
666 'capability' => apply_filters( 'pvc_settings_capability', 'manage_options' ),
667 'callback' => null
668 ];
669
670 $pages['post-views-counter-display'] = [
671 'menu_slug' => 'post-views-counter&tab=display',
672 'parent_slug' => 'post-views-counter',
673 'type' => 'subpage',
674 'page_title' => __( 'Display', 'post-views-counter' ),
675 'menu_title' => __( 'Display', 'post-views-counter' ),
676 'capability' => apply_filters( 'pvc_settings_capability', 'manage_options' ),
677 'callback' => null
678 ];
679
680 $pages['post-views-counter-reports'] = [
681 'menu_slug' => 'post-views-counter&tab=reports',
682 'parent_slug' => 'post-views-counter',
683 'type' => 'subpage',
684 'page_title' => __( 'Reports', 'post-views-counter' ),
685 'menu_title' => __( 'Reports', 'post-views-counter' ),
686 'capability' => apply_filters( 'pvc_settings_capability', 'manage_options' ),
687 'callback' => null
688 ];
689
690 $pages['post-views-counter-other'] = [
691 'menu_slug' => 'post-views-counter&tab=other',
692 'parent_slug' => 'post-views-counter',
693 'type' => 'subpage',
694 'page_title' => __( 'Other', 'post-views-counter' ),
695 'menu_title' => __( 'Other', 'post-views-counter' ),
696 'capability' => apply_filters( 'pvc_settings_capability', 'manage_options' ),
697 'callback' => null
698 ];
699 }
700
701 return $pages;
702 }
703
704 /**
705 * Settings page CSS class(es).
706 *
707 * @param array $class
708 * @return array
709 */
710 public function settings_page_class( $class ) {
711 $is_pro = class_exists( 'Post_Views_Counter_Pro' );
712
713 if ( ! $is_pro )
714 $class[] = 'has-sidebar';
715
716 return $class;
717 }
718
719 /**
720 * Highlight submenu items.
721 *
722 * @param string|null $submenu_file
723 * @param string $parent_file
724 *
725 * @return string|null
726 */
727 public function submenu_file( $submenu_file, $parent_file ) {
728 if ( $parent_file === 'post-views-counter' ) {
729 $tab = isset( $_GET['tab'] ) ? sanitize_key( $_GET['tab'] ) : 'general';
730
731 if ( $tab !== 'general' )
732 return 'post-views-counter&tab=' . $tab;
733 }
734
735 return $submenu_file;
736 }
737
738 /**
739 * Update admin title.
740 *
741 * @global array $submenu
742 * @global string $pagenow
743 *
744 * @param string $admin_title
745 * @param string $title
746 *
747 * @return string
748 */
749 public function admin_title( $admin_title, $title ) {
750 global $submenu, $pagenow;
751
752 // get main instance
753 $pvc = Post_Views_Counter();
754
755 if ( isset( $_GET['page'] ) && $_GET['page'] === 'post-views-counter' ) {
756 if ( $pvc->options['other']['menu_position'] === 'sub' && $pagenow === 'options-general.php' ) {
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( $tab, $pages['post-views-counter']['tabs'] ) ) {
764 // update title
765 $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 );
766 }
767 } else if ( $pvc->options['other']['menu_position'] === 'top' && get_admin_page_parent() === 'post-views-counter' && ! empty( $submenu['post-views-counter'] ) ) {
768 // get tab
769 $tab = isset( $_GET['tab'] ) ? sanitize_key( $_GET['tab'] ) : 'general';
770
771 // get settings pages
772 $pages = $pvc->settings_api->get_pages();
773
774 if ( array_key_exists( 'post-views-counter-' . $tab, $pages ) ) {
775 // update title
776 $admin_title = $pages['post-views-counter']['page_title'] . ' - ' . preg_replace( '/' . $title . '/', $pages['post-views-counter-' . $tab]['page_title'], $admin_title, 1 );
777 }
778 }
779 }
780
781 return $admin_title;
782 }
783
784 /**
785 * Validate options.
786 *
787 * @global object $wpdb
788 *
789 * @param array $input
790 *
791 * @return array
792 */
793 public function validate_settings( $input ) {
794 // check capability
795 if ( ! current_user_can( 'manage_options' ) )
796 return $input;
797
798 global $wpdb;
799
800 // get main instance
801 $pvc = Post_Views_Counter();
802
803 // use internal settings api to validate settings first
804 $input = $pvc->settings_api->validate_settings( $input );
805
806 // update meta key on save changes
807 if ( isset( $_POST['post_views_counter_import_meta_key'] ) && isset( $_POST['save_post_views_counter_settings_other'] ) )
808 $input['import_meta_key'] = sanitize_key( $_POST['post_views_counter_import_meta_key'] );
809
810 // import post views data from another plugin
811 if ( isset( $_POST['post_views_counter_import_wp_postviews'] ) ) {
812 // make sure we do not change anything in the settings
813 $input = $pvc->options['other'];
814
815 // get views key
816 $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'] ) ) );
817
818 // set meta_key option
819 $input['import_meta_key'] = $meta_key;
820
821 // get views
822 $views = $wpdb->get_results( $wpdb->prepare( "SELECT post_id, meta_value FROM " . $wpdb->postmeta . " WHERE meta_key = %s", $meta_key ), ARRAY_A, 0 );
823
824 // any views?
825 if ( ! empty( $views ) ) {
826 $sql = [];
827
828 foreach ( $views as $view ) {
829 $sql[] = $wpdb->prepare( "(%d, 4, 'total', %d)", (int) $view['post_id'], (int) $view['meta_value'] );
830 }
831
832 $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)" );
833
834 add_settings_error( 'wp_postviews_import', 'wp_postviews_import', __( 'Post views data imported successfully.', 'post-views-counter' ), 'updated' );
835 } else
836 add_settings_error( 'wp_postviews_import', 'wp_postviews_import', __( 'There was no post views data to import.', 'post-views-counter' ), 'updated' );
837 // delete all post views data
838 } elseif ( isset( $_POST['post_views_counter_reset_views'] ) ) {
839 // make sure we do not change anything in the settings
840 $input = $pvc->options['other'];
841
842 if ( $wpdb->query( 'TRUNCATE TABLE ' . $wpdb->prefix . 'post_views' ) )
843 add_settings_error( 'reset_post_views', 'reset_post_views', __( 'All existing data deleted successfully.', 'post-views-counter' ), 'updated' );
844 else
845 add_settings_error( 'reset_post_views', 'reset_post_views', __( 'Error occurred. All existing data were not deleted.', 'post-views-counter' ), 'error' );
846 // save general settings
847 } elseif ( isset( $_POST['save_post_views_counter_settings_general'] ) ) {
848 $input['update_version'] = $pvc->options['general']['update_version'];
849 $input['update_notice'] = $pvc->options['general']['update_notice'];
850 $input['update_delay_date'] = $pvc->options['general']['update_delay_date'];
851 // reset general settings
852 } elseif ( isset( $_POST['reset_post_views_counter_settings_general'] ) ) {
853 $input['update_version'] = $pvc->options['general']['update_version'];
854 $input['update_notice'] = $pvc->options['general']['update_notice'];
855 $input['update_delay_date'] = $pvc->options['general']['update_delay_date'];
856 }
857
858 return $input;
859 }
860
861 /**
862 * Get caching compatibility description.
863 *
864 * @return array
865 */
866 public function get_caching_compatibility_description() {
867 // caching compatibility description
868 $caching_compatibility_desc = '';
869
870 // get active caching plugins
871 $active_plugins = $this->get_active_caching_plugins();
872
873 if ( ! empty( $active_plugins ) ) {
874 $empty_active_caching_plugins = false;
875 $active_plugins_html = [];
876
877 $caching_compatibility_desc .= esc_html__( 'Currently detected active caching plugins', 'post-views-counter' ) . ': ';
878
879 foreach ( $active_plugins as $plugin ) {
880 $active_plugins_html[] = '<code>' . esc_html( $plugin ) . '</code>';
881 }
882
883 $caching_compatibility_desc .= implode( ', ', $active_plugins_html ) . '.';
884 } else {
885 $empty_active_caching_plugins = true;
886
887 $caching_compatibility_desc .= esc_html__( 'No compatible caching plugins found.', 'post-views-counter' );
888 }
889
890 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>.';
891 }
892
893 /**
894 * Extend active caching plugins.
895 *
896 * @param string $plugins
897 *
898 * @return array
899 */
900 public function extend_active_caching_plugins( $plugins ) {
901 // breeze
902 if ( $this->is_plugin_active( 'breeze' ) )
903 $plugins[] = 'Breeze';
904
905 return $plugins;
906 }
907
908 /**
909 * Check whether specified plugin is active.
910 *
911 * @param bool $is_plugin_active
912 * @param string $plugin
913 *
914 * @return bool
915 */
916 public function extend_is_plugin_active( $is_plugin_active, $plugin ) {
917 // breeze
918 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', '>=' ) )
919 $is_plugin_active = true;
920
921 return $is_plugin_active;
922 }
923
924 /**
925 * Get active caching plugins.
926 *
927 * @return array
928 */
929 public function get_active_caching_plugins() {
930 $active_plugins = [];
931
932 // autoptimize
933 if ( $this->is_plugin_active( 'autoptimize' ) )
934 $active_plugins[] = 'Autoptimize';
935
936 // hummingbird
937 if ( $this->is_plugin_active( 'hummingbird' ) )
938 $active_plugins[] = 'Hummingbird';
939
940 // litespeed
941 if ( $this->is_plugin_active( 'litespeed' ) )
942 $active_plugins[] = 'LiteSpeed Cache';
943
944 // speed optimizer
945 if ( $this->is_plugin_active( 'speedoptimizer' ) )
946 $active_plugins[] = 'Speed Optimizer';
947
948 // speedycache
949 if ( $this->is_plugin_active( 'speedycache' ) )
950 $active_plugins[] = 'SpeedyCache';
951
952 // wp fastest cache
953 if ( $this->is_plugin_active( 'wpfastestcache' ) )
954 $active_plugins[] = 'WP Fastest Cache';
955
956 // wp-optimize
957 if ( $this->is_plugin_active( 'wpoptimize' ) )
958 $active_plugins[] = 'WP-Optimize';
959
960 // wp rocket
961 if ( $this->is_plugin_active( 'wprocket' ) )
962 $active_plugins[] = 'WP Rocket';
963
964 // wp super cache
965 // if ( $this->is_plugin_active( 'wpsupercache' ) )
966 // $active_plugins[] = 'WP Super Cache';
967
968 return apply_filters( 'pvc_active_caching_plugins', $active_plugins );
969 }
970
971 /**
972 * Check whether specified plugin is active.
973 *
974 * @global object $siteground_optimizer_loader
975 * @global int $wpsc_version
976 *
977 * @param string $plugin
978 *
979 * @return bool
980 */
981 public function is_plugin_active( $plugin = '' ) {
982 // set default flag
983 $is_plugin_active = false;
984
985 switch ( $plugin ) {
986 // autoptimize
987 case 'autoptimize':
988 if ( function_exists( 'autoptimize' ) && defined( 'AUTOPTIMIZE_PLUGIN_VERSION' ) && version_compare( AUTOPTIMIZE_PLUGIN_VERSION, '2.4', '>=' ) )
989 $is_plugin_active = true;
990 break;
991
992 // hummingbird
993 case 'hummingbird':
994 if ( class_exists( 'Hummingbird\\WP_Hummingbird' ) && defined( 'WPHB_VERSION' ) && version_compare( WPHB_VERSION, '2.1.0', '>=' ) )
995 $is_plugin_active = true;
996 break;
997
998 // litespeed
999 case 'litespeed':
1000 if ( class_exists( 'LiteSpeed\Core' ) && defined( 'LSCWP_CUR_V' ) && version_compare( LSCWP_CUR_V, '3.0', '>=' ) )
1001 $is_plugin_active = true;
1002 break;
1003
1004 // speed optimizer
1005 case 'speedoptimizer':
1006 global $siteground_optimizer_loader;
1007
1008 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', '>=' ) )
1009 $is_plugin_active = true;
1010 break;
1011
1012 // speedycache
1013 case 'speedycache':
1014 if ( class_exists( 'SpeedyCache' ) && defined( 'SPEEDYCACHE_VERSION' ) && function_exists( 'speedycache_delete_cache' ) && version_compare( SPEEDYCACHE_VERSION, '1.0.0', '>=' ) )
1015 $is_plugin_active = true;
1016 break;
1017
1018 // wp fastest cache
1019 case 'wpfastestcache':
1020 if ( function_exists( 'wpfc_clear_all_cache' ) )
1021 $is_plugin_active = true;
1022 break;
1023
1024 // wp-optimize
1025 case 'wpoptimize':
1026 if ( function_exists( 'WP_Optimize' ) && defined( 'WPO_VERSION' ) && version_compare( WPO_VERSION, '3.0.12', '>=' ) )
1027 $is_plugin_active = true;
1028 break;
1029
1030 // wp rocket
1031 case 'wprocket':
1032 if ( function_exists( 'rocket_init' ) && defined( 'WP_ROCKET_VERSION' ) && version_compare( WP_ROCKET_VERSION, '3.8', '>=' ) )
1033 $is_plugin_active = true;
1034 break;
1035
1036 // wp super cache
1037 // case 'wpsupercache':
1038 // global $wpsc_version;
1039
1040 // if ( ( ! empty( $wpsc_version ) && $wpsc_version >= 169 ) || ( defined( 'WPSC_VERSION' ) && version_compare( WPSC_VERSION, '1.6.9', '>=' ) ) )
1041 // $is_plugin_active = true;
1042 // break;
1043
1044 // other caching plugin
1045 default:
1046 $is_plugin_active = apply_filters( 'pvc_is_plugin_active', false, $plugin );
1047 }
1048
1049 return $is_plugin_active;
1050 }
1051
1052 /**
1053 * Setting: taxonomies count.
1054 *
1055 * @param array $field
1056 * @return string
1057 */
1058 public function setting_taxonomies_count( $field ) {
1059 $html = '
1060 <label><input id="post_views_counter_general_taxonomies_count" type="checkbox" name="" value="" disabled />' . esc_html( $field['label'] ) . '</label>';
1061
1062 return $html;
1063 }
1064
1065 /**
1066 * Setting: users count.
1067 *
1068 * @param array $field
1069 * @return string
1070 */
1071 public function setting_users_count( $field ) {
1072 // get base instance
1073 $pvc = Post_Views_Counter();
1074
1075 $html = '
1076 <label><input id="post_views_counter_general_users_count" type="checkbox" name="" value="" disabled />' . esc_html( $field['label'] ) . '</label>';
1077
1078 return $html;
1079 }
1080
1081 /**
1082 * Setting: taxonomies count.
1083 *
1084 * @param array $field
1085 * @return string
1086 */
1087 public function setting_taxonomies_display( $field ) {
1088 // get base instance
1089 $pvc = Post_Views_Counter();
1090
1091 $html = '';
1092
1093 foreach ( $field['options'] as $taxonomy => $label ) {
1094 $html .= '
1095 <label><input type="checkbox" name="" value="" disabled />' . esc_html( $label ) . '</label>';
1096 }
1097
1098 $html .= '
1099 <p class="description">' . esc_html__( 'Select taxonomies for which the views count will be displayed.', 'post-views-counter' ) . '</p>';
1100
1101 return $html;
1102 }
1103
1104 /**
1105 * Validate label.
1106 *
1107 * @param array $input
1108 * @param array $field
1109 * @return array
1110 */
1111 public function validate_label( $input, $field ) {
1112 // get main instance
1113 $pvc = Post_Views_Counter();
1114
1115 if ( ! isset( $input ) )
1116 $input = $pvc->defaults['display']['label'];
1117
1118 // use internal settings API to validate settings first
1119 $input = $pvc->settings_api->validate_field( $input, 'input', $field );
1120
1121 if ( function_exists( 'icl_register_string' ) )
1122 icl_register_string( 'Post Views Counter', 'Post Views Label', $input );
1123
1124 return $input;
1125 }
1126
1127 /**
1128 * Restore post views label to default value.
1129 *
1130 * @param array $default
1131 * @param array $field
1132 * @return array
1133 */
1134 public function reset_label( $default, $field ) {
1135 if ( function_exists( 'icl_register_string' ) )
1136 icl_register_string( 'Post Views Counter', 'Post Views Label', $default );
1137
1138 return $default;
1139 }
1140
1141 /**
1142 * Setting: display style.
1143 *
1144 * @param array $field
1145 * @return string
1146 */
1147 public function setting_display_style( $field ) {
1148 // get main instance
1149 $pvc = Post_Views_Counter();
1150
1151 $html = '
1152 <input type="hidden" name="post_views_counter_settings_display[display_style]" value="empty" />';
1153
1154 foreach ( $field['options'] as $key => $label ) {
1155 $html .= '
1156 <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> ';
1157 }
1158
1159 return $html;
1160 }
1161
1162 /**
1163 * Validate display style.
1164 *
1165 * @param array $input
1166 * @param array $field
1167 * @return array
1168 */
1169 public function validate_display_style( $input, $field ) {
1170 // get main instance
1171 $pvc = Post_Views_Counter();
1172
1173 $data = [];
1174
1175 foreach ( $field['options'] as $value => $label ) {
1176 $data[$value] = false;
1177 }
1178
1179 // any data?
1180 if ( ! empty( $input['display_style'] && $input['display_style'] !== 'empty' && is_array( $input['display_style'] ) ) ) {
1181 foreach ( $input['display_style'] as $value ) {
1182 if ( array_key_exists( $value, $field['options'] ) )
1183 $data[$value] = true;
1184 }
1185 }
1186
1187 $input['display_style'] = $data;
1188
1189 return $input;
1190 }
1191
1192 /**
1193 * Setting: count interval.
1194 *
1195 * @param array $field
1196 * @return string
1197 */
1198 public function setting_time_between_counts( $field ) {
1199 // get main instance
1200 $pvc = Post_Views_Counter();
1201
1202 $html = '
1203 <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'] ) . '" />
1204 <select name="post_views_counter_settings_general[time_between_counts][type]">';
1205
1206 foreach ( $field['options'] as $type => $type_name ) {
1207 $html .= '
1208 <option value="' . esc_attr( $type ) . '" ' . selected( $type, $pvc->options['general']['time_between_counts']['type'], false ) . '>' . esc_html( $type_name ) . '</option>';
1209 }
1210
1211 $html .= '
1212 </select>
1213 <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>';
1214
1215 return $html;
1216 }
1217
1218 /**
1219 * Validate count interval.
1220 *
1221 * @param array $input
1222 * @param array $field
1223 * @return array
1224 */
1225 public function validate_time_between_counts( $input, $field ) {
1226 // get main instance
1227 $pvc = Post_Views_Counter();
1228
1229 // number
1230 $input['time_between_counts']['number'] = isset( $input['time_between_counts']['number'] ) ? (int) $input['time_between_counts']['number'] : $pvc->defaults['general']['time_between_counts']['number'];
1231
1232 if ( $input['time_between_counts']['number'] < $field['min'] || $input['time_between_counts']['number'] > $field['max'] )
1233 $input['time_between_counts']['number'] = $pvc->defaults['general']['time_between_counts']['number'];
1234
1235 // type
1236 $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'];
1237
1238 return $input;
1239 }
1240
1241 /**
1242 * Setting: reset data interval.
1243 *
1244 * @param array $field
1245 * @return string
1246 */
1247 public function setting_reset_counts( $field ) {
1248 // get main instance
1249 $pvc = Post_Views_Counter();
1250
1251 $html = '
1252 <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'] ) . '" />
1253 <select name="post_views_counter_settings_general[reset_counts][type]">';
1254
1255 foreach ( array_slice( $field['options'], 2, null, true ) as $type => $type_name ) {
1256 $html .= '
1257 <option value="' . esc_attr( $type ) . '" ' . selected( $type, $pvc->options['general']['reset_counts']['type'], false ) . '>' . esc_html( $type_name ) . '</option>';
1258 }
1259
1260 $html .= '
1261 </select>';
1262
1263 return $html;
1264 }
1265
1266 /**
1267 * Validate reset data interval.
1268 *
1269 * @param array $input
1270 * @param array $field
1271 * @return array
1272 */
1273 public function validate_reset_counts( $input, $field ) {
1274 // get main instance
1275 $pvc = Post_Views_Counter();
1276
1277 // number
1278 $input['reset_counts']['number'] = isset( $input['reset_counts']['number'] ) ? (int) $input['reset_counts']['number'] : $pvc->defaults['general']['reset_counts']['number'];
1279
1280 if ( $input['reset_counts']['number'] < $field['min'] || $input['reset_counts']['number'] > $field['max'] )
1281 $input['reset_counts']['number'] = $pvc->defaults['general']['reset_counts']['number'];
1282
1283 // type
1284 $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'];
1285
1286 // run cron on next visit?
1287 $input['cron_run'] = ( $input['reset_counts']['number'] > 0 );
1288
1289 // cron update?
1290 $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'] ) );
1291
1292 return $input;
1293 }
1294
1295 /**
1296 * Setting: object cache.
1297 *
1298 * @param array $field
1299 * @return string
1300 */
1301 public function setting_object_cache( $field ) {
1302 // get main instance
1303 $pvc = Post_Views_Counter();
1304
1305 // check object cache
1306 $wp_using_ext_object_cache = wp_using_ext_object_cache();
1307
1308 $html = '
1309 <input size="4" type="number" min="' . ( (int) $field['min'] ) . '" max="' . ( (int) $field['max'] ) . '" name="" value="0" disabled /> <span>' . __( 'minutes', 'post-views-counter' ) . '</span>
1310 <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>
1311 <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>';
1312
1313 return $html;
1314 }
1315
1316 /**
1317 * Setting: exclude visitors.
1318 *
1319 * @param array $field
1320 * @return string
1321 */
1322 public function setting_exclude( $field ) {
1323 // get main instance
1324 $pvc = Post_Views_Counter();
1325
1326 $html = '';
1327
1328 foreach ( $field['options']['groups'] as $type => $type_name ) {
1329 $is_disabled = ! empty( $field['disabled']['groups'] ) && in_array( $type, $field['disabled']['groups'], true );
1330
1331 $html .= '
1332 <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>';
1333 }
1334
1335 $html .= '
1336 <p class="description">' . __( 'Use it exclude specific user groups from post views count.', 'post-views-counter' ) . '</p>
1337 <div class="pvc_user_roles pvc_subfield"' . ( in_array( 'roles', $pvc->options['general']['exclude']['groups'], true ) ? '' : ' style="display: none;"' ) . '>';
1338
1339 foreach ( $field['options']['roles'] as $role => $role_name ) {
1340 $html .= '
1341 <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>';
1342 }
1343
1344 $html .= '
1345 <p class="description">' . __( 'Use it to exclude specific user roles from post views count.', 'post-views-counter' ) . '</p>
1346 </div>';
1347
1348 return $html;
1349 }
1350
1351 /**
1352 * Validate exclude visitors.
1353 *
1354 * @param array $input
1355 * @param array $field
1356 * @return array
1357 */
1358 public function validate_exclude( $input, $field ) {
1359 // any groups?
1360 if ( isset( $input['exclude']['groups'] ) ) {
1361 $groups = [];
1362
1363 foreach ( $input['exclude']['groups'] as $group => $set ) {
1364 // disallow disabled checkboxes
1365 if ( ! empty( $field['disabled']['groups'] ) && in_array( $group, $field['disabled']['groups'], true ) )
1366 continue;
1367
1368 if ( isset( $field['options']['groups'][$group] ) )
1369 $groups[] = $group;
1370 }
1371
1372 $input['exclude']['groups'] = array_unique( $groups );
1373 } else
1374 $input['exclude']['groups'] = [];
1375
1376 // any roles?
1377 if ( in_array( 'roles', $input['exclude']['groups'], true ) && isset( $input['exclude']['roles'] ) ) {
1378 $roles = [];
1379
1380 foreach ( $input['exclude']['roles'] as $role => $set ) {
1381 if ( isset( $field['options']['roles'][$role] ) )
1382 $roles[] = $role;
1383 }
1384
1385 $input['exclude']['roles'] = array_unique( $roles );
1386 } else
1387 $input['exclude']['roles'] = [];
1388
1389 return $input;
1390 }
1391
1392 /**
1393 * Setting: exclude IP addresses.
1394 *
1395 * @return string
1396 */
1397 public function setting_exclude_ips() {
1398 // get ip addresses
1399 $ips = Post_Views_Counter()->options['general']['exclude_ips'];
1400
1401 $html = '';
1402
1403 // any ip addresses?
1404 if ( ! empty( $ips ) ) {
1405 foreach ( $ips as $key => $ip ) {
1406 $html .= '
1407 <div class="ip-box">
1408 <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>
1409 </div>';
1410 }
1411 } else {
1412 $html .= '
1413 <div class="ip-box">
1414 <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>
1415 </div>';
1416 }
1417
1418 $html .= '
1419 <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>
1420 <p class="description">' . esc_html__( 'Enter the IP addresses to be excluded from post views count.', 'post-views-counter' ) . '</p>';
1421
1422 return $html;
1423 }
1424
1425 /**
1426 * Validate exclude IP addresses.
1427 *
1428 * @param array $input
1429 * @param array $field
1430 * @return array
1431 */
1432 public function validate_exclude_ips( $input, $field ) {
1433 // any ip addresses?
1434 if ( isset( $input['exclude_ips'] ) ) {
1435 $ips = [];
1436
1437 foreach ( $input['exclude_ips'] as $ip ) {
1438 if ( strpos( $ip, '*' ) !== false ) {
1439 $new_ip = str_replace( '*', '0', $ip );
1440
1441 if ( filter_var( $new_ip, FILTER_VALIDATE_IP, FILTER_FLAG_IPV4 ) )
1442 $ips[] = $ip;
1443 } elseif ( filter_var( $ip, FILTER_VALIDATE_IP, FILTER_FLAG_IPV4 ) )
1444 $ips[] = $ip;
1445 }
1446
1447 $input['exclude_ips'] = array_unique( $ips );
1448 }
1449
1450 return $input;
1451 }
1452
1453 /**
1454 * Setting: tools.
1455 *
1456 * @return string
1457 */
1458 public function setting_import_views() {
1459 $html = '
1460 <div>
1461 <input type="text" class="regular-text" name="post_views_counter_import_meta_key" value="' . esc_attr( Post_Views_Counter()->options['other']['import_meta_key'] ) . '"/>
1462 <p class="description">' . esc_html__( 'Enter the meta key from which the views data is to be retrieved during import.', 'post-views-counter' ) . '</p>
1463 </div>
1464 <div class="pvc-subfield">
1465 <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>
1466 <p class="description">' . esc_html__( 'Click Import Views to start importing the views data.', 'post-views-counter' ) . '</p>
1467 </div>';
1468
1469 return $html;
1470 }
1471
1472 /**
1473 * Setting: delete views.
1474 *
1475 * @return string
1476 */
1477 public function setting_delete_views() {
1478 $html = '
1479 <input type="submit" class="button button-secondary" name="post_views_counter_reset_views" value="' . esc_attr__( 'Delete Views', 'post-views-counter' ) . '" />
1480 <p class="description">' . esc_html__( 'Delete ALL the existing post views data. Note that this is an irreversible process!', 'post-views-counter' ) . '</p>';
1481
1482 return $html;
1483 }
1484
1485 /**
1486 * Setting: user type.
1487 *
1488 * @param array $field
1489 *
1490 * @return string
1491 */
1492 public function setting_restrict_display( $field ) {
1493 // get main instance
1494 $pvc = Post_Views_Counter();
1495
1496 $html = '';
1497
1498 foreach ( $field['options']['groups'] as $type => $type_name ) {
1499 if ( $type === 'robots' || $type === 'ai_bots' )
1500 continue;
1501
1502 $html .= '
1503 <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>';
1504 }
1505
1506 $html .= '
1507 <p class="description">' . __( 'Use it to hide the post views counter from selected type of visitors.', 'post-views-counter' ) . '</p>
1508 <div class="pvc_user_roles pvc-subfield"' . ( in_array( 'roles', $pvc->options['display']['restrict_display']['groups'], true ) ? '' : ' style="display: none;"' ) . '>';
1509
1510 foreach ( $field['options']['roles'] as $role => $role_name ) {
1511 $html .= '
1512 <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>';
1513 }
1514
1515 $html .= '
1516 <p class="description">' . __( 'Use it to hide the post views counter from selected user roles.', 'post-views-counter' ) . '</p>
1517 </div>';
1518
1519 return $html;
1520 }
1521
1522 /**
1523 * Validate user type.
1524 *
1525 * @param array $input
1526 * @param array $field
1527 *
1528 * @return array
1529 */
1530 public function validate_restrict_display( $input, $field ) {
1531 // any groups?
1532 if ( isset( $input['restrict_display']['groups'] ) ) {
1533 $groups = [];
1534
1535 foreach ( $input['restrict_display']['groups'] as $group => $set ) {
1536 if ( $group === 'robots' || $group === 'ai_bots' )
1537 continue;
1538
1539 if ( isset( $field['options']['groups'][$group] ) )
1540 $groups[] = $group;
1541 }
1542
1543 $input['restrict_display']['groups'] = array_unique( $groups );
1544 } else
1545 $input['restrict_display']['groups'] = [];
1546
1547 // any roles?
1548 if ( in_array( 'roles', $input['restrict_display']['groups'], true ) && isset( $input['restrict_display']['roles'] ) ) {
1549 $roles = [];
1550
1551 foreach ( $input['restrict_display']['roles'] as $role => $set ) {
1552 if ( isset( $field['options']['roles'][$role] ) )
1553 $roles[] = $role;
1554 }
1555
1556 $input['restrict_display']['roles'] = array_unique( $roles );
1557 } else
1558 $input['restrict_display']['roles'] = [];
1559
1560 return $input;
1561 }
1562
1563 /**
1564 * Reports page placeholder.
1565 */
1566 public function section_reports_placeholder() {
1567 echo '
1568 <form action="#">
1569 <div id="pvc-reports-placeholder">
1570 <img id="pvc-reports-bg" src="' . esc_url( POST_VIEWS_COUNTER_URL ) . '/css/page-reports.png" alt="Post Views Counter - Reports" />
1571 <div id="pvc-reports-upgrade">
1572 <div id="pvc-reports-modal">
1573 <h2>' . esc_html__( 'Display Reports and Export Views to CSV/XML', 'post-views-counter' ) . '</h2>
1574 <p>' . esc_html__( 'View detailed stats about the popularity of your content.', 'post-views-counter' ) . '</p>
1575 <p>' . esc_html__( 'Generate views reports in any date range you need.', 'post-views-counter' ) . '</p>
1576 <p>' . esc_html__( 'Export, download and share your website views data.', 'post-views-counter' ) . '</p>
1577 <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>
1578 </div>
1579 </div>
1580 </div>
1581 </form>';
1582 }
1583
1584 /**
1585 * Validate license.
1586 *
1587 * @param array $input
1588 * @param array $field
1589 * @return array
1590 */
1591 public function validate_license( $input, $field ) {
1592 // save value from database
1593 return $field['value'];
1594 }
1595 }
1596