PluginProbe ʕ •ᴥ•ʔ
Matomo Analytics – Powerful, Privacy-First Insights for WordPress / 5.8.2
Matomo Analytics – Powerful, Privacy-First Insights for WordPress v5.8.2
5.11.1 5.11.0 5.10.2 5.10.1 trunk 1.0.2 1.0.3 1.0.4 1.0.5 1.0.6 1.1.0 1.1.1 1.1.2 1.1.3 1.2.0 1.3.0 1.3.1 1.3.2 4.0.0 4.0.1 4.0.2 4.0.3 4.0.4 4.1.0 4.1.1 4.1.2 4.1.3 4.10.0 4.11.0 4.12.0 4.13.0 4.13.2 4.13.3 4.13.4 4.13.5 4.14.0 4.14.1 4.14.2 4.15.0 4.15.1 4.15.2 4.15.3 4.2.0 4.3.0 4.3.1 4.4.1 4.4.2 4.5.0 4.6.0 5.0.1 5.0.2 5.0.3 5.0.4 5.0.5 5.0.6 5.0.7 5.0.8 5.1.0 5.1.1 5.1.2 5.1.3 5.1.4 5.1.5 5.1.6 5.1.7 5.10.0 5.2.0 5.2.1 5.2.2 5.3.0 5.3.1 5.3.2 5.3.3 5.6.0 5.6.1 5.7.0 5.7.1 5.8.0 5.8.1 5.8.2
matomo / classes / WpMatomo / Admin / WhatsNewNotifications.php
matomo / classes / WpMatomo / Admin Last commit date
PluginSuggestions 2 months ago TrackingSettings 2 months ago views 2 months ago AccessSettings.php 4 years ago AdBlockDetector.php 7 months ago Admin.php 2 months ago AdminSettings.php 2 months ago AdminSettingsInterface.php 6 years ago AdvancedSettings.php 10 months ago Chart.php 2 months ago CookieConsent.php 4 years ago Dashboard.php 2 months ago ExclusionSettings.php 7 months ago GeolocationSettings.php 2 years ago GetStarted.php 2 months ago ImportWpStatistics.php 2 months ago Info.php 2 months ago InvalidIpException.php 4 years ago Marketplace.php 2 months ago MarketplaceSetupWizard.php 2 months ago MarketplaceSetupWizardBody.php 3 months ago MatomoPage.php 2 months ago MatomoPageContent.php 2 months ago Menu.php 2 months ago PluginMeasurableSettings.php 2 years ago PrivacySettings.php 1 year ago SafeModeMenu.php 2 months ago Summary.php 2 months ago SystemReport.php 2 months ago TrackingSettings.php 4 months ago WhatsNewNotifications.php 2 months ago
WhatsNewNotifications.php
272 lines
1 <?php
2 /**
3 * Matomo - free/libre analytics platform
4 *
5 * @link https://matomo.org
6 * @license http://www.gnu.org/licenses/gpl-3.0.html GPL v3 or later
7 * @package matomo
8 */
9
10 namespace WpMatomo\Admin;
11
12 use WpMatomo\Settings;
13
14 /**
15 * Handles the display of notifications about new features that we definitely want users
16 * to notice and read.
17 *
18 * Notification content is added and removed manually when needed from the get_current_notifications()
19 * function. This function returns an array where each element describes a notification to show.
20 *
21 * Elements of the array can have the following keys:
22 * - notification_marker_page: the MWP admin page to show a small red dot to signify to a user there's
23 * something to see.
24 * - message: the HTML content of the notification.
25 * - show_on: either self::SHOW_ON_ALL_PAGES or self::SHOW_ON_SINGLE_PAGE. SHOW_ON_ALL_PAGES will show
26 * the notification on every MWP admin page. SHOW_ON_SINGLE_PAGE will only show the
27 * full notification on the page specified in the notification_marker_page property.
28 * - show_if: either true or false. If true, it is shown, if false it is not. If absent, defaults to true.
29 * This property should be used to determine if a notification should be used based on the
30 * current request or the current user's capabilities.
31 *
32 * The ID of the notification is specified as the array key.
33 */
34 class WhatsNewNotifications {
35
36 const NOTIFICATION_STATUSES_OPTION_NAME = 'matomo-notification-statuses';
37
38 const STATUS_UNSEEN = 0;
39 const STATUS_SEEN = 1;
40 const STATUS_DISMISSED = 2;
41
42 const SHOW_ON_ALL_PAGES = 'all';
43 const SHOW_ON_SINGLE_PAGE = 'single';
44
45 const NONCE_NAME = 'matomo-whats-new-notifications';
46
47 private $statuses = null;
48
49 /**
50 * @var Settings
51 */
52 private $settings;
53
54 public function __construct( Settings $settings ) {
55 $this->settings = $settings;
56 }
57
58 public function is_active() {
59 if ( ! is_admin() ) {
60 return false;
61 }
62
63 $notifications_to_show = $this->get_notifications_to_show();
64 return ! empty( $notifications_to_show );
65 }
66
67 public function register_hooks() {
68 add_action( 'admin_enqueue_scripts', [ $this, 'on_admin_enqueue_scripts' ] );
69
70 $current_page = Admin::get_current_page();
71 if (
72 Admin::is_matomo_admin()
73 && Menu::SLUG_GET_STARTED !== $current_page
74 ) {
75 add_action( 'admin_notices', [ $this, 'on_admin_notices' ] );
76 }
77 }
78
79 public function register_ajax() {
80 add_action( 'wp_ajax_mtm_dismiss_whats_new', [ $this, 'on_dismiss_notification' ] );
81 }
82
83 public function on_admin_notices() {
84 $matomo_notifications = $this->get_notifications_to_show();
85
86 require __DIR__ . '/views/whats-new-notifications.php';
87 }
88
89 public function on_admin_enqueue_scripts() {
90 $this->mark_current_page_as_seen();
91
92 wp_localize_script(
93 'matomo-admin-js',
94 'mtmWhatsNewNotificationAjax',
95 [
96 'ajax_url' => admin_url( 'admin-ajax.php' ),
97 'nonce' => wp_create_nonce( self::NONCE_NAME ),
98 ]
99 );
100
101 $unseen_notifications = $this->get_unseen_notification_pages();
102 $unseen_notifications = array_values( $unseen_notifications );
103 wp_localize_script(
104 'matomo-admin-js',
105 'mtmUnseenWhatsNewNotifications',
106 $unseen_notifications
107 );
108 }
109
110 public function on_dismiss_notification() {
111 check_ajax_referer( self::NONCE_NAME );
112
113 if ( empty( $_POST['matomo_notification'] ) ) {
114 wp_send_json( false );
115 return;
116 }
117
118 $notifications = $this->get_current_notifications();
119 $notification_id = sanitize_text_field( wp_unslash( $_POST['matomo_notification'] ) );
120 if ( ! isset( $notifications[ $notification_id ] ) ) {
121 wp_send_json( false );
122 return;
123 }
124
125 $statuses = $this->get_notification_statuses();
126 $statuses[ $notification_id ] = self::STATUS_DISMISSED;
127 $this->save_notification_statuses( $statuses );
128
129 wp_send_json( true );
130 }
131
132 private function get_notification_statuses() {
133 if ( null !== $this->statuses ) {
134 return $this->statuses;
135 }
136
137 $option_name = $this->get_notification_status_option_name();
138 if ( $this->settings->is_network_enabled() ) {
139 $this->statuses = get_site_option( $option_name );
140 } else {
141 $this->statuses = get_option( $option_name );
142 }
143
144 if ( ! is_array( $this->statuses ) ) {
145 $this->statuses = [];
146 }
147
148 return $this->statuses;
149 }
150
151 private function save_notification_statuses( $statuses ) {
152 if ( ! is_array( $statuses ) ) {
153 $statuses = [];
154 }
155
156 $option_name = $this->get_notification_status_option_name();
157 if ( $this->settings->is_network_enabled() ) {
158 update_site_option( $option_name, $statuses );
159 } else {
160 update_option( $option_name, $statuses );
161 }
162
163 $this->statuses = $statuses;
164 }
165
166 private function mark_current_page_as_seen() {
167 $current_page = Admin::get_current_page();
168
169 $notifications = $this->get_current_notifications();
170
171 $notifications_to_mark = [];
172 foreach ( $notifications as $notification_id => $notification ) {
173 if ( $notification['notification_marker_page'] === $current_page ) {
174 $notifications_to_mark[ $notification_id ] = self::STATUS_SEEN;
175 }
176 }
177
178 if ( empty( $notifications_to_mark ) ) {
179 return;
180 }
181
182 $statuses = $this->get_notification_statuses();
183 $statuses = array_merge( $statuses, $notifications_to_mark );
184 $this->save_notification_statuses( $statuses );
185 }
186
187 private function get_unseen_notification_pages() {
188 $matomo_notifications = $this->get_current_notifications();
189 $matomo_statuses = $this->get_notification_statuses();
190
191 $matomo_unseen_notifications = [];
192 foreach ( $matomo_notifications as $id => $notification ) {
193 if ( ! isset( $matomo_statuses[ $id ] )
194 || self::STATUS_UNSEEN === $matomo_statuses[ $id ]
195 ) {
196 $matomo_unseen_notifications[ $id ] = $notification['notification_marker_page'];
197 }
198 }
199 return $matomo_unseen_notifications;
200 }
201
202 private function get_notifications_to_show() {
203 $current_page = Admin::get_current_page();
204
205 $matomo_notifications = $this->get_current_notifications();
206 $matomo_notifications = array_filter(
207 $matomo_notifications,
208 function ( $notification ) use ( $current_page ) {
209 if (
210 isset( $notification['show_if'] )
211 && false === $notification['show_if']
212 ) {
213 return false;
214 }
215
216 // do not show notification if configured to show only on one page, and the current page
217 // isn't the page to display
218 if ( self::SHOW_ON_SINGLE_PAGE === $notification['show_on']
219 && $notification['notification_marker_page'] !== $current_page
220 ) {
221 return false;
222 }
223
224 return true;
225 }
226 );
227
228 if ( empty( $matomo_notifications ) ) { // return early to avoid getting the option below
229 return [];
230 }
231
232 $matomo_statuses = $this->get_notification_statuses();
233
234 $notifications = [];
235 foreach ( $matomo_notifications as $id => $notification ) {
236 // do not show the notification if it's been dismissed
237 if ( isset( $matomo_statuses[ $id ] )
238 && self::STATUS_DISMISSED === $matomo_statuses[ $id ]
239 ) {
240 continue;
241 }
242
243 $notifications[ $id ] = $notification;
244 }
245 return $notifications;
246 }
247
248 /**
249 * Example:
250 *
251 * ```
252 * 'crash-analytics-promo' => [
253 * 'notification_marker_page' => 'matomo-marketplace',
254 * 'message' => $this->get_crash_analytics_promo_message(),
255 * 'show_on' => self::SHOW_ON_ALL_PAGES,
256 * 'show_if' => current_user_can( 'install_plugins' ),
257 * ],
258 * ```
259 *
260 * @return array[]
261 */
262 protected function get_current_notifications() {
263 return [
264 // nothing to show
265 ];
266 }
267
268 private function get_notification_status_option_name() {
269 return self::NOTIFICATION_STATUSES_OPTION_NAME . '-' . get_current_user_id();
270 }
271 }
272