PluginProbe ʕ •ᴥ•ʔ
Post Views Counter / 1.7.0
Post Views Counter v1.7.0
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-other.php
post-views-counter / includes Last commit date
class-admin.php 6 months ago class-columns.php 6 months ago class-counter.php 6 months ago class-crawler-detect.php 6 months ago class-cron.php 6 months ago class-dashboard.php 6 months ago class-frontend.php 6 months ago class-functions.php 6 months ago class-import.php 6 months ago class-integration-gutenberg.php 6 months ago class-integrations.php 6 months ago class-query.php 6 months ago class-settings-api.php 6 months ago class-settings-display.php 6 months ago class-settings-general.php 6 months ago class-settings-integrations.php 6 months ago class-settings-other.php 6 months ago class-settings-reports.php 6 months ago class-settings.php 6 months ago class-toolbar.php 6 months ago class-update.php 6 months ago class-widgets.php 6 months ago functions.php 6 months ago
class-settings-other.php
459 lines
1 <?php
2 // exit if accessed directly
3 if ( ! defined( 'ABSPATH' ) )
4 exit;
5
6 /**
7 * Post_Views_Counter_Settings_Other class.
8 *
9 * @class Post_Views_Counter_Settings_Other
10 */
11 class Post_Views_Counter_Settings_Other {
12
13 private $pvc;
14 private $settings;
15
16 /**
17 * Class constructor.
18 *
19 * @param Post_Views_Counter_Settings $settings
20 * @return void
21 */
22 public function __construct( $settings = null ) {
23 $this->pvc = Post_Views_Counter();
24 $this->settings = $settings;
25 }
26
27 /**
28 * Get sections for other tab.
29 *
30 * @return array
31 */
32 public function get_sections() {
33 return [
34 'post_views_counter_other_status' => [
35 'tab' => 'other',
36 'title' => __( 'Plugin Status', 'post-views-counter' ),
37 'callback' => [ $this, 'section_other_status' ]
38 ],
39 'post_views_counter_other_import' => [
40 'tab' => 'other',
41 'title' => __( 'Data Import', 'post-views-counter' ),
42 'callback' => [ $this, 'section_other_import' ]
43 ],
44 'post_views_counter_other_management' => [
45 'tab' => 'other',
46 'title' => __( 'Data Removal', 'post-views-counter' ),
47 'callback' => [ $this, 'section_other_management' ]
48 ]
49 ];
50 }
51
52 /**
53 * Get fields for other tab.
54 *
55 * @return array
56 */
57 public function get_fields() {
58 return [
59 'license' => [
60 'tab' => 'other',
61 'title' => __( 'License Key', 'post-views-counter' ),
62 'section' => 'post_views_counter_other_status',
63 'disabled' => true,
64 'value' => $this->pvc->options['other']['license'],
65 'type' => 'input',
66 'description' => sprintf( __( 'Enter your %s license key (requires Pro version to be installed and active).', 'post-views-counter' ), '<a href="https://postviewscounter.com/" target="_blank">Post Views Counter Pro</a>' ),
67 'subclass' => 'regular-text',
68 'validate' => [ $this, 'validate_license' ],
69 'append' => '<span class="pvc-status-icon"></span>'
70 ],
71 'import_from' => [
72 'tab' => 'other',
73 'title' => __( 'Import From', 'post-views-counter' ),
74 'section' => 'post_views_counter_other_import',
75 'type' => 'custom',
76 'skip_saving' => true,
77 'callback' => [ $this, 'setting_import_from' ]
78 ],
79 'import_strategy' => [
80 'tab' => 'other',
81 'title' => __( 'Import Strategy', 'post-views-counter' ),
82 'section' => 'post_views_counter_other_import',
83 'class' => 'pvc-pro-extended',
84 'type' => 'custom',
85 'skip_saving' => true,
86 'callback' => [ $this, 'setting_import_strategy' ]
87 ],
88 'import_actions' => [
89 'tab' => 'other',
90 'title' => '',
91 'section' => 'post_views_counter_other_import',
92 'type' => 'custom',
93 'description' => __( 'Click Analyse Views to check how many views are available for import, or Import Views to begin the import process.', 'post-views-counter' ),
94 'skip_saving' => true,
95 'callback' => [ $this, 'setting_import_actions' ]
96 ],
97 'delete_views' => [
98 'tab' => 'other',
99 'title' => __( 'Delete Views', 'post-views-counter' ),
100 'section' => 'post_views_counter_other_management',
101 'type' => 'custom',
102 'description' => __( 'Delete ALL the existing post views data. Note that this is an irreversible process!', 'post-views-counter' ),
103 'skip_saving' => true,
104 'callback' => [ $this, 'setting_delete_views' ]
105 ],
106 'deactivation_delete' => [
107 'tab' => 'other',
108 'title' => __( 'Delete on Deactivation', 'post-views-counter' ),
109 'section' => 'post_views_counter_other_management',
110 'type' => 'boolean',
111 'description' => __( 'When enabled, deactivating the plugin will delete all plugin data from the database, including all content view counts.', 'post-views-counter' ),
112 'label' => __( 'Delete all plugin data on deactivation.', 'post-views-counter' )
113 ]
114 ];
115 }
116
117 /**
118 * Validate license.
119 *
120 * @param array $input
121 * @param array $field
122 * @return array
123 */
124 public function validate_license( $input, $field ) {
125 // save value from database
126 return $field['value'];
127 }
128
129 /**
130 * Setting: import from.
131 *
132 * @return string
133 */
134 public function setting_import_from() {
135 // get all providers (not just available ones)
136 $all_providers = $this->pvc->import->get_all_providers();
137
138 // get currently selected provider
139 $selected_provider = isset( $this->pvc->options['other']['import_provider_settings']['provider'] ) ? $this->pvc->options['other']['import_provider_settings']['provider'] : 'custom_meta_key';
140
141 // if selected provider is not available, fallback to custom_meta_key
142 if ( isset( $all_providers[$selected_provider] ) ) {
143 $is_selected_available = is_callable( $all_providers[$selected_provider]['is_available'] ) && call_user_func( $all_providers[$selected_provider]['is_available'] );
144 if ( ! $is_selected_available ) {
145 $selected_provider = 'custom_meta_key';
146 }
147 }
148
149 $html = '<div class="pvc-import-provider-selection">';
150 $html .= '<div class="pvc-field-group pvc-radio-group">';
151
152 foreach ( $all_providers as $slug => $provider ) {
153 $is_available = is_callable( $provider['is_available'] ) && call_user_func( $provider['is_available'] );
154 $is_checked = ( $selected_provider === $slug );
155 $disabled_attr = ! $is_available ? ' disabled="disabled"' : '';
156 $disabled_class = ! $is_available ? ' class="pvc-provider-disabled"' : '';
157 $tooltip = ! $is_available ? ' title="' . esc_attr( sprintf( __( '%s is not currently available. Please install and activate the required plugin.', 'post-views-counter' ), $provider['label'] ) ) . '"' : '';
158
159 $html .= '
160 <label' . $disabled_class . $tooltip . '>
161 <input type="radio" name="pvc_import_provider" value="' . esc_attr( $slug ) . '" ' . checked( $is_checked, true, false ) . $disabled_attr . ' />
162 ' . esc_html( $provider['label'] ) . '
163 </label>';
164 }
165
166 $html .= '</div>';
167 $html .= '<p class="description">' . esc_html__( 'Choose a data source to import existing view counts from.', 'post-views-counter' ) . '</p>';
168
169 $html .= '</div><div class="pvc-import-provider-fields">';
170
171 foreach ( $all_providers as $slug => $provider ) {
172 $is_available = is_callable( $provider['is_available'] ) && call_user_func( $provider['is_available'] );
173 $is_active = ( $selected_provider === $slug );
174 $provider_html = '';
175
176 if ( $is_available && is_callable( $provider['render'] ) ) {
177 $provider_html = call_user_func( $provider['render'] );
178 } elseif ( ! $is_available ) {
179 $provider_html = '<p class="description pvc-provider-unavailable">' . sprintf( __( '%s is not available. Please install and activate the required plugin to use this import source.', 'post-views-counter' ), '<strong>' . esc_html( $provider['label'] ) . '</strong>' ) . '</p>';
180 }
181
182 $html .= '
183 <div class="pvc-provider-content pvc-provider-' . esc_attr( $slug ) . '" ' . ( ! $is_active ? 'style="display:none;"' : '' ) . '>
184 ' . $provider_html . '
185 </div>';
186 }
187
188 $html .= '</div>';
189
190 return $html;
191 }
192
193 /**
194 * Setting: import strategy.
195 *
196 * @return string
197 */
198 public function setting_import_strategy() {
199 // get import strategy
200 $import_strategy = isset( $this->pvc->options['other']['import_provider_settings']['strategy'] ) ? $this->pvc->import->normalize_strategy( $this->pvc->options['other']['import_provider_settings']['strategy'] ) : $this->pvc->import->get_default_strategy();
201 $strategies = $this->pvc->import->get_import_strategies();
202
203 $html = '<div class="pvc-field-group pvc-radio-group">';
204
205 foreach ( $strategies as $slug => $strategy ) {
206 $label = isset( $strategy['label'] ) ? $strategy['label'] : ucwords( str_replace( '_', ' ', $slug ) );
207 $description = isset( $strategy['description'] ) ? $strategy['description'] : '';
208 $is_enabled = $this->pvc->import->is_strategy_enabled( $slug );
209 $input_id = 'pvc_import_strategy_' . $slug;
210
211 if ( $slug === $import_strategy ) {
212 $current_description = $description;
213 }
214
215 $html .= '<label for="' . esc_attr( $input_id ) . '" class="pvc-import-strategy-option" data-description="' . esc_attr( $description ) . '">
216 <input type="radio" id="' . esc_attr( $input_id ) . '" name="pvc_import_strategy" value="' . esc_attr( $slug ) . '" ' . checked( $import_strategy, $slug, false ) . ' ' . disabled( ! $is_enabled, true, false ) . ' />
217 ' . esc_html( $label );
218
219 // Future idea: display description text next to each strategy option.
220 // if ( $description !== '' ) {
221 // $html .= '<span class="description pvc-import-strategy-description">' . esc_html( $description ) . '</span>';
222 // }
223
224 $html .= '</label>';
225 }
226
227 $html .= '</div>';
228
229 $html .= '</div>';
230
231 $html .= '<p class="description">' . esc_html__( 'Choose how to handle existing view counts when importing.', 'post-views-counter' ) . '</p>';
232
233 $html .= '<div class="pvc-provider-fields pvc-import-strategy-details">';
234
235 foreach ( $strategies as $slug => $strategy ) {
236 $description = isset( $strategy['description'] ) ? $strategy['description'] : '';
237 $is_active = ( $slug === $import_strategy );
238
239 $html .= '<div class="pvc-strategy-content pvc-strategy-' . esc_attr( $slug ) . '"' . ( $is_active ? '' : ' style="display:none;"' ) . '>
240 <p class="description">' . esc_html( $description ) . '</p>
241 </div>';
242 }
243
244 $html .= '</div>';
245
246 return $html;
247 }
248
249 /**
250 * Setting: import actions.
251 *
252 * @return string
253 */
254 public function setting_import_actions() {
255 $html = '<input type="submit" class="button button-secondary" name="post_views_counter_analyse_views" value="' . esc_attr__( 'Analyse Views', 'post-views-counter' ) . '" />
256 <input type="submit" class="button button-secondary" name="post_views_counter_import_views" value="' . esc_attr__( 'Import Views', 'post-views-counter' ) . '" />';
257
258 return $html;
259 }
260
261 /**
262 * Setting: delete views.
263 *
264 * @return string
265 */
266 public function setting_delete_views() {
267 $html = '
268 <input type="submit" class="button button-secondary" name="post_views_counter_reset_views" value="' . esc_attr__( 'Delete Views', 'post-views-counter' ) . '" />';
269
270 return $html;
271 }
272
273 /**
274 * Section description: other - status.
275 *
276 * @return void
277 */
278 public function section_other_status() {
279 echo '<p class="description">' . esc_html__( 'View license details and other status information.', 'post-views-counter' ) . '</p>';
280
281 // render plugin status rows
282 $rows = $this->get_plugin_status_rows();
283
284 echo '<table class="form-table pvc-status-table"><tbody>';
285 foreach ( (array) $rows as $row ) {
286 $label = isset( $row['label'] ) ? $row['label'] : '';
287 $value = isset( $row['value'] ) ? $row['value'] : '';
288 $active = isset( $row['active'] ) ? (bool) $row['active'] : null;
289 $tables = isset( $row['tables'] ) ? $row['tables'] : null;
290
291 echo '<tr>';
292 echo '<th scope="row">' . esc_html( $label ) . '</th>';
293 echo '<td>';
294
295 // handle tables structure with individual badges
296 if ( is_array( $tables ) && ! empty( $tables ) ) {
297 foreach ( $tables as $table ) {
298 $table_name = isset( $table['name'] ) ? esc_html( $table['name'] ) : '';
299 $table_label = isset( $table['label'] ) ? esc_html( $table['label'] ) : $table_name;
300 $table_exists = isset( $table['exists'] ) ? (bool) $table['exists'] : false;
301
302 echo '<p>';
303 echo $table_label;
304 if ( $table_exists ) {
305 echo ' <span class="pvc-status pvc-status-active">&#10003;</span>';
306 } else {
307 echo ' <span class="pvc-status pvc-status-missing">&#10007;</span>';
308 }
309 echo '</p>';
310 }
311 // handle lines array
312 } elseif ( isset( $row['lines'] ) && is_array( $row['lines'] ) ) {
313 foreach ( $row['lines'] as $line ) {
314 echo '<p>' . wp_kses( $line, [ 'span' => [ 'class' => [] ] ] ) . '</p>';
315 }
316 // handle boolean active status
317 } elseif ( $active === true ) {
318 echo '<span class="pvc-status pvc-status-active">&#10003; ' . esc_html__( 'Active', 'post-views-counter' ) . '</span>';
319 } elseif ( $active === false ) {
320 echo '<span class="pvc-status pvc-status-missing">&#10007; ' . esc_html__( 'Not Detected', 'post-views-counter' ) . '</span>';
321 // handle plain text value
322 } else {
323 echo wp_kses( $value, [ 'br' => [] ] );
324 } echo '</td>';
325 echo '</tr>';
326 }
327 echo '</tbody></table>';
328 }
329
330 /**
331 * Prepare an array with plugin status rows.
332 *
333 * Rows should be associative arrays with: label, value (string) and optional active (bool) key.
334 * The returned rows will be filtered by 'pvc_plugin_status_rows' which allows extensions to add/modify rows.
335 *
336 * @return array
337 */
338 protected function get_plugin_status_rows() {
339 global $wpdb;
340
341 $version = isset( $this->pvc->defaults['version'] ) ? $this->pvc->defaults['version'] : '';
342
343 if ( empty( $version ) ) {
344 $version = esc_html__( 'unknown', 'post-views-counter' );
345 }
346
347 // detect pro activation status
348 $pvc_pro_active = class_exists( 'Post_Views_Counter_Pro' );
349
350 // get pro version
351 $pro_version = $pvc_pro_active ? get_option( 'post_views_counter_pro_version', '1.0.0' ) : '<span class="pvc-status pvc-status-missing">✗</span>';
352
353 // get database tables via filter
354 $tables = $this->get_plugin_status_tables();
355
356 $rows = [
357 [
358 'label' => __( 'Plugin Version', 'post-views-counter' ),
359 'lines' => [ 'Post Views Counter: ' . $version, 'Post Views Counter Pro: ' . $pro_version ]
360 ]
361 ];
362
363 // add database tables row if any tables are defined
364 if ( ! empty( $tables ) ) {
365 $rows[] = [
366 'label' => __( 'Database Tables', 'post-views-counter' ),
367 'tables' => $tables
368 ];
369 }
370
371 /**
372 * Filter the plugin status rows.
373 *
374 * Allows extensions to add or modify status rows displayed in the settings page.
375 *
376 * @since 1.5.9
377 * @param array $rows Status rows
378 * @param Post_Views_Counter_Settings $this Instance of settings class
379 */
380 $rows = apply_filters( 'pvc_plugin_status_rows', $rows, $this->settings );
381
382 return $rows;
383 }
384
385 /**
386 * Get database tables for status display.
387 *
388 * Collects table definitions via filter, validates that table names contain 'post_views',
389 * checks actual existence in database, and returns formatted array.
390 *
391 * @return array
392 */
393 protected function get_plugin_status_tables() {
394 global $wpdb;
395
396 /**
397 * Filter the database tables to check for plugin status.
398 *
399 * @since 1.5.9
400 * @param array $table_definitions Array of table definitions
401 * @param Post_Views_Counter_Settings $this Instance of settings class
402 */
403 $table_definitions = apply_filters( 'pvc_plugin_status_tables', [], $this->settings );
404
405 if ( empty( $table_definitions ) || ! is_array( $table_definitions ) ) {
406 return [];
407 }
408
409 $validated_tables = [];
410
411 foreach ( $table_definitions as $table_def ) {
412 // validate structure
413 if ( ! is_array( $table_def ) || empty( $table_def['name'] ) ) {
414 continue;
415 }
416
417 $table_name = sanitize_key( $table_def['name'] );
418
419 // security: only allow tables with 'post_views' in the name
420 if ( strpos( $table_name, 'post_views' ) === false ) {
421 continue;
422 }
423
424 // check if table exists
425 $full_table_name = $wpdb->prefix . $table_name;
426 $exists = (bool) $wpdb->get_var( $wpdb->prepare( "SHOW TABLES LIKE %s", $full_table_name ) );
427
428 // use provided label or fallback to table name
429 $label = ! empty( $table_def['label'] ) ? $table_def['label'] : $table_name;
430
431 $validated_tables[] = [
432 'name' => $table_name,
433 'label' => $label,
434 'exists' => $exists
435 ];
436 }
437
438 return $validated_tables;
439 }
440
441 /**
442 * Section description: other - data import.
443 *
444 * @return void
445 */
446 public function section_other_import() {
447 echo '<p class="description">' . esc_html__( 'Import view counts when migrating from custom meta key or other analytics plugins.', 'post-views-counter' ) . '</p>';
448 }
449
450 /**
451 * Section description: other - admin & cleanup.
452 *
453 * @return void
454 */
455 public function section_other_management() {
456 echo '<p class="description">' . esc_html__( 'Choose what happens to stored view data on uninstall, and manage other removal-related tools.', 'post-views-counter' ) . '</p>';
457 }
458 }
459