PluginProbe ʕ •ᴥ•ʔ
Matomo Analytics – Powerful, Privacy-First Insights for WordPress / 5.10.1
Matomo Analytics – Powerful, Privacy-First Insights for WordPress v5.10.1
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 / Menu.php
matomo / classes / WpMatomo / Admin Last commit date
Marketplace 1 month ago PluginSuggestions 2 months ago TrackingSettings 1 month ago views 1 month ago AccessSettings.php 4 years ago AdBlockDetector.php 6 months ago Admin.php 1 month ago AdminSettings.php 2 months ago AdminSettingsInterface.php 6 years ago AdvancedSettings.php 10 months ago Chart.php 1 month ago CookieConsent.php 4 years ago Dashboard.php 2 months ago ExclusionSettings.php 6 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 1 month ago MarketplaceSetupWizard.php 1 month ago MarketplaceSetupWizardBody.php 1 month ago MatomoPage.php 2 months ago MatomoPageContent.php 2 months ago Menu.php 1 month ago PluginMeasurableSettings.php 2 years ago PrivacySettings.php 1 year ago SafeModeMenu.php 2 months ago Summary.php 2 months ago SystemReport.php 1 month ago TrackingSettings.php 1 month ago WhatsNewNotifications.php 2 months ago
Menu.php
465 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 Piwik\Plugins\UsersManager\UserPreferences;
13 use WpMatomo\Bootstrap;
14 use WpMatomo\Capabilities;
15 use WpMatomo\Feature;
16 use WpMatomo\Report\Dates;
17 use WpMatomo\Settings;
18 use WpMatomo\Site;
19
20 if ( ! defined( 'ABSPATH' ) ) {
21 exit; // if accessed directly
22 }
23
24 class Menu extends Feature {
25 /**
26 * @var Settings
27 */
28 private $settings;
29
30 public static $parent_slug = 'matomo';
31
32 const REPORTING_GOTO_ADMIN = 'matomo-admin';
33 const REPORTING_GOTO_GDPR_TOOLS = 'matomo-gdpr-tools';
34 const REPORTING_GOTO_GDPR_OVERVIEW = 'matomo-gdpr-overview';
35 const REPORTING_GOTO_ASK_CONSENT = 'matomo-gdpr-consent';
36 const REPORTING_GOTO_OPTOUT = 'matomo-privacy-optout';
37 const REPORTING_GOTO_ANONYMIZE_DATA = 'matomo-anonymize-date';
38 const REPORTING_GOTO_DATA_RETENTION = 'matomo-data-retention';
39 const SLUG_SYSTEM_REPORT = 'matomo-systemreport';
40 const SLUG_REPORT_SUMMARY = 'matomo-summary';
41 const SLUG_TAGMANAGER = 'matomo-tagmanager';
42 const SLUG_REPORTING = 'matomo-reporting';
43 const SLUG_SETTINGS = 'matomo-settings';
44 const SLUG_GET_STARTED = 'matomo-get-started';
45 const SLUG_ABOUT = 'matomo-about';
46 const SLUG_MARKETPLACE = 'matomo-marketplace';
47 const SLUG_IMPORTWPS = 'matomo-importwps';
48
49 const CAP_NOT_EXISTS = 'unknownfoobar';
50
51 /**
52 * @param Settings $settings
53 */
54 public function __construct( $settings ) {
55 $this->settings = $settings;
56 }
57
58 public function register_hooks() {
59 parent::register_hooks();
60
61 // Hook for adding admin menus
62 add_action( 'admin_menu', [ $this, 'add_menu' ] );
63 add_action( 'network_admin_menu', [ $this, 'add_menu' ] );
64 add_action( 'admin_head', [ $this, 'menu_external_icons' ] );
65 add_action( 'admin_head', [ $this, 'hide_non_matomo_notifications' ], 99999 );
66
67 // as we are redirecting we need to perform the redirect as soon as possible before WP has eg echoed the header
68 add_action( 'load-matomo-analytics_page_' . self::SLUG_REPORTING, [ $this, 'reporting' ] );
69 add_action( 'load-' . self::$parent_slug . '_page_' . self::SLUG_REPORTING, [ $this, 'reporting' ] );
70 add_action( 'load-matomo-analytics_page_' . self::SLUG_TAGMANAGER, [ $this, 'tagmanager' ] );
71 add_action( 'load-' . self::$parent_slug . '_page_' . self::SLUG_TAGMANAGER, [ $this, 'tagmanager' ] );
72
73 add_action( 'admin_enqueue_scripts', [ $this, 'enqueue_scripts' ] );
74 }
75
76 public function enqueue_scripts() {
77 if (
78 ! empty( $_REQUEST['page'] )
79 && self::SLUG_MARKETPLACE === $_REQUEST['page']
80 ) {
81 wp_enqueue_style( 'matomo_marketplace_css', plugins_url( 'assets/css/marketplace-style.css', MATOMO_ANALYTICS_FILE ), false, matomo_get_asset_version() );
82 }
83 }
84
85 public function hide_non_matomo_notifications() {
86 // only hide for matomo- pages
87 // phpcs:ignore WordPress.Security.ValidatedSanitizedInput.InputNotSanitized
88 $page = isset( $_REQUEST['page'] ) ? wp_unslash( $_REQUEST['page'] ) : '';
89 if ( strpos( $page, 'matomo-' ) !== 0 ) {
90 return;
91 }
92
93 // phpcs:ignore WordPress.Security.EscapeOutput.OutputNotEscaped
94 echo <<<EOF
95 <style>
96 .matomo-notice {
97 display: block;
98 }
99
100 .notice:not(.matomo-notice) {
101 display: none;
102 }
103 </style>
104 EOF;
105 }
106
107 public function add_menu() {
108 do_action( 'matomo_before_add_menu' );
109
110 $info = new MatomoPage( new Info() );
111 $get_started = new MatomoPage( new GetStarted( $this->settings ) );
112 $marketplace = new MatomoPage( new Marketplace( $this->settings ) );
113 $summary = new MatomoPage( new Summary( $this->settings ) );
114 $import_wp_s = new MatomoPage( new ImportWpStatistics() );
115 $admin_settings = new MatomoPage( new AdminSettings( $this->settings ) );
116
117 $matomo_logo_url = $this->get_light_grey_brand_icon();
118
119 add_menu_page( 'Matomo Analytics', 'Matomo Analytics', self::CAP_NOT_EXISTS, 'matomo', null, $matomo_logo_url, 2 );
120
121 if ( $this->settings->get_global_option( Settings::SHOW_GET_STARTED_PAGE ) && $get_started->get_content()->can_user_manage() ) {
122 if ( ! is_multisite() || ! is_network_admin() ) {
123 add_submenu_page(
124 self::$parent_slug,
125 __( 'Get Started', 'matomo' ),
126 __( 'Get Started', 'matomo' ),
127 Capabilities::KEY_SUPERUSER,
128 self::SLUG_GET_STARTED,
129 [
130 $get_started,
131 'show',
132 ]
133 );
134 }
135 }
136
137 if ( is_network_admin() ) {
138 $info_multisite = new MatomoPage( new Info( true ), 'show_multisite' );
139
140 add_submenu_page(
141 self::$parent_slug,
142 __( 'Multi Site', 'matomo' ),
143 __( 'Multi Site', 'matomo' ),
144 Capabilities::KEY_SUPERUSER,
145 'matomo-multisite',
146 [
147 $info_multisite,
148 'show',
149 ]
150 );
151 } else {
152 add_submenu_page(
153 self::$parent_slug,
154 __( 'Summary', 'matomo' ),
155 __( 'Summary', 'matomo' ),
156 Capabilities::KEY_VIEW,
157 self::SLUG_REPORT_SUMMARY,
158 [
159 $summary,
160 'show',
161 ]
162 );
163
164 // the network itself is not a blog
165 add_submenu_page(
166 self::$parent_slug,
167 __( 'Reporting', 'matomo' ),
168 __( 'Reporting', 'matomo' ),
169 Capabilities::KEY_VIEW,
170 self::SLUG_REPORTING,
171 [
172 $this,
173 'reporting',
174 ]
175 );
176 // the network itself is not a blog
177 if ( matomo_has_tag_manager() ) {
178 add_submenu_page(
179 self::$parent_slug,
180 __( 'Tag Manager', 'matomo' ),
181 __( 'Tag Manager', 'matomo' ),
182 Capabilities::KEY_WRITE,
183 self::SLUG_TAGMANAGER,
184 [
185 $this,
186 'tagmanager',
187 ]
188 );
189 }
190 }
191
192 // we always show settings except when multi site is used, plugin is not network enabled, and we are in network admin
193 $can_matomo_be_managed = ( ! is_multisite() || $this->settings->is_network_enabled() || ! is_network_admin() );
194
195 if ( $can_matomo_be_managed ) {
196 add_submenu_page(
197 self::$parent_slug,
198 __( 'Settings', 'matomo' ),
199 __( 'Settings', 'matomo' ),
200 Capabilities::KEY_SUPERUSER,
201 self::SLUG_SETTINGS,
202 [
203 $admin_settings,
204 'show',
205 ]
206 );
207 }
208
209 if ( ! is_plugin_active( MATOMO_MARKETPLACE_PLUGIN_NAME ) ) {
210 add_submenu_page(
211 self::$parent_slug,
212 __( 'Marketplace', 'matomo' ),
213 __( 'Marketplace', 'matomo' ),
214 Capabilities::KEY_VIEW,
215 self::SLUG_MARKETPLACE,
216 [
217 $marketplace,
218 'show',
219 ]
220 );
221 }
222
223 if ( $this->settings->is_network_enabled() || ! is_network_admin() ) {
224 $system_report = new MatomoPage( new SystemReport( $this->settings ) );
225
226 $warning = '';
227 if ( Admin::is_matomo_admin() ) {
228 if ( ! get_user_meta( get_current_user_id(), \WpMatomo\ErrorNotice::OPTION_NAME_SYSTEM_REPORT_ERRORS_DISMISSED ) && $system_report->get_content()->errors_present() ) {
229 $warning = '<span class="awaiting-mod">!</span>';
230 }
231 }
232
233 add_submenu_page(
234 self::$parent_slug,
235 __( 'Diagnostics', 'matomo' ),
236 __( 'Diagnostics', 'matomo' ) . $warning,
237 Capabilities::KEY_SUPERUSER,
238 self::SLUG_SYSTEM_REPORT,
239 [
240 $system_report,
241 'show',
242 ]
243 );
244 }
245
246 if ( is_plugin_active( 'wp-statistics/wp-statistics.php' ) ) {
247 add_submenu_page(
248 self::$parent_slug,
249 __( 'Import WP Statistics', 'matomo' ),
250 __( 'Import WP Statistics', 'matomo' ),
251 Capabilities::KEY_SUPERUSER,
252 self::SLUG_IMPORTWPS,
253 [
254 $import_wp_s,
255 'show',
256 ]
257 );
258 }
259 add_submenu_page(
260 self::$parent_slug,
261 __( 'Help', 'matomo' ),
262 __( 'Help', 'matomo' ),
263 Capabilities::KEY_VIEW,
264 self::SLUG_ABOUT,
265 [
266 $info,
267 'show',
268 ]
269 );
270 }
271
272 public function menu_external_icons() {
273 global $submenu;
274
275 if ( isset( $submenu[ self::$parent_slug ] ) ) {
276 $reporting = __( 'Reporting', 'matomo' );
277 $tagmanager = __( 'Tag Manager', 'matomo' );
278 foreach ( $submenu[ self::$parent_slug ] as $key => $menu_item ) {
279 if ( 0 === strpos( $menu_item[0], $reporting ) || 0 === strpos( $menu_item[0], $tagmanager ) ) {
280 // No other choice
281 // phpcs:ignore WordPress.WP.GlobalVariablesOverride.Prohibited
282 $submenu[ self::$parent_slug ][ $key ][0] .= ' <span class="dashicons-before dashicons-external"></span>';
283 }
284 }
285 }
286 }
287
288 public static function get_matomo_goto_url( $goto ) {
289 return add_query_arg( [ 'goto' => $goto ], menu_page_url( self::SLUG_REPORTING, false ) );
290 }
291
292 public static function get_reporting_url() {
293 return plugins_url( 'app', MATOMO_ANALYTICS_FILE ) . '/index.php';
294 }
295
296 public function tagmanager() {
297 if ( matomo_has_tag_manager() ) {
298 $this->go_to_matomo_page( 'TagManager', 'manageContainers', Capabilities::KEY_WRITE );
299 }
300 exit;
301 }
302
303 public function reporting() {
304 if ( ! empty( $_GET['goto'] ) ) {
305 switch ( sanitize_text_field( wp_unslash( $_GET['goto'] ) ) ) {
306 case self::REPORTING_GOTO_ADMIN:
307 $this->go_to_matomo_page( 'CoreAdminHome', 'home', Capabilities::KEY_SUPERUSER );
308 break;
309 case self::REPORTING_GOTO_GDPR_TOOLS:
310 $this->go_to_matomo_page( 'PrivacyManager', 'gdprTools', Capabilities::KEY_SUPERUSER );
311 break;
312 case self::REPORTING_GOTO_GDPR_OVERVIEW:
313 $this->go_to_matomo_page( 'PrivacyManager', 'gdprOverview', Capabilities::KEY_SUPERUSER );
314 break;
315 case self::REPORTING_GOTO_ASK_CONSENT:
316 $this->go_to_matomo_page( 'PrivacyManager', 'consent', Capabilities::KEY_SUPERUSER );
317 break;
318 case self::REPORTING_GOTO_OPTOUT:
319 $this->go_to_matomo_page( 'PrivacyManager', 'usersOptOut', Capabilities::KEY_SUPERUSER );
320 break;
321 case self::REPORTING_GOTO_ANONYMIZE_DATA:
322 $this->go_to_matomo_page( 'PrivacyManager', 'privacySettings', Capabilities::KEY_SUPERUSER );
323 break;
324 case self::REPORTING_GOTO_DATA_RETENTION:
325 $this->go_to_matomo_page( 'CoreAdminHome', 'generalSettings', Capabilities::KEY_SUPERUSER );
326 break;
327 }
328 }
329
330 $url = self::get_reporting_url();
331
332 $site = new Site();
333 $idsite = $site->get_current_matomo_site_id();
334
335 if ( $idsite ) {
336 $url = add_query_arg( [ 'idSite' => (int) $idsite ], $url );
337 }
338
339 if ( ! empty( $_GET['report_date'] ) ) {
340 $report_date = sanitize_text_field( wp_unslash( $_GET['report_date'] ) );
341 $url = add_query_arg(
342 [
343 'module' => 'CoreHome',
344 'action' => 'index',
345 ],
346 $url
347 );
348
349 $date = new Dates();
350 list( $period, $date ) = $date->detect_period_and_date( $report_date );
351 $url = add_query_arg(
352 [
353 'period' => $period,
354 'date' => $date,
355 ],
356 $url
357 );
358 }
359
360 wp_safe_redirect( $url );
361 exit;
362 }
363
364 /**
365 * @api
366 */
367 public static function get_matomo_reporting_url( $category, $subcategory, $params = [] ) {
368 $site = new Site();
369 $idsite = $site->get_current_matomo_site_id();
370
371 if ( ! $idsite ) {
372 return;
373 }
374
375 $idsite = (int) $idsite;
376 $params['category'] = $category;
377 $params['subcategory'] = $subcategory;
378 $params['idSite'] = $idsite;
379
380 if ( empty( $params['period'] ) ) {
381 $params['period'] = 'day';
382 }
383 if ( empty( $params['date'] ) ) {
384 $params['date'] = 'today';
385 }
386
387 $url = self::make_matomo_app_base_url();
388 $url .= '?module=CoreHome&action=index&idSite=' . (int) $idsite . '&period=' . rawurlencode( $params['period'] ) . '&date=' . rawurlencode( $params['date'] ) . '#?&' . http_build_query( $params );
389
390 return $url;
391 }
392
393 private static function make_matomo_app_base_url() {
394 $url = plugins_url( 'app', MATOMO_ANALYTICS_FILE );
395
396 return $url . '/index.php';
397 }
398
399 /**
400 * @api
401 */
402 public static function get_matomo_action_url( $module, $action, $params = [] ) {
403 $site = new Site();
404 $idsite = $site->get_current_matomo_site_id();
405
406 if ( ! $idsite ) {
407 return;
408 }
409
410 $idsite = (int) $idsite;
411 $params['module'] = $module;
412 $params['action'] = $action;
413 $params['idSite'] = $idsite;
414
415 if ( empty( $params['period'] ) ) {
416 $params['period'] = 'day';
417 }
418 if ( empty( $params['date'] ) ) {
419 $params['date'] = 'today';
420 }
421
422 $url = self::make_matomo_app_base_url() . '?' . http_build_query( $params );
423
424 return $url;
425 }
426
427 public function go_to_matomo_page( $module, $action, $cap ) {
428 if ( ! current_user_can( $cap ) ) {
429 return;
430 }
431 Bootstrap::do_bootstrap();
432
433 $user_preferences = new UserPreferences();
434 $website_id = $user_preferences->getDefaultWebsiteId();
435 $default_date = $user_preferences->getDefaultDate();
436 $default_period = $user_preferences->getDefaultPeriod( false );
437
438 $url = self::make_matomo_app_base_url();
439 $url .= '?idSite=' . (int) $website_id . '&period=' . rawurlencode( $default_period ) . '&date=' . rawurlencode( $default_date );
440 $url .= '&module=' . rawurlencode( $module ) . '&action=' . rawurlencode( $action );
441 wp_safe_redirect( $url );
442 exit;
443 }
444
445 private function get_light_grey_brand_icon() {
446 $svg = <<<EOF
447 <?xml version="1.0" encoding="UTF-8"?>
448 <svg data-name="Layer 1" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 590 400" height="20" width="20">
449 <defs>
450 <style>
451 .cls-1 {
452 fill: #f0f0f1;
453 }
454 </style>
455 </defs>
456 <path class="cls-1" d="M528.8,224.35l-76.26-132.09c-33.59-62.63-132.66-51.05-151.87,16.66-52.88-119.94-218.21-34.64-148.86,75.97-51.11-12.04-102.27,28.82-101.6,81.44-.95,94.29,136.48,114.11,163.06,25.01,32.01,76.13,133.35,78.62,161.24-.43,50.04,114.29,208.02,43.94,154.29-66.56ZM133.66,322.78c-74.19-1.33-74.18-111.59,0-112.9,74.19,1.33,74.18,111.59,0,112.9ZM338.64,229.24c2.93,5.11,5.51,10.43,7.55,15.96,9.37,25.39,7.6,50.58-23.02,69.6-25.97,15.71-62.49,5.93-77.12-20.66,0,0-76.26-132.09-76.26-132.09-7.54-13.06-9.54-28.27-5.64-42.84,12.04-47.99,79.4-56.84,103.42-13.61,0,0,39.99,69.32,40.42,70.12l30.64,53.53ZM323.84,134.03c1.27-74.19,111.63-74.18,112.88,0-1.27,74.19-111.63,74.18-112.88,0ZM511.06,280.69c-7.25,29.47-39.99,48.38-69.14,39.92-14.56-3.9-26.74-13.24-34.28-26.3-3.85-6.59-42.93-74.4-45.46-78.84,41.93,9.96,85.91-16.68,97.71-56.47l45.53,78.86c7.54,13.06,9.54,28.27,5.64,42.84Z"/>
457 </svg>
458 EOF;
459
460 // phpcs:ignore WordPress.PHP.DiscouragedPHPFunctions.obfuscation_base64_encode
461 $svg = 'data:image/svg+xml;base64,' . base64_encode( $svg );
462 return $svg;
463 }
464 }
465