PluginProbe
Tag, Category, and Taxonomy Manager – Autotagger Automatically Add Terms / 3.4.4
Tag, Category, and Taxonomy Manager – Autotagger Automatically Add Terms v3.4.4
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.4, at review-request/review.php

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