Nav apraksta

reviews.php 14KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562
  1. <?php
  2. if ( ! defined( 'ABSPATH' ) ) {
  3. exit;
  4. }
  5. /**
  6. * Class PUM_Modules_Reviews
  7. *
  8. * This class adds a review request system for your plugin or theme to the WP dashboard.
  9. */
  10. class PUM_Modules_Reviews {
  11. /**
  12. * Tracking API Endpoint.
  13. *
  14. * @var string
  15. */
  16. public static $api_url = 'https://api.wppopupmaker.com/wp-json/pmapi/v1/review_action';
  17. /**
  18. *
  19. */
  20. public static function init() {
  21. //add_action( 'init', array( __CLASS__, 'hooks' ) );
  22. add_filter( 'pum_alert_list', array( __CLASS__, 'review_alert' ) );
  23. add_action( 'wp_ajax_pum_review_action', array( __CLASS__, 'ajax_handler' ) );
  24. }
  25. /**
  26. * Hook into relevant WP actions.
  27. */
  28. public static function hooks() {
  29. if ( is_admin() && current_user_can( 'edit_posts' ) ) {
  30. self::installed_on();
  31. add_action( 'admin_notices', array( __CLASS__, 'admin_notices' ) );
  32. add_action( 'network_admin_notices', array( __CLASS__, 'admin_notices' ) );
  33. add_action( 'user_admin_notices', array( __CLASS__, 'admin_notices' ) );
  34. }
  35. }
  36. /**
  37. * Get the install date for comparisons. Sets the date to now if none is found.
  38. *
  39. * @return false|string
  40. */
  41. public static function installed_on() {
  42. $installed_on = get_option( 'pum_reviews_installed_on', false );
  43. if ( ! $installed_on ) {
  44. $installed_on = current_time( 'mysql' );
  45. update_option( 'pum_reviews_installed_on', $installed_on );
  46. }
  47. return $installed_on;
  48. }
  49. /**
  50. *
  51. */
  52. public static function ajax_handler() {
  53. $args = wp_parse_args( $_REQUEST, array(
  54. 'group' => self::get_trigger_group(),
  55. 'code' => self::get_trigger_code(),
  56. 'pri' => self::get_current_trigger( 'pri' ),
  57. 'reason' => 'maybe_later',
  58. ) );
  59. if ( ! wp_verify_nonce( $_REQUEST['nonce'], 'pum_review_action' ) ) {
  60. wp_send_json_error();
  61. }
  62. try {
  63. $user_id = get_current_user_id();
  64. $dismissed_triggers = self::dismissed_triggers();
  65. $dismissed_triggers[ $args['group'] ] = $args['pri'];
  66. update_user_meta( $user_id, '_pum_reviews_dismissed_triggers', $dismissed_triggers );
  67. update_user_meta( $user_id, '_pum_reviews_last_dismissed', current_time( 'mysql' ) );
  68. switch ( $args['reason'] ) {
  69. case 'maybe_later':
  70. update_user_meta( $user_id, '_pum_reviews_last_dismissed', current_time( 'mysql' ) );
  71. break;
  72. case 'am_now':
  73. case 'already_did':
  74. self::already_did( true );
  75. break;
  76. }
  77. wp_send_json_success();
  78. } catch ( Exception $e ) {
  79. wp_send_json_error( $e );
  80. }
  81. }
  82. /**
  83. * @return int|string
  84. */
  85. public static function get_trigger_group() {
  86. static $selected;
  87. if ( ! isset( $selected ) ) {
  88. $dismissed_triggers = self::dismissed_triggers();
  89. $triggers = self::triggers();
  90. foreach ( $triggers as $g => $group ) {
  91. foreach ( $group['triggers'] as $t => $trigger ) {
  92. if ( ! in_array( false, $trigger['conditions'] ) && ( empty( $dismissed_triggers[ $g ] ) || $dismissed_triggers[ $g ] < $trigger['pri'] ) ) {
  93. $selected = $g;
  94. break;
  95. }
  96. }
  97. if ( isset( $selected ) ) {
  98. break;
  99. }
  100. }
  101. }
  102. return $selected;
  103. }
  104. /**
  105. * @return int|string
  106. */
  107. public static function get_trigger_code() {
  108. static $selected;
  109. if ( ! isset( $selected ) ) {
  110. $dismissed_triggers = self::dismissed_triggers();
  111. foreach ( self::triggers() as $g => $group ) {
  112. foreach ( $group['triggers'] as $t => $trigger ) {
  113. if ( ! in_array( false, $trigger['conditions'] ) && ( empty( $dismissed_triggers[ $g ] ) || $dismissed_triggers[ $g ] < $trigger['pri'] ) ) {
  114. $selected = $t;
  115. break;
  116. }
  117. }
  118. if ( isset( $selected ) ) {
  119. break;
  120. }
  121. }
  122. }
  123. return $selected;
  124. }
  125. /**
  126. * @param null $key
  127. *
  128. * @return bool|mixed|void
  129. */
  130. public static function get_current_trigger( $key = null ) {
  131. $group = self::get_trigger_group();
  132. $code = self::get_trigger_code();
  133. if ( ! $group || ! $code ) {
  134. return false;
  135. }
  136. $trigger = self::triggers( $group, $code );
  137. return empty( $key ) ? $trigger : ( isset( $trigger[ $key ] ) ? $trigger[ $key ] : false );
  138. }
  139. /**
  140. * Returns an array of dismissed trigger groups.
  141. *
  142. * Array contains the group key and highest priority trigger that has been shown previously for each group.
  143. *
  144. * $return = array(
  145. * 'group1' => 20
  146. * );
  147. *
  148. * @return array|mixed
  149. */
  150. public static function dismissed_triggers() {
  151. $user_id = get_current_user_id();
  152. $dismissed_triggers = get_user_meta( $user_id, '_pum_reviews_dismissed_triggers', true );
  153. if ( ! $dismissed_triggers ) {
  154. $dismissed_triggers = array();
  155. }
  156. return $dismissed_triggers;
  157. }
  158. /**
  159. * Returns true if the user has opted to never see this again. Or sets the option.
  160. *
  161. * @param bool $set If set this will mark the user as having opted to never see this again.
  162. *
  163. * @return bool
  164. */
  165. public static function already_did( $set = false ) {
  166. $user_id = get_current_user_id();
  167. if ( $set ) {
  168. update_user_meta( $user_id, '_pum_reviews_already_did', true );
  169. return true;
  170. }
  171. return (bool) get_user_meta( $user_id, '_pum_reviews_already_did', true );
  172. }
  173. /**
  174. * Gets a list of triggers.
  175. *
  176. * @param null $group
  177. * @param null $code
  178. *
  179. * @return bool|mixed
  180. */
  181. public static function triggers( $group = null, $code = null ) {
  182. static $triggers;
  183. if ( ! isset( $triggers ) ) {
  184. $time_message = __( 'Hi there! You\'ve been using Popup Maker on your site for %s - I hope it\'s been helpful. If you\'re enjoying my plugin, would you mind rating it 5-stars to help spread the word?', 'popup-maker' );
  185. $triggers = array(
  186. 'time_installed' => array(
  187. 'triggers' => array(
  188. 'one_week' => array(
  189. 'message' => sprintf( $time_message, __( '1 week', 'popup-maker' ) ),
  190. 'conditions' => array(
  191. strtotime( self::installed_on() . ' +1 week' ) < time(),
  192. ),
  193. 'link' => 'https://wordpress.org/support/plugin/popup-maker/reviews/?rate=5#rate-response',
  194. 'pri' => 10,
  195. ),
  196. 'one_month' => array(
  197. 'message' => sprintf( $time_message, __( '1 month', 'popup-maker' ) ),
  198. 'conditions' => array(
  199. strtotime( self::installed_on() . ' +1 month' ) < time(),
  200. ),
  201. 'link' => 'https://wordpress.org/support/plugin/popup-maker/reviews/?rate=5#rate-response',
  202. 'pri' => 20,
  203. ),
  204. 'three_months' => array(
  205. 'message' => sprintf( $time_message, __( '3 months', 'popup-maker' ) ),
  206. 'conditions' => array(
  207. strtotime( self::installed_on() . ' +3 months' ) < time(),
  208. ),
  209. 'link' => 'https://wordpress.org/support/plugin/popup-maker/reviews/?rate=5#rate-response',
  210. 'pri' => 30,
  211. ),
  212. ),
  213. 'pri' => 10,
  214. ),
  215. 'open_count' => array(
  216. 'triggers' => array(),
  217. 'pri' => 50,
  218. ),
  219. );
  220. $pri = 10;
  221. $open_message = __( 'Hi there! You\'ve recently hit %s popup views on your site – that’s awesome!! If you\'d like to celebrate this milestone, rate Popup Maker 5-stars to help spread the word!', 'popup-maker' );
  222. foreach ( array( 50, 100, 500, 1000, 5000, 10000, 50000, 100000, 500000, 1000000, 5000000 ) as $num ) {
  223. $triggers['open_count']['triggers'][ $num . '_opens' ] = array(
  224. 'message' => sprintf( $open_message, number_format( $num ) ),
  225. 'conditions' => array(
  226. get_option( 'pum_total_open_count', 0 ) > $num,
  227. ),
  228. 'link' => 'https://wordpress.org/support/plugin/popup-maker/reviews/?rate=5#rate-response',
  229. 'pri' => $pri,
  230. );
  231. $pri += 10;
  232. }
  233. $triggers = apply_filters( 'pum_reviews_triggers', $triggers );
  234. // Sort Groups
  235. uasort( $triggers, array( __CLASS__, 'rsort_by_priority' ) );
  236. // Sort each groups triggers.
  237. foreach ( $triggers as $k => $v ) {
  238. uasort( $triggers[ $k ]['triggers'], array( __CLASS__, 'rsort_by_priority' ) );
  239. }
  240. }
  241. if ( isset( $group ) ) {
  242. if ( ! isset( $triggers[ $group ] ) ) {
  243. return false;
  244. }
  245. if ( ! isset( $code ) ) {
  246. return $triggers[ $group ];
  247. } else {
  248. return isset( $triggers[ $group ]['triggers'][ $code ] ) ? $triggers[ $group ]['triggers'][ $code ] : false;
  249. }
  250. }
  251. return $triggers;
  252. }
  253. /**
  254. * Register alert when review request is available.
  255. *
  256. * @param array $alerts
  257. *
  258. * @return array
  259. */
  260. public static function review_alert( $alerts = array() ) {
  261. if ( self::hide_notices() ) {
  262. return $alerts;
  263. }
  264. $trigger = self::get_current_trigger();
  265. // Used to anonymously distinguish unique site+user combinations in terms of effectiveness of each trigger.
  266. $uuid = wp_hash( home_url() . '-' . get_current_user_id() );
  267. ob_start();
  268. ?>
  269. <script type="text/javascript">
  270. window.pum_review_nonce = '<?php echo wp_create_nonce( 'pum_review_action' ); ?>';
  271. window.pum_review_api_url = '<?php echo self::$api_url; ?>';
  272. window.pum_review_uuid = '<?php echo $uuid; ?>';
  273. window.pum_review_trigger = {
  274. group: '<?php echo self::get_trigger_group(); ?>',
  275. code: '<?php echo self::get_trigger_code(); ?>',
  276. pri: '<?php echo self::get_current_trigger( 'pri' ); ?>'
  277. };
  278. </script>
  279. <ul>
  280. <li>
  281. <a class="pum-dismiss" target="_blank" href="<?php echo $trigger['link']; ?>>" data-reason="am_now"> <strong><?php _e( 'Ok, you deserve it', 'popup-maker' ); ?></strong> </a>
  282. </li>
  283. <li>
  284. <a href="#" class="pum-dismiss" data-reason="maybe_later">
  285. <?php _e( 'Nope, maybe later', 'popup-maker' ); ?>
  286. </a>
  287. </li>
  288. <li>
  289. <a href="#" class="pum-dismiss" data-reason="already_did">
  290. <?php _e( 'I already did', 'popup-maker' ); ?>
  291. </a>
  292. </li>
  293. </ul>
  294. <?php
  295. $html = ob_get_clean();
  296. $alerts[] = array(
  297. 'code' => 'review_request',
  298. 'message' => '<strong>' . $trigger['message'] . '<br />~ danieliser' . '</strong>',
  299. 'html' => $html,
  300. 'type' => 'success',
  301. );
  302. return $alerts;
  303. }
  304. /**
  305. * Render admin notices if available.
  306. *
  307. * @deprecated 1.8.0
  308. */
  309. public static function admin_notices() {
  310. if ( self::hide_notices() ) {
  311. return;
  312. }
  313. $group = self::get_trigger_group();
  314. $code = self::get_trigger_code();
  315. $pri = self::get_current_trigger( 'pri' );
  316. $trigger = self::get_current_trigger();
  317. // Used to anonymously distinguish unique site+user combinations in terms of effectiveness of each trigger.
  318. $uuid = wp_hash( home_url() . '-' . get_current_user_id() );
  319. ?>
  320. <script type="text/javascript">
  321. (function ($) {
  322. var trigger = {
  323. group: '<?php echo $group; ?>',
  324. code: '<?php echo $code; ?>',
  325. pri: '<?php echo $pri; ?>'
  326. };
  327. function dismiss(reason) {
  328. $.ajax({
  329. method: "POST",
  330. dataType: "json",
  331. url: ajaxurl,
  332. data: {
  333. action: 'pum_review_action',
  334. nonce: '<?php echo wp_create_nonce( 'pum_review_action' ); ?>',
  335. group: trigger.group,
  336. code: trigger.code,
  337. pri: trigger.pri,
  338. reason: reason
  339. }
  340. });
  341. <?php if ( ! empty( self::$api_url ) ) : ?>
  342. $.ajax({
  343. method: "POST",
  344. dataType: "json",
  345. url: '<?php echo self::$api_url; ?>',
  346. data: {
  347. trigger_group: trigger.group,
  348. trigger_code: trigger.code,
  349. reason: reason,
  350. uuid: '<?php echo $uuid; ?>'
  351. }
  352. });
  353. <?php endif; ?>
  354. }
  355. $(document)
  356. .on('click', '.pum-notice .pum-dismiss', function (event) {
  357. var $this = $(this),
  358. reason = $this.data('reason'),
  359. notice = $this.parents('.pum-notice');
  360. notice.fadeTo(100, 0, function () {
  361. notice.slideUp(100, function () {
  362. notice.remove();
  363. });
  364. });
  365. dismiss(reason);
  366. })
  367. .ready(function () {
  368. setTimeout(function () {
  369. $('.pum-notice button.notice-dismiss').click(function (event) {
  370. dismiss('maybe_later');
  371. });
  372. }, 1000);
  373. });
  374. }(jQuery));
  375. </script>
  376. <style>
  377. .pum-notice p {
  378. margin-bottom: 0;
  379. }
  380. .pum-notice img.logo {
  381. float: right;
  382. margin-left: 10px;
  383. width: 128px;
  384. padding: 0.25em;
  385. border: 1px solid #ccc;
  386. }
  387. </style>
  388. <div class="notice notice-success is-dismissible pum-notice">
  389. <p>
  390. <img class="logo" src="<?php echo POPMAKE_URL; ?>/assets/images/icon-256x256.jpg" />
  391. <strong>
  392. <?php echo $trigger['message']; ?>
  393. <br />
  394. ~ danieliser
  395. </strong>
  396. </p>
  397. <ul>
  398. <li>
  399. <a class="pum-dismiss" target="_blank" href="<?php echo $trigger['link']; ?>>" data-reason="am_now">
  400. <strong><?php _e( 'Ok, you deserve it', 'popup-maker' ); ?></strong>
  401. </a>
  402. </li>
  403. <li>
  404. <a href="#" class="pum-dismiss" data-reason="maybe_later">
  405. <?php _e( 'Nope, maybe later', 'popup-maker' ); ?>
  406. </a>
  407. </li>
  408. <li>
  409. <a href="#" class="pum-dismiss" data-reason="already_did">
  410. <?php _e( 'I already did', 'popup-maker' ); ?>
  411. </a>
  412. </li>
  413. </ul>
  414. </div>
  415. <?php
  416. }
  417. /**
  418. * Checks if notices should be shown.
  419. *
  420. * @return bool
  421. */
  422. public static function hide_notices() {
  423. $trigger_code = self::get_trigger_code();
  424. $conditions = array(
  425. self::already_did(),
  426. self::last_dismissed() && strtotime( self::last_dismissed() . ' +2 weeks' ) > time(),
  427. empty( $trigger_code ),
  428. );
  429. return in_array( true, $conditions );
  430. }
  431. /**
  432. * Gets the last dismissed date.
  433. *
  434. * @return false|string
  435. */
  436. public static function last_dismissed() {
  437. $user_id = get_current_user_id();
  438. return get_user_meta( $user_id, '_pum_reviews_last_dismissed', true );
  439. }
  440. /**
  441. * Sort array by priority value
  442. *
  443. * @param $a
  444. * @param $b
  445. *
  446. * @return int
  447. */
  448. public static function sort_by_priority( $a, $b ) {
  449. if ( ! isset( $a['pri'] ) || ! isset( $b['pri'] ) || $a['pri'] === $b['pri'] ) {
  450. return 0;
  451. }
  452. return ( $a['pri'] < $b['pri'] ) ? - 1 : 1;
  453. }
  454. /**
  455. * Sort array in reverse by priority value
  456. *
  457. * @param $a
  458. * @param $b
  459. *
  460. * @return int
  461. */
  462. public static function rsort_by_priority( $a, $b ) {
  463. if ( ! isset( $a['pri'] ) || ! isset( $b['pri'] ) || $a['pri'] === $b['pri'] ) {
  464. return 0;
  465. }
  466. return ( $a['pri'] < $b['pri'] ) ? 1 : - 1;
  467. }
  468. }
  469. PUM_Modules_Reviews::init();