PluginProbe
ThinkRank AI SEO – AI SEO Plugin for WordPress: Schema, XML Sitemaps, Meta Tags, Search Console & Local SEO / 2.10.0
ThinkRank AI SEO – AI SEO Plugin for WordPress: Schema, XML Sitemaps, Meta Tags, Search Console & Local SEO v2.10.0
2.10.0 2.9.0 2.8.0 2.7.0 2.6.0 2.5.0 2.4.0 2.3.0 2.2.0 2.1.1 2.1.0 2.0.2 2.0.1 2.0.0 1.32.0 1.31.0 1.30.0 1.29.0 1.28.0 1.27.0 1.26.0 1.25.0 trunk 1.0.0 1.0.1 All 51 releases
← All changes | includes/core/class-plugin-usage-tracker.php +90 -0 1.28.0 → 2.10.0 View file →
@@ -79,8 +79,19 @@
79 79 private $item_id;
80 80 private $notice_options;
81 81
82 82 /**
83 + * Unix timestamp before which the opt-in notice stays hidden.
84 + *
85 + * 0 keeps the SDK's original behaviour (ask on the first admin page load).
86 + * ThinkRank sets it to install time + a grace period via
87 + * {@see Usage_Tracker_Manager::start_tracking()}.
88 + *
89 + * @var int
90 + */
91 + private $notice_after = 0;
92 +
93 + /**
83 94 * Get Instance of Plugin_Usage_Tracker
84 95 *
85 96 * @return Plugin_Usage_Tracker
86 97 */
@@ -192,9 +203,16 @@
192 203 */
193 204 public function init() {
194 205 add_action('admin_init', array($this, 'clicked'));
195 206 add_action($this->event_hook, array($this, 'do_tracking'));
207 +
208 + // Both hooks, deliberately: Admin\Manager::remove_admin_notice() strips
209 + // every `admin_notices` callback on ThinkRank's own screens and re-fires
210 + // `thinkrank_admin_notices` in their place. Since notice() now renders
211 + // only on those screens, registering on `admin_notices` alone would mean
212 + // it never renders anywhere. The two never both run on one request.
196 213 add_action('admin_notices', array($this, 'notice'));
214 + add_action('thinkrank_admin_notices', array($this, 'notice'));
197 215 /**
198 216 * Deactivation Reason Form and Submit Data to Insights.
199 217 */
200 218 add_filter('plugin_action_links_' . plugin_basename($this->plugin_file), array($this, 'deactivate_action_links'));
@@ -663,8 +681,24 @@
663 681 }
664 682 if (!current_user_can('manage_options')) {
665 683 return;
666 684 }
685 + /**
686 + * Too soon after install to ask. A consent request on the user's very
687 + * first admin page load is the loudest possible first impression, and
688 + * it competes with the Setup Wizard the activation redirect just put
689 + * them in.
690 + */
691 + if ($this->notice_after > 0 && time() < $this->notice_after) {
692 + return;
693 + }
694 + /**
695 + * Ask on ThinkRank's own screens only. The card used to render on every
696 + * admin screen in the site, including other plugins' settings pages.
697 + */
698 + if (!$this->is_own_screen()) {
699 + return;
700 + }
667 701
668 702 $url_yes = add_query_arg([
669 703 'plugin' => $this->plugin_name,
670 704 'plugin_action' => 'yes',
@@ -714,8 +748,57 @@
714 748 echo $output;
715 749 }
716 750
717 751 /**
752 + * Hold the opt-in notice back until the given time.
753 + *
754 + * @since 2.8.1
755 + * @param int $timestamp Unix timestamp; 0 restores "ask immediately".
756 + * @return void
757 + */
758 + public function set_notice_after($timestamp) {
759 + $this->notice_after = max(0, (int) $timestamp);
760 + }
761 +
762 + /**
763 + * Whether the current admin screen belongs to ThinkRank.
764 + *
765 + * Matched on the screen id rather than against a list of page slugs:
766 + * Admin\Manager already keeps such a list and it has drifted from the
767 + * pages actually registered, and Pro adds screens of its own that a list
768 + * living in free could not know about.
769 + *
770 + * The Setup Wizard screen is excluded — it suppresses admin notices
771 + * wholesale and collects consent itself, so a card there would be both
772 + * invisible and redundant.
773 + *
774 + * @since 2.8.1
775 + * @return bool
776 + */
777 + private function is_own_screen() {
778 + if (!function_exists('get_current_screen')) {
779 + return false;
780 + }
781 +
782 + $screen = get_current_screen();
783 + if (!$screen instanceof \WP_Screen || empty($screen->id)) {
784 + return false;
785 + }
786 +
787 + $is_own = strpos($screen->id, 'thinkrank') !== false
788 + && strpos($screen->id, 'thinkrank_setup_wizard') === false;
789 +
790 + /**
791 + * Filter whether the usage-tracking opt-in notice may render here.
792 + *
793 + * @since 2.8.1
794 + * @param bool $is_own Whether this is a ThinkRank screen.
795 + * @param \WP_Screen $screen Current screen.
796 + */
797 + return (bool) apply_filters('thinkrank_usage_notice_is_own_screen', $is_own, $screen);
798 + }
799 +
800 + /**
718 801 * Set all notice options to customized notice.
719 802 *
720 803 * @since 1.12.0
721 804 * @param array $options
@@ -806,8 +889,15 @@
806 889 * @since 1.12.0
807 890 */
808 891 public function deactivate_reasons_form_submit() {
809 892 check_ajax_referer('wpins_deactivation_nonce', 'security');
893 +
894 + // The form is only reachable from the plugins screen; require the same
895 + // capability that screen does so the nonce isn't the only control.
896 + if (!current_user_can('activate_plugins')) {
897 + wp_die('', '', ['response' => 403]);
898 + }
899 +
810 900 if (isset($_POST['values'])) {
811 901 $values = sanitize_text_field(wp_unslash($_POST['values']));
812 902 update_option('wpins_deactivation_reason_' . $this->plugin_name, $values);
813 903 }