PluginProbe
Tag, Category, and Taxonomy Manager – Autotagger Automatically Add Terms / 3.4.0
Tag, Category, and Taxonomy Manager – Autotagger Automatically Add Terms v3.4.0
3.53.0 3.52.0 3.51.0 3.50.0 3.45.0 3.38.0 3.4.0 3.4.1 3.4.2 3.4.3 3.4.4 3.4.5 3.40.0 3.40.1 3.41.0 3.42.0 3.43.0 3.44.0 3.5.0 3.5.1 3.5.2 3.5.3 3.6.0 3.6.1 3.6.2 All 177 releases
simple-tags / review-request / review.php

review.php in Tag, Category, and Taxonomy Manager – Autotagger Automatically Add Terms 3.4.0, at review-request/review.php

556 lines 18.7 KB
No matching file
Up and down to move Enter to open Esc to close
Raw Download Zip
1 <?php
2 /**
3 * This class can be customized to quickly add a review request system.
4 *
5 * It includes:
6 * - Multiple trigger groups which can be ordered by priority.
7 * - Multiple triggers per group.
8 * - Customizable messaging per trigger.
9 * - Link to review page.
10 * - Request reviews on a per user basis rather than per site.
11 * - Allows each user to dismiss it until later or permanently seamlessly via AJAX.
12 * - Integrates with attached tracking server to keep anonymous records of each triggers effectiveness.
13 * - Tracking Server API: https://gist.github.com/danieliser/0d997532e023c46d38e1bdfd50f38801
14 *
15 * To use this please include the following credit block as well as completing the following TODOS.
16 *
17 * Original Author: danieliser
18 * Original Author URL: https://danieliser.com
19 *
20 * TODO Search & Replace taxopress_ with your prefix
21 * TODO Search & Replace Taxopress_ with your prefix
22 * TODO Search & Replace 'simple-tags' with your 'simple-tags'
23 * TODO Change the $api_url if your using the accompanying tracking server. Leave it blank to disable this feature.
24 * TODO Modify the ::triggers function array with your custom triggers & text.
25 * TODO Keep in mind highest priority group/code combination that has all passing conditions will be chosen.
26 */
27
28 if (!defined('ABSPATH')) {
29 exit;
30 }
31
32 if (!class_exists('Taxopress_Modules_Reviews')) {
33 /**
34 * Class Taxopress_Modules_Reviews
35 *
36 * This class adds a review request system for your plugin or theme to the WP dashboard.
37 */
38 class Taxopress_Modules_Reviews
39 {
40
41 /**
42 * Tracking API Endpoint.
43 *
44 * @var string
45 */
46 public static $api_url = '';
47
48 /**
49 *
50 */
51 public static function init()
52 {
53 add_action('init', [__CLASS__, 'hooks']);
54 add_action('wp_ajax_taxopress_review_action', [__CLASS__, 'ajax_handler']);
55 }
56
57 /**
58 * Hook into relevant WP actions.
59 */
60 public static function hooks()
61 {
62 if (is_admin() && current_user_can('edit_posts')) {
63 self::installed_on();
64 if(is_taxopress_admin_page()){
65 add_action('admin_notices', [__CLASS__, 'admin_notices']);
66 add_action('network_admin_notices', [__CLASS__, 'admin_notices']);
67 add_action('user_admin_notices', [__CLASS__, 'admin_notices']);
68 //moved assets to footer due to a plugin stripping out assets in admin notice (https://wordpress.org/plugins/disable-admin-notices/)
69 add_action('admin_footer', [__CLASS__, 'admin_footer']);
70 }
71 }
72 }
73
74 /**
75 * Get the install date for comparisons. Sets the date to now if none is found.
76 *
77 * @return false|string
78 */
79 public static function installed_on()
80 {
81 $installed_on = get_option('taxopress_reviews_installed_on', false);
82
83 if (!$installed_on) {
84 $installed_on = current_time('mysql');
85 update_option('taxopress_reviews_installed_on', $installed_on);
86 }
87
88 return $installed_on;
89 }
90
91 /**
92 *
93 */
94 public static function ajax_handler()
95 {
96 $args = wp_parse_args($_REQUEST, [
97 'group' => self::get_trigger_group(),
98 'code' => self::get_trigger_code(),
99 'pri' => self::get_current_trigger('pri'),
100 'reason' => 'maybe_later',
101 ]);
102
103 if (!wp_verify_nonce($_REQUEST['nonce'], 'taxopress_review_action')) {
104 wp_send_json_error();
105 }
106
107 try {
108 $user_id = get_current_user_id();
109
110 $dismissed_triggers = self::dismissed_triggers();
111 $dismissed_triggers[$args['group']] = $args['pri'];
112 update_user_meta($user_id, '_taxopress_reviews_dismissed_triggers', $dismissed_triggers);
113 update_user_meta($user_id, '_taxopress_reviews_last_dismissed', current_time('mysql'));
114
115 switch($args['reason']) {
116 case 'maybe_later':
117 update_user_meta($user_id, '_taxopress_reviews_last_dismissed', current_time('mysql'));
118 break;
119 case 'am_now':
120 case 'already_did':
121 self::already_did(true);
122 break;
123 }
124
125 wp_send_json_success();
126
127 } catch (Exception $e) {
128 wp_send_json_error($e);
129 }
130 }
131
132 /**
133 * @return int|string
134 */
135 public static function get_trigger_group()
136 {
137 static $selected;
138
139 if (!isset($selected)) {
140
141 $dismissed_triggers = self::dismissed_triggers();
142
143 $triggers = self::triggers();
144
145 foreach ($triggers as $g => $group) {
146 foreach ($group['triggers'] as $t => $trigger) {
147 if (!in_array(false,
148 $trigger['conditions']) && (empty($dismissed_triggers[$g]) || $dismissed_triggers[$g] < $trigger['pri'])) {
149 $selected = $g;
150 break;
151 }
152 }
153
154 if (isset($selected)) {
155 break;
156 }
157 }
158 }
159
160 return $selected;
161 }
162
163 /**
164 * @return int|string
165 */
166 public static function get_trigger_code()
167 {
168 static $selected;
169
170 if (!isset($selected)) {
171
172 $dismissed_triggers = self::dismissed_triggers();
173
174 foreach (self::triggers() as $g => $group) {
175 foreach ($group['triggers'] as $t => $trigger) {
176 if (!in_array(false,
177 $trigger['conditions']) && (empty($dismissed_triggers[$g]) || $dismissed_triggers[$g] < $trigger['pri'])) {
178 $selected = $t;
179 break;
180 }
181 }
182
183 if (isset($selected)) {
184 break;
185 }
186 }
187 }
188
189 return $selected;
190 }
191
192 /**
193 * @param null $key
194 *
195 * @return bool|mixed|void
196 */
197 public static function get_current_trigger($key = null)
198 {
199 $group = self::get_trigger_group();
200 $code = self::get_trigger_code();
201
202 if (!$group || !$code) {
203 return false;
204 }
205
206 $trigger = self::triggers($group, $code);
207
208 if(empty($key)){
209 $return = $trigger;
210 }elseif(isset($trigger[$key])){
211 $return = $trigger[$key];
212 }else {
213 $return = false;
214 }
215
216 return $return;
217 }
218
219 /**
220 * Returns an array of dismissed trigger groups.
221 *
222 * Array contains the group key and highest priority trigger that has been shown previously for each group.
223 *
224 * $return = array(
225 * 'group1' => 20
226 * );
227 *
228 * @return array|mixed
229 */
230 public static function dismissed_triggers()
231 {
232 $user_id = get_current_user_id();
233
234 $dismissed_triggers = get_user_meta($user_id, '_taxopress_reviews_dismissed_triggers', true);
235
236 if (!$dismissed_triggers) {
237 $dismissed_triggers = [];
238 }
239
240 return $dismissed_triggers;
241 }
242
243 /**
244 * Returns true if the user has opted to never see this again. Or sets the option.
245 *
246 * @param bool $set If set this will mark the user as having opted to never see this again.
247 *
248 * @return bool
249 */
250 public static function already_did($set = false)
251 {
252 $user_id = get_current_user_id();
253
254 if ($set) {
255 update_user_meta($user_id, '_taxopress_reviews_already_did', true);
256
257 return true;
258 }
259
260 return (bool)get_user_meta($user_id, '_taxopress_reviews_already_did', true);
261 }
262
263 /**
264 * Gets a list of triggers.
265 *
266 * @param null $group
267 * @param null $code
268 *
269 * @return bool|mixed|void
270 */
271 public static function triggers($group = null, $code = null)
272 {
273 static $triggers;
274
275 if (!isset($triggers)) {
276
277 $time_message = __("Hey, you've been using TaxoPress for %s on your site. We hope the plugin has been useful. Please could you quickly leave a 5-star rating on WordPress.org? It really does help to keep TaxoPress growing.",
278 'simple-tags');
279
280 $triggers = apply_filters('taxopress_reviews_triggers', [
281 'time_installed' => [
282 'triggers' => [
283 'one_week' => [
284 'message' => sprintf($time_message, __('1 week', 'simple-tags')),
285 'conditions' => [
286 strtotime(self::installed_on() . ' +1 week') < time(),
287 ],
288 'link' => 'https://wordpress.org/support/plugin/simple-tags/reviews/?rate=5#rate-response',
289 'pri' => 10,
290 ],
291 'one_month' => [
292 'message' => sprintf($time_message, __('1 month', 'simple-tags')),
293 'conditions' => [
294 strtotime(self::installed_on() . ' +1 month') < time(),
295 ],
296 'link' => 'https://wordpress.org/support/plugin/simple-tags/reviews/?rate=5#rate-response',
297 'pri' => 20,
298 ],
299 'three_months' => [
300 'message' => sprintf($time_message, __('3 months', 'simple-tags')),
301 'conditions' => [
302 strtotime(self::installed_on() . ' +3 months') < time(),
303 ],
304 'link' => 'https://wordpress.org/support/plugin/simple-tags/reviews/?rate=5#rate-response',
305 'pri' => 30,
306 ],
307
308 ],
309 'pri' => 10,
310 ]
311 ]);
312
313 // Sort Groups
314 uasort($triggers, [__CLASS__, 'rsort_by_priority']);
315
316 // Sort each groups triggers.
317 foreach ($triggers as $k => $v) {
318 uasort($triggers[$k]['triggers'], [__CLASS__, 'rsort_by_priority']);
319 }
320 }
321
322 if (isset($group)) {
323 if (!isset($triggers[$group])) {
324 return false;
325 }
326
327
328 if (!isset($code)) {
329 $return = $triggers[$group];
330 } elseif (isset($triggers[$group]['triggers'][$code])) {
331 $return = $triggers[$group]['triggers'][$code];
332 } else {
333 $return = false;
334 }
335
336 return $return;
337 }
338
339 return $triggers;
340 }
341
342 /**
343 * Render admin notices if available.
344 */
345 public static function admin_notices()
346 {
347
348 if (self::hide_notices()) {
349 return;
350 }
351 $tigger = self::get_current_trigger();
352
353 ?>
354
355 <div class="notice notice-success is-dismissible taxopress-notice">
356
357 <img src="<?php echo STAGS_URL ?>/assets/images/logo-notice.png" class="logo" alt=""/>
358 <p>
359 <?php echo $tigger['message']; ?>
360 </p>
361 <p>
362 <a class="button button-primary taxopress-dismiss" target="_blank"
363 href="https://wordpress.org/support/plugin/simple-tags/reviews/?rate=5#rate-response"
364 data-reason="am_now">
365 <strong><?php _e('Click here to add your rating for TaxoPress', 'simple-tags'); ?></strong>
366 </a> <a href="#" class="button taxopress-dismiss" data-reason="maybe_later">
367 <?php _e('Maybe later', 'simple-tags'); ?>
368 </a> <a href="#" class="button taxopress-dismiss" data-reason="already_did">
369 <?php _e('I already did', 'simple-tags'); ?>
370 </a>
371 </p>
372
373 </div>
374
375 <?php
376 }
377
378 /**
379 * Render admin notice assets if available.
380 */
381 public static function admin_footer()
382 {
383
384 if (self::hide_notices()) {
385 return;
386 }
387
388 $group = self::get_trigger_group();
389 $code = self::get_trigger_code();
390 $pri = self::get_current_trigger('pri');
391 $tigger = self::get_current_trigger();
392
393 // Used to anonymously distinguish unique site+user combinations in terms of effectiveness of each trigger.
394 $uuid = wp_hash(home_url() . '-' . get_current_user_id());
395
396 ?>
397
398 <script type="text/javascript">
399 (function($) {
400 var trigger = {
401 group: '<?php echo $group; ?>',
402 code: '<?php echo $code; ?>',
403 pri: '<?php echo $pri; ?>'
404 }
405
406 function dismiss(reason) {
407 $.ajax({
408 method: "POST",
409 dataType: "json",
410 url: ajaxurl,
411 data: {
412 action: 'taxopress_review_action',
413 nonce: '<?php echo wp_create_nonce('taxopress_review_action'); ?>',
414 group: trigger.group,
415 code: trigger.code,
416 pri: trigger.pri,
417 reason: reason
418 }
419 })
420
421 <?php if ( !empty(self::$api_url) ) : ?>
422 $.ajax({
423 method: "POST",
424 dataType: "json",
425 url: '<?php echo self::$api_url; ?>',
426 data: {
427 trigger_group: trigger.group,
428 trigger_code: trigger.code,
429 reason: reason,
430 uuid: '<?php echo $uuid; ?>'
431 }
432 })
433 <?php endif; ?>
434 }
435
436 $(document)
437 .on('click', '.taxopress-notice .taxopress-dismiss', function(event) {
438 var $this = $(this),
439 reason = $this.data('reason'),
440 notice = $this.parents('.taxopress-notice')
441
442 notice.fadeTo(100, 0, function() {
443 notice.slideUp(100, function() {
444 notice.remove()
445 })
446 })
447
448 dismiss(reason)
449 })
450 .ready(function() {
451 setTimeout(function() {
452 $('.taxopress-notice button.notice-dismiss').click(function(event) {
453 dismiss('maybe_later')
454 })
455 }, 1000)
456 })
457 }(jQuery))
458 </script>
459 <style>
460 .taxopress-notice {
461 min-height: 100px;
462 }
463 .taxopress-notice img.logo {
464 float: right;
465 width: 75px;
466 padding: 10px 0 10px 20px;
467 }
468 .taxopress-notice p,
469 .taxopress-notice .button {
470 font-size: 15px;
471 }
472 .taxopress-notice .button:not(.button-primary),
473 .taxopress-notice .button:not(.button-primary):hover,
474 .taxopress-notice .button:not(.button-primary):active,
475 .taxopress-notice .button:not(.button-primary):focus {
476 border-color: #1F48AC !important;
477 color: #1F48AC !important;
478 }
479 .taxopress-notice .button-primary,
480 .taxopress-notice .button-primary:hover,
481 .taxopress-notice .button-primary:active,
482 .taxopress-notice .button-primary:focus {
483 border-color: #1F48AC !important;
484 background: #1F48AC !important;
485 }
486 </style>
487 <?php
488 }
489
490 /**
491 * Checks if notices should be shown.
492 *
493 * @return bool
494 */
495 public static function hide_notices()
496 {
497 $conditions = [
498 self::already_did(),
499 self::last_dismissed() && strtotime(self::last_dismissed() . ' +2 weeks') > time(),
500 empty(self::get_trigger_code()),
501 ];
502
503 return in_array(true, $conditions);
504 }
505
506 /**
507 * Gets the last dismissed date.
508 *
509 * @return false|string
510 */
511 public static function last_dismissed()
512 {
513 $user_id = get_current_user_id();
514
515 return get_user_meta($user_id, '_taxopress_reviews_last_dismissed', true);
516 }
517
518 /**
519 * Sort array by priority value
520 *
521 * @param $a
522 * @param $b
523 *
524 * @return int
525 */
526 public static function sort_by_priority($a, $b)
527 {
528 if (!isset($a['pri']) || !isset($b['pri']) || $a['pri'] === $b['pri']) {
529 return 0;
530 }
531
532 return ($a['pri'] < $b['pri']) ? -1 : 1;
533 }
534
535 /**
536 * Sort array in reverse by priority value
537 *
538 * @param $a
539 * @param $b
540 *
541 * @return int
542 */
543 public static function rsort_by_priority($a, $b)
544 {
545 if (!isset($a['pri']) || !isset($b['pri']) || $a['pri'] === $b['pri']) {
546 return 0;
547 }
548
549 return ($a['pri'] < $b['pri']) ? 1 : -1;
550 }
551
552 }
553 }
554
555 Taxopress_Modules_Reviews::init();
556